From:	ADVAX::"""l_leahy""@star.enet.dec.com" "Lee Leahy DTN 381-0570 17-May-1991 1015" 17-MAY-1991 23:13:08.26
To:	arisia::everhart
CC:	
Subj:	MONLAT.MAR - Third section of 4

Received: by ADVAX.DECnet (utk-mail11 v1.5) ; Fri, 17 May 91 23:11:34 EDT
Received:  from mcnc by ge-dab.GE.COM (5.61/GE-DAB 1.15) with UUCP
	id AA27154 for ; Fri, 17 May 91 21:06:41 -0400
Received: from enet-gw.pa.dec.com by mcnc.mcnc.org (5.59/MCNC/3-21-91)
	id AA13568; Fri, 17 May 91 10:15:36 -0400
	for ARISIA.dnet.ge.com!EVERHART
Received: by enet-gw.pa.dec.com; id AA27337; Fri, 17 May 91 07:14:43 -0700
Message-Id: <9105171414.AA27337@enet-gw.pa.dec.com>
Received: from star.enet; by decwrl.enet; Fri, 17 May 91 07:14:55 PDT
Date: Fri, 17 May 91 07:14:55 PDT
From: Lee Leahy DTN 381-0570  17-May-1991 1015 <"l_leahy"@star.enet.dec.com>
To: arisia::everhart
Subject: MONLAT.MAR - Third section of 4
 
	MOVZBL	(R5)+,R6		; Get number of sets
	BEQL	60$			; Branch if none
	CLRL	R3			; Nothing to skip right now
 
; Print the service name if there is one.
 
30$:	INCL	R5			; Skip service rating
	ADDL	R3,R5			; Address of size
	MOVZBL	(R5)+,R3		; Get size
	BEQL	40$			; If EQL, none to print
	MOVL	#80,FAOLEN
	$FAO_S	CTRSTR=M3IDN3,-
		OUTLEN=FAOLEN,-
		OUTBUF=FAODESC,-
		P1=R3,-
		P2=R5
	PUSHAB	FAODESC	
	CALLS	#1,G^LIB$PUT_OUTPUT
 
; Print the service descriptor if there is one.
 
40$:	ADDL	R3,R5			; Address of size
	MOVZBL	(R5)+,R3		; Get size
	BEQL	50$			; If EQL, none to print
	MOVL	#80,FAOLEN
	$FAO_S	CTRSTR=M3IDN4,-
		OUTLEN=FAOLEN,-
		OUTBUF=FAODESC,-
		P1=R3,-
		P2=R5
	PUSHAB	FAODESC	
	CALLS	#1,G^LIB$PUT_OUTPUT
 
; If more service sets, print them.
 
50$:
	SOBGTR	R6,30$
 
; Print the group code header.
 
60$:	PUSHAB	M3HDR1
	CALLS	#1,G^LIB$PUT_OUTPUT
 
; Print all the enabled group code's.
 
	CLRL	R1
70$:	CLRL	R0
	CLRL	R2
	EDIV	#8,R1,R0,R2
	BBC	R2,GCBITS(R0),80$
	PUSHL	R1
	MOVL	#80,FAOLEN
	$FAO_S	CTRSTR=M3GCOD,-
		OUTLEN=FAOLEN,-
		OUTBUF=FAODESC,-
		P1=R1
	PUSHAB	FAODESC
	CALLS	#1,G^LIB$PUT_OUTPUT
	POPL	R1
80$:	INCL	R1
	CMPL	R1,#^D256
	BLSS	70$
	RSB

RCV_LAT:
 
; Read a LAT multicast service announcement frame.  Return if time has run
; out (R0=0) or if a frame was received successfully (R0=1).
 
; First check if time has run out.
 
	$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	30$			; If LSSU, continue
	BRB	20$			; Else end search for the node
10$:	CMPL	TIME,ENDTIM		; Check low longword
	BLSSU	30$			; If LSSU, continue
 
20$:	CLRL	R0			; Say that time ran out
	RSB
 
30$:	$QIOW_S	FUNC=#IO$_READVBLK!IO$M_NOW,-
		CHAN=CHNLAT,-
		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	RCV_LAT
	BRW	ERROR
 
RCV_IO_OK:
 
; Check if this is a multicast message.  If not, throw it away and look for
; another message.
 
	BLBC	RCVDA,RCV_LAT		; Ignore packet if sent to physical
 
; Make sure this is a service announcement message.  If not, throw it away
; and look for another message.
 
	CMPB	#^X28,RCVBUF		; Is this a service announcement?
	BNEQ	RCV_LAT			; If NEQ, no, try again
 
; The message is good, return success
 
	MOVZBL	#1,R0
	RSB

STORE_NODE:
; RCVSA  = Source address
; RCVBUF = Received LAT message
 
; Check if this is a new node.  If so, store it.  However, if the source
; address is multicast, then we will throw the packet away because we use
; a multicast source address to show that the node has already been printed.
 
	BLBC	RCVSA,10$		; If not multicast source, store it
	RSB
10$:	CMPL	#2,REQ			; Is this test 2?
	BEQL	20$			; If EQL, yes, don't need GCBITS
	MOVZBL	RCVBUF+12,R1		; Get size of mask in message
	MOVC5	R1,RCVBUF+13,#0,-	; Store the group codes in GCBITS
		#^X20,GCBITS
 
; Check to see if the source address is already in the node table.  If so,
; throw this message away and read another one.
 
20$:	MOVAL	NODTBL,R2		; Start at beginning of table
	SUBL	#NODSIZ,R2		; Get to negative one entry
	MOVL	NODCNT,R1		; Get number of entries
	BEQL	50$			; If none, just add this one
30$:	ADDL	#NODSIZ,R2		; Get to next entry
	CMPL	RCVSA,(R2)		; Source address match?
	BNEQ	40$			; If NEQ, no, so check next entry
	CMPW	RCVSA+4,4(R2)		; Source address match?
	BEQL	60$			; If EQL, yes, so ignore message
40$:	SOBGTR	R1,30$			; Check next entry in table
 
; The node was not in the table, so add it if there's room.
 
50$:	CMPL	NODCNT,#NODMAX		; Is there room?
	BEQL	60$			; If EQL, no, so ignore message
	ADDL	#NODSIZ,R2		; Get to next entry
	MOVL	RCVSA,(R2)		; Store SA
	MOVW	RCVSA+4,4(R2)		; Store SA
	MOVQ	GCBITS+00,06(R2)	; Store group code mask
	MOVQ	GCBITS+08,14(R2)	; Store group code mask
	MOVQ	GCBITS+16,22(R2)	; Store group code mask
	MOVQ	GCBITS+24,30(R2)	; Store group code mask
	BSBB	STORE_NAME
	INCL	NODCNT			; Bump number of used entries
60$:	RSB

STORE_NAME:
; R2 = Address of node entry
; 
; Now get the node name and service name (if they exist).  First fill the
; node name section of the entry with spaces.  If the first service name is
; the same as the node name, then store the second service name (if there
; is one).
 
	MOVL	#^X20202020,38(R2)	; Start with spaces for the node name
	MOVW	#^X2020,42(R2)
	MOVZBL	RCVBUF+12,R1		; Get size of group code bits
	ADDL3	#^D13,R1,R4		; Offset to node name size
	MOVAL	RCVBUF+1,R5		; Calc address of string
	ADDL	R4,R5			; Address of string
	MOVZBL	RCVBUF(R4),R3		; Get size
	BEQL	20$			; If EQL, none to print
	PUSHR	#^M<R1,R2,R3,R4,R5>	; Save registers
	CMPL	R3,#6			; String too big?
	BLEQU	10$			; If LEQU, no
	MOVL	#6,R3			; Only copy what fits
10$:	SUBL3	R3,#6,R0		; Number of bytes to skip in dest
	MOVAL	38(R2),R1		; Node name storage area
	ADDL	R1,R0			; Where to store this node name
	PUSHR	#^M<R1,R2,R3,R4,R5>	; Save registers
	MOVC3	R3,(R5),(R0)		; Store the name
	POPR	#^M<R1,R2,R3,R4,R5>	; Restore registers
	MOVC3	R3,(R5),NODNAM		; Store here for comparison
	POPR	#^M<R1,R2,R3,R4,R5>	; Restore registers
 
; Skip over the node descriptor.
 
20$:	ADDL	R3,R5			; Address of size
	MOVZBL	(R5)+,R3		; Get size
	ADDL	R3,R5			; Skip over node descriptor
 
; See if there are any service sets.
 
	MOVL	#^X20202020,SERNAM	; Start with spaces in service name
	MOVW	#^X2020,SERNAM+4
	MOVZBL	(R5)+,R6		; Get number of sets
	BEQL	40$			; Branch if none
 
; Save the first service name if there is one.
 
25$:	INCL	R5			; Skip service rating
	MOVZBL	(R5)+,R3		; Get size
	BEQL	40$			; Exit if none
	PUSHL	R3			; Save the size
	CMPL	R3,#6			; String too big?
	BLEQU	30$			; If LEQU, no
	MOVL	#6,R3			; Only copy what fits
30$:	MOVL	#^X20202020,SERNAM	; Put spaces in service name again
	MOVW	#^X2020,SERNAM+4	; because there may be junk there
	PUSHR	#^M<R1,R2,R3,R4,R5>	; Save registers
	MOVC3	R3,(R5),SERNAM		; Store the name
	POPR	#^M<R1,R2,R3,R4,R5>	; Restore registers
	PUSHR	#^M<R1,R2,R3,R4,R5>	; Save registers
	CMPC3	R3,SERNAM,NODNAM	; Are the names the same?
	BNEQ	35$			; If NEQ, no, so use this name
	POPR	#^M<R1,R2,R3,R4,R5>	; Restore registers
	POPL	R3			; Get original size back
	ADDL	R3,R5			; Get to service description
	MOVZBL	(R5)+,R3		; Get size of service description
	ADDL	R3,R5			; Get to next service name
	SOBGTR	R6,25$			; Loop if more entries
	BRB	40$			; Else use what we have
 
35$:	POPR	#^M<R1,R2,R3,R4,R5>	; Restore registers
	POPL	R3			; Clean up the stack
40$:	PUSHR	#^M<R1,R2,R3,R4,R5>	; Save registers
	MOVC3	#6,SERNAM,44(R2)	; Store the service name we found
	POPR	#^M<R1,R2,R3,R4,R5>	; Restore registers
	RSB

PRINT_NODE:
; R2 is pointing to the entry we want to print.
 
	MOVL	(R2),SIDADDR		; Get the source address so we can ...
	MOVW	4(R2),SIDADDR+4
	BSBW	GET_DEVID		; Get the device information
	MOVL	#80,FAOLEN
	$FAO_S	CTRSTR=M1DAT1,-
		OUTLEN=FAOLEN,-
		OUTBUF=FAODESC,-
		P1=0(R2),-
		P2=1(R2),-
		P3=2(R2),-
		P4=3(R2),-
		P5=4(R2),-
		P6=5(R2),-
		P7=DEVID,-
		P8=#DEVDSC
	CMPL	(R2),#^X000400AA	; Is this a DECnet address?
	BNEQ	10$			; If NEQ, no
	MOVW	4(R2),R0
	BICW	#^XFC00,R0
	MOVZBL	5(R2),R1
	ASHL	#-2,R1,R3
	MOVL	#80-33,FAOLEN
	MOVAL	33+FAOBUF,FAODESC+4
	$FAO_S	CTRSTR=M1DAT2,-
		OUTLEN=FAOLEN,-
		OUTBUF=FAODESC,-
		P1=DEVHWA,-
		P2=DEVHWA+1,-
		P3=DEVHWA+2,-
		P4=DEVHWA+3,-
		P5=DEVHWA+4,-
		P6=DEVHWA+5,-
		P7=R3,-
		P8=R0
10$:	MOVL	#80-62,FAOLEN
	MOVAL	62+FAOBUF,FAODESC+4
	MOVAL	38(R2),R3
	MOVAL	44(R2),R0
	$FAO_S	CTRSTR=M1DAT3,-
		OUTLEN=FAOLEN,-
		OUTBUF=FAODESC,-
		P1=#6,-
		P2=R3,-
		P3=#6,-
		P4=R0
	ADDL	#62,FAOLEN
	MOVAL	FAOBUF,FAODESC+4
	PUSHAB	FAODESC
	CALLS	#1,G^LIB$PUT_OUTPUT
	RSB

GET_DEVID:
 
; Get the node's device ID and device name.  This is done by requesting a
; SYSID message from the node.  The response (if any) contains the 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,
; DEVDSC will point to the device name, and DEVHWA will have the device's
; hardware address.
 
; Transmit the request ID message to the node we want to find out about.
 
	$QIOW_S	FUNC=#IO$_WRITEVBLK,-
		CHAN=CHNRMC,-
		IOSB=IOSB,-
		P1=XMTP2BUF,-
		P2=#XMTP2LEN,-
		P5=#SIDADDR
 
	BLBS	R0,DXMT_REQ_OK
	BRW	ERROR
 
DXMT_REQ_OK:
 
	MOVL	IOSB,R0
	BLBS	R0,DXMT_IO_OK
	BRW	ERROR
 
DXMT_IO_OK:
 
; Receive the SYSID response.  If there is no data ready to receive, then the
; Ethernet driver will return immediately with SS$_ENDOFFILE.
 
	CLRL	RCVTRY			; Clear the number of read attempts
 
DRCV:
 
	$QIOW_S	FUNC=#IO$_READVBLK!IO$M_NOW,-
		CHAN=CHNRMC,-
		IOSB=IOSB,-
		P1=RCVBUF2,-
		P2=#RCVBUFLEN2,-
		P5=#RCVP52
 
	BLBS	R0,DRCV_REQ_OK
	BRW	ERROR
 
DRCV_REQ_OK:
 
	MOVL	IOSB,R0
	BLBS	R0,DRCV_IO_OK
	CMPW	IOSB,#SS$_ENDOFFILE
	BEQL	DRCV_TRY
	BRW	ERROR
 
DRCV_TRY:
	CMPL	RCVTRY,#4000		; Have we tried enough times?
	BGTR	20$			; If GTR, yes, so message is lost
	INCL	RCVTRY			; Count this attempt
	BRB	DRCV			; Try again
20$:	CLRB	DEVID			; Clear the Device ID number
	MOVQ	DEVNAN,DEVDSC		; Set the device name to no response
	INCW	CTRNAN			; Count this no answer case
	CLRL	DEVHWA			; No Hardware address
	CLRW	DEVHWA+4
	RSB				; Return to caller
 
DRCV_IO_OK:
 
; Check that this is a SYSTEM ID message from the correct node.
 
	CMPB	RCVBUF2,#7		; Is this a SYSTEM ID message?
	BNEQ	DRCV_TRY		; If NEQ, no, try again
	CMPL	RCVSA2,SIDADDR		; Correct node?
	BNEQ	DRCV_TRY		; If NEQ, no
	CMPW	RCVSA2+4,SIDADDR+4	; Correct node?
	BNEQ	DRCV_TRY		; If NEQ, no
 
; We received a message from the remote node.  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	70$			; Else report Device ID missing
20$:	CMPW	RCVBUF2(R3),#^D100	; Is this the device ID entry?
	BEQL	30$			; If EQL, yes
	MOVZBL	RCVBUF2+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.
 
30$:	ADDL	#3,R3			; Skip over Device ID header
	MOVB	RCVBUF2(R3),DEVID	; Store the Device ID
 
; See if the device ID is one we know about.  If so, store the address of
; the text descriptor in DEVDSC.
 
	MOVAB	DEVTBL,R5		; Start at beginning of table
40$:	TSTB	(R5)			; End of table?
	BEQL	60$			; 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$:	INCW	(R5)+			; Count one more of these devices
	MOVQ	@(R5),DEVDSC		; Save descriptor
	BRB	140$
 
; There was no match for the DEVICE entry in the SYSID response.
 
60$:	INCW	1(R5)			; One more of these devices found
	MOVQ	DEVUNK,DEVDSC		; This is an unknown device
	BRB	140$
 
; There was no DEVICE entry in the SYSID response.
 
70$:	INCW	CTRMIS			; Count this missing device ID
	CLRB	DEVID			; No Device ID was found
	MOVQ	DEVMIS,DEVDSC		; Device ID is missing
 
; Now look for the Hardware address entry in this SYSID message.
 
140$:	MOVL	#4,R3			; Skip over SYSID header
 
; Loop through the entries in the SYSID looking for the hardware address
; entry.
 
150$:	CMPW	R3,IOSB+2		; Any buffer left to look at?
	BGEQU	160$			; If GEQU, no, so clear DEVHWA
	CMPW	RCVBUF2(R3),#7		; Is this the HWA entry?
	BEQL	170$			; If EQL, yes
	MOVZBL	RCVBUF2+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	150$			; Check next entry
 
; There was no HWA field in the SYSID; so just return a value of all zeros.
 
160$:	CLRL	DEVHWA			; Zero first longword
	CLRW	DEVHWA+4		; Zero last word
	BRB	180$			; Skip over "found HWA" code
 
; The Hardware address was found; so store it in DEVHWA.
 
170$:	ADDL	#3,R3			; Skip over Device ID header
	MOVL	RCVBUF2(R3),DEVHWA	; Store first longword
	MOVW	RCVBUF2+4(R3),DEVHWA+4	; Store last word
 
180$:	RSB

GET_GCODES:
; R2 = address where the entry is stored.
 
; Convert the group code bit mask into the actual group codes enabled.  We
; will only convert as many as we have space for.
 
	CLRL	NUMGC			; Start with no group codes found
	CLRL	R0			; Group code number starts at 0
	MOVL	06(R2),GCMASK		; Convert the 1st longword
	BEQL	1$
	BSBW	20$
	MOVL	GCMASK,06(R2)		; Save the longword
1$:	ADDL	#32,R0			; Add 32 to group code base number
	MOVL	10(R2),GCMASK		; Convert the 2nd longword
	BEQL	2$
	BSBW	20$
	MOVL	GCMASK,10(R2)		; Save the longword
2$:	ADDL	#32,R0			; Add 32 to group code base number
	MOVL	14(R2),GCMASK		; Convert the 3rd longword
	BEQL	3$
	BSBB	20$
	MOVL	GCMASK,14(R2)		; Save the longword
3$:	ADDL	#32,R0			; Add 32 to group code base number
	MOVL	18(R2),GCMASK		; Convert the 4th longword
	BEQL	4$
	BSBB	20$
	MOVL	GCMASK,18(R2)		; Save the longword
4$:	ADDL	#32,R0			; Add 32 to group code base number
	MOVL	22(R2),GCMASK		; Convert the 5th longword
	BEQL	5$
	BSBB	20$
	MOVL	GCMASK,22(R2)		; Save the longword
5$:	ADDL	#32,R0			; Add 32 to group code base number
	MOVL	26(R2),GCMASK		; Convert the 6th longword
	BEQL	6$
	BSBB	20$
	MOVL	GCMASK,26(R2)		; Save the longword
6$:	ADDL	#32,R0			; Add 32 to group code base number
	MOVL	30(R2),GCMASK		; Convert the 7th longword
	BEQL	7$
	BSBB	20$
	MOVL	GCMASK,30(R2)		; Save the longword
7$:	ADDL	#32,R0			; Add 32 to group code base number
	MOVL	34(R2),GCMASK		; Convert the 8th longword
	BEQL	8$
	BSBB	20$
	MOVL	GCMASK,34(R2)		; Save the longword
8$:	RSB
 
; This routine will store the Group code number of all the bits set in
; GCMASK.
