.TITLE MONHWA .IDENT /V1.0/ ; This program will dump information about all nodes sending a SYSID. It ; listens to the Remote Console multicast to gather information about nodes. ; Author = David Gagne .LIBRARY "SYS$LIBRARY:LIB.MLB" $IODEF ;Define I/O functions and modifiers $NMADEF ;Define Network Management parameters $LNMDEF ;Define logical name parameters ; Modification history ; ; 1.0 David Gagne ; 01 Initial creation ; QIO data structures for the MOP (SYSTEM ID) channel. ; P2 parameter buffer for starting the channel. SIDPARM: .WORD NMA$C_PCLI_PTY ; Protocol Type .LONG ^X0260 .WORD NMA$C_PCLI_MCA ; Multicast address .WORD 8 .WORD NMA$C_LINMC_SET .BYTE ^XAB,00,00,02,00,00 SIDPARMLEN = .-SIDPARM SIDPARMDSC: .LONG SIDPARMLEN .ADDRESS SIDPARM ; Read buffer for receiving System IDs RCVBUF: .BLKB 1504 RCVBUFLEN = .-RCVBUF ; Place to store incoming P5 buffer (the frame header) RCVP5: RCVDA: .BLKB 6 RCVSA: .BLKB 6 RCVPT: .BLKB 2 ; Message structures ; General message buffer FAODESC: FAOLEN: .LONG 80 .ADDRESS FAOBUF FAOBUF: .BLKB 80 HDRMSG1: .ASCID "MONHWA - Ethernet HWA monitoring program. Version 1.0" IOMSG: .ASCID "!/The contents of the 2nd longword in the IOSB is !XL" NDMSG: .ASCID "No device found. Please define ETH appropriately." DNEMSG: .ASCID "MONHWA complete. Thank you for your continued support." BLNKMSG: .ASCID "" ; Output strings for monitoring all periodic SYSID messages M1HDR0: .ASCID " Monitor output from all periodic SYSID messages" M1HDR1: .ASCID " -----------------------------------------------" M1HDR2: .ASCID " Hardware Address Device Physical Address Node #" M1HDR3: .ASCID " ---------------- -------- ----------------- -------" M1INFO: .ASCID " " M1HWA: .ASCID "!XB!XB!XB!XB!XB!XB" M1DTYP: .ASCID "!2UB=!AS" M1ADDR: .ASCID "!XB-!XB-!XB-!XB-!XB-!XB" M1NODE: .ASCID "!2UB.!UW " M1NNOD: .ASCID " " M1NONE: .ASCID " There were no SYSID messages found." M2HDR: .ASCID " Address usage summary" M2SUM1: .ASCID " Nodes using their hardware address: !4UW" M2SUM2: .ASCID " Nodes using a DECnet address: !4UW" M2SUM3: .ASCID " Nodes using their another address: !4UW" M2SUM4: .ASCID " ----------------------------------------" M2SUM5: .ASCID " Total number of nodes found: !4UW" M3HDR1: .ASCID " Device usage summary" M3HDR2: .ASCID " Device Amount" M3HDR3: .ASCID " ------ ------" M3INFO: .ASCID " !5AS !5UW" ; Running totals for address usage SUMHWA: .WORD 0 SUMDEC: .WORD 0 SUMOTH: .WORD 0 ; Strings for various device names DEV01: .ASCID "DEUNA" DEV05: .ASCID "DEQNA" DEV11: .ASCID "DELUA" DEV17: .ASCID "DS100" DEV21: .ASCID "DEBET" DEV23: .ASCID "DEBNA" DEV25: .ASCID "PCLAN" DEV33: .ASCID "DS200" DEV35: .ASCID "DS500" DEV37: .ASCID "DELQA" DEV39: .ASCID "DESVA" DEV47: .ASCID "DESNC" DEV65: .ASCID "DEBNI" DEVNR: .ASCID "Noans" DEVUK: .ASCID "Unkwn" DEVMS: .ASCID "Misng" DEVTBL: .BYTE 1 .WORD 0 .ADDRESS DEV01 .BYTE 5 .WORD 0 .ADDRESS DEV05 .BYTE 11 .WORD 0 .ADDRESS DEV11 .BYTE 17 .WORD 0 .ADDRESS DEV17 .BYTE 21 .WORD 0 .ADDRESS DEV21 .BYTE 23 .WORD 0 .ADDRESS DEV23 .BYTE 25 .WORD 0 .ADDRESS DEV25 .BYTE 33 .WORD 0 .ADDRESS DEV33 .BYTE 35 .WORD 0 .ADDRESS DEV35 .BYTE 37 .WORD 0 .ADDRESS DEV37 .BYTE 39 .WORD 0 .ADDRESS DEV39 .BYTE 47 .WORD 0 .ADDRESS DEV47 .BYTE 65 .WORD 0 .ADDRESS DEV65 .BYTE 0 .WORD 0 DEVMSG: .WORD 0 ; Number of missing device IDs DEVDSC: .BLKQ 1 ; General device name descriptor DEVID: .BLKB 1 ; Device ID from SYSID response HWA: .BLKB 6 ; Device HWA from SYSID response CNTADR: .BLKL 1 ; Address of device counter ; Buffers, variables, and strings for the time control of the program HOURS: .BYTE 0 ; Storage of requested input MINUTES:.BYTE 0 SECONDS:.BYTE 0 ; The following variable are for reading input from the user after prompting. INPSTRDSC: ; Input buffer descriptor .LONG 0 .ADDRESS INPSTR INPSTR: .BLKB 18 ; Input buffer INPSIZ: .BLKL 1 ; The prompts are defined next. HPRMT: .ASCID "How many hours would you like to monitor: " MPRMT: .ASCID "How many minutes would you like to monitor: " SPRMT: .ASCID "How many seconds would you like to monitor: " ENDTIM: .BLKQ 1 ; Time to end test TIME: .BLKQ 1 ; Temporary time buffer DTIME: .ASCID /0 !2ZB:!2ZB:!2ZB.00/ ; String for calculating delta time ; Miscellaneous variables IOSB: .BLKQ 1 ; I/O status block ; Device names DEVDSC1:.ASCID 'ETH' ; Units to use for test DEVDSC2:.ASCID 'ESA0' DEVDSC3:.ASCID 'XQA0' DEVDSC4:.ASCID 'ETA0' DEVDSC5:.ASCID 'XEA0' DEVDSC6:.ASCID 'EXA0' DEVDSC7:.ASCID 'EZA0' ; Table of pointers to device names DEVADR: .ADDRESS DEVDSC1 .ADDRESS DEVDSC2 .ADDRESS DEVDSC3 .ADDRESS DEVDSC4 .ADDRESS DEVDSC5 .ADDRESS DEVDSC6 .ADDRESS DEVDSC7 .LONG 0 ; Channels - one for Remote Console CHNRMC: .BLKL 1 .ENTRY START,^M<> ; Assign the channel to the first device found which is available CLRL R5 ; Check each channel name to see if one 10$: TSTL DEVADR(R5) ; is available until one is found: the BEQL 20$ ; first name checked is "ETH", a dummy MOVL DEVADR(R5),R4 ; name which can be defined to the $ASSIGN_S- ; device desired if either: DEVNAM=(R4),- ; 1) An unregistered device is used CHAN=CHNRMC ; or 2) One device is prefered BLBS R0,ASSIGN_OK ; If success, exit the loop ADDL #4,R5 ; Skip to next device name CMPW R0,#SS$_NOSUCHDEV ; Was the error "no such device"? BEQL 10$ ; If yes, try next device name BRW ERROR ; Else, exit with error ; No device was found. 20$: BSBW BLANK ; No device was found, so say so and PUSHAB NDMSG ; then exit. CALLS #1,G^LIB$PUT_OUTPUT BRW EXIT ASSIGN_OK: ; Start up the channel for listening to SYSID messages. $QIOW_S FUNC=#,- CHAN=CHNRMC,- IOSB=IOSB,- P2=#SIDPARMDSC BLBS R0,START_REQ_OK BRW ERROR START_REQ_OK: MOVL IOSB,R0 BLBS R0,START_IO_OK BRW ERROR START_IO_OK: ; Print program header BSBW BLANK PUSHAB HDRMSG1 CALLS #1,G^LIB$PUT_OUTPUT ; Find out how long they want to listen for SYSID messages and then start ; listening. BSBW GET_TIME BSBW BLANK BSBW SET_TIME ;========================================================================== ; Print the header BSBW BLANK PUSHAB M1HDR0 CALLS #1,G^LIB$PUT_OUTPUT PUSHAB M1HDR1 CALLS #1,G^LIB$PUT_OUTPUT BSBW BLANK ; Collect SYSID information until we've either filled our data area or until ; we've listened for the requested amount of time. BSBW COLLECT ; Now print the results and exit BSBW PRTBL BSBW PRADR BSBW PRDEV BRW EXIT COLLECT: ; Collect SYSID information until we've either filled our data area or until ; we've listened for the requested amount of time. ; Check if we've been looping for the requested amount of time. $GETTIM_S- ; Get current time TIMADR=TIME CMPL TIME+4,ENDTIM+4 ; Did we look long enough? BEQL 10$ ; If equal, need to check low longword BLSSU 20$ ; If LSSU, continue RSB ; Else return 10$: CMPL TIME,ENDTIM ; Check low longword BLSSU 20$ ; If LSSU, continue RSB ; Else return ; Try to read another SYSID message. 20$: $QIOW_S FUNC=#IO$_READVBLK!IO$M_NOW,- CHAN=CHNRMC,- IOSB=IOSB,- P1=RCVBUF,- P2=#RCVBUFLEN,- P5=#RCVP5 BLBS R0,RCV_REQ_OK BRW ERROR RCV_REQ_OK: MOVZWL IOSB,R0 BLBS R0,RCV_IO_OK CMPW R0,#SS$_ENDOFFILE BEQL COLLECT BRW ERROR RCV_IO_OK: ; Check if this is a multicast message. If not, throw it away and look for ; another message. If this is not a SYSTEM ID message, then throw it away. BLBC RCVDA,COLLECT ; Ignore packet if sent to physical CMPB RCVBUF,#7 ; Is this a SYSTEM ID message? BNEQ COLLECT ; If NEQ, no, read another ; Get the information about this node. If it's not in the table yet, add it. ; Both the HWA and the physical address must match for it to already be in ; the table. This allows us to capture information about nodes that run ; with multiple physical addresses and physical addresses that run on ; multiple nodes. BSBW GET_IDHWA ; Get the Device ID and HWA CMPB HWA,#^XFF ; Was there a HWA? BNEQ 10$ ; If yes, continue BRW COLLECT ; If none, don't list this one 10$: MOVAL NODTBL,R4 ; Get beginning of table MOVL NODCNT,R5 ; Get number of entries to compare BEQL ADDNODE ; If none yet, just add this one 20$: CMPL HWA,(R4) ; HWA match? BNEQ 30$ ; If NEQ, no match on this entry CMPW HWA+4,4(R4) ; HWA match? BNEQ 30$ ; If NEQ, no match on this entry CMPL RCVSA,16(R4) ; PHA match? BNEQ 30$ ; If NEQ, no match on this entry CMPW RCVSA+4,20(R4) ; PHA match? BNEQ 30$ ; If NEQ, no match on this entry BRW COLLECT ; Identical entry, ignore this SYSID 30$: ADDL #NODSIZ,R4 ; Get next entry in the table SOBGTR R5,20$ ; Look at more entries ; This is a new SYSID, so add it to the table. ADDNODE: MOVL HWA,(R4)+ ; Add HWA MOVW HWA+4,(R4)+ MOVB DEVID,(R4)+ ; Add device ID TSTB (R4)+ MOVQ DEVDSC,(R4)+ ; Add Device name descriptor MOVL RCVSA,(R4)+ ; Add Physical address MOVW RCVSA+4,(R4) INCW @CNTADR ; One more of this specific device INCL NODCNT ; One more node in the table CMPL NODCNT,#MAXNOD ; Table full? BGEQU 10$ ; If EQL, yes, so return BRW COLLECT ; Else read another SYSID 10$: RSB PRTBL: ; Print the results. If no entries were found, just print that none were ; found. MOVL NODCNT,R5 ; Get the number of nodes BNEQ 10$ ; If some exist, print table ; else print none found message ;========================================================================== ; Print the "no nodes found" message PUSHAB M1NONE CALLS #1,G^LIB$PUT_OUTPUT RSB ;========================================================================== ; Print the table header 10$: PUSHAB M1HDR2 CALLS #1,G^LIB$PUT_OUTPUT PUSHAB M1HDR3 CALLS #1,G^LIB$PUT_OUTPUT 20$: BSBW GET_NODE ; Get a node MOVL R2,R4 ; Any found? BNEQ 21$ ; If NEQ, yes RSB ;========================================================================== ; Get the hardware address into the table string 21$: MOVL #80,FAOLEN $FAO_S CTRSTR=M1HWA,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=5(R4),- P2=4(R4),- P3=3(R4),- P4=2(R4),- P5=1(R4),- P6=0(R4) MOVQ R4,-(SP) MOVC3 FAOLEN,FAOBUF,M1INFO+8+4 MOVQ (SP)+,R4 ;========================================================================== ; Get the Ethernet controller ID and name into the table string MOVL #80,FAOLEN MOVQ 8(R4),DEVDSC $FAO_S CTRSTR=M1DTYP,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=6(R4),- P2=#DEVDSC MOVQ R4,-(SP) MOVC3 FAOLEN,FAOBUF,M1INFO+8+4+19 MOVQ (SP)+,R4 ; If the HWA is the same as the physical address, then the rest of the ; table string can be left blank. CMPL (R4),16(R4) ; Addresses the same? BNEQ 25$ ; If NEQ, no CMPW 4(R4),20(R4) ; Addresses the same? BNEQ 25$ ; If NEQ, no MOVQ R4,-(SP) MOVC5 #0,FAOBUF,#^A' ',#27,M1INFO+8+4+19+11 MOVQ (SP)+,R4 INCW SUMHWA ; Another node using its HWA BRW 29$ ;========================================================================== ; Get the physical address into the table string 25$: MOVL #80,FAOLEN $FAO_S CTRSTR=M1ADDR,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=16(R4),- P2=17(R4),- P3=18(R4),- P4=19(R4),- P5=20(R4),- P6=21(R4) MOVQ R4,-(SP) MOVC3 FAOLEN,FAOBUF,M1INFO+8+4+19+11 MOVQ (SP)+,R4 ;========================================================================== ; Get the node number in the table string if the PHA is a DECnet address CMPL #^X000400AA,16(R4) ; Is this a DECnet address? BEQL 27$ ; If EQL, yes, so print it MOVQ R4,-(SP) MOVC5 #0,FAOBUF,#^A' ',#7,M1INFO+8+4+19+11+20 MOVQ (SP)+,R4 INCW SUMOTH ; Another node using some other address BRW 29$ 27$: MOVZWL 20(R4),R0 BICW #^XFC00,R0 MOVZBL 21(R4),R1 ASHL #-2,R1,R1 MOVL #80,FAOLEN $FAO_S CTRSTR=M1NODE,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=R1,- P2=R0 MOVQ R4,-(SP) MOVC3 #7,FAOBUF,M1INFO+8+4+19+11+20 MOVQ (SP)+,R4 INCW SUMDEC ; Another node using a DECnet address ;========================================================================== ; Print the table string 29$: PUSHAB M1INFO CALLS #1,G^LIB$PUT_OUTPUT ;========================================================================== CLRL 8(R4) ; This entry has been printed BRW 20$ PRADR: ; Print the address totals. ;========================================================================== ; Print the header PUSHAB M2HDR CALLS #1,G^LIB$PUT_OUTPUT BSBW BLANK ;========================================================================== ; Print the SUMS MOVL #80,FAOLEN $FAO_S CTRSTR=M2SUM1,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=SUMHWA PUSHAB FAODESC CALLS #1,G^LIB$PUT_OUTPUT MOVL #80,FAOLEN $FAO_S CTRSTR=M2SUM2,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=SUMDEC PUSHAB FAODESC CALLS #1,G^LIB$PUT_OUTPUT MOVL #80,FAOLEN $FAO_S CTRSTR=M2SUM3,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=SUMOTH PUSHAB FAODESC CALLS #1,G^LIB$PUT_OUTPUT PUSHAB M2SUM4 CALLS #1,G^LIB$PUT_OUTPUT MOVL #80,FAOLEN $FAO_S CTRSTR=M2SUM5,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=NODCNT PUSHAB FAODESC CALLS #1,G^LIB$PUT_OUTPUT RSB PRDEV: ; Print the device totals. ;========================================================================== ; Print the header PUSHAB M3HDR1 CALLS #1,G^LIB$PUT_OUTPUT BSBW BLANK PUSHAB M3HDR2 CALLS #1,G^LIB$PUT_OUTPUT PUSHAB M3HDR3 CALLS #1,G^LIB$PUT_OUTPUT ;========================================================================== ; Print the device totals MOVAB DEVTBL,R5 ; Start at beginning of table ; Loop printing each device in the device table. 10$: TSTB (R5) ; End of table? BEQL 20$ ; If EQL, yes MOVL 3(R5),R6 ; Get the address of the descriptor MOVL #80,FAOLEN $FAO_S CTRSTR=M3INFO,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=R6,- P2=1(R5) PUSHAB FAODESC CALLS #1,G^LIB$PUT_OUTPUT ADDL #7,R5 ; Skip this entry BRB 10$ ; Loop for more devices ; Now print the number of unknown devices. 20$: MOVL #80,FAOLEN $FAO_S CTRSTR=M3INFO,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=#DEVUK,- P2=1(R5) PUSHAB FAODESC CALLS #1,G^LIB$PUT_OUTPUT ; Now print the number of missing devices. MOVL #80,FAOLEN $FAO_S CTRSTR=M3INFO,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=#DEVMS,- P2=DEVMSG PUSHAB FAODESC CALLS #1,G^LIB$PUT_OUTPUT RSB GET_IDHWA: ; Get the node's device ID, device name, and HWA. This is done by looking ; at the message received. The message contains a device ID. From the ; device ID, we will select the correct device name. Upon completion of ; this routine, DEVID (a byte) will have the device ID and DEVDSC will point ; to the device name. The message also contains the hardware address. Upon ; completion of this routine, HWA will contain the hardware address or FF ; in the first byte if none was found. Another field initialized is the ; CNTADR field which will contain the address of the counter which should ; be incremented if this SYSID is unique. ; Look for the Device ID entry in this SYSID message. MOVL #4,R3 ; Skip over SYSID header ; Loop through the entries in the SYSID looking for the Device ID entry. 10$: CMPW R3,IOSB+2 ; Any buffer left to look at? BLSSU 20$ ; If LSSU, yes, so look for more BRW 210$ ; Else report Device ID missing 20$: CMPW RCVBUF(R3),#^D100 ; Is this the device ID entry? BEQL 30$ ; If EQL, yes MOVZBL RCVBUF+2(R3),R1 ; Get size of this entry ADDL #3,R3 ; Skip over entry type and size ADDL R1,R3 ; Skip over entry value BRW 10$ ; Check next entry ; The Device ID was found. Store the Device ID and select a device name. 30$: ADDL #3,R3 ; Skip over Device ID header MOVB RCVBUF(R3),DEVID ; Store the Device ID MOVAB DEVTBL,R5 ; Start at beginning of table 40$: TSTB (R5) ; End of table? BEQL 200$ ; If EQL, yes CMPB DEVID,(R5)+ ; Device number match? BEQL 50$ ; If EQL, yes ADDL #6,R5 ; Skip to next entry BRB 40$ ; Check next entry ; We found a match in the table. 50$: MOVL R5,CNTADR ; Save address of counter TSTW (R5)+ ; Skip the device count MOVQ @(R5),DEVDSC ; Save descriptor BRB 300$ 200$: MOVAL 1(R5),CNTADR ; Save address of counter MOVQ DEVUK,DEVDSC ; This is an unknown device BRB 300$ 210$: MOVAL DEVMSG,CNTADR ; Save address of counter CLRB DEVID ; No Device ID was found MOVQ DEVMS,DEVDSC ; Device ID is missing ; Now look for the Hardware address in the SYSID response. 300$: MOVL #4,R3 ; Skip over SYSID header ; Loop through the entries in the SYSID looking for the HWA entry. 310$: CMPW R3,IOSB+2 ; Any buffer left to look at? BLSSU 320$ ; If LSSU, yes, so look for more BRW 340$ ; Else report HWA missing 320$: CMPW RCVBUF(R3),#^D7 ; Is this the HWA entry? BEQL 330$ ; If EQL, yes MOVZBL RCVBUF+2(R3),R1 ; Get size of this entry ADDL #3,R3 ; Skip over entry type and size ADDL R1,R3 ; Skip over entry value BRW 310$ ; Check next entry ; The HWA was found. Store the HWA. 330$: ADDL #3,R3 ; Skip over HWA header MOVL RCVBUF(R3),HWA ; Store first longword MOVW RCVBUF+4(R3),HWA+4 ; Store last word RSB 340$: MOVB #^XFF,HWA ; Set "no HWA found" RSB GET_TIME: ; Get number of hours to run test for GET_HOUR: BSBW BLANK MOVL #6,INPSTRDSC PUSHAB INPSIZ PUSHAB HPRMT PUSHAB INPSTRDSC CALLS #3,G^LIB$GET_INPUT ; Convert number of hours CLRL R1 CLRW R2 NUM_LOOP2: MOVZBL INPSTR(R2),R0 SUBL2 #^A/0/,R0 MULL2 #^D10,R1 ADDL2 R0,R1 INCW R2 CMPW R2,INPSIZ BLSS NUM_LOOP2 CMPL R1,#^D23 BGTR GET_HOUR MOVL R1,HOURS ; Get number of minutes to run test for GET_MINUTE: MOVL #6,INPSTRDSC PUSHAB INPSIZ PUSHAB MPRMT PUSHAB INPSTRDSC CALLS #3,G^LIB$GET_INPUT ; Convert number of minutes CLRL R1 CLRW R2 NUM_LOOP3: MOVZBL INPSTR(R2),R0 SUBL2 #^A/0/,R0 MULL2 #^D10,R1 ADDL2 R0,R1 INCW R2 CMPW R2,INPSIZ BLSS NUM_LOOP3 CMPL R1,#^D59 BGTR GET_MINUTE MOVL R1,MINUTES ; Get number of seconds to run test for GET_SECOND: MOVL #6,INPSTRDSC PUSHAB INPSIZ PUSHAB SPRMT PUSHAB INPSTRDSC CALLS #3,G^LIB$GET_INPUT ; Convert number of seconds CLRL R1 CLRW R2 NUM_LOOP4: MOVZBL INPSTR(R2),R0 SUBL2 #^A/0/,R0 MULL2 #^D10,R1 ADDL2 R0,R1 INCW R2 CMPW R2,INPSIZ BLSS NUM_LOOP4 CMPL R1,#^D59 BGTR GET_SECOND MOVL R1,SECONDS RSB SET_TIME: ; Determine the time to stop the test ; Now put the total time into one string MOVL #80,FAOLEN $FAO_S CTRSTR=DTIME,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=HOURS,- P2=MINUTES,- P3=SECONDS ; Change the ASCII string for the time to a quadword value. $BINTIM_S- TIMBUF=FAODESC,- TIMADR=TIME MNEGL TIME+4,TIME+4 MNEGL TIME,TIME SBWC #0,TIME+4 ; Now get the present time and add the test time to get the end time. $GETTIM_S- TIMADR=ENDTIM ADDL TIME,ENDTIM ADWC TIME+4,ENDTIM+4 RSB GET_NODE: ; Locate the next node in the table to be printed. We will locate the node ; with the lowest hardware address. We will skip over nodes that have a ; zero in their device descriptor field. MOVQ R0,-(SP) ; Save R0 and R1 CLRL R1 ; Start our counter at zero CLRL R0 ; Start with no node found MOVAL NODTBL,R2 ; Start at beginning of table 10$: TSTL 8(R2) ; Is this a valid entry? BEQL 30$ ; If EQL, no ; If this is the first entry found, just store it. Else compare it with the ; smallest found so far. TSTL R0 ; Did we find a node yet? BEQL 20$ ; If EQL, no, so save this one CMPL 2(R2),2(R0) ; Is the new one smaller? BGTRU 30$ ; If GTRU, no, so skip this node BLSSU 20$ ; If LSSU, yes, so save it CMPW (R2),(R0) ; Is the new one smaller? BGEQU 30$ ; If GEQU, no, so skip this node 20$: MOVL R2,R0 ; Save this as the smallest node ; Skip to next node and continue if there are more nodes to look at. 30$: ADDL #NODSIZ,R2 ; Skip to next entry in table INCL R1 ; Bump node counter CMPL R1,NODCNT ; Are we done? BLSSU 10$ ; If LSSU, no, so loop MOVL R0,R2 ; Return pointer to smallest node MOVQ (SP)+,R0 ; Restore R0 and R1 RSB EXIT: BSBW BLANK PUSHAB DNEMSG CALLS #1,G^LIB$PUT_OUTPUT BSBW BLANK $DASSGN_S- CHAN=CHNRMC $EXIT_S BLANK: ; Print blank line PUSHAB BLNKMSG CALLS #1,G^LIB$PUT_OUTPUT RSB ; An error has occured, so print R0 value and 2nd longword of IOSB. ERROR: PUSHL R0 ; Pass R0 error code CALLS #1,RBL$ERCODE ; Print error code ; Print IOSB 2nd longword value in hex MOVL #80,FAOLEN $FAO_S CTRSTR=IOMSG,- OUTLEN=FAOLEN,- OUTBUF=FAODESC,- P1=IOSB+4 PUSHAB FAODESC CALLS #1,G^LIB$PUT_OUTPUT BRW EXIT ; Now exit normally .PAGE ; RBL$ERCODE ; ; This subroutine accepts a VMS error code in binary ; and print the message on the terminal. ; ; INPUT: 4(AP) = Error Code ; ; OUTPUT: all registers saved except R0 and R1 ; ; CALLING SEQ: PUSHx error code ; CALL_S #1,RBL$ERCODE ; .ENTRY RBL$ERCODE,^M MOVL 4(AP),R3 ; Get error code $GETMSG_S- ; Convert error code to message MSGID=R3,- MSGLEN=ERRMSG_LEN,- BUFADR=ERRMSG_BUF_DESC PUSHAB ERRMSG_BUF_DESC CALLS #1,G^LIB$PUT_OUTPUT RET ; Return to caller ; Structures used to build error message from error code ERRMSG_BUF_DESC: ERRMSG_LEN: .LONG 256 .ADDRESS- ERRMSG_BUF ERRMSG_BUF: .BLKB 256 ; Table for information on nodes already found. ; Each entry consists of: ; ; 6 bytes of hardware address ; 1 byte of DEVICE ID ; 1 byte of spare info ; 8 bytes of DEVICE NAME descriptor ; 6 bytes of physical address ; 4 bytes of address of device counter NODSIZ = 26 MAXNOD = 1000 NODCNT: .LONG 0 NODTBL: .BLKB MAXNOD*NODSIZ .END START