Google
 

Trailing-Edge - PDP-10 Archives - BB-F492Z-DD_1986 - 10,7/703mon/llmop.mac
There are 26 other files named llmop.mac in the archive. Click here to see a list.
;DSKT:LLMOP.MAC[30,5653,CPYRIT] 6-Sep-1985:21:11:54, Edit by SPIDER
;Update copyright notice.
; UPD ID= 1701, SNARK:<6.1.MONITOR>LLMOP.MAC.39,  30-Mar-85 11:26:40 by GROSSMAN
;TCO 6.1.1299 - Set RBABT in RCRRSV, RCRREL, and RCRRBT to force RB's to get
;released.
; UPD ID= 1700, SNARK:<6.1.MONITOR>LLMOP.MAC.38,  30-Mar-85 09:42:35 by GROSSMAN
;TCO 6.1.1298 - Don't queue up RB in RCSRCT.
; UPD ID= 1696, SNARK:<6.1.MONITOR>LLMOP.MAC.37,  28-Mar-85 15:09:01 by GROSSMAN
;TCO 6.1.1294 - Read service password for .RCRSV function.
; UPD ID= 1601, SNARK:<6.1.MONITOR>LLMOP.MAC.36,   7-Mar-85 16:10:31 by GROSSMAN
;TCO 6.1.1241 - Prevent COMMMS's when KLNI crashes and gets restarted.
; UPD ID= 1459, SNARK:<6.1.MONITOR>LLMOP.MAC.35,   1-Feb-85 17:46:07 by GUNN
;Clean up sources for final release; update copyright date,
; remove meaningless comments and unused code.
;
;Add call to MULKCR from RCSXTC if MSD points to user page.
;
; UPD ID= 1389, SNARK:<6.1.MONITOR>LLMOP.MAC.34,  22-Jan-85 13:29:02 by GUNN
;Fix source of COMMMS BUGHLT's. Call's to LLMRCV from LPSRCV and RCSRCV
;  need to handle failure return.
; UPD ID= 1336, SNARK:<6.1.MONITOR>LLMOP.MAC.33,  15-Jan-85 14:01:29 by GROSSMAN
;TCO 6.1.1136 - Remove all references to KNIN - replace with NKLNI.
; UPD ID= 1314, SNARK:<6.1.MONITOR>LLMOP.MAC.32,  11-Jan-85 15:40:13 by GLINDELL
;Change KNIN to KNINS (number of supported NI's)
; UPD ID= 1295, SNARK:<6.1.MONITOR>LLMOP.MAC.31,   9-Jan-85 14:17:26 by GUNN
;Make some code common between RC and LP. Adds feature of allowing multiple
;  loop responses from transmit to multicast address to be returned to
;  user as is done for Remote Console. Also gives interrupt to user on
;  receipt of response.
;Add some documentation of data structures. 
;Change several BUGxxx's to output source Ethernet address for problem
;isolation.
;Put LLMSTC and LLMSCA BUGINF's under FTDEBUG conditional.
;
; UPD ID= 1144, SNARK:<6.1.MONITOR>LLMOP.MAC.30,   3-Dec-84 17:31:29 by GLINDELL
;Change calls to D36COM to call into XCDSEC
; UPD ID= 1116, SNARK:<6.1.MONITOR>LLMOP.MAC.29,  20-Nov-84 17:21:39 by GUNN
;Fix TYPO in IFKSP. ==> IFSKP.
; UPD ID= 1108, SNARK:<6.1.MONITOR>LLMOP.MAC.28,  20-Nov-84 15:24:33 by GUNN
;Fix .RCRBT function to properly handle -1 in .LMSID (Software Id field).
; UPD ID= 907, SNARK:<6.1.MONITOR>LLMOP.MAC.27,  22-Oct-84 15:34:11 by PAETZOLD
;Fix assembly error
; UPD ID= 906, SNARK:<6.1.MONITOR>LLMOP.MAC.26,  22-Oct-84 14:13:00 by GUNN
;Fix to make .ELRPY function return source address of loop response. Set up
;MS in routine LPRRPY.
; UPD ID= 891, SNARK:<6.1.MONITOR>LLMOP.MAC.25,  17-Oct-84 14:56:16 by GUNN
;Fix source of RCRRPY causing COMMMS BUGCHK's. Only store received MSD
; address in RB for first response. This is a quick fix.
; Really need to handle multiple responses to a loop request as is
; done for Remote Console.
;Remove GETWRD routine. It's no longer used.
;Update Table of Contents.
; UPD ID= 884, SNARK:<6.1.MONITOR>LLMOP.MAC.24,  15-Oct-84 16:39:27 by GUNN
;Make proper use of RBAIC bit, use SKIPN not SKIPE when testing.
;Fix definition of LMAIC and LMICH.
;Put Device Id field in BOOT message conditionally depending on
; value of Boot Device field.
;Protect against Ethernet Data Link Pad Counts that are too large.
; UPD ID= 854, SNARK:<6.1.MONITOR>LLMOP.MAC.23,   8-Oct-84 14:44:54 by GUNN
;Fix .RCRBT function.
;  Move code to set receipt number in RB and LM blocks to separate
;	routine and call only where needed. (From RCRRID and RCRCTR)
;	This was overlaying user's verification password field in
;	RCRRBT.
;  Store RBICH in CRQINI since it's used by many functions.
;  Remove call to DNG1BY from RCSRAK. It was also called from
;	RCRPOL and caused the MDBYT field to go -1.
;  Handle +1 return after call to DNG1BY in RCRPOL.
;  Change all LOAD references to MDBYT to CALL's to DNRPOS.
;  Comment out AOS MDBYT in RCSRID. I can't recall now why it was needed.
;  ***** Still need to fix other references to MDBYT *****
; UPD ID= 847, SNARK:<6.1.MONITOR>LLMOP.MAC.22,   2-Oct-84 15:29:02 by GUNN
;Fix .RCSND function.
;  RCRSND didn't handle skip return from CALL SCCINI.
;  LSH of UNSAD shifted wrong direction.
;  Store RBICH in SCCINI.
; UPD ID= 841, SLICE:<6.1.MONITOR>LLMOP.MAC.20,  28-Sep-84 14:42:17 by GUNN
;Add a *HACK* in SCCINI to use the destination nodes Ethernet address
;as the RB Request Number when doing the Send Console Command function.
;This is so RCSRAK can find the RB on the Request Queue when the Console
;Response ACK message arrives.
;Also, fix routines called from RCSFCD to always RETSKP when succeding.
;I don't know how this was working to this point. Maybe this is the source
;of the COMMMS/COMFBO/COMFBT (COMBNP) bugs?
; UPD ID= 829, SLICE:<6.1.MONITOR>LLMOP.MAC.19,  26-Sep-84 14:18:22 by GUNN
;Finally fix LM structure symbols to make ULOAD/USTOR work.
; The last edit, UID 820, didn't cut it.
; UPD ID= 820, SLICE:<6.1.MONITOR>LLMOP.MAC.18,  24-Sep-84 17:25:49 by GUNN
;Fix LM% symbols.
; UPD ID= 810, SLICE:<6.1.MONITOR>LLMOP.MAC.17,  20-Sep-84 14:29:22 by GUNN
;Make LLMOP edit # be decimal.
; UPD ID= 809, SLICE:<6.1.MONITOR>LLMOP.MAC.16,  20-Sep-84 13:56:16 by GUNN
;Add code in LPRRPY to return Ethernet source address of Loop Response
; message to user.
;Move D36OFF/D36ON code sequence in RCRRPY to new routine DEQMSD. D36xxx
; have been changed to expand to PIOFF/PION and RCRRPY is SWAPCD.
;Change code to always pick up LLMOP% arguments from user correctly by
; using ULOAD and USTOR to make use of MONSYM defined fields.
; UPD ID= 808, SLICE:<6.1.MONITOR>LLMOP.MAC.15,  20-Sep-84 11:01:41 by GUNN
;Fix the elusive unpredictable MACRO bug. INPMSD which gets called at
;interrupt level from NISRV was using AC0, which is a preserved AC,
;without saving it.
; UPD ID= 790, SNARK:<6.1.MONITOR>LLMOP.MAC.14,   6-Sep-84 16:02:23 by GUNN
;Fix LPSRCI and LPSSCA to correctly store the local Ethernet address.
; UPD ID= 725, SNARK:<6.1.MONITOR>LLMOP.MAC.13,   3-Aug-84 17:05:28 by GUNN
;Remove LLMOPF BUGCHK.
; UPD ID= 722, SNARK:<6.1.MONITOR>LLMOP.MAC.12,   1-Aug-84 10:54:51 by GUNN
;Remove LIT Pseudo-Op after RSCOD. It causes MACRO to generate phase
;errors.
; UPD ID= 644, SNARK:<6.1.MONITOR>LLMOP.MAC.11,  29-Jun-84 12:08:19 by GUNN
;Fix RCRADR to return correct physical address.
; UPD ID= 636, SNARK:<6.1.MONITOR>LLMOP.MAC.10,  21-Jun-84 14:31:48 by GUNN
;Fix bug introduced in edit for UPD ID 634. Rearrange sequence of code
; in RCRRPY prior to calling DNCM2U.
;Accomodate for KLNI port putting bit mask in bit 31.
; UPD ID= 634, SNARK:<6.1.MONITOR>LLMOP.MAC.9,  19-Jun-84 16:45:06 by GUNN
;Fix code in QUEMSD
;Add code to return source address to user on RCS reply.
;Interlock RB when updating MSD queue.
;Set SVDLS to 0 or -1 only.
;Change TMNE to TMNN in code added for multiple responses.
;
;Make reset routines work for Remote Console.
;
;Allow for multiple reponses for Remote console request functions.
;	Add a 'shadow' UN block when posting receive buffer.
;	Copy from NISRV's UN block to 'shadow' on receive.
;	Return Source Ethernet address to user from 'shadow' UN.
;	Keep linked list of receive MSD datagrams.
;
;Add .RCADR function. 
;
;Remove .LMCCL,.LMCBL,.LMLBL,.LMCCP,.LMCBP,.LMLBP and 
; use .LMRBL,.LMRBP instead.
;
; UPD ID= 534, SNARK:<6.1.MONITOR>LLMOP.MAC.8,  21-May-84 13:29:04 by GUNN
;Fix KPALVH bug. LPSRCV/RCSRCV not checking receive status code. Add a
; quick fix.
; UPD ID= 528, SNARK:<6.1.MONITOR>LLMOP.MAC.7,  18-May-84 15:20:51 by GUNN
;Change calculation of RB address from MS address in RCSXTC. The 
; Remote Console RB doesn't have an LB subblock.
;Add patches found while debugging.
;Make NU.RCI call to NISRV from BLDSID to get hardware address each time.
;Add code for RCRPOL. Need symbol for control flags in MONSYM.
;Clean up some structure references by using MS as index pointer.
;Move call to DNPINI to LRQINI from LPRDIR and LPRAST. Add call to DNPINI
; in CRQINI.
;Put RETBAD after CALL CRQINI, it returns +1/+2.
;Make quick fix to allow for bug in EVDWC sending 3 byte Request-ID message.
;Make XMTMSD resident, allow for skip return of DNG1BY in RCSFCD.
;Initialize SVDLS to be non-zero, so RCSIDS doesn't try to transmit until
; LLMOP has opened its portals.
;Add code for Remote Console Request Abort.
;Add SCCINI routine to initialize an ASCII Console Carrier request.
;Add code for Send Console Command.
;Add code for receipt of COUNTERS message.
;Add code for Request Counters.
;Put request state setting code in subroutine.
;Remove some unused code and symbol definitions.
; UPD ID= 501, SNARK:<6.1.MONITOR>LLMOP.MAC.6,   4-May-84 10:31:45 by GUNN
;Fix typo, change spelling of SAVPQ to SAVEPQ.
; UPD ID= 500, SNARK:<6.1.MONITOR>LLMOP.MAC.5,   3-May-84 15:35:17 by GUNN
;Consolidate all BUG.'s
;Remove ERRRET.
;Change LLMINI to loop thru all KNIN channels.
;Change LLMINI to reset the CLKLV2 timer only after portal is open.
;Pass SV address in all calls to PSTBUF.
;Fix RCSIDS. Fix multicast address in PIDSUN.
;Replace $HIGH/$LOW with RESCD/RESDT/RESVR
;Make RESBUG resident.
;Remove ACVAR's and use DEFAC's instead.
;Remove SVCPA and use UNCAR instead.
;Make major changes to loop server to use input MSD's.
;Change algorithm for posting receive buffers.
;Change to use 2 word global pointers for receive buffers.
;Release IM block in RCSIDS if DLLUNI transmit fails.
;Delete RB state handling code which was commented out.
;Fix RCSATB right this time. Define symbols for time units.
;Pass UN block address in T1 on call to INPMSD.
;Store a temporary MDBYT value when setting up input MSD.
;Handle skip return when calling INPMSD from RCSRCV.
;Change index pointer in DNP4BY from T6 to T4.
;Make the Identify Self interval be 1 minute in RCSATB.
;Fix ILLUUO bug in RCSIDS. Release IM block in RCSIDS.
;Go NOSKED while incrementing SVNXR.
;Add field SVCPA in SVB to hold Channel Physical Address and use it.
;Add more counters to track received message loss.
;Add INCRF and DECRF macros.
;Fix range check for LLMOP% function code in .LLMOP use of FUNTAB dispatch.
;Add code to send SYSTEM ID message.
;Implement changes to conform to new NISRV interface.
;	1. Search NIPAR in addition to D36PAR.
;	2. Remove use of packing mode (PMODE).
;	3. Remove use of channel scan (SCAN/NOSCAN).
;	4. Remove use of UNPSC for doing CRC generation.
;	5. Update calls to DLLUNI to new argument calling sequence.
;		NU.CLO function
;		NU.OPN function
;		NU.EMA function
;		NU.RCV function
;		NU.XMT function (for LPS only)
;
; UPD ID= 327, SNARK:<6.1.MONITOR>LLMOP.MAC.16,  10-Feb-84 14:17:35 by GUNN
;Fix race in XMTREQ,LPSXTC
;Change use of VMC.NO type MSD to conform to new NISRV functionality
;Change all NOSKED's & OKSKED's to D36OFF & D36ON to handle PI Level NIDLL
;Fix LPRDIR & LPRAST to use RTRHOM as part of Ethernet address
;Release receive buffer in RCSSID if unsolicited System ID received.
;Expand scope of NOSKED's in various routines.
;Fix test for received Remote Console message length in RCSRCV
;Change LPRIXC from BUGCHK to BUGHLT. Fix typo in comment.
; UPD ID= 305, SNARK:<6.1.MONITOR>LLMOP.MAC.15,  23-Jan-84 21:03:04 by GUNN
;Add code to check for Request state in LPSXTC.
;Check for input buffer address in RB in LPRABT and release.
;Change LPSRMQ to BUGCHK on error
;Add some code to do read counters processing.
;
;Remove NOSKED from XMTREQ which is SWAPCD.
;
;Fix 'lost loop datagram' problem. Put RB on queue prior to transmitting
; the request packet.
;
;Add a comment section to record possible future enhancements,
; improvements, optimizations, etc.
;
; UPD ID= 272, SNARK:<6.1.MONITOR>LLMOP.MAC.14,   7-Dec-83 11:55:18 by GUNN
;Add code to do Loop Assisted.
;
; UPD ID= 262, SNARK:<6.1.MONITOR>LLMOP.MAC.13,  28-Nov-83 15:39:04 by GUNN
;Keep better track of received and transmitted messages by
; adding more counters.
;
;Add code to perform periodic Identify-Self.
;
; UPD ID= 230, SNARK:<6.1.MONITOR>LLMOP.MAC.12,  31-Oct-83 09:46:07 by GUNN
;Add code to store PRO and PID fields in UN Block allocated
; in XMTREQ.
;
;Allocate a UN block individually for each process at XMTREQ and go
; NOSKED during transmit call to DLL.
;Call DNGWDx individually at each place resources are needed.
;
;New code for RCS
;
;Change label DLLSPP to LPSDSP for consistency.

;Move MIN.,MAX., and MAKENT macros to definition section.
;
;Change code which increments SVRCT and SVTCT to not be dependent
; on full word fields.
;
;Change label DLLSPP to RCSDSP in routine RCSCBR
;Add start of code for Remote Console protocol server
;
;Change Remote Console to the correct architectural value, 60-02.
;
;Fix order of protocol type bytes in SV Blocks
;
;Add code to release loop reply buffer, if allocated, in LLMRSJ/LLMRSF
;
;Change Loop Server to use the UN block passed from the DLL on
; callback to transmit the loop replys, rather than the one
; built in the SV block.
;
;Make Loop Reply MSD separate from Loop Data MSD, they can't overlay
; each other since we can't be guaranteed that the transmit will
; complete before the reply is received.
;
; UPD ID= 202, SNARK:<6.1.MONITOR>LLMOP.MAC.11,  28-Sep-83 07:03:13 by GUNN
;Rework SUBTTL's for CONTEN
;Remove BUG. skeleton
;Add a table of contents
;Add check for lost buffers at label LPSRCX in routine LPSRCV
;Change check for buffer type in LPSXTC to use field UNBTY in UN block
;Rename routine LPSQUE to LLMQUE to reflect its use in both protocol servers
;Change use of FORKN to FORKX
;Remove routine LPSDEQ (Code is in LPSDEQ.MAC)
;Add routines LLMGNQ, LLMUNQ and LLMRSJ/LLMRSF
;TITLE	LLMOP - Low Level Maintenance OPeration Layer of Phase IV DECnet V010
; By D. C. Gunn 17 SEP 85

	SUBTTL Module Header

	SEARCH D36PAR,MACSYM

;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE ONLY USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1985,1986 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
;ALL RIGHTS RESERVED.

; FUTURE ENHANCEMENT LOG

; 1. Change to use D36COM queue routines
; 2. Change buffer posting algorithm to account for responses to requests.
; 3. Fix D36SYM AC purge definition problem.
; 4. Add system time field to System Id message.
; 5. Move $BUILD macro and friends to MACSYM.

; DATE		LOAD	EDIT #
; ----		----	------
;
LLMOP==:1+^D1458		;Insert file M61A:UID.TXT here

	ENTRY LLMINI		;The entry point
				; see procedures for calling sequence

	SALL

IFN FTOPS20,<
	SEARCH PROLOG,MONSYM,NIPAR
	TTITLE (LLMOP,,< - Low Level Maintenance OPeration Layer of Phase IV DECnet>)
	>

IFN FTOPS10,<
	SEARCH	F,S,LLMPRM,ETHPRM

.CPYRT<1985,1986>

	$RELOC
	$HIGH

	TITLE	LLMOP - Low Level Maintenance Operation Layer
>

	D36SYM

	RESCD

;This module implements the Low Level Maintenance Operation (LLMOP)
;portion of the Network Management layer (NML) of Phase IV DECnet.  It
;is the system independent MOP service for the Ethernet.  Below LLMOP
;is the Data Link layer, which handles access to the NI Ethernet
;communications medium..  Above NML is the Application layer, in which
;the user of this service resides.
	SUBTTL	Special Definitions for TOPS10/TOPS20 Compatibility

DEFINE	JSUERR(JSE,UUE),<
IFN FTOPS20,<RETBAD (JSE)>
IFN FTOPS10,<RETBAD (UUE)>
>; END DEFINE JSUERR

IFN FTOPS10,<

	EXTERN	RTN		;COMMON SUBROUTINE RETURN (CPOPJ)
	EXTERN	LLMACT		;IDENTIFY SELF TIMER WORD

	Q1==T5
	Q2==T6
	Q3==FREE1

	OPDEF	NOP	[TRN]

	DEFINE	RESCD	<$HIGH>
	DEFINE	SWAPCD	<$HIGH>
	DEFINE	EA.ENT	<SE1ENT>
	DEFINE	MCENT	<>	;DON'T NEED THESE IN TOPS10
	DEFINE	NOSKED	<>
	DEFINE	OKSKED	<>
	DEFINE	SAVEPQ	<SAVEAC	<P1,P2,P3,P4,Q1,Q2,Q3>>

	DEFINE	RETBAD(COD),<
		IFNB <COD>,<RETBD1  \COD>
		IFB  <COD>,<POPJ  P,>
	>; END DEFINE RETBAD
	DEFINE	RETBD1(COD),<
		IFLE <COD+1-ECDMAX>,<JRST  ECDX'COD##>
		IFG  <COD+1-ECDMAX>,<JRST  [MOVEI T1,COD
					    MOVS  M,.USMUO
					    JRST  STOTAC##]>
	>; END DEFINE RETBD1

	DEFINE	DEFAC	(NEW,OLD) <
	  IF1,<
	    NEW=OLD
	    PURGE OLD>>

	XCDSEC==MS.HGH		;USED FOR TOPS20 SECTION CALLING

	DEFINE	XCALL	(XCD,ROUTN),<
	SNCALL (ROUTN,XCD)
>

	DEFINE	XCALLRET (XCD,ROUTN),<
	JRST [SNCALL (ROUTN,XCD)
	        TRNA
	      AOS (P)
	      RET]
>
;THE FOLLOWONG IS USED IN PLACE OF THE LOAD AND STOR MACROS WHEN
;PREVIOUS CONTEXT IS TO BE REFERENCED. LOAD AND STOR CANNOT
;BE USED DIRECTLY UNDER XCTU BECAUSE THEY MAY ASSEMBLE BYTE
;INSTRUCTIONS WHICH REQUIRE DIFFERENT XCT BITS.

DEFINE	ULOAD	(AC,STR,Y)<
	..STR0 (..ULDB,AC,STR,Y)>

  DEFINE ..ULDB	(AC,LOC,MSK)<
	..TSIZ (..PST,MSK)
	.CASE ..PST,<<
	  XCTU	[MOVE	AC,LOC]>,<
	  XCTU	[HRRZ	AC,LOC]>,<
	  XCTU	[HLRZ	AC,LOC]>,<
	  XCTBMU[LDB AC,[POINTR (LOC,MSK)]]>>>

DEFINE	USTOR	(AC,STR,Y)<
	..STR0 (..UDPB,AC,STR,Y)>

  DEFINE ..UDPB (AC,LOC,MSK)<
	..TSIZ (..PST,MSK)
	.CASE ..PST,<<
	  XCTU	[MOVEM	AC,LOC]>,<
	  XCTU	[HRRM	AC,LOC]>,<
	  XCTU	[HRLM	AC,LOC]>,<
	  XCTBMU[DPB AC,[POINTR (LOC,MSK)]]>>>

>; END IFN FTOPS10
	SUBTTL Table of Contents
	SUBTTL Symbol Definitions -- Register Definitions

;Registers T1 through T6 and P1 through P2 are defined in D36PAR for
;all of DECnet-36.  Register P4 is redefined as MS for
;the DNxyBY routines in D36COM.  Register MB is defined in D36PAR for
;NSP and Router only.  The registers defined below are additions
;used in LLMOP only.  The registers FREEn are defined in D36PAR to be
;registers not otherwise used in DECnet-36.

	MS=MS			;THESE ARE DEFINED AS .NODDT GLOBALS
	CX=CX			; IN THE UNIVERSAL, CHANGE THAT HERE

	DEFAC (WK,Q1)		;Define a preserved general purpose work AC
	DEFAC (FX,Q3)		;Define fork index pointer
	DEFAC (LM,FREE1)	;Preserved global 
	DEFAC (RB,FREE2)
	DEFAC (SB,P1)
	DEFAC (UN,P2)


	SUBTTL Symbol Definitions -- Macros $BUILD,$SET,$EOB

;Following page is from GLXMAC...

; - Build pre-formed data blocks

;Many components have a need to build simple and complex blocks which
;	contain pre-formatted data, such as FOBs,IBs and other blocks
;	which are made up of several words, each containing from 1 to several
;	fields.  Since data structures change, these blocks should not be
;	just created using EXP or whatever.  These macros will take values
;	and install them in the right field and word of a structure.

; Start off a structure, argument is the size of the structure.

	DEFINE $BUILD(SIZE)<
	  IFDEF ..BSIZ,<PRINTX ?Missing $EOB after a $BUILD>
	  ..BSIZ==0			;;START COUNTER
	  ..BLOC==.			;;REMEMBER OUR STARTING ADDRESS
	  REPEAT SIZE,<			;;FOR EACH WORD IN THE BLOCK
		BLD0.(\..BSIZ,0)	;;ZERO OUT IT'S ACCUMULATOR
		..BSIZ==..BSIZ+1>	;;AND STEP TO NEXT
	>;END OF $BUILD DEFINITION

; For each value installed somewhere in the structure, set it into the block
; 	Arguments are word offset,field in word (optional) and value to set.

	DEFINE $SET(STR,VALUE,OFFSET),<
	  IFNDEF ..BSIZ,<PRINTX ?$SET without previous $BUILD>
	  IFNB <STR>,<
		IFB <OFFSET>,<..STR0 (..SET,<VALUE>,STR)>
		IFNB <OFFSET>,<..STR0 (..SET,<VALUE>,STR,OFFSET)>>
	  IFB  <STR>,<
		IFB <OFFSET>,<..STR0 (..SET,<VALUE>,FWMASK)>
		IFNB <OFFSET>,<..STR0 (..SET,<VALUE>,FWMASK,OFFSET)>>
	> ; END OF $SET DEFINITION

	DEFINE ..SET (VALUE,LOC,MSK) <
	  IFGE <<<LOC>&777777>-..BSIZ>,<
		PRINTX ?WORD offset greater than $BUILD size parameter>
	  SET0. (\<LOC>,MSK,<VALUE>)
	> ;END ..SET DEFINITION

; After all values are declared, the block must be closed to do its actual
;	creation.

	DEFINE $EOB,<
	  IFNDEF ..BSIZ,<PRINTX ?$EOB without previous $BUILD>
	  IFN <.-..BLOC>,<PRINTX ?Address change between $BUILD and $EOB>
	  LSTOF.			;;DON'T SHOW THE BLOCK
	  ..T==0
	  REPEAT ..BSIZ,<
	    BLD0.(\..T,1)		;;STORE EACH WORD
	    ..T==..T+1 >
	  PURGE ..BSIZ,..T,..BLOC	;;REMOVE SYMBOLS
	  LSTON.
	>; END OF $EOB DEFINITION

	DEFINE BLD0.(N,WHAT),<
	  IFE WHAT,<..T'N==0>
	  IFN WHAT,<EXP ..T'N
		    PURGE ..T'N>
	> ;END OF BLD0. DEFINITION

	DEFINE SET0.(LOC,MSK,VALUE),<
	IFN <<..T'LOC>&MSK>,<PRINTX ?Initial field not zero in $SET>
	  ..TVAL==<VALUE>
	  ..TMSK==<MSK>
	  ..T'LOC==..T'LOC!<FLD(..TVAL,..TMSK)>
	  PURGE ..TVAL,..TMSK
	>;END OF SET0. DEFINITION

	SUBTTL Symbol Definitions -- Macros LSTIN.,LSTOF.

;Other Miscellaneous GLXMAC def's

;Macros to turn on and off listings with nesting and level control
;	LSTOF.			;TURNS OFF LISTINGS ONLY
;	LSTOF. XCREF		;TURNS OFF LISTINGS AND CREF
;	LSTON.			;RESTORES LISTINGS AND CREF AT TOP LEVEL
;IF LSTIN. IS DEFINED AS .MINFI THEN ALL LISTINGS ARE ON

DEFINE	LSTOF.(FOO),<
	IFNDEF LSTIN.,LSTIN.==0		;;INITIALIZE LEVEL COUNTER
IFE LSTIN.,<
	IFIDN <XCREF><FOO>,<.XCREF>	;;CONDITIONALLY SUPPRESS CREF
		   XLIST>		;;TURN OFF LISTINGS
	LSTIN.==LSTIN.+1>		;;BUMP LIST LEVEL

DEFINE	LSTON.,<
	IFG LSTIN.,LSTIN.==LSTIN.-1	;;DECR LIST LEVEL
	IFLE LSTIN.,<.CREF		;;RESUME CREFS
		      LIST>>		;;RESUME LISTS

	SUBTTL Symbol Definitions -- Macros INCRF and DECRF

DEFINE INCRF (STR,Y),<
	..STR1 (..INC1,,<STR>,<Y>)>

    DEFINE ..INC1 (AC,LOC,MSK),<
		..TSIZ (..PST,MSK) ;;SET ..PST TO CASE NUMBER
		.CASE ..PST,<<
			JSP .SAC,[AOSG LOC ;;FULLWORD CASE
				  SOS LOC
				  JRST (.SAC)]>,<
			JSP .SAC,[HRRE AC,LOC ;;RIGHT HALFWORD CASE
				  AOSLE AC
				  HRRM AC,LOC
				  JRST (.SAC)]>,<
			JSP .SAC,[HLRE AC,LOC ;;LEFT HALFWORD CASE
				  SOSL AC
				  HRLM AC,LOC
				  JRST (.SAC)]>,<
			JSP .SAC,[LDB AC,[POINTR (<LOC>,MSK)]
				  ..MSK==MASK.(WID(MSK),35)
				  TXNE AC,LFTBT.(..MSK)	;;TEST SIGN BIT OF BYTE
				  TXO AC,^-..MSK	;;NEG, ALL 1S IN REST
				  PURGE ..MSK
				  SOSL AC
				  DPB AC,[POINTR (<LOC>),MSK)]
				  JRST (.SAC)]>>>

DEFINE DECRF (STR,Y),<
	..STR1 (..DEC1,,<STR>,<Y>)>

    DEFINE ..DEC1 (AC,LOC,MSK),<
		..TSIZ (..PST,MSK) ;;SET ..PST TO CASE NUMBER
		.CASE ..PST,<<
			JSP .SAC,[SOSGE LOC ;;FULLWORD CASE
				  AOS LOC
				  JRST (.SAC)]>,<
			JSP .SAC,[HRRE AC,LOC ;;RIGHT HALFWORD CASE
				  SOSL AC
				  HRRM AC,LOC
				  JRST (.SAC)]>,<
			JSP .SAC,[HLRE AC,LOC ;;LEFT HALFWORD CASE
				  SOSL AC
				  HRLM AC,LOC
				  JRST (.SAC)]>,<
			JSP .SAC,[LDB AC,[POINTR (<LOC>,MSK)]
				  ..MSK==MASK.(WID(MSK),35)
				  TXNE AC,LFTBT.(..MSK)	;;TEST SIGN BIT OF BYTE
				  TXO AC,^-..MSK	;;NEG, ALL 1S IN REST
				  PURGE ..MSK
				  SOSL AC
				  DPB AC,[POINTR (<LOC>),MSK)]
				  JRST (.SAC)]>>>

	SUBTTL Symbol Definitions -- Macros MIN.,MAX.,MAXENT

;
; Macro MIN. (symbol,list) - Assigns minimum arithmetic value of list of items.
;

DEFINE MIN. (SYM,LIST),
	<IRP LIST,<..X==LIST	;;Assign first value in list
		   STOPI>
	 IRP LIST,<IFL <LIST-..X>,<..X==LIST>> ;;Assign lowest in list
	 SYM==:..X>		;;Generate value

;
; Macro MAX. (symbol,list) - Assigns maximum arithmetic value of list of items.
;

DEFINE MAX. (SYM,LIST),
	<IRP LIST,<..X==LIST	;;Assign first value in list
		   STOPI>
	 IRP LIST,<IFG <LIST-..X>,<..X==LIST>> ;;Assign highest in list
	SYM==:..X>		;;Generate value

DEFINE MAKENT (TABLE,CODE,ROUTINE) <
	.ORG <TABLE+CODE>
	IFIW ROUTINE
	.ORG>

	SUBTTL Data Structure Definitions -- Request Block (RB)

;Low Level MOP Request Block

BEGSTR	RB			;Common header portion of RB
	WORD FWD		;List chain pointer to next RB
	WORD STT		;Request State
	FIELD FLG,^D18		;Flags
	  BIT FTI		;  Transmit Request Initiated
	  BIT FTC		;  Transmit Request Complete
	  BIT FTF		;  Transmit Request Failed
	  BIT FRC		;  Receive Response Complete
	  BIT FRF		;  Receive Response Failed
	  BIT ABT		;  Abort this request
IFN FTOPS10,<
	  BIT EVW		;  Job in event wait for this RB
>; END IFN FTOPS10
IFN FTOPS20,<
	FIELD AIC,^D1		;Assign Interrupt Channel
	FILLER ^D10
	FIELD ICH,^D6		;Interrupt Channel Number (0 to 35)
>; END IFN FTOPS20
	WORD RNO		;Receipt Number
	WORD CID		;Channel Id
	WORD DST,2		;Destination Address
	WORD MSO		;MSD Address for Output
	WORD MSI		;MSD Address for Input
IFN FTOPS20,<
	WORD FRK		;Fork Number
	WORD JOB		;Job Number
>; END IFN FTOPS20
IFN FTOPS10,<
	WORD JCH		;Job-Context Number
>; END IFN FTOPS10
ENDSTR

	RBL.LN==:RB.LEN		;Save length of RB header

;Request (RB) State Definitions

	.RQINV==:-1		;Request state invalid
	.RQPND==:.LMPND		;Request pending
	.RQCMP==:.LMSUC		;Request complete
	.RQCCE==:.LMCCE		;Channel Communication Error

;Loopback portion of Request Block

BEGSTR	LB,RB.LST		;Message Block for Loopback
	WORD AAD		;Assistant Address
	WORD ALV		;Assistance Level
ENDSTR

;Loopback LLMOP Header MSD

	LHH.LN==^D<2+3*<2+6>+2+2+2> ;(32) Header Length in bytes

BEGSTR	LH,LB.LST		;MSD for header
	WORD IDD		;***** ID word to hack for Transmit Complete
	WORD MSD,MD.LEN
	WORD DAT,<<LHH.LN+3>/4>	;Room for Largest Loopback header (Full Assist)
ENDSTR

;Loopback Data Area, Data Buffer supplied by User

BEGSTR	LD,LH.LST		;Loopback Data Output MSD
	WORD MSD,MD.LEN
ENDSTR

;Remote Console LLMOP Header MSD

	MAX. (RCH.LN,<<^D1+^D8+^D1+^D1+^D18+^D18>,<^D4>,<^D3>,<^D9>,1,2>)

BEGSTR	CH,RB.LST		;MSD for header
	WORD IDD		;***** ID word to hack for Transmit Complete
	WORD MSD,MD.LEN
	WORD DAT,<<RCH.LN+3>/4>	;Room for Largest Remote Console header
ENDSTR

;Remote Console Command Data Area, Data Buffer supplied by User

BEGSTR	CD,LH.LST		;Remote Console Command Data Output MSD
	WORD MSD,MD.LEN
ENDSTR

;Remote Console Response Buffer MSD

	MAX. (RB.LEN,<LD.LST,CD.LST>) ;Redefine length of RB

	SUBTTL Symbol Definitions -- External Declarations

	EXTERN RTN		;NON-SKIP RETURN LABEL
	EXTERN RSKP		;SKIP RETURN LABEL

;NISRV -- The NI Data Link Layer interface

	EXTERN DLLUNI		;DLL Interface Routine

;NTMAN -- The Network Management Interface

;D36COM -- The DECnet-36 Common Utilities

	EXTERN DNPINI		;Initialize MSD for output use by DNPxxx
	EXTERN DNP1BY		;Put a byte
	EXTERN DNP2BY		;Put a word, 2 bytes
	EXTERN DNP4BY		;Put double word, 4 bytes
	EXTERN DNP2BS		;Put word at caller specified offset
	EXTERN DNPENA		;Put 6 byte Ethernet address
	EXTERN DNPHIO		;Put bytes 0,1,2,3 from AC

	EXTERN DNGMSI		;Initialize MSD to point to input buffer
	EXTERN DNGMSS		;Initialize MSD for input use by DNGxxx
	EXTERN DNRPOS		;Read the current position in the input data
	EXTERN DNG1BY		;Get a byte
	EXTERN DNG2BY		;Get a word, 2 bytes
	EXTERN DNSKBY		;Skip over caller specified number of bytes
	EXTERN DNBKBY		;Backup 'n' bytes in message
	EXTERN DNGENA		;Get 6 byte Ethernet address

	EXTERN DNGWDS		;Get block of memory words
	EXTERN DNGWDZ		;Get block of zeroed memory words
	EXTERN DNFWDS		;return free words
	EXTERN DNCM2U		;Copy message to user buffer
	EXTERN DNCU2M		;Copy user buffer to message

IFN FTOPS20,<
;PAGUTL -- Pager utility routines

	EXTERN MLKMA		;Lock down a page given virtual address
	EXTERN MULKCR		;Unlock a page given physical page number

;STG -- Monitor Storage 

	EXTERN LLMACT		;CLK2TM entry, Periodic Identify-Self timer
>; END IFN FTOPS20
	SUBTTL Symbol Definitions -- LLMOP Internal Definitions

	NOPAD==0		;Don't let KLNI do padding on transmit
	PAD==1			;Let KLNI do padding on transmit
	EN.MAX==^D1500		;Maximum Ethernet Data in Bytes
	EN.CRC==^D4		;Ethernet CRC length
	BUFLEN==EN.MAX+EN.CRC	;Ethernet Buffer Length in Bytes
	BUFSIZ==<<BUFLEN+3>/4>	;Ethernet Buffer Size in Words
	LPSIBN==^D20		;Initial Number of Buffers for LPS
IFN FTOPS20,<
	LLPILM==<1B<POS(PICHNM)-WID(PICHNM)+DLSCHN>> ;PI Level mask for KLNI
>; END IFN FTOPS20
	NKLNI==1		;Number of KLNI's supported by LLMOP

;
; Define LLMOP arg block fields as BEGSTR fields for use by ULOAD/USTOR
;

	MSKSTR	LMMRF,.LMCID,LM%MRF
	MSKSTR	LMCBF,.LMCID,LM%CBF
	MSKSTR	LMMNO,.LMCID,LM%MNO
	MSKSTR	LMCCF,.LMCID,LM%CCF
	MSKSTR	LMRDL,.LMCID,LM%RDL
	MSKSTR	LMRDO,.LMCID,LM%RDO
	MSKSTR	LMCDL,.LMCID,LM%CDL
	MSKSTR	LMRCF,.LMCID,LM%RCF
	MSKSTR	LMCID,.LMCID,LM%CID
	MSKSTR	LMDST,.LMDST,.FWORD
	MSKSTR	LMSRC,.LMSRC,.FWORD
	MSKSTR	LMMCA,.LMDST,LM%MCA
	MSKSTR	LMRTC,.LMSTF,LM%RTC
IFN FTOPS20,<
	MSKSTR	LMAIC,.LMREQ,LM%AIC
	MSKSTR	LMICH,.LMREQ,LM%ICH
>; END IFN FTOPS20
	MSKSTR	LMHWA,.LMHWA,.FWORD
	MSKSTR	LMCST,.LMCST,.FWORD
	MSKSTR	LMPYA,.LMPYA,.FWORD
	MSKSTR	LMPID,.LMPID,LM%PID
	MSKSTR	LMREQ,.LMREQ,LM%REQ
	MSKSTR	LMPWD,.LMPWD,.FWORD
	MSKSTR	LMBSV,.LMCIF,LM%BSV
	MSKSTR	LMBDV,.LMCIF,LM%BDV
	MSKSTR	LMPRO,.LMCIF,LM%PRO
	MSKSTR	LMCFB,.LMCIF,<LM%BDV!LM%BSV!LM%PRO>
	MSKSTR	LMDID,.LMDID,.FWORD
	MSKSTR	LMSID,.LMSID,.FWORD
	MSKSTR	LMRML,.LMRBL,LM%RML
	MSKSTR	LMMBL,.LMRBL,LM%MBL
	MSKSTR	LMRBP,.LMRBP,.FWORD
	MSKSTR	LMAST,.LMAST,.FWORD
	MSKSTR	LMHLP,.LMHLP,.FWORD

	SUBTTL Symbol Definitions -- LLMOP Protocol


;MOP Message Function codes

	FCBOOT==^D6		;Boot
	FCRQID==^D5		;Request ID
	FCSSID==^D7		;System ID
	FCRQCT==^D9		;Request Counters
	FCCNTR==^D11		;Counters
	FCRSVC==^D13		;Reserve Console
	FCRELC==^D15		;Release Console
	FCCCAP==^D17		;Console Command and Poll
	FCCRAK==^D19		;Console Response and Acknowledge

;INFO TYPE values

	IT.MVN==^D1		;Maintenance Version
	IT.FCT==^D2		;Functions
	IT.CSU==^D3		;Console User
	IT.RVT==^D4		;Reservation Timer
	IT.CCS==^D5		;Console Command Size
	IT.CRS==^D6		;Console Response Size
	IT.HAD==^D7		;Hardware Address
	IT.SYT==^D8		;System Time
	IT.CDV==^D100		;Communication Device
	IT.SID==^D200		;Software ID
	IT.SPR==^D300		;System Processor
	IT.DLK==^D400		;Data Link
	IT.DBS==^D401		;Data Link Buffer Size

;PDP-11 bit definitions

	BIT0==1B35
	BIT1==1B34
	BIT2==1B33
	BIT3==1B32
	BIT4==1B31
	BIT5==1B30
	BIT6==1B29
	BIT7==1B28

;Maintenance Function bit definitions

	MFLOOP==BIT0		;Loop
	MFDUMP==BIT1		;Dump
	MFPLOD==BIT2		;Primary Loader
	MFMBLD==BIT3		;Multi-block Loader
	MFBOOT==BIT4		;Boot
	MFCCAR==BIT5		;Console Carrier
	MFDLCT==BIT6		;Data Link Counters
	MFCCRS==BIT7		;Console Carrier Reservation

	SUBTTL Symbol Definitions -- INTERNAL Symbols

;The following INTERNALs are for NMXSER, which reads and writes these
;parameters.

	INTERNAL MOPVER		;MOP VERSION NUMBER
	INTERNAL MOPECO		;MOP VENDOR ECO NUMBER
	INTERNAL MOPUEC		;MOP USER ECO NUMBER

	SUBTTL Data Structure Definitions -- Counters Block (CB)

;Counters Block

BEGSTR	CB
	WORD ID			;Requester ID for this block
	WORD BR			;BYTES RECEIVED
	WORD BX			;BYTES TRANSMITTED
	WORD FR			;FRAMES RECEIVED
	WORD FX			;FRAMES TRANSMITTED
	WORD MCB		;MULTICAST BYTES RECEIVED
	WORD MCF		;MULTICAST FRAMES RECEIVED
	WORD FXD		;FRAMES XMITTED, INITIALLY DEFERRED
	WORD FXS		;FRAMES XMITTED, SINGLE COLLISION
	WORD FXM		;FRAMES XMITTED, MULTIPLE COLLISIONS
	WORD XF			;TRANSMIT FAILURES
	WORD XFM		;TRANSMIT FAILURE BIT MASK
	WORD CDF		;CARRIER DETECT CHECK FAILED
	WORD RF			;RECEIVE FAILURES
	WORD RFM		;RECEIVE FAILURE BIT MASK
	WORD DUN		;DISCARDED UNKNOWN
	WORD D01		;DISCARDED POSITION 1
	WORD D02		;DISCARDED POSITION 2
	WORD D03		;DISCARDED POSITION 3
	WORD D04		;DISCARDED POSITION 4
	WORD D05		;DISCARDED POSITION 5
	WORD D06		;DISCARDED POSITION 6
	WORD D07		;DISCARDED POSITION 7
	WORD D08		;DISCARDED POSITION 8
	WORD D09		;DISCARDED POSITION 9
	WORD D10		;DISCARDED POSITION 10
	WORD D11		;DISCARDED POSITION 11
	WORD D12		;DISCARDED POSITION 12
	WORD D13		;DISCARDED POSITION 13
	WORD D14		;DISCARDED POSITION 14
	WORD D15		;DISCARDED POSITION 15
	WORD D16		;DISCARDED POSITION 16
	WORD FBE		;FREE BUFFER LIST EMPTY
	WORD SBU		;SYSTEM BUFFER UNAVAILABLE
	WORD UBU		;USER BUFFER UNAVAILABLE
	WORD UFD		;UNRECOGNIZED FRAME DEST
	WORD XXX		;THIS WORD ACTUALLY RESERVED FOR UCODE
	WORD UNI		;PORTAL ID
ENDSTR

	SUBTTL Data Structure Definitions -- Overview


;			The Request Block queue
;
;
;LPSSVB: +-------+
;        |       |
;        |       |
;        |       |
;        |-------|
;        | SVRQH |========>RB:+-------+
;        |-------|            | RBFWD |======>RB:+-------+
;        | SVRQT |======      |-------|          | RBFWD |========>RB:+-------+
;        |-------|     |      |       |          |-------|    =======>| RBFWD |
;        |       |     |      |       |          |       |    |       |-------|
;        |       |     |      |       |          |       |    |       |       |
;        |       |     |      +-------+          |       |    |       |       |
;        |       |     |                         +-------+    |       |       |
;        |       |     |                                      |       +-------+
;        +-------+     |                                      |                
;                      ========================================                
;
;
;
;                       The Response MSD Input list
;
;
;     RB:+-------+
;        |       |
;        |-------|
;        | RBMSI |===========>MD:+-------+
;        |-------|               | MDNXT |=============>MD:+-------+
;        |       |               |-------|        =======> | MDNXT |=======>...
;        |       |               |       |        |        |-------|
;        |       |               |-------|        |        |       |
;        +-------+               | MDALA |        |        |-------|
;                                |-------|        |        | MDALA |=======
;                                |       |        |        |-------|      |
;                             UN:|=======|        |        |       |      |
;                                |       |        |     UN:|=======|      |
;                                |-------|        |        |       |      |
;                                | UNRID |        |        |-------|      |
;                                |-------|        =========| UNRID |      |
;                                |       |                 |-------|      |
;                                |       |                 |       |      |
;                                |=======|                 |       |      |
;                                |       |                 |=======|      |
;                                |       |                 |       |<======
;                                |       |                 |       |
;                                |       |                 |       |
;                                +-------+                 |       |
;                                                          +-------+
;
	SUBTTL Data Structure Definitions -- Server Variable Block (SVB)

;LLMOP Generic Server Variable Block
;
;	The definition, structure and use of this block 
;	is shared between the Loopback Protocol Server
;	and the Remote Console Server.
;

BEGSTR	SV			;Server Variable Block
	WORD IFG		;Initialization Flag
	WORD DLS		;Data Link State
	WORD STT		;Server State
	WORD AST		;Server Assistant State
IFN FTOPS20,<
	FIELD AIC,^D1		;Assign Interrupt Channel
	FILLER ^D11
	FIELD ICH,^D6		;Interrupt Channel Number (0 to 35)
	FILLER ^D2
>; END IFN FTOPS20
	FIELD NXR,^D16		;Next Receipt Number
	WORD QLK		;Queue Lock 
	WORD RQH		;Request Queue Head
	WORD RQT		;Request Queue Tail
	WORD RCT		;Total Receive Count
	WORD TIC		;Total Invalid Receive Count
	WORD SRC		;Server Receive Count
	WORD SIC		;Server Invalid Receive Count
	WORD RRC		;Requestor Receive Count
	WORD RIC		;Requestor Invalid Receive Count
	WORD TTI		;Total Transmit Initiated Count
	WORD TCT		;Total Transmit Complete Count
	WORD TTF		;Total Transmit Failure Count
	WORD STC		;Server Transmit Count
	WORD RTC		;Requestor Transmit Count
	WORD BPC		;Buffer Post Count
	WORD LBC		;Lost Buffer Count
	WORD IBN		;Initial Buffer Number
	WORD MCA,2		;Multicast Address
IFN FTOPS20,<
	WORD CJN		;Configurator Job Number
	WORD CFN		;Configurator Fork Number
>; END IFN FTOPS20
IFN FTOPS10,<
	WORD CJC		;Configurator Job-Context Number
>; END IFN FTOPS10
	WORD IXB,UN.LEN		;DLL Interface Block
	WORD CCB,CC.LEN		;Start of Channel Counters Block
;	WORD PCB,CB.LEN		;Start of Portal Counters Block
ENDSTR

	SUBTTL Data Structure Definitions -- Identify-self Message Block (IM)

	SID.SZ==^D100		;Size of System Id message in bytes

BEGSTR	IM
	WORD IDD		;Special ID word
	WORD MSD,MD.LEN		;MSD for System ID message
	WORD DAT,<<SID.SZ+3>/4>	;Buffer for message
ENDSTR

	SUBTTL Storage Allocation -- Resident Write-protected

	RESCD

;The architecture version number of this implementation

MOPVER:	DEC 3			;MOP PROTOCOL VERSION NUMBER (AS SEEN BY USERS)
MOPECO:	DEC 0			;DEC ECO NUMBER
MOPUEC:	DEC 0			;USER ECO NUMBER

	SUBTTL LLMOP BUG. Expansions

;The following contains all BUG.'s issued within this module.

	BUG. (CHK,LPSIFC,LLMOP,SOFT,<LLMOP LPSCBR called with invalid function code>,<<T1,FUNCODE>>,<

Cause:	The LLMOP Loopback Protocol Server Call Back Routine was called by
	the Data Link Layer with an invalid callback function code. This is
	a software bug. Call your DIGITAL Software Specialist.

	>)

	BUG. (INF,LLMIL1,LLMOP,SOFT,<LLMOP Received Invalid Loopback Message>,<<T1,MSGLEN>,<T2,HIORD>,<T3,LOORD>>,<

Cause:	LLMOP Received a Loopback message that was too short or was
	improperly formatted. This is a MOP protocol violation by a
	remote node.

	T1 contains the received message length.
	T2-T3 contains the Ethernet address of the transmitting node.

	>)

	BUG. (INF,LLMILF,LLMOP,SOFT,<LLMOP Invalid Loopback Function Code>,<<T1,FUNCOD>,<T2,HIORD>,<T3,LOORD>>,<

Cause:	LLMOP Received a Loopback message that was neither a Loopback
	reply message or a forward data message. This is a MOP protocol
	violation by a remote node.

	T1 contains the function code.
	T2-T3 contains the Ethernet address of the transmitting node.

	>)

	BUG. (HLT,LPRIXC,LLMOP,SOFT,<LLMOP Invalid Xmit Complete>
		  ,<<T1,RBSTT>,<T3,STATUS>>,<

Cause:	NIDLL called back to LLMOP with a transmit complete event
	for an RB which is not in Transmit Initiated state. This is
	a software bug. Call your DIGITAL Software Specialist.

	T1 contains the current RB state
	T3 contains the status in the UN block

	    >)

	BUG. (INF,LLMSTC,LLMOP,SOFT,<LLMOP Data Link State Change - CHAN,PID,STS>,<<T1,CHANNEL>,<T2,PRTLID>,<T3,STATUS>>,<

Cause:	LLMOP was called by NIDDL on change of state. This is for
	information only. No corrective action required.

	>)

	BUG. (INF,LLMSCA,LLMOP,SOFT,<LLMOP Ethernet Channel Address Change - CHAN,ADDR1,ADDR2>,<<T1,CHANNEL>,<T2,ADDR1>,<T3,ADDR2>>,<

Cause:	LLMOP was called by NIDDL on change of state.

	>)

	BUG. (INF,LLMLXF,LLMOP,SOFT,<LLMOP Loopback Transmit Failed>
		,<<T1,DLLERC>,<T2,STATUS>,<T3,CHANNEL>>,<

Cause:	LLMOP was unable to transmit a forward data message.

	T1 contains the error code returned from the DLL
	T2 contains the channel status returned from the DLL
	T3 contains the channel on which the failure occurred

	  >)

	BUG. (CHK,RCSIFC,LLMOP,SOFT,<LLMOP RCSCBR called with invalid function code>,<<T1,FUNCODE>>,<

Cause:	The LLMOP Remote Console Protocol Server Call Back Routine was
	called by the Data Link Layer with an invalid callback function
	code. This is a software bug. Call your DIGITAL Software Specialist.

	>)

	BUG. (INF,LLMIR1,LLMOP,SOFT,<LLMOP Received Invalid Remote Console Message>,<<T1,MSGLEN>>,<

Cause:	LLMOP Received a Remote Console message that was too short, too long
	or was improperly formatted. This is a MOP protocol violation by a
	remote node.

	>)

	BUG. (INF,MOPIFC,LLMOP,SOFT,<LLMOP Received an invalid MOP message>,<<T1,FUNCODE>>,<

Cause:	The LLMOP Remote Console Protocol Server received a MOP message
	with an invalid function code. This is a MOP protocol violation by a
	remote node.
	>)

	BUG. (INF,LLMRRF,LLMOP,SOFT,<LLMOP Response Transmit Failed>,<<T1,DLLERC>,<T2,CHANNEL>>,<

Cause:	LLMOP was unable to transmit a MOP request message.

	T1 contains the error code returned from the DLL
	T3 contains the channel on which the failure occurred

	  >)

	BUG. (INF,RCS3XF,LLMOP,SOFT,<LLMOP Transmit Failed>,<<T1,DLLERC>,<T2,CHANNEL>>,<

Cause:	LLMOP was unable to transmit a forward data message.

	T1 contains the error code returned from the DLL
	T2 contains the channel on which the failure occurred

	  >)

	BUG. (INF,RCSPIS,LLMOP,SOFT,<LLMOP Ethernet Periodic Identify-Self>,,<

Cause:	This is a temporary debugging BUGINF. It is here to provide an
	indication that the periodic Identify-Self transmission
	is being performed.

	  >)

	BUG. (INF,LPRLXF,LLMOP,SOFT,<LLMOP Loop Request Transmit Failed>,<<T1,DLLERC>,<T2,STATUS>,<T3,CHANNEL>>,<

Cause:	LLMOP was unable to transmit a forward data message.

	T1 contains the error code returned from the DLL
	T3 contains the channel on which the failure occurred

	  >)

	BUG. (CHK,LLMOPF,LLMOP,SOFT,<LLMOP Open Portal Failed>,<<T1,DLLERC>>,<

Cause:	LLMOP Failed to open an NI portal with the Data Link Layer.

	T1 contains the error code returned from the DLL

	>)

	BUG. (CHK,LLMMCF,LLMOP,SOFT,<LLMOP Declare Multicast Address Failed>,<<T1,DLLERC>>,<

Cause:	LLMOP Attempt to declare the Assistant Multi-Cast Address
	failed when the Data Link Layer was called.

	T1 contains the error code returned from the DLL

	>)

	BUG. (CHK,LLMCIF,LLMOP,SOFT,<LLMOP Read Channel Info Failed>,<<T1,DLLERC>>,<

Cause:	LLMOP Attempt to read the Ethernet channel status
	failed when the Data Link Layer was called.

	T1 contains the error code returned from the DLL

	>)

	BUG. (CHK,LLMRQC,LLMOP,SOFT,<LLMOP RB Queue Corrupted>,<<T1,RBADDRESS>>,<

 Cause:	LLMOP Attempted to remove an RB queue entry from an empty queue or
	 the RB was not on the queue.

	 >)

	BUG. (CHK,LLMRXF,LLMOP,SOFT,<LLMOP Resource Failure>,,<

Cause:	LLMOP was not able to obtain resources from the memory manager.

	>)

	SUBTTL Storage Allocation -- Resident Writeable

	RESDT

;Server Variable Blocks for Loopback Server, one per channel

	..CH==0			;Initialize at Channel 0
LPSSVB:	REPEAT <NKLNI>,<
	$BUILD (SV.LEN)		;Loopback Protocol Server Variable Block
	$SET (SVIFG,0)		;Initialization Flag - Clear
	$SET (SVDLS,<-1>)	;Data Link State - Initially invalid
	$SET (SVSTT,1)		;Server State - ON
	$SET (SVAST,1)		;Server Assistant State - ON
	$SET (SVRQH,0)		;Request Queue Head - Empty
	$SET (SVRQT,<..LRQH>)	;Request Queue Tail - Empty
	$SET (SVIBN,2)		;Initial Buffer Number - 2
	$SET (SVMCA,<BYTE (8)317,0,0,0>) ;Loopback Multicast
	$SET (SVMCA,<BYTE (8)0,0,0,0>,<+1>) ;Address CF-00-00-00-00-00
	$SET (UNCHN,..CH,SV.IXB) ;Channel
	$SET (UNPAD,NOPAD,SV.IXB) ;No padding for Loopback
	$SET (UNPRO,<BYTE (4)0(8)0,0,220,0>,SV.IXB) ;Protocol Type 90-00
IFN FTOPS20,<
	$SET (UNPMS,<LLPILM>,SV.IXB) ;PI level at which we call NI Data Link
>; END IFN FTOPS20
	$SET (UNUID,<LPSSVB+..CH>,SV.IXB) ;Address of SVB is our UID
	$SET (UNCBA,<IFIW LPSCBR>,SV.IXB) ;Call Back Vector Address
	$EOB
	..LRQH==<LPSSVB+<<1+..CH>*SV.RQH>>
	..CH==..CH+1>

;Server Variable Blocks for Remote Console Server, one per channel

	..CH==0			;Initialize at Channel 0
RCSSVB:	REPEAT <NKLNI>,<
	$BUILD (SV.LEN)		;Remote Console Server Variable Block
	$SET (SVIFG,0)		;Initialization Flag - Clear
	$SET (SVDLS,<-1>)	;Data Link State - Initially invalid
	$SET (SVSTT,1)		;Server State - ON
	$SET (SVAST,1)		;Server Assistant State - ON
	$SET (SVRQH,0)		;Request Queue Head - Empty
	$SET (SVRQT,<..CRQH>)	;Request Queue Tail - Empty
	$SET (SVIBN,2)		;Initial Buffer Number - 2
	$SET (SVMCA,<BYTE (8)253,0,0,02>) ;Remote Console Multicast
	$SET (SVMCA,<BYTE (8)0,0,0,0>,<+1>) ;Address AB-00-00-02-00-00
	$SET (UNCHN,..CH,SV.IXB) ;Channel
	$SET (UNPAD,PAD,SV.IXB)	;Padding for Remote Console
	$SET (UNPRO,<BYTE (4)0(8)0,0,140,02>,SV.IXB) ;Protocol Type 60-02
IFN FTOPS20,<
	$SET (UNPMS,<LLPILM>,SV.IXB) ;PI level at which we call NI Data Link
>; END IFN FTOPS20
	$SET (UNUID,<RCSSVB+..CH>,SV.IXB) ;Address of SVB is our UID
	$SET (UNCBA,<IFIW RCSCBR>,SV.IXB) ;Call Back Vector Address
	$EOB
	..CRQH==<RCSSVB+<<1+..CH>*SV.RQH>>
	..CH==..CH+1>

	SUBTTL Storage Allocation -- Resident Writeable

;Storage for Remote Console Server Identify Self function

RCSSIM:	$BUILD (IM.LEN)
	$SET (IMIDD,<'SID'>)
	$SET (MDVMC,<VMC.XC>,<IM.MSD>)
	$SET (MDALA,<RCSSIM+IM.DAT>,<IM.MSD>)
	$EOB

PIDSUN:
	$BUILD (UN.LEN)		;UN Block for Periodic Identify-Self
	$SET (UNCHN,0)		;Channel
	$SET (UNBSZ,0)		;Will always use MSD's
	$SET (UNUID,<PIDSUN>)	;Address of PIDSUN is our UID
	$SET (UNDAD,<BYTE (8)253,0,0,02>) ;Remote Console Multicast
	$SET (UNDAD,<BYTE (8)0,0,0,0>,<+1>) ;Address AB-00-00-02-00-00
	$SET (UNCBA,<IFIW RCSCBR>) ;Call Back Vector Address
	$EOB

	ONESEC==<^D1000>	;One second -- 1000 milliseconds
	ONEMIN==<^D60*ONESEC>	;One minute -- sixty seconds
	TENMIN==<^D10*ONEMIN>	;Ten minutes

RCSATB:	EXP TENMIN		;Periodic Identify-Self Time Base (10 Min)
RCSITF:	EXP 0			;Initial Timer Flag

	SUBTTL LLMINI - LLMOP Server/Requestor Initialization

;LLMINI - Initialize NI Ethernet LLMOP Protocol Servers
;
;Call:
;	CALL LLMINI
;	Normal Return, Always
;Changes T1

;This entry is called at system startup.  Before this initialization
;is done, all calls to LLMOP will fail.

	CN=WK
	RESCD
LLMINI:	SAVEAC <CN>		;Storage for negative channel loop counter
	SETZ CN,		;Set up loop counter to start at channel 0
LLMIN1:	CAIL CN,NKLNI		;Done all channels?
	JRST LLMIN2		;Yes, finish up initialization
	MOVE T1,CN		;Get channel number to initialize
	IMULI T1,SV.LEN		;Get offset of SVB for this channel
	XMOVEI T1,LPSSVB(T1)	;Get address of LPS SV block for this channel
	CALL PSVINI		;Initialize Loopback Protocol Server
	 NOP			;Initialization Failed - Ignore
	MOVE T1,CN		;Get channel number to initialize
	IMULI T1,SV.LEN		;Get offset of SVB for this channel
	XMOVEI T1,RCSSVB(T1)	;Get address of SV block for RCS
	CALL PSVINI		;Initialize Remote Console Protocol Server
	 NOP			;Initialization Failed - Ignore
	AOJA CN,LLMIN1		;Bump channel number, loop for each channel

LLMIN2:	
IFN FTOPS20,<
	CAILE CN,0		;Any channels at all?
	IFSKP.			;Yes, Set up Identify Self timer
	  CALL NRANDM		;Get a 16 bit random value treated as MS/4
	  LSH T1,2		;Make it milliseconds and sign bit in B17
	  HRREI T1,(T1)		;Make it a signed value +/- 2 Min 11 Sec
	  ADDX T1,TENMIN	;Timer goes off every ten (10) +/- minutes
	ELSE.
	  MOVX T1,<^-<1_^D35>>	;Get largest positive 36 bit value
	ENDIF.
>; END IFN TOPS20
IFN FTOPS10,<
	MOVEI	T1,^D10		;Identify self is every ten minutes
>; END IFN FTOPS10
	MOVEM T1,RCSATB		;Store in Identify-Self Timer Base
	MOVEM T1,LLMACT		;Yes, store in timer word
	RET			;RETURN from LLMINI

;END of Routine LLMINI
	SUBTTL	LLMMIN - Once a minute identify self timer routine
IFN FTOPS10,<
;Routine to decrement the identify self timer and send
;identify self message if time.
;
;Called from: CLOCK1 once a minute.
;
;	PUSHJ	P,LLMMIN##
;	Always returns here

LLMMIN::SOSLE	LLMACT##	;TEN MINUTES UP YET?
	  RET			;NO, JUST RETURN
	PUSHJ	P,RCSIDS	;YES, SEND SID MESSAGE
	RET			;RETURN
>; END IFN FTOPS10
	SUBTTL LLMOFF - LLMOP Server/Requestor Reset (Turn OFF)

;LLMOFF - Reset (turn OFF) Ethernet LLMOP for a channel
;
;Call:	T1/ NI Channel Number
;	CALL LLMOFF
;	Normal Return
;Changes T1

IFN FTDEBUG,<			;Include this code only for debugging
				;until the network management MODULE
				;LOOPER is implemented to call here.
	SWAPCD
LLMOFF:	SAVEAC <CN,SB>		;Allocate named AC variables for block pointers
	MOVEM T1,CN		;Save channel number
				;Turn off Loopback Protocol Server
	IMULI T1,SV.LEN		;Get offset of SVB for this channel
	XMOVEI SB,LPSSVB(T1)	;Get address of SV block for LPS
	MOVEI T1,NU.CLO		;DLL Close Function code
	XMOVEI T2,SV.IXB(SB)	;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface Block
	 NOP			;Ignore any failure
	SETZRO SVIFG,(SB)	;Not initialized any longer
	MOVE T1,CN		;Restore channel number
				;Turn off Remote Console Protocol Server
	IMULI T1,SV.LEN		;Get offset of SVB for this channel
	XMOVEI SB,RCSSVB(T1)	;Get address of SV block for LPS
	MOVEI T1,NU.CLO		;DLL Close Function code
	XMOVEI T2,SV.IXB(SB)	;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface Block
	 NOP			;Ignore any failure
	SETZRO SVIFG,(SB)	;Not initialized any longer

	RET			;Return
>

;END of Routine LLMOFF

	SUBTTL LLMPSI - PSISER Status Routine

;Routine called when an LLMOP PSI is granted by PSISER.  Routine should
;return status word.
;
;Call:	J/ JCH
;	CALL LLMPSI
;
;Returns status word in T2.

IFN FTOPS10,<
LLMPSI::SETZ T2,		;Needs to be written
	POPJ P,			;Return
>; END IFN FTOPS10
	SUBTTL Loopback Protocol Server -- LPSCBR - DLL Callback Routine

;LPSCBR - DLL Callback Dispatch Routine
;
;Call:	T1/ DLL Interface Function Code NU.xxx
;	T2/ UN Block address
;	CALL LPSCBR
;	Normal Return
;Changes UN,SB

;Get minumum/maximum valued function

	MIN. (MINLPF,<NU.CLO,NU.RCV,NU.XMT,NU.EMA,NU.DMA,NU.RPC,NU.RCI,NU.SCA,NU.RCC>)
	MAX. (MAXLPF,<NU.CLO,NU.RCV,NU.XMT,NU.EMA,NU.DMA,NU.RPC,NU.RCI,NU.SCA,NU.RCC>)

	LPFSIZ==<MAXLPF-MINLPF+1> ;Size of Dispatch Table

	RESCD
LPSCBR:	SAVEPQ			;Save all AC's to be safe
	TRVAR <SKPCNT>		;Allocate named stack variables
	CAIL T1,MINLPF		;Range check function code
	CAILE T1,MAXLPF
	IFSKP.
	  MOVE UN,T2		;Get address of DLL's UN Block
	  LOAD SB,UNUID,(UN)	;Get SVB address
	  CALL @LPSDSP-MINLPF(T1) ;Call the function dependent routine
	ELSE.
	  XCT LPSIFC		;Do the BUG.
	ENDIF.
	RET			;Return

LPSDSP:	BLOCK <LPFSIZ>		;DLL Callback Dispatch Table
	MAKENT (LPSDSP,NU.CLO-MINLPF,RTN) ;Close complete
	MAKENT (LPSDSP,NU.RCV-MINLPF,LPSRCV) ;DLL Receive Complete
	MAKENT (LPSDSP,NU.XMT-MINLPF,LPSXTC) ;DLL Transmit Complete
	MAKENT (LPSDSP,NU.EMA-MINLPF,RTN) ;Enable Multicast Addr Complete
	MAKENT (LPSDSP,NU.DMA-MINLPF,RTN) ;Disable Multicast Addr Complete
	MAKENT (LPSDSP,NU.RPC-MINLPF,RTN) ;Read Portal Ctrs Complete
	MAKENT (LPSDSP,NU.RCI-MINLPF,LPSRCI) ;Read Channel Info Complete
	MAKENT (LPSDSP,NU.SCA-MINLPF,RTN) ;Set Channel Address Complete
	MAKENT (LPSDSP,NU.RCC-MINLPF,RTN) ;DLL Read Channel Ctrs Complete

;END of Routine LPSCBR

	SUBTTL Loopback Protocol Server -- LPSRCV - Receive Datagram Handler

;LPSRCV - Exit Routine to Handle Received Loopback Datagram
;
;This routine is called by the DLL at interrupt level,
;when an Ethernet Loopback Protocol Datagram is received.
;
;Call:	T1/ NU.RCV
;	T2,UN/ DLL's UN Block address
;	SB/ SV Block address
;	CALL LPSRCV
;	Normal Return
;Changes T1,T2
;	SKPCNT/ Skip Count

	RESCD
LPSRCV:	CALL LLMRCV		;Do common receive processing
	  RETBAD		;Return on failure
	CAILE T1,^D14		;Message must be at least minimum size
	IFSKP.
	  LOAD T2,UNSAD,(UN)	;Get source of this request
	  LOAD T3,UNSAD,+1(UN)
	  XCT LLMIL1		;Do the BUG.
	  JRST LPSRCY		;Go to common exit on BUG
	ENDIF.

;Get function code from loopback message

	XCALL (XCDSEC,DNG2BY)	;Get skip count
	  JRST LPSRCY
	MOVEM T1,SKPCNT		;Save skip count
	XCALL (XCDSEC,DNSKBY)	;Skip past that in message
	  JRST LPSRCY
	XCALL (XCDSEC,DNG2BY)	;Get the function code
	  JRST LPSRCY
	CAIE T1,1		;Is this a reply message?
	IFSKP.
	  CALL LPSRPY		;Yes, go process reply
	    JRST LLMRCX		;Error, Drop message
	  RET			;Return to DLL
	ENDIF.

	CAIN T1,2		;Is this a forward data message?
	IFSKP.			;No..., It's invalid
	  LOAD T2,UNSAD,(UN)	;Get source of this request
	  LOAD T3,UNSAD,+1(UN)
	  XCT LLMILF		;Do the BUG.
	  JRST LPSRCY		;Go to common exit on BUG
	ENDIF.

;YES, Check to ensure Loop Server state is enabled

	OPSTR <SKIPN>,SVSTT,(SB) ;Loopback server enabled?
	  JRST LLMRCX		;No, Go to common exit

;Check if destination address is a multi-cast address (CF-00-00-00-00-00)

	LOAD T1,UNDAD,(UN)	;Get first 4 bytes of destination address
	LSH T1,^D7		;Shift to make multicast bit the sign bit
	SKIPL T1		;Is it multi-cast?
	IFSKP.			;Yes, Destination is Multicast address
	  OPSTR <SKIPN>,SVAST,(SB) ;Loop Assistance enabled?
	  IFSKP.		;Yes, Enabled
	    CALL LPSLBK		;Process Loopback data message
	      JRST LLMRCX	;Failed, Drop it, release buffer
	    RET			;Return
	  ELSE.			;No, Disabled
	    JRST LLMRCX		;Drop it, release buffer
	  ENDIF.
	ELSE.			;No, Destination not Multicast address
	  CALL LPSLBK		;Process Loopback data message
	    JRST LLMRCX		;Failed, Drop it, release buffer
	  RET			;Return
	ENDIF.

LPSRCY:	MOVE T1,SB		;Pass SV block address
	CALL PSTBUF		;Post a receive buffer
	  NOP			;Ignore failure
	CALLRET LLMRCX

;END of Routine LPSRCV

	SUBTTL Loopback Protocol Server -- LPSXTC - Process Transmit Complete

;LPSXTC - Exit Routine to Handle NI Datagram Transmit Completion
;
;Call:	T1/ NU.XMT
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL LPSXTC
;	Normal Return
;Changes T1,T2,RB

	RESCD
LPSXTC:	LOAD T1,UNBSZ,(UN)	;Get Transmitted Message length
	INCRF SVTCT,(SB)	;Increment total count of transmits completed

;Nota Bene: Have to know whether this is transmitted by server or requester

	LOAD MS,UNRID,(UN)	;Get MSD address
	MOVX T2,'LLM'		;Get special ID
	CAMN T2,-1(MS)		;Transmitted by requester?
	IFSKP.			;NO - Transmitted by Loop Server
	  INCRF SVSTC,(SB)	;Bump Loop Server transmit count
	  MOVE T1,MS		;Pass buffer address
	  XCALL (XCDSEC,DNFWDS)	;Release the buffer
	  MOVE T1,SB		;Pass SV block address
	  CALL PSTBUF		;Post a receive buffer
	    NOP			;Ignore failure
	ELSE.			;YES - Transmitted by Loop Requestor
	  XMOVEI RB,-<RBL.LN+LB.LEN+1>(MS) ;Get address of RB
	  TMNN RBFTI,(RB)	;Ensure transmit was initiated
	    XCT LPRIXC		;It wasn't, Do the BUG.
	  INCRF SVRTC,(SB)	;Bump requester transmit count
	  SKIPN T3		;Check Transmit Status
	  IFSKP.		;Failed...
	    SETONE RBFTF,(RB)	;Set Transmit Failure flag
	  ELSE.			;Success...
	    SETONE RBFTC,(RB)	;Set Transmit Complete flag
	  ENDIF.
	  CALL SETRBS		;Set state in RB
IFN FTOPS20,<
	  LOAD T1,MDALA,+LD.MSD(RB) ;Get physical address
	  LSH T1,-<WID(777)>	;Convert to core page number
	  CALL MULKCR		;Unlock the page
>; END IFN FTOPS20
IFN FTOPS10,<
	  XMOVEI T1,LD.MSD(RB)	;Get address of MSD
	  CALL FREMBF		;Free up monitor buffer
>; END IFN FTOPS10
	ENDIF.

	RET			;Success - RETURN from LPSXTC

;END of Routine LPSXTC

	SUBTTL Loopback Protocol Server -- LPSRCI - Process Chan State Change

;LPSRCI - Exit Routine to Handle NI Channel State Change
;
;Call:	T1/ NU.RCI
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL LPSRCI
;	Normal Return
;Changes T1,T2

	RESCD
LPSRCI:	LOAD T1,UNCHN,+SV.IXB(SB) ;Get channel from static UN block
	LOAD T2,UNPID,(UN)	;Get portal id
	LOAD T3,UNSTA,(UN)	;Get Data Link status
IFN FTDEBUG,<
IFN FTOPS10,<SKIPA>		;Enable BUGINF by patching
	XCT LLMSTC		;BUGINF to let someone know what's happened
>
	LOAD T1,UNCAR,(UN)	;Get current physical address
	LOAD T2,UNCAR,+1(UN)
	STOR T1,UNCAR,+SV.IXB(SB) ;Store physical adrress
	STOR T2,UNCAR,+SV.IXB+1(SB) ; in the static UN block
	STOR T3,UNSTA,+SV.IXB(SB) ;Store status in static UN Block
	LOAD T1,UNHAD,(UN)	;Get hardware address
	LOAD T2,UNHAD,+1(UN)
	STOR T1,UNHAD,+SV.IXB(SB) ;Store it in the static UN block
	STOR T2,UNHAD,+SV.IXB+1(SB)
IFN FTOPS20,<
	LOAD T1,UNEXS,(UN)	;Get external DLL state
	CAIE T1,UNS.RN		;Running?
>; END IFN FTOPS20
IFN FTOPS10,<
	TMNN UNRUN,(UN)		;Portal running?
>; END IFNF TOPS10
	IFSKP.
	  SETZRO SVDLS,(SB)	;Yes...
IFN FTOPS10,<
	  MOVE T1,SB		;Pass SVB address
	  CALL PSTBUF		;Post buffers
	    NOP			;Ignore failure
>; END IFN FTOPS10
	ELSE.
	  SETONE SVDLS,(SB)	;No...
	ENDIF.
	RET			;Success - RETURN from LPSRCI

;END of Routine LPSRCI

	SUBTTL Loopback Protocol Server -- LPSSCA - Process Channel Address

;LPSSCA - Exit Routine to Handle Set Channel Address Callback
;
;Call:	T1/ NU.SCA
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL LPSSCA
;	Normal Return
;Changes T1,T2

	RESCD
LPSSCA:	LOAD T1,UNCHN,+SV.IXB(SB) ;Get channel
	LOAD T2,UNDAD,(UN)	;Get new physical address
	LOAD T3,UNDAD,+1(UN)
IFN FTDEBUG,<
IFN FTOPS10,<SKIPA>		;Enable BUGINF by patching
	XCT LLMSCA		;BUGINF to let someone know what's happened
>
	LOAD T1,UNSTA,(UN)	;Get Data Link status
	XMOVEI UN,SV.IXB(SB)	;Address the static UN block for this channel
	STOR T1,UNSTA,+SV.IXB(SB) ;Store status in static UN Block
	STOR T2,UNCAR,+SV.IXB(SB) ;Store new physical adrress
	STOR T3,UNCAR,+SV.IXB+1(SB) ; in the static UN block
	LOAD T1,UNHAD,(UN)	;Get hardware address
	LOAD T2,UNHAD,+1(UN)
	STOR T1,UNHAD,+SV.IXB(SB) ;Store it in the static UN block
	STOR T2,UNHAD,+SV.IXB+1(SB)
IFN FTOPS20,<
	LOAD T1,UNEXS,(UN)	;Get external DLL state
	CAIE T1,UNS.RN		;Running?
>; END IFN FTOPS20
IFN FTOPS10,<
	TMNN UNRUN,(UN)		;Portal running?
>; END IFN FTOPS10
	IFSKP.
	  SETZRO SVDLS,(SB)	;Yes...
	ELSE.
	  SETONE SVDLS,(SB)	;No...
	ENDIF.

	RET			;Success - RETURN from LPSSCA

;END of Routine LPSSCA

	SUBTTL Loop Server -- LPSLBK - Process Forward Data Loop Message

;LPSLBK - Loopback a message
;
;Call:
;	T2,UN/ DLL's UN Block address
;	SKPCNT/ Skip Count
;	MS/ MSD address
;	SB/ SVB address
;	CALL LPSLBK
;	 Error Return, Drop message
;	Normal Return
;Note:	This routine expects the MSD pointer to point to the next byte
;	after the function code in the loopback message.
;
;Changes T1,T2,T3,T4

	RESCD
LPSLBK:	INCRF SVSRC,(SB)	;Bump received loopback server message count
	XCALL (XCDSEC,DNGENA)	;Get forward address in UNDAD format
	  RET
	STOR T1,UNDAD,(UN)	;Set as destination address in UN block
	STOR T2,UNDAD,+1(UN)
IFN FTOPS20,<
	SETZRO UNPTR,(UN)	;Indicate immediate address passed in UNDAD
>; END IFN FTOPS20

;If forward address is a multicast address (CF-00-00-00-00-00-00),
;then drop the message. Otherwise process for transmission.

	LOAD T1,UNDAD,(UN)	;Get first 4 bytes of destination address
	LSH T1,^D7		;Shift to make multicast bit the sign bit
	SKIPGE T1		;Is it multi-cast?
	  RET			;Yes, It is; Drop this message

;Bump skip count by 8 and store in message

	MOVX T1,0		;Position of skip count in message
	MOVE T2,SKPCNT		;Get current skip count
	ADDI T2,^D8		;Add eight to skip count
	XCALL (XCDSEC,DNP2BS)	;Put back updated skip count

;Send to forward address on this portal id, using DLL's UN block

	MOVEI T1,NU.XMT		;DLL Transmit Function code
	MOVE T2,UN		;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface Block
	IFNSK.
;
;***** Analyze why failed here. If it's because the port is off or
;broken that's OK. But any other reason might indicate some software
;problem. If it's a port problem, that's interesting because it means
;the port was well enough to receive this datagram, but now it can't
;do a transmit. Or, maybe the driver is sick.

	  LOAD T3,UNCHN,+SV.IXB(SB) ;Get channel number
	  LOAD T2,UNSTA,(UN)	;Get Channel Status
	  XCT LLMLXF		;Do the BUG.
	  INCRF SVTTF,(SB)	;Bump count of total transmit failures
	  RET			;Take failure return
	ENDIF.

	INCRF SVTTI,(SB)	;Keep count of transmits initiated

	RETSKP			;Success - RETURN from LPSLBK

;END of Routine LPSLBK

	SUBTTL Loop Requester -- LPSRPY - Process Loopback Reply Message

;LPSRPY - Handle Loopback Reply Message
;
;Call:
;	SKPCNT/ Skip Count
;	SB/ SVB address
;	CALL LPSRPY
;	 Error Return, Drop message
;	Normal Return
;Note:	This routine expects the MSD pointer to point to the next byte
;	after the function code in the loopback message.
;Changes T1,T2,RB
;	RB/ Request Block address

	RESCD
LPSRPY:	INCRF SVRRC,(SB)	;Bump received loopback requestor message count
	XCALL (XCDSEC,DNG2BY)	;Get receipt number from message
	  RET

;Lookup the request for this receipt number

				;Pass the receipt number in T1
	MOVE T2,SB		;Pass SVB address
	CALL LPSSXQ		;Search queue for this RB
	IFNSK.			;Not found..., count and drop the packet
	  INCRF SVRIC,(SB)	;Bump count of invalid request replies
	  RET
	ENDIF.
	MOVE RB,T2		;Found, T2 contains address of RB
	CALL QUEMSD		;Queue this MSD
	SETONE RBFRC,(RB)	;Set receive complete flag
	CALL SETRBS		;Set state in RB

IFN FTOPS20,<
	OPSTR <SKIPN >,RBAIC,(RB) ;Interrupt channel assigned?
	  RETSKP		;No, return now
	LOAD T1,RBICH,(RB)	;Get Interrupt Channel number
	LOAD T2,RBFRK,(RB)	;Get Fork Index
	CALL PSIRQ		;Notify user that request completed
>; END IFN FTOPS20
IFN FTOPS10,<
	CALL RBWAKE		;Wake up job
>; END IFN FTOPS10
	RETSKP			;Success - RETURN from LPSRPY

;END of Routine LPSRPY

	ENDTV.			;End scope of SKPCNT

	SUBTTL Remote Console Protocol Server -- RCSCBR - DLL Callback Routine

;RCSCBR - DLL Callback Dispatch Routine
;
;Call:	T1/ DLL Interface Function Code NU.xxx
;	T2/ UN Block address
;	CALL RCSCBR
;	Normal Return
;Changes 

;Get minumum/maximum valued function

	MIN. (MINRCF,<NU.CLO,NU.RCV,NU.XMT,NU.EMA,NU.DMA,NU.RPC,NU.RCI,NU.SCA,NU.RCC>)
	MAX. (MAXRCF,<NU.CLO,NU.RCV,NU.XMT,NU.EMA,NU.DMA,NU.RPC,NU.RCI,NU.SCA,NU.RCC>)
	RCFSIZ==<MAXRCF-MINRCF+1>	;Size of Dispatch Table

	RESCD
RCSCBR:	SAVEPQ			;Save all AC's to be safe
	CAIL T1,MINRCF		;Range check function code
	CAILE T1,MAXRCF
	IFSKP.
	  MOVE UN,T2		;Get address of DLL's UN Block
	  LOAD SB,UNUID,(UN)	;Get SVB address
	  CALL @RCSDSP-MINRCF(T1) ;Call the function dependent routine
	ELSE.
	  XCT RCSIFC		;Do the BUG.
	ENDIF.
	RET			;Return

RCSDSP:	BLOCK <RCFSIZ>		;DLL Callback Dispatch Table
	MAKENT (RCSDSP,NU.CLO-MINRCF,RTN) ;Close complete
	MAKENT (RCSDSP,NU.RCV-MINRCF,RCSRCV) ;DLL Receive Complete
	MAKENT (RCSDSP,NU.XMT-MINRCF,RCSXTC) ;DLL Transmit Complete
	MAKENT (RCSDSP,NU.EMA-MINRCF,RTN) ;Enable Multicast Addr Complete
	MAKENT (RCSDSP,NU.DMA-MINRCF,RTN) ;Disable Multicast Addr Complete
	MAKENT (RCSDSP,NU.RPC-MINRCF,RTN) ;Read Portal Ctrs Complete
	MAKENT (RCSDSP,NU.RCI-MINRCF,RCSRCI) ;Read Channel Info Complete
	MAKENT (RCSDSP,NU.SCA-MINRCF,RTN) ;Set Channel Address Complete
	MAKENT (RCSDSP,NU.RCC-MINRCF,RCSRCC) ;DLL Read Channel Ctrs Complete

;END of Routine RCSCBR

	SUBTTL Remote Console Protocol Server -- RCSXTC - Process Transmit Complete

;RCSXTC - Exit Routine to Handle NI Datagram Transmit Completion
;
;Call:	T1/ NU.XMT
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL RCSXTC
;	Normal Return
;Changes T1,T2,RB

	RESCD
RCSXTC:	LOAD T1,UNBSZ,(UN)	;Get Transmitted Message length
	INCRF SVTCT,(SB)	;Increment total count of transmits completed

;Nota Bene: Have to know whether this is transmitted by server or requester

	LOAD MS,UNRID,(UN)	;Get MSD address
	MOVX T2,'SID'		;Get special ID for Identify Self System ID
	CAMN T2,-1(MS)		;Transmitted by requester?
	IFSKP.			;NO - Transmitted by Remote Console Server
	  MOVX T2,'LLM'		;Get special ID for RC Requestor
	  CAMN T2,-1(MS)	;Transmitted by RC Server or Requestor?
	  IFSKP.		;Transmitted by RC Server
	    INCRF SVSTC,(SB)	;Bump server transmit count
	    MOVE T1,MS		;Pass buffer address
	    XCALL (XCDSEC,DNFWDS) ;Release the buffer
	    MOVE T1,SB		;Pass SV block address
	    CALL PSTBUF		;Post a receive buffer
	      NOP		;Ignore failure
	  ELSE.			;Transmitted by RC Requestor, Really have RB
	  XMOVEI RB,-<RBL.LN+1>(MS) ;Get address of RB
	  TMNN RBFTI,(RB)	;Ensure transmit was initiated
	    XCT LPRIXC		;It wasn't, Do the BUG.
	  INCRF SVRTC,(SB)	;Bump requester transmit count
	  SKIPN T3		;Check Transmit Status
	  IFSKP.		;Failed...
	    SETONE RBFTF,(RB)	;Set Transmit Failure flag
	  ELSE.			;Success...
	    SETONE RBFTC,(RB)	;Set Transmit Complete flag
	  ENDIF.
	  CALL SETRBS		;Set state in RB
IFN FTOPS20,<
	  LOAD T1,MDALA,+LD.MSD(RB) ;Get physical address
	  LSH T1,-<WID(777)>	;Convert to core page number
	  LOAD T2,MDVMC,+LD.MSD(RB) ;Get the memory type code
	  CAIN T2,VMC.NO	;If this was a user page...
	  CALL MULKCR		;Unlock the page
>; END IFN FTOPS20
IFN FTOPS10,<
	  XMOVEI T1,LD.MSD(RB)	;Get address of MSD
	  CALL FREMBF		;Free up monitor buffer
>; END IFN FTOPS10
	  TMNN RBABT,(RB)	; Function aborted?
	  IFSKP.		; Yes.
	    LOAD T1,RBMSI,(RB)	;   Get address of input MSD and buffer
	    CAIN T1,0		;   An MSD there?
	    IFSKP.		;   Yes...
	     XCALL (XCDSEC,DNFWDS);  Release the buffer
	    ENDIF.
	    MOVE T1,RB		;   Get address of RB
	    XCALLRET (XCDSEC,DNFWDS) ; Release the RB
	  ENDIF.		; End of abort code
	  ENDIF.
	ELSE.			;MSD - SID Transmitted by Console Requestor
	  INCRF SVRTC,(SB)	;Bump requester transmit count
	ENDIF.

	RET			;Success - RETURN from RCSXTC

;END of Routine RCSXTC

	SUBTTL Remote Console Protocol Server -- RCSRCI - Process Chan State Change

;RCSRCI - Exit Routine to Handle NI Channel State Change
;
;Call:	T1/ NU.RCI
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL RCSRCI
;	Normal Return
;Changes T1,T2

	RESCD
RCSRCI:
IFN FTOPS20,<
	LOAD T1,UNEXS,(UN)	;Get external DLL state
	CAIE T1,UNS.RN		;Running?
>; END IFN FTOPS20
IFN FTOPS10,<
	TMNN UNRUN,(UN)		;Portal running?
>; END IFNF TOPS10
	IFSKP.
	  SETZRO SVDLS,(SB)	;Yes...
IFN FTOPS10,<
	  MOVE T1,SB		;Pass SVB address
	  CALL PSTBUF		;Post buffers
	    NOP			;Ignore failure
>; END IFN FTOPS10
	ELSE.
	  SETONE SVDLS,(SB)	;No...
	ENDIF.
	RET			;Success - RETURN from RCSRCI

;END of Routine RCSRCI

	SUBTTL Remote Console Protocol Server -- RCSRCV - Receive Datagram Handler

;RCSRCV - Exit Routine to Handle Received Remote Console Datagram
;
;This routine is called by the DLL, at **scheduler/interrupt** level,
;when an Ethernet Remote Console Protocol Datagram is received.
;
;Call:	T1/ NU.RCV
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL RCSRCV
;	Normal Return
;Changes T1,T2

	RESCD
RCSRCV:	CALL LLMRCV		;Do common receive processing
	  RETBAD		;Return on failure
	CAIL T1,^D1		;Is it at least minimum of 1 byte?
	IFSKP.			;No...
	  XCT LLMIR1		;Do the BUG.
	  JRST LLMRCX		;Go to common exit
	ELSE.			;Yes...
	  CAIG T1,^D1500	;Bigger than Ethernet allows?
	  IFSKP.
	    XCT LLMIR1		;It's a BUG.
	    JRST LLMRCX		;Go to common exit
	  ENDIF.
	ENDIF.
	CALL RCSFCD		;Go process message based on function code
	  JRST LLMRCX		;On RET
	RET			;On RETSKP Success - RETURN from RCSRCV

;END of Routine RCSRCV

	SUBTTL Protocol Server -- LLMRCV - Common Receive Datagram Processing

;LLMRCV - Routine to Handle Received Remote Console Datagram
;
;
;Call:	T1/ NU.RCV
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL LLMRCV
;	 Error Return, Drop message
;	Normal Return T1/ Message length
;Changes T1,T2

	RESCD
LLMRCV:	CAIE T3,0		;Receive error?
	  JRST LLMRCX		;Yes...
	MOVE T1,UN		;Pass UN Block address
	CALL INPMSD		;Set up input MSD
	INCRF SVRCT,(SB)	;Count receipt of all messages
	DECRF SVBPC,(SB)	;Decrement count of receive buffers posted
	MOVE T1,SB		;Pass SV block address
	CALL PSTBUF		;Post a receive buffer
	  NOP			;Ignore failure
	XCALL (XCDSEC,DNRPOS)	;Get message length
	RETSKP			;Return +2 with length in T1

LLMRCX:				;Common error exit from LLMRCV
	INCRF SVTIC,(SB)	;Count Total Invalid receive Counter
	LOAD T1,UNRID,(UN)	;Get buffer address saved when buffer posted
	XCALLRET (XCDSEC,DNFWDS) ;Free the buffer and RETURN from LLMRCV

;END of Routine LLMRCV

	SUBTTL Remote Console Protocol Server -- RCSFCD - MOP Function Code Dispatch

;RCSFCD - Dispatch on Received MOP Function Code
;
;Call:	SB/ SV Block address
;	UN/ UN Block address
;	MS/ MS Block address
;	CALL RCSFCD
;	Normal Return
;Changes T1,T2

	MIN. (MINFCD,<FCBOOT,FCRQID,FCSSID,FCRQCT,FCCNTR,FCRSVC,FCRELC,FCCCAP,FCCRAK>)
	MAX. (MAXFCD,<FCBOOT,FCRQID,FCSSID,FCRQCT,FCCNTR,FCRSVC,FCRELC,FCCCAP,FCCRAK>)

	FCDSIZ==<MAXFCD-MINFCD+1> ;Size of Dispatch Table

	RESCD
RCSFCD:	XCALL (XCDSEC,DNG1BY)	;Get MOP function code
	  RET			;Protect against short message
	CAIL T1,MINFCD		;Range check function code
	CAILE T1,MAXFCD
	IFSKP.
	  CALL @FCDDSP-MINFCD(T1) ;Call the function dependent routine
	    RET			;Pass RETURN upwards
	ELSE.
	  XCT MOPIFC		;Do the BUG.
	  RET
	ENDIF.
	RETSKP			;Success - RETURN from RCSFCD

FCDDSP:	BLOCK <FCDSIZ>		;Remote Console MOP Functon Dispatch Table
	MAKENT (FCDDSP,FCBOOT-MINFCD,RTN) ;Don't support BOOT
	MAKENT (FCDDSP,FCRQID-MINFCD,RCSRID) ;Process REQUEST ID
	MAKENT (FCDDSP,FCSSID-MINFCD,RCSSID) ;Process SYSTEM ID
	MAKENT (FCDDSP,FCRQCT-MINFCD,RCSRCT) ;Process REQUEST COUNTERS
	MAKENT (FCDDSP,FCCNTR-MINFCD,RCSCTR) ;Process COUNTERS
	MAKENT (FCDDSP,FCRSVC-MINFCD,RTN) ;Don't support RESERVE CONSOLE
	MAKENT (FCDDSP,FCRELC-MINFCD,RTN) ;Don't support RELEASE CONSOLE
	MAKENT (FCDDSP,FCCCAP-MINFCD,RTN) ;Don't support CONSOLE COMMAND POLL
	MAKENT (FCDDSP,FCCRAK-MINFCD,RCSRAK) ;Process CONSOLE RESPONSE ACK

;END of Routine RCSFCD

	SUBTTL Console Server -- RCSRID - Process Request ID

;RCSRID - Process MOP REQUEST ID message
;
;Call:	SB/ SV Block address
;	UN/ UN Block address
;	MS/ MS Block address
;	CALL RCSRID
;	Normal Return
;Changes T1,T2

	RESCD
RCSRID:	XCALL (XCDSEC,DNG1BY)	;Get the reserved field
	  RET
;	OPSTRM <AOS >,MDBYT,(MS) ;***** Patch - EVDWC sends wrong pad count ***
	XCALL (XCDSEC,DNG2BY)	;Get the receipt number
	  RET
	INCRF SVSRC,(SB)	;Bump count of server receives
	MOVE T2,MS		;Get MSD address
	CALL BLDSID
	CALL XMTRPY		;Transmit the reply resonse
	  RET			;Take failure return
	RETSKP			;Success - RETURN from RCSRID

;END of Routine RCSRID

	SUBTTL Console Server/Requestor -- RCSSID - Process System ID

;RCSSID - Process MOP SYSTEM ID message
;
;Call:	SB/ SV Block address
;	UN/ UN Block address
;	MS/ MS Block address
;	CALL RCSSID
;	Normal Return
;Changes T1,T2

	RESCD
RCSSID:	XCALL (XCDSEC,DNG1BY)	;Ignore Reserved field
	  RET
	XCALL (XCDSEC,DNG2BY)	;Get the receipt number
	  RET
	SKIPE T1		;Is the receipt number zero?
	IFSKP.			;Yes, this is an unsolicited configuration msg
IFN FTOPS20,<
	  OPSTR <SKIPN>,SVCFN,(SB) ;Is there a Configurator Fork?
>; END IFN FTOPS20
IFN FTOPS10,<
	  OPSTR <SKIPN>,SVCJC,(SB) ;Is there a Configurator JCH?
>; END IFN FTOPS10
	  IFSKP.		;Yes..., Notify process requesting SID messages
	  INCRF SVSRC,(SB)	;Bump count of server receives

;Note: The Configurator process obtains the ability to be notified when
; unsolicited SYSTEM ID messages arrive by issuing an LLMOP% JSYS with
; function code .RCAIC and flag LM%ENU set. The process will then get a
; software interrupt on the channel provided in the call. Only one process
; on the system may be enabled to get this interrupt. When the process
; gets the interrupt indicating a SYSTEM ID message is available it must
; issue an LLMOP% JSYS with function code .RCRPY with a request number of
; zero.
	    ;Build an RB for this buffer...
	    MOVEI T1,RB.LEN	;Allocate block for an RB
	    XCALL (XCDSEC,DNGWDZ) ;Cleared to zeroes
	      JSUERR (MONX07,)	;Failed... Return with Error Code
	    MOVE RB,T1		;Save address of RB
	    STOR MS,RBMSI,(RB)	;Store address of input MSD in RB
	    SETZRO RBRNO,(RB)	;Set Receipt Number to zero
	    SETONE RBFRC,(RB)	;Set receive complete flag
	    MOVX T1,.RQCMP	;Set state to COMPLETE
	    STOR T1,RBSTT,(RB)	;Initialize the state in RB
IFN FTOPS20,<
	    LOAD T1,SVCFN,(SB)	;Get Fork Number of Configurator Module
	    STOR T1,RBFRK,(RB)	;Store in RB
	    LOAD T1,SVICH,(SB)	;Get PSI channel number
	    STOR T1,RBICH,(RB)	;Store in RB
>; END IFN FTOPS20
IFN FTOPS10,<
	    LOAD T1,SVCJC,(SB)	;Get JCH of Configurator Module
	    STOR T1,RBJCH,(RB)	;Store in RB
>; END IFN FTOPS10
	    MOVE T1,RB		;Get address of RB
	    MOVE T2,SB		;Pass address of SVB
	    CALL LLMQUE		;Queue RB on request queue
	  ELSE.			;No..., just drop the message and free buffer
	    RET			;Return now
	  ENDIF.
	ELSE.			;No..., Handle response to RC request
	  INCRF SVRRC,(SB)	;Bump count of requestor receives
	  MOVE T2,SB		;Pass SVB address
	  CALL LPSSXQ		;Search the request queue for this RB
	    RET			;Not found, drop it. Maybe keep a count?
	  MOVE RB,T2		;Found, T2 contains address of RB
	  CALL QUEMSD		;Queue this MSD
	  SETONE RBFRC,(RB)	;Set receive complete flag
	  CALL SETRBS		;Set state in RB
	ENDIF.

IFN FTOPS20,<
	OPSTR <SKIPN >,RBAIC,(RB) ;Interrupt channel assigned?
	  RETSKP		;No, return now
	LOAD T1,RBICH,(RB)	;Get Interrupt Channel number
	LOAD T2,RBFRK,(RB)	;Get Fork Index
	CALL PSIRQ		;Notify user that request completed
>; END IFN FTOPS20
IFN FTOPS10,<
	CALL RBWAKE		;Wake up job
>; END IFN FTOPS10

	RETSKP			;Success - RETURN from RCSSID

;END of Routine RCSSID

	SUBTTL Console Server -- RCSRCT - Process Request Counters

;RCSRCT - Process MOP REQUEST COUNTERS message
;
;Call:	SB/ SV Block address
;	UN/ UN Block address
;	MS/ MS Block address
;	CALL RCSRCT
;	Normal Return
;Changes T1,T2

	RESCD
RCSRCT:	STKVAR <RCPTNO>
	XCALL (XCDSEC,DNG2BY)	;Get the receipt number
	  RET
	MOVEM T1,RCPTNO		;Save receipt number
	INCRF SVSRC,(SB)	;Bump count of server receives

	MOVX T1,RB.LEN		;Allocate an RB for this request
	XCALL (XCDSEC,DNGWDZ)
	  RET
	MOVE RB,T1		;Point to RB
	MOVE T2,SB		;Pass address of SVB
	STOR MS,RBMSO,(RB)	;Save MSD address for output later
	MOVE T1,RCPTNO		;Get receipt number
	STOR T1,RBRNO,(RB)	;Save it in RB
	LOAD T1,UNSAD,(UN)	;Get source of this request
	LOAD T2,UNSAD,+1(UN)
	STOR T1,RBDST,(RB)	;Store as request destination
	STOR T2,RBDST,+1(RB)

;Get the current counters from the port driver

	LOAD T1,UNCHN,(UN)	;Get channel request received on
	STOR T1,RBCID,(RB)	;Save Channel ID in RB
	XMOVEI T1,SV.CCB(SB)	;Get address of counters buffer
	STOR T1,UNBFA,(UN)	;Store in UN
	MOVEI T1,CC.LEN		;Size of Counters Block
	STOR T1,UNBSZ,(UN)	;Save length in UN
	STOR RB,UNRID,(UN)	;Store RB address
	SETZRO UNZRO,(UN)	;Don't zero counters when read
	MOVEI T1,NU.RCC		;DLL Read Counters Function code
	MOVE T2,UN		;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface Block
	  RET			;A real problem?
	RETSKP			;Success - RETURN from RCSRCT

;END of Routine RCSRCT

	SUBTTL Console Requestor -- RCSCTR - Process Counters

;RCSCTR - Process MOP COUNTERS message
;
;Call:	SB/ SV Block address
;	UN/ UN Block address
;	MS/ MS Block address
;	CALL RCSCTR
;	Normal Return
;Changes T1,T2

	RESCD
RCSCTR:	XCALL (XCDSEC,DNG2BY)	;Get the receipt number
	  RET
	INCRF SVRRC,(SB)	;Bump count of requestor receives
	MOVE T2,SB		;Pass SVB address
	CALL LPSSXQ		;Search the request queue for this RB
	  RET			;Not found, drop it. Maybe keep a count?
	MOVE RB,T2		;Found, T2 contains address of RB
	SETONE RBFRC,(RB)	;Set receive complete flag
	STOR MS,RBMSI,(RB)	;Store address of input MSD in RB
	CALL SETRBS		;Set state in RB
IFN FTOPS20,<
	OPSTR <SKIPN >,RBAIC,(RB) ;Interrupt channel assigned?
	  RETSKP		;No, return now
	LOAD T1,RBICH,(RB)	;Get Interrupt Channel number
	LOAD T2,RBFRK,(RB)	;Get Fork Index
	CALL PSIRQ		;Notify user that request completed
>; END IFN FTOPS20
IFN FTOPS10,<
	CALL RBWAKE		;Wake up job
>; END IFN FTOPS10
	RETSKP			;Success - RETURN from RCSCTR

;END of Routine RCSCTR

	SUBTTL Console Requestor -- RCSRAK - Process Console Response Ack

;RCSRAK - Process MOP CONSOLE RESPONSE ACK message
;
;Call:	SB/ SV Block address
;	UN/ UN Block address
;	MS/ MS Block address
;	CALL RCSRAK
;	Normal Return
;Changes T1,T2

	RESCD
RCSRAK:	INCRF SVRRC,(SB)	;Bump count of requestor receives
;
;Here we use the low order source Ethernet address to use as a faked
;up Request Number. This was set in the RB in SCCINI.
;
	LOAD T1,UNSAD,+1(UN)	;Get the low order destination address
	LSH T1,-<^D36-^D16>
	MOVE T2,SB		;Pass SVB address
	CALL LPSSXQ		;Search the request queue for this RB
	  RET			;Not found, drop it. Maybe keep a count?
	MOVE RB,T2		;Found, T2 contains address of RB
	SETONE RBFRC,(RB)	;Set receive complete flag
	STOR MS,RBMSI,(RB)	;Store address of input MSD in RB
	CALL SETRBS		;Set state in RB
IFN FTOPS20,<
	OPSTR <SKIPN >,RBAIC,(RB) ;Interrupt channel assigned?
	  RETSKP		;No, return now
	LOAD T1,RBICH,(RB)	;Get Interrupt Channel number
	LOAD T2,RBFRK,(RB)	;Get Fork Index
	CALL PSIRQ		;Notify user that request completed
>; END IFN FTOPS20
IFN FTOPS10,<
	CALL RBWAKE		;Wake up job
>; END IFN FTOPS10
	RETSKP			;Success - RETURN from RCSRAK

;END of Routine RCSRAK

	SUBTTL Remote Console Protocol Server -- RCSRCC - Process Read Counters Complete

;RCSRCC - Exit Routine to Handle KLNI Read Counters Completion
;
;Call:	T1/ NU.RCC
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL RCSRCC
;	Normal Return
;Changes T1,T2,RB

	RESCD
RCSRCC:	LOAD RB,UNRID,(UN)	;Get RB address
	LOAD MS,RBMSO,(RB)	;Get MSD address
	LOAD T1,RBRNO,(RB)	;Pass receipt number
	LOAD T2,UNBFA,(UN)	;Pass address of counter block
	MOVE T3,MS		;Pass MSD address
	CALL BLDCTR		;Build counters message
	LOAD T1,RBDST,(RB)	;Get source of this request
	LOAD T2,RBDST,+1(RB)
	STOR T1,UNSAD,(UN)	;Store as request source for XMTRPY
	STOR T2,UNSAD,+1(UN)
	MOVE T1,RB		;Pass RB address
	XCALL (XCDSEC,DNFWDS)	;Release the RB
	CALL XMTRPY		;Transmit the reply resonse
	  RET			;Take failure return
	RET			;Success - RETURN from RCSRCC

;END of Routine RCSRCC

	SUBTTL Remote Console Protocol Server -- RCSRSC - Process Read Station Complete

;RCSRSC - Exit Routine to Handle KLNI Read Station Info Completion
;
;Call:	T1/ NU.RSC
;	T2,UN/ UN Block address
;	SB/ SV Block address
;	CALL RCSRSC
;	Normal Return
;Changes T1,T2,RB

	RESCD
RCSRSC:	RET
	RETSKP			;Success - RETURN from RCSRSC

;END of Routine RCSRSC

	SUBTTL Console Server -- XMTRPY - Transmit MOP Reply

;XMTRPY - Transmit LLMOP Reply Using Received MSD/Buffer and Callback UN
;
;Call:	SB/ SV Block address
;	UN/ UN Block address
;	MS/ MSD address
;	CALL XMTRPY
;	 Error Return
;	Normal Return
;Changes T1,T2
;

	RESCD
XMTRPY:	LOAD T1,UNSAD,(UN)	;Get Source Address
	LOAD T2,UNSAD,+1(UN)	; ans send from whence it came
	CALL XMTMSD		;Transmit this MSD
	  RET			;Failed...
	RETSKP			;Success - RETURN from XMTRPY

;END of Routine XMTRPY

	SUBTTL Console Server -- RCSIDS - Identify Self

;RCSIDS - Perform Remote Console Server Identify Self Function
;
;Call:			From SCHED CLKLV2
;	CALL RCSIDS
;	Normal Return
;Changes T1
;
;Nota Bene: The periodic Identify-Self function must always
;	succeed in order to meet the DIGITAL Ethernet Node
;	Product Architecture Specification requirements. To
;	meet this requirement all memory for performing this
;	function is preallocated here.
;
; ***** This routine needs to be updated to handle multiple KLNI's *****
;

	RESCD
RCSIDS::SAVEAC <UN,SB>
	TRVAR <MSGLEN,BP,MP>
	XMOVEI SB,RCSSVB	;Set up SB
	MOVE T1,RCSATB		;Get Identify-Self Timer Base
	MOVEM T1,LLMACT		;Reset the clock timer
	TMNE SVDLS,(SB)		;Data Link State ON for this channel?
	  RET			;No, just return

;Send to multi-cast address on each channel

	XMOVEI UN,SV.IXB(SB)	;Get address of RCS UN block
	LOAD T3,UNPID,(UN)	;Get RCS's Portal-id
	XMOVEI UN,PIDSUN	;Get address of our UN Block
	STOR T3,UNPID,(UN)	;Set our Portal-id in this UN

	XMOVEI T1,RCSSIM	;Get address of IM block
	XMOVEI MS,IM.MSD(T1)	;Get address of MSD

	MOVX T1,0		;Pass receipt number of zero
	MOVE T2,MS		;Pass MSD address
	CALL BLDSID		;Build the SYSTEM ID message

	STOR MS,UNBFA,(UN)	;Store MSD address in UN
	STOR MS,UNRID,(UN)	;And make it our return ID

	MOVEI T1,NU.XMT		;DLL Transmit Function code
	MOVE T2,UN		;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface Block
	IFNSK.
	  LOAD T2,UNCHN,(UN)	;Get channel number
	  XCT RCS3XF		;Do the BUG.
	ELSE.
	  INCRF SVTTI,(SB)	;Bump count of transmits initiated
	  SKIPA			;Enable BUGINF by patching
	  XCT RCSPIS		;Do the BUG.
	ENDIF.

	RET			;Normal return

;END of Routine RCSIDS

	SUBTTL Console Server -- BLDSID - Build SYSTEM ID message

;BLDSID - Build SYSTEM ID message
;
;Call:	T1/ Receipt Number
;	T2/ MSD Address
;	CALL BLDSID
;	  Error Return
;	Normal Return
;Changes T1,T2
;

	RESCD
BLDSID: SAVEAC <P1>		;Preserve an AC
	MOVE P1,T1		;Save RECEIPT NUMBER
	MOVE T1,T2		;Get MSD Address
	XCALL (XCDSEC,DNPINI)	;Initialize MSD for output
	MOVEI T1,FCSSID		;Get System ID function code
	XCALL (XCDSEC,DNP1BY)	;Store in message
	MOVEI T1,0		;Store reserved field
	XCALL (XCDSEC,DNP1BY)
	MOVE T1,P1		;Get receipt number given us
	XCALL (XCDSEC,DNP2BY)	;Store receipt number in message

;Build MAINTENANCE VERSION in SYSTEM ID message

	MOVEI T1,3		;Pass INFO LENGTH
	MOVEI T2,IT.MVN		;Pass INFO TYPE
	CALL INFHDR		;Build INFO header

	MOVE T1,MOPVER
	XCALL (XCDSEC,DNP1BY)	;Store maintenance version
	MOVE T1,MOPECO
	XCALL (XCDSEC,DNP1BY)	;Store ECO
	MOVE T1,MOPUEC
	XCALL (XCDSEC,DNP1BY)	;Store User ECO

;Build FUNCTIONS in SYSTEM ID message

	MOVEI T1,2
	MOVEI T2,IT.FCT		;Functions
	CALL INFHDR		;Build INFO header
	MOVX T1,<MFLOOP!MFDLCT>	;We support Loop and Data Link counters
	XCALL (XCDSEC,DNP2BY)

;Build HARDWARE ADDRESS in SYSTEM ID message

	MOVX T1,NU.RCI		;Get Read Channel Info function code
	MOVE T2,UN		;Pass address of UN Block
	SETZRO UNBSZ,(UN)	;Indicate no aux buffer
	CALL DLLUNI		;Call DLL User to NI Interface
	  NOP			;Ignore error
	MOVEI T1,6
	MOVEI T2,IT.HAD		;Hardware Address
	CALL INFHDR		;Build INFO header
	LOAD T1,UNHAD,(UN)	;Get hardware address
	LOAD T2,UNHAD,+1(UN)
	XCALL (XCDSEC,DNPENA)

;Build SYSTEM TIME in SYSTEM ID message
;
;*****
;Might have to do this in JOB0 (MEXEC) or look into possibility
; of calling routines in DATIME.
;*****

	MOVEI T1,^D10
	MOVEI T2,IT.SYT		;System Time
	CALL INFHDR		;Build INFO header
	MOVX T1,^D19
	XCALL (XCDSEC,DNP1BY)	;Store CENTURY
	MOVX T1,^D84
	XCALL (XCDSEC,DNP1BY)	;Store YEAR
	MOVX T1,^D2
	XCALL (XCDSEC,DNP1BY)	;Store MONTH
	MOVX T1,^D23
	XCALL (XCDSEC,DNP1BY)	;Store DAY
	MOVX T1,^D12
	XCALL (XCDSEC,DNP1BY)	;Store HOUR
	MOVX T1,^D30
	XCALL (XCDSEC,DNP1BY)	;Store MINUTE
	MOVX T1,^D30
	XCALL (XCDSEC,DNP1BY)	;Store SECOND
	MOVX T1,^D50
	XCALL (XCDSEC,DNP1BY)	;Store 100TH
	MOVX T1,-^D5
	XCALL (XCDSEC,DNP1BY)	;Store TDFH
	MOVX T1,^D0
	XCALL (XCDSEC,DNP1BY)	;Store TDFM

;Build COMMUNICATION DEVICE in SYSTEM ID message

	MOVEI T1,1
	MOVEI T2,IT.CDV		;Communication Device
	CALL INFHDR		;Build INFO header
	MOVX T1,^D15		;Code for KLNI Device
	XCALL (XCDSEC,DNP1BY)

;Build DATA LINK in SYSTEM ID message

	MOVEI T1,1
	MOVEI T2,IT.DLK		;Data Link
	CALL INFHDR		;Build INFO header
	MOVX T1,1
	XCALL (XCDSEC,DNP1BY)

;Build DATA LINK BUFFER SIZE in SYSTEM ID message

	MOVEI T1,2
	MOVEI T2,IT.DBS		;Data Link Buffer Size
	CALL INFHDR		;Build INFO header
	MOVX T1,^D262
	XCALLRET (XCDSEC,DNP2BY)

;END of Routine BLDSID

	SUBTTL Console Server -- QUEMSD - Queue an INPut MSD

;QUEMSD - Queue an INPut MSD
;
;Call:	RB/ Request Block address
;	MS/ address of MSD to be queued
;	CALL QUEMSD
;	Normal Return always
;Changes T1
;

	RESCD
QUEMSD:	ETHLOK			;Interlock the RB
	TMNE RBMSI,(RB)		;Is the queue empty?
	IFSKP.			;Yes...
	  STOR MS,RBMSI,(RB)	;Just link this MSD
	ELSE.			;No...
	  LOAD T1,RBMSI,(RB)	;Get first MSD address
	  DO.			;Loop thru to end of list
	  TMNN MDNXT,(T1)	;At end?
	  IFSKP.		;No...
	    LOAD T1,MDNXT,(T1)	;Get next MSD address
	    JRST TOP.		;Do next
	  ENDIF.
	  ENDDO.		;Yes..
	  STOR MS,MDNXT,(T1)	;Link this MSD at end
	ENDIF.
	ETHULK			;Let go of RB interlock
	RET

;END of Routine QUEMSD

	SUBTTL Console Server -- DEQMSD - DEQueue an input MSD

;DEQMSD - DEQueue an input MSD
;
;Call:	RB/ Request Block address
;	CALL DEQMSD
;	  Return +1: Queue Empty
;	Return +2: MS/ Address of MSD Dequeued
;Changes T1
;

	RESCD
DEQMSD:	ETHLOK			;Interlock the RB
	TMNE RBMSI,(RB)		;Is there an MSD available?
	IFSKP.			;No...
	  ETHULK
	  SETZ MS,		;Clear the MSD address
	  RET
	ENDIF.
	LOAD MS,RBMSI,(RB)	;Get address of input MSD
	LOAD T1,MDNXT,(MS)	;Get next MSD address
	STOR T1,RBMSI,(RB)	;Make this the next MSD
	ETHULK			;Let go of RB interlock
	RETSKP

;END of Routine DEQMSD

	SUBTTL Console Server -- INFHDR - Build INFO Header

;INFHDR - Build INFO Header in SYSTEM ID message
;
;Call:	T1/ INFO LENGTH value
;	T2/ INFO TYPE value
;	CALL INFHDR
;	  Error Return
;	Normal Return
;Changes T1,T2
;

	RESCD
INFHDR:	SAVEAC <P1>		;Preserve an AC
	MOVE P1,T1		;Save INFO LENGTH
	MOVE T1,T2		;Get INFO TYPE
	XCALL (XCDSEC,DNP2BY)	;Store INFO TYPE in message
	MOVE T1,P1		;Get INFO LENGTH
	XCALL (XCDSEC,DNP1BY)	;Store INFO LENGTH in message
	RET

;END of Routine INFHDR

	SUBTTL Console Server -- BLDCTR - Build COUNTERS Message

;BLDCTR - Build COUNTERS Message
;
;Call:	T1/ Receipt Number
;	T2/ Counter Block Address
;	T3/ MSD Address
;	CALL BLDCTR
;	  Error Return
;	Normal Return
;Changes T1,T2
;

	CC=WK			;CC used in this routine only 
	RESCD
BLDCTR: SAVEAC <P1,P2>		;Preserve some ACs
	DMOVE P1,T1		;Save RECEIPT NUMBER and COUNTER BLOCK address
	SAVEAC <CC>
	MOVE T1,T3		;Get MSD Address
	XCALL (XCDSEC,DNPINI)	;Initialize MSD for output
	MOVEI T1,FCCNTR		;Get COUNTERS function code
	XCALL (XCDSEC,DNP1BY)	;Store in message
	MOVE T1,P1		;Get receipt number given us
	XCALL (XCDSEC,DNP2BY)	;Set receipt number
	MOVE CC,P2		;Get address of counter block
	LOAD T1,CCSLZ,(CC)	;Pass Seconds since last zeroed
	XCALL (XCDSEC,DNP2BY)	;Output Seconds since last zeroed
	LOAD T1,CCBYR,(CC)	;Pass Bytes received
	XCALL (XCDSEC,DNP4BY)	;Output Bytes Received
	LOAD T1,CCBYS,(CC)	;Pass Bytes sent
	XCALL (XCDSEC,DNP4BY)	;Output Bytes Sent 
	LOAD T1,CCDGR,(CC)	;Pass Datagrams received
	XCALL (XCDSEC,DNP4BY)	;Output Frames Received
	LOAD T1,CCDGS,(CC)	;Pass Datagrams sent
	XCALL (XCDSEC,DNP4BY)	;Output Frames Sent 
	LOAD T1,CCMBR,(CC)	;Pass Multicast bytes received
	XCALL (XCDSEC,DNP4BY)	;Output Multicast Bytes Received
	LOAD T1,CCMDR,(CC)	;Pass Multicast datagrams received
	XCALL (XCDSEC,DNP4BY)	;Output Multicast Frames Received
	LOAD T1,CCDSD,(CC)	;Pass Datagrams sent, initially deferred
	XCALL (XCDSEC,DNP4BY)	;Output Frames Sent, Initially Deferred
	LOAD T1,CCDS1,(CC)	;Pass Datagrams sent, single collision
	XCALL (XCDSEC,DNP4BY)	;Output Frames Sent, Single Collision
	LOAD T1,CCDSM,(CC)	;Pass Datagrams sent multiple collisions
	XCALL (XCDSEC,DNP4BY)	;Output Frames Sent, Multiple Collisions
	LOAD T1,CCSF,(CC)	;Pass Send failures
	XCALL (XCDSEC,DNP2BY)	;Output Send Failure
	LOAD T1,CCSFM,(CC)	;Pass Send failure bit mask
	LSH T1,-4		;Right justify it
	XCALL (XCDSEC,DNP2BY)	;Output Send Failure Reason Bitmap
	LOAD T1,CCRF,(CC)	;Pass Receive failure
	XCALL (XCDSEC,DNP2BY)	;Output Receive Failure
	LOAD T1,CCRFM,(CC)	;Pass Receive failure bit mask
	LSH T1,-4		;Right justify it
	XCALL (XCDSEC,DNP2BY)	;Output Receive Failure Reason Bitmap
	LOAD T1,CCUFD,(CC)	;Pass Unrecognized frame destination
	XCALL (XCDSEC,DNP2BY)	;Output Unrecognized Frame Destination
	LOAD T1,CCDOV,(CC)	;Pass Data overrun
	XCALL (XCDSEC,DNP2BY)	;Output Data Overrun
	LOAD T1,CCSBU,(CC)	;Pass System buffer unavailable
	XCALL (XCDSEC,DNP2BY)	;Output System Buffer Unavailable
	LOAD T1,CCUBU,(CC)	;Pass User buffer unavailable
	XCALL (XCDSEC,DNP2BY)	;Output User Buffer Unavailable
	RET

;END of Routine BLDCTR

	SUBTTL Console Server -- INPMSD - Initialize INPut MSD

;INPMSD - Initialize INPut MSD
;
;Call:	T1/ UN Block Address
;	CALL INPMSD
;	Normal Return always, MS/ MSD address
;Changes T1,T2,T3,T4
;

	RESCD
INPMSD: SAVEAC <UN>		;Allocate UN block pointer
	MOVE UN,T1		;Save address of UN block
	MOVX T1,UN.LEN		;Get length of UN block
	MOVE T2,UN		;Get source UN address
	LOAD T3,UNRID,(UN)	;Get address of MSD we saved as ID
	XMOVEI T3,MD.LEN(T3)	;'Shadow' UN is appended to MD
	EXTEND T1,[XBLT]	;Copy the UN block to 'shadow'
	LOAD T1,UNRID,(UN)	;Get address of MSD we saved as ID
	LOAD T2,UNBFA,(UN)	;Get received pointer
	LOAD T3,UNBFA,+1(UN)	; and global address
	LOAD T4,UNBSZ,(UN)	;Get received message length in bytes
	XCALLRET (XCDSEC,DNGMSS) ;Set up MSD for receive buffer

;END of Routine INPMSD

	SUBTTL Protocol Server -- SETRBS - SET RB State

;SETRBS - SET RB State based on status flags
;
;Call:	RB/ Request Block address 
;	CALL SETRBS
;	Normal Return
;Changes T1
;

	RESCD
SETRBS:	LOAD T1,RBFLG,(RB)	;Get flags
	TXNN T1,RB%FTI		;Transmit initiated?
	IFSKP.			;And...
	TXNN T1,<RB%FRC!RB%FRF> ;Receive done?
	ANSKP.			;And...
	TXNN T1,<RB%FTC!RB%FTF> ;Transmit done?
	ANSKP.			;Yes...
	  MOVX T1,.RQCMP	;Then request is complete to user
	ELSE.			;No...
	  MOVX T1,.RQPND	;Then its pending to user
	ENDIF.
	STOR T1,RBSTT,(RB)	;Set state in RB
	RET

;END of Routine SETRBS

	SUBTTL LLMOP Requestor -- .LLMOP - LLMOP% (Low Level MOP) JSYS Entry

IFN FTOPS20,<
;.LLMOP - Entry point to LLMOP JSYS handler
;
;Call:	T1/ LLMOP% Function Code
;	T2/ Argument Block Address
;	CALL .LLMOP
;	 Error Return
;	Normal Return
;Changes T2,T3,SB,LM

	SWAPCD
.LLMOP::MCENT			;Establish "slow" JSYS context
	SAVEAC <SB,RB,LM,UN>	;Allocate named AC variables for block pointers
	MOVE LM,T2		;Save address of users LLMOP% argument block
	MOVX T3,SC%WHL!SC%OPR!SC%MNT ;Check for sufficient privilege
	TDNN T3,CAPENB		;Against ENABLED capabilities
	  ITERR <WHELX1>	;Not good enough
	CAIGE T1,.LLMIN		;Function code within range?
	  ITERR <ARGX02>	;No, error return 'Invalid Function'
	ULOAD T2,LMCID,(LM)	;Get channel number
	CAIL T2,0		;Check for valid channel 0 to NKLNI-1
	CAILE T2,NKLNI-1
	  ITERR <LLMX05>	;Not valid, return 'Invalid Channel Number'
	IMULI T2,SV.LEN		;Get offset to SVB for this channel
	CAILE T1,.ELSTS		;Is it a Loopback function?
	IFSKP.			;Yes...
	  XMOVEI SB,LPSSVB(T2)	;Get address of channels SVB
	ELSE.			;No..., Not Loopback
	  CAIL T1,LMTBMX	;Within range for Remote Console?
	    ITERR <ARGX02>	;No, error return 'Invalid Function'
	  XMOVEI SB,RCSSVB(T2)	;Get address of channels SVB
	ENDIF.
	TMNE SVDLS,(SB)		;Data Link State ON for this channel?
	  ITERR <LLMX02>	;No, LLMOP is OFF
	CALL @FUNTAB(T1)	;Yes, Dispatch to Function specific routine
	 ITERR			;Return on error from .LLMOP
	MRETNG			;Return on success from .LLMOP
>; END IFN FTOPS20
	SUBTTL	LLMOP - TOPS10 .LLMOP UUO Handler

IFN FTOPS10,<
;LLMOP. - Entry point for LLMOP. UUO handler
;
;Call:	T1/ LLMOP. Function Code
;	T2/ Argument Block Address
;	CALL	LLMOP.
;	 Error Return
;	Normal Return
;
;	Changes: T2,T3,SB,LM


.LLMOP::SE1ENT			;RUN IN SECTION 1
	SAVEAC	<SB,RB,LM,UN>	;ALLOCATE VARIABLES FOR BLOCK POINTERS
	CALL	PRVJ##		;CHECK FOR SUFFICIENT PRIVILEGES
	  SKIPA			;OK, CONTINUE
	JSUERR	(,LMPRV%)	;INSUFFICIENT PRIVILEGES
	MOVE	M,P1		;GET UUO AC
	CALL	GETWDU##	;GET FIRST AC
	MOVE	P2,T1		;SAVE FUNCTION CODE
	CALL	GETWD1##	;GET SECOND AC
	MOVE	LM,T1		;SAVE ARG BLOCK ADDRESS
	MOVEI	T2,10		;CHECK ARG LIST
	PUSHJ	P,ARNGE##	;...
	  JSUERR (,LMADC%)	;ADDRESS CHECK
	 JFCL			;ADDRESS ILLEGAL FOR I/O
	CAIGE	P2,.LLMIN	;FUNCTION CODE WITHIN RANGE?
	  JSUERR (,LMILF%)	;NO, ILLEGAL FUNCTION
	ULOAD	T2,LMCID,(LM)	;GET CHANNEL NUMBER
	CAIL	T2,0		;CHECK FOR VALID CHANNEL 0 TO NKLNI-1
	CAILE	T2,NKLNI-1
	  JSUERR (,LMICN%)	;INVALID CHANNEL NUMBER
	IMULI	T2,SV.LEN	;GET OFFSET TO SVB FOR THIS CHANNEL
	CAILE	P2,.ELSTS	;IS IT A LOOPBACK FUNCTION?
	IFSKP.			;YES
	  XMOVEI SB,LPSSVB(T2)	;GET ADDRESS OF CHANNELS SVB
	ELSE.			;NO, NOT LOOPBACK
	  CAIL	P2,LMTBMX	;WITHIN RANGE FOR REMOTE CONSOLE?
	    JSUERR (,LMILF%)	;NO, ILLEGAL FUNCTION
	  XMOVEI SB,RCSSVB(T2)	;GET ADDRESS OF CHANNELS SVB
	ENDIF.
	TMNE	SVDLS,(SB)	;DATA LINK STATE ON FOR THIS CHANNEL?
	  JSUERR (,LMOFF%)	;NO, LLMOP IS OFF
	MOVX	T1,FUNBUF	;DOES THIS FUNCTION HAVE A BUFFER?
	TDNN	T1,FUNTAB(P2)	;...
	PJRST	@FUNTAB(P2)	;NO, DISPATCH TO ROUTINE
	ULOAD	T1,LMRBP,(LM)	;GET BUFFER POINTER
	ULOAD	T2,LMMBL,(LM)	;AND LENGTH OF BUFFER
	PUSHJ	P,CHKBPT##	;ADDRESS CHECK BUFFER
	  JSUERR (,LMADC%)	;ADDRESS CHECK
	PJRST	@FUNTAB(P2)	;DISPATCH TO ROUTINE

>; END IFN FTOPS10
	SUBTTL	LLMOP - JSYS/UUO FunctionTable

FUNBUF==100000,,000000		;Function has secondary buffer
FUNTAB:	IFIW+FUNBUF+LPRDIR	;Ethernet Loop Direct
	IFIW+FUNBUF+LPRAST	;Ethernet Loop Assisted
	IFIW+FUNBUF+LPRRPY	;Ethernet Loop Read Reply
	IFIW LPRAIC		;Ethernet Loop Assign Interrupt Channel
	IFIW LPRABT		;Ethernet Loop Abort
	IFIW LPRSTS		;Ethernet Loop Get Request Status
	IFIW RCRRID		;Remote Console Read Identity
	IFIW RCRRCT		;Remote Console Read Counters
	IFIW RCRIDS		;Remote Console Identify Self
	IFIW RCRRBT		;Remote Console Remote Boot
	IFIW+FUNBUF+RCRRPY	;Remote Console Read Reply
	IFIW RCRRSV		;Reserve Remote Console
	IFIW RCRREL		;Release Remote Console
	IFIW+FUNBUF+RCRSND	;Send Console Command
	IFIW+FUNBUF+RCRPOL	;Console Response Poll
	IFIW RCRAIC		;Assign Interrupt channel
	IFIW RCRABT		;Abort Request
	IFIW RCRSTS		;Remote Console Check Request Status
	IFIW RCRADR		;Obtain Ethernet Addresses
	LMTBMX==.-FUNTAB	;Maximum Table Entry
	SUBTTL Loop Protocol Requestor -- LPRDIR - Ethernet Loop Direct

;LPRDIR - Perform Ethernet Loop Direct Loopback Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block address
;	SB/ SV Block address
;	CALL LPRDIR
;	 Error Return
;	Normal Return
;Changes T1,T2
;	RB/ Request Block address
;
	SWAPCD
LPRDIR:	CALL LRQINI		;Initialize Protocol Request Block
	  RETBAD		;If failed...
	CALL LPHDRI		;Initialize loopback message header
	LOAD T1,UNCAR,+SV.IXB(SB) ;Get HI order Channel Physical Address bytes
	LOAD T2,UNCAR,+<SV.IXB+1>(SB) ;Get LO order CPA
	CALL LPHDRF		;Create forward data packet
	CALL LPHDRN		;Create reply data packet
				;Set up destination address
	ULOAD T2,LMDST,(LM)	;Get 1st word of destination address
	STOR T2,RBDST,(RB)	;Store in RB
	ULOAD T2,LMDST,+1(LM)	;Get 2nd word of destination address
	STOR T2,RBDST,+1(RB)	;Store in RB
	CALL XMTREQ		;Transmit the request message
	 RETBAD			;If failed...
	RETSKP			;Success - RETURN from LPRDIR

;END of Routine LPRDIR

	SUBTTL Loop Protocol Requestor -- LPRAST - Ethernet Loop Assisted

;LPRAST - Perform Ethernet Loop Assisted Loopback Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL LPRAST
;	 Error Return
;	Normal Return
;Changes T1,T2
;	RB/ Request Block address
;

	SWAPCD
LPRAST:	CALL LRQINI		;Initialize Protocol Request Block
	  RETBAD		;If failed...
	CALL LPHDRI		;Initialize loopback message header
	ULOAD T3,LMHLP,(LM)	;Get the assistance level
	CAIE T3,.LMRCV
	IFSKP.			;Do receive assistance
	  ULOAD T2,LMDST,(LM)	;Get destination address
	  STOR T2,RBDST,(RB)	;Store in RB
	  ULOAD T2,LMDST,+1(LM)
	  STOR T2,RBDST,+1(RB)
	  ULOAD T1,LMAST,(LM)	;Get assistance address
	  ULOAD T2,LMAST,+1(LM)
	  CALL LPHDRF		;Create forward data packet
	ELSE.			;Do transmit or full assistance
	  ULOAD T2,LMAST,(LM)	;Get assistance address
	  STOR T2,RBDST,(RB)	;Store in RB
	  ULOAD T2,LMAST,+1(LM)
	  STOR T2,RBDST,+1(RB)
	  ULOAD T1,LMDST,(LM)	;Get destination address
	  ULOAD T2,LMDST,+1(LM)
	  CAIN T3,.LMXMT
	  IFSKP.
	    CAIE T3,.LMFUL
	    IFSKP.		;Do full assistance
	      CALL LPHDRF	;Create forward data packet
	      ULOAD T1,LMAST,(LM) ;Get assistance address
	      ULOAD T2,LMAST,+1(LM)
	      CALL LPHDRF	;Create forward data packet
	    ELSE.		;Invalid assistance level
	      RETBAD
	    ENDIF.
	  ELSE.			;Do transmit assistance
	    CALL LPHDRF		;Create forward data packet
	  ENDIF.
	ENDIF.
	LOAD T1,UNCAR,+SV.IXB(SB) ;Get HI order Channel Physical Address bytes
	LOAD T2,UNCAR,+<SV.IXB+1>(SB) ;Get LO order CPA
	CALL LPHDRF		;Create forward data packet
	CALL LPHDRN		;Create reply data packet
	CALL XMTREQ		;Transmit the request message
	 RETBAD			;If failed...
	RETSKP			;Success - RETURN from LPRAST

;END of Routine LPRAST

	SUBTTL Loop Protocol Requestor -- LPHDRI - Loopback Message Header Initialization

;LPHDRI - Initialize the header portion of a loopback request message
;
;Call:	RB/ Request Block address
;	CALL LPHDRI
;	Normal Return MS/ Loop header MSD address
;Changes T1,MS
;

	SWAPCD
LPHDRI:				;Entry
	;Set skip count to zero

	MOVEI T1,0		;Skip count zero
	XCALLRET (XCDSEC,DNP2BY) ;Write into message and RETURN from LPHDRI

;END of Routine LPHDRI

	SUBTTL Loop Protocol Requestor -- LPHDRF - Loopback Message Header Forward Packet

;LPHDRF - Create Loopback Message Forward Packet
;
;Call:	T1/ Bytes 0-3 of Ethernet Address
;	T2/ Bytes 4,5 of Ethernet Address
;	MS/ Loop header MSD address
;	CALL LPHDRF
;	Normal Return
;Changes T1,T2
;

	SWAPCD
LPHDRF:	SAVEAC <P1,P2>		;Preserve some ACs
	DMOVE P1,T1		;Save Hi and LO order bytes

	;Set function code to 'forward data' (02)

	MOVEI T1,2		;Function code 02
	XCALL (XCDSEC,DNP2BY)	;Write into message

	;Store our Ethernet address as forward address

	MOVE T1,P1		;Get Hi Order 4 bytes
	MOVE T2,P2		;Get Lo Order 2 bytes
	XCALL (XCDSEC,DNPENA)	;Store address in message

	RET			;RETURN from LPHDRF

;END of Routine LPHDRF

	SUBTTL Loop Protocol Requestor -- LPHDRN - Loopback Message Header Reply and Request Number

;LPHDRN - Create Loopback Reply Packet
;
;Call:	MS/ MSD address
;	RB/ Request Block address
;	CALL LPHDRN
;	Normal Return
;Changes T1
;

	SWAPCD
LPHDRN:				;Entry

	;Set next function code to 'reply data' (01)

	MOVEI T1,1		;Function code 01
	XCALL (XCDSEC,DNP2BY)	;Write into message

	;Set receipt number

	LOAD T1,RBRNO,(RB)	;Get receipt number from RB
	XCALL (XCDSEC,DNP2BY)	;Write into message

	RET			;RETURN from LPHDRN

;END of Routine LPHDRN

	SUBTTL Loop Protocol Requestor -- LPRRPY - Read Loop Reply

;LPRRPY -  Read Loop Reply
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL LPRRPY
;	 Error Return
;	Normal Return
;Changes T1,T2,MS

	SWAPCD
LPRRPY: CALLRET RCRRPY		;Same function as RCRRPY

;END of Routine LPRRPY

	SUBTTL Loop Protocol Requestor -- LPRAIC - Assign Interrupt Channel

;LPRAIC - Assign Interrupt Channel
;
; Nota bene: This function was originally planned but later
; implemented by LPRAIC bit in request. It's not needed but left
; in as a dinosaur.
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Flags, Interrupt Channel
;	SB/ SV Block address
;	CALL LPRAIC
;	 Error Return
;	Normal Return
;Changes T1 

	SWAPCD
LPRAIC:				;Ethernet Loop Assign Interrupt Channel
	JSUERR (ARGX02,)	;Error return 'Invalid Function' from LPRAIC

;END of Routine LPRAIC

	SUBTTL Loop Protocol Requestor -- LPRABT - Ethernet Loop Abort

;LPRABT - Perform Ethernet Loop Abort Loopback Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL LPRABT
;	 Error Return
;	Normal Return
;Changes T1,T2,RB

	SWAPCD
LPRABT:	ULOAD T1,LMREQ,(LM)	;Get the Receipt Number of the request
	MOVE T2,SB		;Pass address of SVB
	CALL LPSSXQ		;Search queue for RB for this request
	  JSUERR (LLMX04,)	;Request does not exist
	MOVE RB,T2		;Make RB Address safe
	MOVE T1,RB		;Get address of RB
	MOVE T2,SB		;Pass address of SVB
	CALL LPSRMQ		;Remove it from queue
	  JFCL			;Failed...
	LOAD T1,RBMSI,(RB)	;Get address of input MSD and buffer
	CAIN T1,0		;An MSD there?
	IFSKP.			;Yes...
	  XCALL (XCDSEC,DNFWDS)	;Release the buffer
	ENDIF.
	MOVE T1,RB		;Get address of RB
	XCALL (XCDSEC,DNFWDS)	;Release the RB
	RETSKP			;Success - RETURN from LPRABT

;END of Routine LPRABT

	SUBTTL Loop Protocol Requestor -- LPRSTS - Get Request Status

;LPRSTS - Get Request Status of Loop Request
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL LPRSTS
;	 Error Return
;	Normal Return
;Changes T1,T2

	SWAPCD
LPRSTS:	ULOAD T1,LMREQ,(LM)	;Get the Receipt Number of the request
	MOVE T2,SB		;Pass address of SVB
	CALL LPSSXQ		;Search queue for RB for this request
	  JSUERR (LLMX04,)	;Request does not exist
	MOVE RB,T2		;Get RB address
	LOAD T1,RBFLG,(RB)	;Get flags, Assume RB%FTI
	TXNN T1,<RB%FRC!RB%FRF>	;Receive done?
	IFSKP.			;And...
	TXNN T1,<RB%FTC!RB%FTF>	;Transmit done?
	ANSKP.			;Yes...
	  MOVX T1,.RQCMP	;Then request is complete to user
	ELSE.			;No...
	  MOVX T1,.RQPND	;Then its pending to user
	ENDIF.
	USTOR T1,LMRTC,(LM)	;Store the new status and flags
	RETSKP			;Success - RETURN from LPRSTS

;END of Routine LPRSTS

	SUBTTL Loop Protocol Requestor -- LRQINI - Request Block Initialization

;LRQINI - Perform Ethernet Protocol Requestor Request Block Initialization
;
;Call:	LM/ Argument Block Address
;	CALL LRQINI
;	 Error Return
;	Normal Return RB/ Request Block Address
;Changes T1,T2,RB

	SWAPCD
LRQINI:				;Request Block Initialization
	MOVEI T1,RB.LEN		;Obtain and Initialize a Request Block (RB)
	XCALL (XCDSEC,DNGWDZ)	;Get a clean block for RB
	  JSUERR (MONX07,)	;Failed... Return with Error Code
	MOVE RB,T1		;Save address of RB
				;Initialize the state in RB
	MOVX T1,.RQINV		;Set request state invalid
	STOR T1,RBSTT,(RB)
IFN FTOPS20,<
	MOVE T1,JOBNO		;Get Users Job Number
	STOR T1,RBJOB,(RB)	;Store in RB
	MOVE T1,FORKX		;Get Users Fork Number
	STOR T1,RBFRK,(RB)	;Store in RB
>; END IFN FTOPS20
IFN FTOPS10,<
	MOVE T1,.CPJCH##	;Get current JCH
	STOR T1,RBJCH,(RB)	;Store in RB
>; END IFN FTOPS10
				;Initialize MSD chain in RB
	XMOVEI MS,LH.MSD(RB)	;Get address of Header MSD
	XMOVEI T1,LD.MSD(RB)	;Get address of User Data MSD
	MOVX T2,LHH.LN		;Length of LH buffer
	XMOVEI T3,LH.DAT(RB)	;Get address of LH buffer
	CALL MSDINI		;Initialize MSD

	;Store a special ID for transmit complete

	MOVX T1,'LLM'		;Identifier for LLMOP
	STOR T1,LHIDD,(RB)	;Store special ID

	;Copy info from users argument block to RB

	ULOAD T2,LMCID,(LM)	;Get channel id
	STOR T2,RBCID,(RB)	;Store in RB
IFN FTOPS20,<
	ULOAD T1,LMAIC,(LM)	;Interrupt channel assigned?
	STOR T1,RBAIC,(RB)	;Store interrupt assigned flag
	ULOAD T1,LMICH,(LM)	;Get the interrupt channel
	STOR T1,RBICH,(RB)	;Store Interrupt Channel number
>; END IFN FTOPS20

	;Initialize User Data MSD

	SETZRO MDALL,+LD.MSD(RB) ;Clear allocated length, not relevant here
	SETZRO MDALA,+LD.MSD(RB) ;Clear allocated address, not relevant here

	;Set receipt number in RB

	NOSKED			;Interlock the SVB from other processes
	LOAD T2,RBCID,(RB)	;Get channel number
	IMULI T2,SV.LEN		;Get offset of SVB for this channel
	XMOVEI SB,LPSSVB(T2)	;Get address of SV block for LPS
	CALL SETRNO		;Set up receipt number
	OKSKED			;Let go of SVB interlock

;Build Request Block (RB) from User's Argument Block

	;Store receipt number in user argument block

	LOAD T2,RBRNO,(RB)	;Get receipt assigned to this request
	USTOR T2,LMREQ,(LM)	;Give to user as Request Number

	;Set up MSD for user data

	ULOAD T1,LMMBL,(LM)	;Get length of user loopback data
	STOR T1,MDBYT,+LD.MSD(RB) ;Store bytes written in user data MSD

	;*****
	;
	; Convert users Loopback data pointer to user virtual address.
	; MAP User Virtual Address to Physical page number and LOCK
	; the page down in resident memory. Store the Physical address
	; in the MSD for use by the driver. LPSXTC will UNLOCK the page
	; when Transmit is complete.
	;
	;*****

	ULOAD T1,LMRBP,(LM)	;Get users Loopback data pointer
	STOR T1,MDPTR,+LD.MSD(RB) ;Store users virtual pointer in MSD
	CALL CNVPTR		;Convert User pointer to address
	 RET			;Illegal Ptr, Return with error
	STOR T1,MDAUX,+LD.MSD(RB) ;Store indexed pointer
	STOR T2,MDALA,+LD.MSD(RB) ;Store users virtual address
IFN FTOPS20,<
	MOVE T1,T2		;Make copy of virtual address
	TXO T1,<1B0>		;Set bit 0 to indicate user virtual
	CALL MLKMA		;Lock the page, returning core page number
	LSH T1,WID(777)		;Convert page to physical address
	LOAD T2,MDALA,+LD.MSD(RB) ;Get users virtual address
	TXZ T2,<777777,,777000>	;Get just the offset
	IOR T1,T2		;Set offset into physical page
	STOR T1,MDALA,+LD.MSD(RB) ;Store physical address
	MOVX T1,VMC.NO		;Get code for Physical Address
	STOR T1,MDVMC,+LD.MSD(RB) ;Store it in MSD
>; END IFN FTOPS20
IFN FTOPS10,<
	XMOVEI T1,LD.MSD(RB)	;Get address of MSD
	CALL MAKMBF		;Create a monitor buffer
	  RET			;Error
>; END IFN FTOPS10
	RETSKP			;Success - RETURN from LRQINI

;END of Routine LRQINI

	SUBTTL Remote Console Protocol Requestor -- RCRRID - Read Identity

;RCRRID - Perform Read Identity Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRRID
;	 Error Return
;	Normal Return
;Changes 

	SWAPCD
RCRRID:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	CALL SETRNO		;Set up receipt number
	MOVX T1,FCRQID		;Get Request ID function code
	XCALL (XCDSEC,DNP1BY)	;Store function code in message
	MOVX T1,0
	XCALL (XCDSEC,DNP1BY)	;Store reserved byte in message
	LOAD T1,RBRNO,(RB)	;Get Receipt Number of this request
	XCALL (XCDSEC,DNP2BY)	;Store in message
	CALL XMTREQ		;Transmit the request message
	 RETBAD			;If failed...
	RETSKP			;Success - RETURN from RCRRID

;END of Routine RCRRID

	SUBTTL Remote Console Protocol Requestor -- RCRRCT - Read Counters

;RCRRCT - Perform Read Counters Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRRCT
;	 Error Return
;	Normal Return
;Changes 

	SWAPCD
RCRRCT:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	CALL SETRNO		;Set up receipt number
	MOVX T1,FCRQCT		;Get Request Counters function code
	XCALL (XCDSEC,DNP1BY)	;Store function code in message
	LOAD T1,RBRNO,(RB)	;Get Receipt Number of this request
	XCALL (XCDSEC,DNP2BY)	;Store in message
	CALL XMTREQ		;Transmit the request message
	 RETBAD			;If failed...
	RETSKP			;Success - RETURN from RCRRCT

;END of Routine RCRRCT

	SUBTTL Remote Console Protocol Requestor -- RCRIDS - Identify Self

;RCRIDS - Perform Identify Self Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRIDS
;	 Error Return
;	Normal Return
;Changes 

	SWAPCD
RCRIDS:				;Remote Console Identify Self
	CALL RCSIDS		;Same as server
	RETSKP			;Success - RETURN from RCRIDS

;END of Routine RCRIDS

	SUBTTL Remote Console Protocol Requestor -- RCRRBT - Remote Boot

;RCRRBT - Perform Remote Boot Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRRBT
;	 Error Return
;	Normal Return
;Changes 

	SWAPCD
RCRRBT:
IFN FTOPS10,<
	ULOAD T1,LMCFB,(LM)	;Get Control Information
	TXNN T1,LM%BDV		;Specify boot device?
	IFSKP.			;Yes, address check string
	  ULOAD T1,LMDID,(LM)	;Get byte pointer to string
	  MOVEI T2,^D18		;And maximum string length
	  PUSHJ P,CHKBPT##	;Check byte pointer
	    JSUERR (,LMADC%)	;Address check
	ENDIF.
	ULOAD T1,LMSID,(LM)	;Get byte pointer to string
	MOVEI T2,^D18		;And maximum string length
	PUSHJ P,CHKBPT##	;Check byte pointer
	  JSUERR (,LMADC%)	;Address check
>; END IFN FTOPS10
	SAVEAC <WK>		;Save preserved work AC
	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	MOVX T1,FCBOOT		;Get Remote Boot function code
	XCALL (XCDSEC,DNP1BY)	;Store function code in message
	ULOAD T1,LMPWD,(LM)	;Get Verification Password
	XCALL (XCDSEC,DNPHIO)	;Use this also for password bytes 0,1,2,3
	ULOAD T1,LMPWD,+1(LM)	;And bytes 4,5,6,7 also
	XCALL (XCDSEC,DNPHIO)
	ULOAD T1,LMCFB,(LM)	;Get Control Information
	XCALL (XCDSEC,DNP2BY)	;Store fields in message
	TXNN T1,LM%BDV		;Boot Device Specified?
	IFSKP.			;Yes, put Device Id field in message
	  MOVX T1,1		;Copy just first byte (count)
	  ULOAD T2,LMDID,(LM)	;Get Device Id (Pointer)
	  XCALL (XCDSEC,DNCU2M)	;Copy from user buffer to message
	  OPSTR <LDB T1,>,MDPTR,(MS) ;Get the count byte back
	  CAIG T1,^D17		;Ensure C-17 field
	  IFSKP.
	    XCALL (XCDSEC,DNBKBY) ;Back up over count byte
	    MOVX T1,^D17	;Get maximum count
	    XCALL (XCDSEC,DNP1BY) ;Put count in message
	  ENDIF.
	  ULOAD T2,LMDID,(LM)	;Get Device Id (Pointer) again
	  IBP T2		;Bump pointer past count byte
	  XCALL (XCDSEC,DNCU2M)	;Copy from user buffer to message
	ENDIF.
	MOVX T1,1		;Copy just first byte (count)
	ULOAD T2,LMSID,(LM)	;Get Software Id (Pointer)
	XCALL (XCDSEC,DNCU2M)	;Copy from user buffer to message
	OPSTR <LDB T1,>,MDPTR,(MS) ;Get the count byte back
	CAILE T1,277		;Is it negative? (-n for generic form)
	IFSKP.			;No, T1 has length of Id field
	  CAIG T1,^D17		;Ensure C-17 field
	  IFSKP.		;Field too long...
	    XCALL (XCDSEC,DNBKBY) ;Back up over count byte
	    MOVX T1,^D17	;Get maximum count
	    XCALL (XCDSEC,DNP1BY) ;Put count in message
	  ENDIF.
	  ULOAD T2,LMSID,(LM)	;Get Software Id (Pointer) again
	  IBP T2		;Bump pointer past count byte
	  XCALL (XCDSEC,DNCU2M)	;Copy from user buffer to message
	ENDIF.

	SETONE RBABT,(RB)	;Force interrupt level to release RB
	CALL XMTRCM		;Transmit the request message
	 RETBAD			;If failed...
	RETSKP			;Success - RETURN from RCRRBT

;END of Routine RCRRBT

	SUBTTL Remote Console Protocol Requestor -- RCRRPY - Read Reply

;RCRRPY - Read Remote Console Requestor Reply Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRRPY
;	 Error Return
;	Normal Return
;Changes

	SWAPCD
RCRRPY:	ULOAD T1,LMREQ,(LM)	;Get Request Number
	MOVE T2,SB		;Pass address of SVB
	CALL LPSSXQ		;Search RB queue
	  JSUERR (LLMX04,)	;Not found
	MOVE RB,T2		;Save RB address in RB
	LOAD T1,RBSTT,(RB)	;Get state
	CAIN T1,.RQCMP		;Complete?
	IFSKP.			;No..., Dismiss user until reply arrives
IFN FTOPS20,<
	 LOAD T1,RBRNO,(RB)	;Get request number
	 HRL T1,T1		;In left half
	 HRRI T1,RCRWAI		;Wait routine address in right half
	 MOVEM RB,FKSTA2(FX)	;Store RB address for use by SCHED test routine
	 MDISMS			;T1/ Request #,,Routine Addr
>; END IFN FTOPS20
IFN FTOPS10,<
	 CALL RBWAIT		;Wait for RB completion
>; END IFN FTOPS10
	ENDIF.
	CALL DEQMSD		;Dequeue an MSD
	  JSUERR (LLMX99,)	;None there...
	XCALL (XCDSEC,DNRPOS)	;Get length of user data
	ULOAD T2,LMMBL,(LM)	;Get User Max Buffer Length
	CAMLE T1,T2		;Will it fit in buffer?
	  MOVE T1,T2		;No, truncate  **** Or RETBAD? *****
	USTOR T1,LMRML,(LM)	;Return received length to user
	ULOAD T2,LMRBP,(LM)	;Pass users command response buffer pointer
	XCALL (XCDSEC,DNCM2U)	;Move data to user
	  JSUERR (ATSX17,)	;Failed, Why?... BUG?

	XMOVEI UN,MD.LEN(MS)	;Get address of 'shadow' UN block
	LOAD T1,UNSAD,(UN)	;Get the source address
	USTOR T1,LMSRC,(LM)	;Give to user
	LOAD T1,UNSAD,+1(UN)
	USTOR T1,LMSRC,+1(LM)

	TMNN RBMSI,(RB)		;Is there another MSD available?
	IFSKP.			;Yes...
	  SETO T1,		;Set the 'more replies flag'
	  USTOR T1,LMMRF,(LM)	; in users flags word
	ELSE.			;No...
	  MOVE T1,RB		;Get address of RB
	  MOVE T2,SB		;Pass address of SVB
	  CALL LPSRMQ		;Remove it from queue
	    JFCL		;Failed...
	  MOVE T1,RB		;Get address of RB
	  XCALL (XCDSEC,DNFWDS)	;Release the RB
	ENDIF.
	MOVE T1,MS		;Get address of input MSD and receive buffer
	XCALL (XCDSEC,DNFWDS)	;Release the MSD and buffer
	MOVE T1,SB		;Pass SV block address
	CALL PSTBUF		;Post a receive buffer
	  NOP			;Ignore failure
	RETSKP			;Success - RETURN from RCRRPY

;Wait routine for scheduler, called with Request # in T1
; RB address in FKSTA2, FX with fork table index

	RESCD
IFN FTOPS20,<
RCRWAI:	MOVE T2,FKSTA2(FX)	;Get RB address
	OPSTR <CAME T1,>,RBRNO,(T2) ;This the right request?
	  RET			;No...
	LOAD T1,RBSTT,(T2)	;Get current request state
	CAIE T1,.RQCMP		;Is Request Complete?
	 RET			;No, wait some more
	RETSKP			;Yes, let it go
>; END IFN FTOPS20

;END of Routine RCRRPY

	SUBTTL Remote Console Protocol Requestor -- RCRSTS - Check Request Status

;RCRSTS - Perform Check Request Status Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRSTS
;	 Error Return
;	Normal Return
;Changes

	SWAPCD
RCRSTS:	ULOAD T1,LMREQ,(LM)	;Get the Receipt Number of the request
	MOVE T2,SB		;Pass address of SVB
	CALL LPSSXQ		;Search queue for RB for this request
	  JSUERR (LLMX04,)	;Request does not exist

	MOVE RB,T2		;Get RB address
	LOAD T1,RBFLG,(RB)	;Get flags
				;Assume RB%FTI
	TXNN T1,<RB%FRC!RB%FRF>	;Receive done?
	IFSKP.			;And...
	TXNN T1,<RB%FTC!RB%FTF>	;Transmit done?
	ANSKP.			;Yes...
	  MOVX T1,.RQCMP	;Then request is complete to user
	ELSE.			;No...
	  MOVX T1,.RQPND	;Then its pending to user
	ENDIF.
	USTOR T1,LMRTC,(LM)	;Store the new status and flags
	RETSKP			;Success - RETURN from RCRSTS

;END of Routine RCRSTS

	SUBTTL Remote Console Protocol Requestor -- RCRADR - Get Addresses

;RCRADR - Obtain KLNI Ethernet Local Addresses
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRADR
;	Normal Return Always
;Changes

	SWAPCD
RCRADR:	XMOVEI UN,SV.IXB(SB)	;Get address of UN block
	MOVX T1,NU.RCI		;Get Read Channel Info function code
	MOVE T2,UN		;Pass address of UN Block
	SETZRO UNBSZ,(UN)	;Indicate no aux buffer
	CALL DLLUNI		;Call DLL User to NI Interface
	  NOP			;Ignore error
	LOAD T1,UNHAD,(UN)	;Get hardware address
	LOAD T2,UNHAD,+1(UN)
	USTOR T1,LMHWA,(LM)	;Store the hardware address
	USTOR T2,LMHWA,+1(LM)
	LOAD T1,UNCAR,(UN)	;Get the current physical address
	LOAD T2,UNCAR,+1(UN)
	USTOR T1,LMPYA,(LM)	;Store the physical address
	USTOR T2,LMPYA,+1(LM)
	RETSKP			;Success - RETURN from RCRADR

;END of Routine RCRADR

	SUBTTL Remote Console Protocol Requestor -- RCRRSV - Reserve Remote Console

;RCRRSV - Perform Reserve Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRRSV
;	 Error Return
;	Normal Return
;Changes 

	SWAPCD
RCRRSV:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	MOVX T1,FCRSVC		;Get Reserve Console function code
	XCALL (XCDSEC,DNP1BY)	;Store function code in message

	ULOAD T1,LMPWD,(LM)	;Get Verification Password
	XCALL (XCDSEC,DNPHIO)	;Use this also for password bytes 0,1,2,3
	ULOAD T1,LMPWD,+1(LM)	;And bytes 4,5,6,7 also
	XCALL (XCDSEC,DNPHIO)

	SETONE RBABT,(RB)	;Force interrupt level to release RB
	CALL XMTRCM		;Transmit the request message
	 RETBAD			;If failed...
	RETSKP			;Success - RETURN from RCRRSV

;END of Routine RCRRSV

	SUBTTL Remote Console Protocol Requestor -- RCRREL - Release Remote Console

;RCRREL - Perform Release Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRREL
;	 Error Return
;	Normal Return
;Changes 

	SWAPCD
RCRREL:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	MOVX T1,FCRELC		;Get Release Console function code
	XCALL (XCDSEC,DNP1BY)	;Store function code in message

	SETONE RBABT,(RB)	;Force interrupt level to release RB
	CALL XMTRCM		;Transmit the request message
	 RETBAD			;If failed...
	RETSKP			;Success - RETURN from RCRREL

;END of Routine RCRREL

	SUBTTL Remote Console Protocol Requestor -- RCRSND - Send Console Command

;RCRSND - Perform Send Console Command Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRSND
;	 Error Return
;	Normal Return
;Changes 

	SWAPCD			;Send Console Command
RCRSND:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	CALL SCCINI		;Set up RB for Console Command data
	  RETBAD
	XMOVEI T1,CH.MSD(RB)	;Get address of Console header MSD
	XCALL (XCDSEC,DNPINI)	;Initialize for output
	MOVX T1,FCCCAP		;Get Console Command and Poll function code
	XCALL (XCDSEC,DNP1BY)	;Store function code in message
	ULOAD T1,LMCCF,(LM)	;Get message number and command break flag
	XCALL (XCDSEC,DNP1BY)	;Store Control Flags
	CALL XMTREQ		;Transmit the request message
	 RETBAD			;If failed...
	RETSKP			;Success - RETURN from RCRSND

;END of Routine RCRSND

	SUBTTL Remote Console Protocol Requestor -- RCRPOL - Console Response Poll

;RCRPOL - Perform Console Response Poll Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRPOL
;	 Error Return
;	Normal Return
;Changes 

	SWAPCD
RCRPOL:				;Console Response Poll
	ULOAD T1,LMREQ,(LM)	;Get Request Number
	MOVE T2,SB		;Pass address of SVB
	CALL LPSSXQ		;Search RB queue
	  JSUERR (LLMX04,)	;Not found
	MOVE RB,T2		;Save RB address in RB
	LOAD T1,RBSTT,(RB)	;Get state
	CAIN T1,.RQCMP		;Complete?
	IFSKP.			;No..., Dismiss user until reply arrives
IFN FTOPS20,<
	 LOAD T1,RBRNO,(RB)	;Get request number
	 HRL T1,T1		;In left half
	 HRRI T1,RCRWAI		;Wait routine address in right half
	 MOVEM RB,FKSTA2(FX)	;Store RB address for use by SCHED test routine
	 MDISMS			;T1/ Request #,,Routine Addr
>; END IFN FTOPS20
IFN FTOPS10,<
	 CALL RBWAIT		;Wait for RB completion
>; END IFN FTOPS10
	ENDIF.
	LOAD MS,RBMSI,(RB)	;Get address of input MSD
	XCALL (XCDSEC,DNG1BY)	;Get control flags byte
	  MOVEI T1,0		;If short message, set flags to zero
	USTOR T1,LMRCF,(LM)	;Store Console Response Control Flags
	XCALL (XCDSEC,DNRPOS)	;Get length of user data
	CAIGE T1,0		;If negative?
	  SETZI T1,0		;  Make it zero
	ULOAD T2,LMMBL,(LM)	;Get User Max Buffer Length
	CAMLE T1,T2		;Will it fit in buffer?
	  MOVE T1,T2		;No, truncate  **** Or RETBAD? *****
	USTOR T1,LMRML,(LM)	;Return received length to user
	ULOAD T2,LMRBP,(LM)	;Pass users command response buffer pointer
	XCALL (XCDSEC,DNCM2U)	;Move data to user
	  JSUERR (ATSX17,)	;Failed, Why?... BUG?
	MOVE T1,RB		;Get address of RB
	MOVE T2,SB		;Pass address of SVB
	CALL LPSRMQ		;Remove it from queue
	  JFCL			;Failed...
	LOAD T1,RBMSI,(RB)	;Get address of input MSD and receive buffer
	XCALL (XCDSEC,DNFWDS)	;Release the MSD and buffer
	MOVE T1,RB		;Get address of RB
	XCALL (XCDSEC,DNFWDS)	;Release the RB
	MOVE T1,SB		;Pass SV block address
	CALL PSTBUF		;Post a receive buffer
	  NOP			;Ignore failure

	RETSKP			;Success - RETURN from RCRPOL

;END of Routine RCRPOL

	SUBTTL Remote Console Protocol Requestor -- RCRAIC - Assign Interrupt Channel

;RCRAIC - Assign Interrupt Channel Remote Console Requestor Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRAIC
;	 Error Return
;	Normal Return
;Changes T1

	SWAPCD
RCRAIC:				;Assign Interrupt Channel
IFN FTOPS20,<
	ULOAD T1,LMAIC,(LM)
	SKIPN T1		;Assigning channel for unsolicited SID's?
	IFSKP.			;Yes...
	  NOSKED		;Interlock the SVB
	  OPSTR <SKIPE>,SVCFN,(SB) ;Already assigned? If so, don't allow.
	  IFSKP.		;Not yet assigned, give it to this process
	    ULOAD T1,LMICH,(LM)	;Get the interrupt channel
	    CALL CHKCHL		;Verify it's validity
	    IFSKP.		;If it's OK...
	      STOR T1,SVICH,(SB) ;Store the Configurator Interrupt Channel
	      MOVE T1,FORKX
	      STOR T1,SVCFN,(SB) ;Store Configurator fork index
	      OKSKED
	    ELSE.		;If it's an invalid channel...
	      OKSKED
	      RETBAD		;Return error from CHKCHL
	    ENDIF.
	  ELSE.			;If it's already been assigned...
	    OKSKED
	    RETBAD (LLMX06)	;Give 'already assigned' error return
	  ENDIF.
	ENDIF.
>; END IFN TOPS20
	RETSKP			;Success - RETURN from RCRAIC

;END of Routine RCRAIC

	SUBTTL Remote Console Protocol Requestor -- RCRABT - Abort Request

;RCRABT - Abort Remote Console Request Function
;
;Call:	T1/ LLMOP% Function Code
;	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL RCRABT
;	 Error Return
;	Normal Return
;Changes T1,T2

	SWAPCD
RCRABT:	ULOAD T1,LMREQ,(LM)	;Get the Receipt Number of the request
	MOVE T2,SB		;Pass address of SVB
	CALL LPSSXQ		;Search queue for RB for this request
	  JSUERR (LLMX04,)	;Request does not exist
	MOVE RB,T2		;Make RB Address safe
	MOVE T1,RB		;Get address of RB
	MOVE T2,SB		;Pass address of SVB
	CALL LPSRMQ		;Remove it from queue
	  JFCL			;Failed...

	ETHLOK			; Absolutely, positively, no interrupts
	LOAD T1,RBSTT,(RB)	; Get state
	CAIN T1,.RQCMP		; Did this request complete?
	IFSKP.			; Nope, abort this function
	  SETONE RBABT,(RB)	; Abort when NISRV returns the buffer
	  ETHULK		; Enable interrupts
	  RETSKP		; Return success
	ENDIF.
	ETHULK			; Re-enable interrupts

	LOAD T1,RBMSI,(RB)	;Get address of input MSD and buffer
	CAIN T1,0		;An MSD there?
	IFSKP.			;Yes...
	  XCALL (XCDSEC,DNFWDS)	;Release the buffer
	ENDIF.
	MOVE T1,RB		;Get address of RB
	XCALL (XCDSEC,DNFWDS)	;Release the RB
	RETSKP			;Success - RETURN from RCRABT

;END of Routine RCRABT

	SUBTTL Remote Console Protocol Requestor -- CRQINI - Request Block Initialization

;CRQINI - Perform Ethernet Protocol Requestor Request Block Initialization
;
;Call:	LM/ Argument Block Address
;	SB/ SV Block address
;	CALL CRQINI
;	 Error Return
;	Normal Return RB/ Request Block Address
;Changes T1,T2,RB

	SWAPCD			;Request Block Initialization
CRQINI:	MOVEI T1,RB.LEN		;Obtain and Initialize a Request Block (RB)
	XCALL (XCDSEC,DNGWDZ)	;Get a clean block for RB
	  JSUERR (MONX07,)	;Failed... Return with Error Code
	MOVE RB,T1		;Save address of RB
				;Initialize the state in RB
	MOVX T1,.RQINV		;Set request state invalid
	STOR T1,RBSTT,(RB)
IFN FTOPS20,<
	MOVE T1,JOBNO		;Get Users Job Number
	STOR T1,RBJOB,(RB)	;Store in RB
	MOVE T1,FORKX		;Get Users Fork Number
	STOR T1,RBFRK,(RB)	;Store in RB
>; END IFN FTOPS20
IFN FTOPS10,<
	MOVE T1,.CPJCH##	;Get current JCH
	STOR T1,RBJCH,(RB)	;Store in RB
>; END IFN FTOPS10
				;Initialize MSD chain in RB
	XMOVEI MS,CH.MSD(RB)	;Get address of Header MSD
	SETZ T1,		;No Data MSD
	MOVX T2,RCH.LN		;Length of CH buffer
	XMOVEI T3,CH.DAT(RB)	;Get address of CH buffer
	CALL MSDINI		;Initialize MSD

	;Store a special ID for transmit complete

	MOVX T1,'LLM'		;Identifier for LLMOP
	STOR T1,CHIDD,(RB)	;Store special ID

	;Copy info from users argument block to RB

	ULOAD T2,LMCID,(LM)	;Get channel id
	STOR T2,RBCID,(RB)	;Store in RB
IFN FTOPS20,<
	ULOAD T1,LMAIC,(LM)	;Interrupt channel assigned?
	STOR T1,RBAIC,(RB)	;Store interrupt assigned flag
	ULOAD T1,LMICH,(LM)	;Get the interrupt channel
	STOR T1,RBICH,(RB)	;Store Interrupt Channel number
>; END IFN FTOPS20
				;Set up destination in RB
	ULOAD T2,LMDST,(LM)	;Get 1st word of destination address
	STOR T2,RBDST,(RB)	;Store in RB
	ULOAD T2,LMDST,+1(LM)	;Get 2nd word of destination address
	STOR T2,RBDST,+1(RB)	;Store in RB
	RETSKP			;Success - RETURN from CRQINI

;END of Routine CRQINI

	SUBTTL Remote Console Protocol Requestor -- MSDINI - MSD Request Block Initialization

;MSDINI - MSD Request Block Initialization
;
;Call:	T1/ Address of Data MSD
;	T2/ Length of Header MSD Data Buffer
;	T3/ Address of Header MSD Data Buffer
;	MS/ Address of (1st) Header MSD
;	RB/ Request Block Address
;	CALL MSDINI
;	Normal Return Always
;Changes T1

MSDINI:	SWAPCD			;Request Block MSD Initialization
	STOR MS,RBMSO,(RB)	;Initialize MSD chain in RB
	STOR T1,MDNXT,(MS)	;Link Data MSD to Header MSD
	SETZRO MDNXT,(T1)	;Clear link field of Data MSD

	;Initialize Header MSD

	STOR T2,MDALL,(MS)	;Set allocated Header MSD Data Buffer size
	STOR T3,MDALA,(MS)	;Set address of Header MSD Data Buffer
	MOVX T1,VMC.XC		;Mark this as an EXEC context buffer
	STOR T1,MDVMC,(MS)	;Store it in MSD
	MOVE T1,MS		;Get address of Header MSD
	XCALL (XCDSEC,DNPINI)	;Initialize for output
	RET

	SUBTTL Remote Console Protocol Requestor -- SETRNO - Set Request Receipt Number

;SETRNO - Set Request Receipt Number in RB and User's argument block
;
;Call:	LM/ Argument Block Address
;	SB/ SV Block address
;	RB/ Request Block Address
;	CALL SETRNO
;	  Normal Return Always
;Changes T2

	SWAPCD			;Request Block Initialization
SETRNO:	LOAD T2,SVNXR,(SB)	;Get next receipt number
	STOR T2,RBRNO,(RB)	;Store in RB

	;Store receipt number in user argument block

	USTOR T2,LMREQ,(LM)	;Give to user as Request Number

	;Calculate the Next Receipt Number

	ADDI T2,1		;Increment receipt number
	TXNE T2,<1B<35-16>>	;Overflow 16 bits?
	  MOVEI T2,1		;Yes..., Start over again at 1
	STOR T2,SVNXR,(SB)	;Store updated receipt number
	RET			;Success - RETURN from SETRNO

;END of Routine SETRNO

	SUBTTL Remote Console Protocol Requestor -- SCCINI - ASCII Console Cxr Initialization

;SCCINI - Perform Initialization for Send Console Command
;
;Call:	LM/ Argument Block Address
;	SB/ SV Block address
;	RB/ Request Block Address
;	CALL SCCINI
;	 Error Return
;	Normal Return
;Changes T1,T2

	SWAPCD			;ASCII Console Carrier RB Initialization
SCCINI:	XMOVEI MS,CD.MSD(RB)	;Point to Command Data MSD
	STOR MS,MDNXT,+CH.MSD(RB) ;Link CD from CH
	SETZRO MDNXT,(MS)	;Clear link field to make CD the last MSD
	ULOAD T1,LMMBL,(LM)	;Get length of Command data
	STOR T1,MDBYT,(MS)	;Store bytes written in Command data MSD

	;*****
	;
	; Convert users data pointer to user virtual address.
	; MAP User Virtual Address to Physical page number and LOCK
	; the page down in resident memory. Store the Physical address
	; in the MSD for use by the driver. The Transmit Callback
	; routine will UNLOCK the page when Transmit is complete.
	;
	;*****

	ULOAD T1,LMRBP,(LM)	;Get Users Command data pointer
	STOR T1,MDPTR,(MS)	;Store User virtual pointer in MSD
	CALL CNVPTR		;Convert User pointer to address
	 RET			;Illegal Ptr, Return with error
	STOR T1,MDAUX,(MS)	;Store indexed pointer
	STOR T2,MDALA,(MS)	;Store users virtual address
IFN FTOPS20,<
	MOVE T1,T2		;Make copy of virtual address
	TXO T1,<1B0>		;Set bit 0 to indicate user virtual
	CALL MLKMA		;Lock the page, returning core page number
	LSH T1,WID(777)		;Convert page to physical address
	LOAD T2,MDALA,(MS)	;Get users virtual address
	TXZ T2,<777777,,777000>	;Get just the offset
	IOR T1,T2		;Set offset into physical page
	STOR T1,MDALA,(MS)	;Store physical address
	MOVX T1,VMC.NO		;Get code for Physical Address
	STOR T1,MDVMC,(MS)	;Store it in MSD
>; END IFN FTOPS20
IFN FTOPS10,<
	MOVE T1,MS		;Get address of MSD
	CALL MAKMBF		;Create a monitor buffer
	  RET			;Error
>; END IFN FTOPS10
;
;Hack a request number here as a special case for CONSOLE RESPONSE POLL.
;We use the low order portion of the destination Ethernet address. We
;can do this safely, since, there can be only one host node reserving
;the console on the remote node. Note, that this code overides what
;has already been done in CRQINI.
;

	LOAD T1,RBDST,+1(RB)	;Use low order bits of destination address
	LSH T1,-<^D36-^D16>
	STOR T1,RBRNO,(RB)	;Store in RB
	USTOR T1,LMREQ,(LM)
	RETSKP			;Success - RETURN from SCCINI

;END of Routine SCCINI

	SUBTTL Loop Protocol Requestor -- XMTREQ - Transmit MOP Request Message

;XMTREQ - Transmit LLMOP Request Message
;
;Call:	RB/ Request Block address
;	SB/ SV Block address
;	CALL XMTREQ
;	 Error Return
;	Normal Return
;Changes T1,T2
;

	SWAPCD
XMTREQ:	MOVE T1,RB		;Pass address of RB
	MOVE T2,SB		;Pass address of SVB
	CALL LLMQUE		;Queue RB on protocol server request queue
	MOVE T1,SB		;Pass SV Block address
	CALL PSTBUF		;Try to have a receive buffer ready
	  NOP			;Ignore failure
	CALL XMTRCM		;Transmit this MSD
	IFNSK.			;Failed...
	  MOVE T1,RB		;Get address of RB
	  MOVE T2,SB		;Pass address of SVB
	  CALL LPSRMQ		;Remove RB from Queue
	    JFCL		;Failed...
	  RETBAD		;Error - Pass error up
	ENDIF.
	RETSKP			;Success - RETURN from XMTREQ

;END of Routine XMTREQ

	SUBTTL Loop Protocol Requestor -- XMTRCM - Transmit MOP Remote Console Message

;XMTRCM - Transmit LLMOP Remote Console Message
;
; Send a Remote Console message when no response is expected.
;
;Call:	RB/ Request Block address
;	SB/ SV Block address
;	CALL XMTRCM
;	 Error Return
;	Normal Return
;Changes T1,T2
;

	SWAPCD
XMTRCM:	MOVX T1,UN.LEN		;Pass length of UN block
	XCALL (XCDSEC,DNGWDZ)	;Allocate a UN block
	  JSUERR (MONX07,)	;Failed..., Say system resources exhausted
	XMOVEI UN,SV.IXB(SB)	;Get address of protocol server UN block
	LOAD T3,UNPID,(UN)	;Get Server's Portal-id
	MOVE UN,T1		;Get address of our UN Block
	STOR T3,UNPID,(UN)	;Set our Portal-id
	LOAD MS,RBMSO,(RB)	;Get head of output MSD chain
	LOAD T1,RBDST,(RB)	;Get Destination Address
	LOAD T2,RBDST,+1(RB)
	SETONE RBFTI,(RB)	;Set Transmit Initiated flag
	CALL XMTMSD		;Transmit this MSD
	IFNSK.			;Failed...
	  MOVE T1,RB		;Get address of RB
	  XCALL (XCDSEC,DNFWDS)	;Release RB
	  MOVE T1,UN		;Get address of UN
	  XCALL (XCDSEC,DNFWDS)	;Release UN
	  RETBAD		;Error - Pass error up
	ENDIF.
	MOVE T1,UN		;Get address of UN block
	XCALL (XCDSEC,DNFWDS)	;Release UN
	RETSKP			;Success - RETURN from XMTRCM

;END of Routine XMTRCM

	SUBTTL LLMOP Local Utility -- XMTMSD - Transmit MOP Message using MSD

;XMTMSD - Transmit LLMOP Message pointed to by MSD
;
;Call:	MS/ MSD Address
;	UN/ UN Block Address
;	SB/ SV Block address
;	T1,T2/ Ethernet Destination Address
;	CALL XMTMSD
;	 Error Return
;	Normal Return
;Changes T1,T2
;

	RESCD
XMTMSD:	STOR MS,UNBFA,(UN)	;Store MSD as buffer address 
	SETZRO UNBSZ,(UN)	;Must be zero for MSD buffer
	STOR MS,UNRID,(UN)	;Store our Request ID
IFN FTOPS20,<
	SETZRO UNPTR,(UN)	;Indicate UNDAD contains immediate address
>; END IFN FTOPS20
	STOR T1,UNDAD,(UN)	;Set Destination Address in UN Block
	STOR T2,UNDAD,+1(UN)
	INCRF SVTTI,(SB)	;Bump count of transmits initiated
	MOVEI T1,NU.XMT		;DLL Transmit Function code
	MOVE T2,UN		;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface Block
	IFNSK.			;Failed...
	  INCRF SVTTF,(SB)	;Bump count of transmit failures
	  LOAD T2,UNSTA,(UN)	;Get Channel Status
	  LOAD T3,UNCHN,(UN)	;Get channel number
	  XCT LPRLXF		;Do the BUG.
	  JSUERR (LLMX01,)	;Error - Transmit Failed
	ENDIF.
	RETSKP			;Success - RETURN from XMTMSD

;END of Routine XMTMSD

	SUBTTL LLMOP Global Utility -- LLMRSF/LLMRSJ - ReSet for Fork/Job

IFN FTOPS20,<
;LLMRSQ - Reset RB Queue for LLMOP Protocol Servers
;
; This routine is called, at entry point LLMRSF, from .KFORK (.KSELF?) in
; FORK to release any RB's that might have been created by the
; fork which is being killed. The fork can be killed as a result
; of a superior fork doing either a RESET% or a KFORK% JSYS.
; 
; This routine is called, at entry point LLMRSF, from .RESET in
; JSYSA to release any RB's that might have been created by the
; fork doing the RESET% JSYS.
;
; This routine is called, at entry point LLMRSJ, from FLOGO in
; MEXEC to clean up whenever the top fork in a job is killed.
; The top fork in a job is killed as a result of itself or some
; other fork doing a LGOUT% JSYS. This entry point may be
; unnecessary.
;
;Call:
;	CALL LLMRSJ		to kill LLMOP resources for entire job
;	CALL LLMRSF		to kill LLMOP resources for current fork
;	Normal Return always
;Changes T1,T2

	RESCD

;Entry for call to reset for whole job

LLMRSQ::
LLMRSJ::MOVE T1,[LOAD T4,RBJOB,(T2)] ;Instruction to check job ownership
	MOVE T2,JOBNO		;Get this Job's number
	JRST LLMRS2

;Entry for call to reset for current fork

LLMRSF::MOVE T1,[LOAD T4,RBFRK,(T2)] ;Instruction to check fork ownership
	MOVE T2,FORKX		;Get this fork's fork index

LLMRS2:	SAVEAC <SB>		;Make SB safe
	TRVAR <XID,TSTOWN>	;Place to store Job/Fork id and test instr
	MOVEM T1,TSTOWN		;Store instruction for owner compare
	MOVEM T2,XID		;Store Job/Fork ID
	XMOVEI SB,LPSSVB	;Get address of SVB for Loop Server
	CALL LLMRST		;Go do the work
	XMOVEI SB,RCSSVB	;Get address of SVB for Remote Console Server
	LOAD T1,SVCFN,(SB)	;Get fork number of configurator
	CAMN T1,FORKX		;This one?...
	  SETZRO SVCFN,(SB)	;Yes, clear it
	CALL LLMRST		;Go do the work
	RET			;RETURN from LLMRSQ

;END of Routine LLMRSQ

	SUBTTL LLMOP Local Utility -- LLMRST - Reset Request Queue

;LLMRST - Reset Request Queue
;
;Call:	SB/ Address of SVB
;	XID/ Job/Fork Id (in TRansient VARiable)
;	TSTOWN/ Instruction to test XID against RB (in TRansient VARiable)
;	CALL LLMRST
;	Normal Return Always
;Changes T1,T2
;

LLMRST:	SAVEAC <RB>		;Make RB safe
	OPSTR <XMOVEI T1,>,SVRQH,(SB) ;Get address of RB queue head
LLMRS1:				;Top of Loop
	CALL LLMGNQ		;Point to next RB in queue
	IFSKP.			;Got next RB
	  MOVE RB,T2		;Save RB
	  XCT TSTOWN		;Get owners ID (Fork or Job) in T4
	  CAME T4,XID		;Belong to this owner?
	  IFSKP.		;Yes...
	    ETHLOK		;Interlock the queue structure
	    MOVE T3,SB		;Get address of SVB
				;T1 has previous RB address
				;T2 has address of RB to unqueue
	    CALL LLMUNQ		;Unqueue this RB
	      NOP		;Failed, Probably BUG!?
	    LOAD T3,RBSTT,(RB)	; Get state
	    CAIN T3,.RQCMP	; Did this request complete?
	    IFSKP.		; Nope, abort this function
	      SETONE RBABT,(RB)	; Abort when NISRV returns the buffer
	      ETHULK		; Enable interrupts
	      JRST LLMRS1	; Loop till done
	    ENDIF.
	    ETHULK		; Re-enable interrupts

	    LOAD MS,RBMSI,(RB)	;Get Loop Reply MSD address
	    SKIPN MS		;Buffer allocated?
	    IFSKP.		;Yes, release it
	      EXCH T1,MS	;Get address and save T1
	      XCALL (XCDSEC,DNFWDS) ;Release buffer
	      EXCH MS,T1	;Get T1 back
	    ENDIF.
	    EXCH T1,RB		;Pass address of RB, save previous
	    XCALL (XCDSEC,DNFWDS) ;Release the RB
	    MOVE T1,RB		;Restore previous
	    JRST LLMRS1		;Go check for next RB in queue until done
	  ENDIF.
	ENDIF.
	RET			;End of queue - RETURN from LLMRST

;END of Routine LLMRST
>; END IFN FTOPS20
	SUBTTL LLMOP Local Utility -- PSVINI - Protocol Server Initialization

;PSVINI - Initialize an Ethernet Protocol Server
;
;	This routine initializes a protocol server on a single
;	channel. The SV block contains the channel number, protocol
;	type, multicast address, and callback vector.
;
;Call:	T1/ SV Block Address
;	CALL PSVINI
;	 Error Return if not initialized
;	Normal Return
;Changes T1

	RESCD
PSVINI:	SAVEAC <SB,UN>		;Allocate named AC variables for block pointers
	STKVAR <LOOPCT>
	MOVE SB,T1		;Save Address of SV Block
	SETZRO SVIFG,(SB)	;Clear initialize flag and ...
	SETZRO SVRCT,(SB)	; Total Received Count
	SETZRO SVSRC,(SB)	; Server Received Count
	SETZRO SVRRC,(SB)	; Requestor Received Count
	SETZRO SVTTI,(SB)	; Total Transmits Initiated
	SETZRO SVTCT,(SB)	; Total Transmit Count (Completed)
	SETZRO SVSTC,(SB)	; Server Transmit Count
	SETZRO SVRTC,(SB)	; Requestor Transmit Count
	SETZRO SVBPC,(SB)	; Buffer Posted Count
	MOVX T1,1		;Indicate we've tried to initialize
	STOR T1,SVIFG,(SB)
	XMOVEI UN,SV.IXB(SB)	;Get address of static UN Block
	LOAD T1,UNCBA,(UN) ;Get callback address
	XMOVEI T1,(T1)		;Make it extended address
	STOR T1,UNCBA,(UN) ;Set extended callback address

;Initialize the Protocol Server Next Receipt Number

	CALL NRANDM		;Get Non-Repeating Random Number
	STOR T1,SVNXR,(SB)	;Store as next receipt number to use

;Open an NI DLL Portal for this Protocol Type

	MOVEI T1,NU.OPN		;DLL Open Function code
	MOVE T2,UN		;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface
	  IFNSK.		;Failed
	    SETONE SVDLS,(SB)	;Set an invalid Data Link state
	    RET			;Return on this failure
	  ENDIF.
IFN FTOPS20,<
	SETZRO UNRSP,(UN)	;Set no completion callback desired
	SETZRO UNPTR,(UN)	;Indicate UNDAD is immediate address
>; END IFN FTOPS20
	LOAD T1,SVMCA,(SB)	;Get Multicast Address Bytes 0-3
	STOR T1,UNDAD,(UN)	;Set in UN Block
	LOAD T1,SVMCA,+1(SB)	;Get Multicast Address Bytes 4,5
	STOR T1,UNDAD,+1(UN)	;Set in UN Block
	MOVEI T1,NU.EMA		;DLL Declare Multicast Address Function code
	MOVE T2,UN		;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface
	  IFNSK.
	    SETONE SVDLS,(SB)	;Set an invalid Data Link state
	    XCT LLMMCF		;Do the BUG.
	    RET			;Return on this failure
	  ENDIF.
	MOVX T1,NU.RCI		;Get Read Channel Info function code
	MOVE T2,UN		;Pass address of UN Block
	CALL DLLUNI		;Call DLL User to NI Interface
	  IFNSK.
	    SETONE SVDLS,(SB)	;Set an invalid Data Link state
	    XCT LLMCIF		;Do the BUG.
	    RET			;Return on this failure
	  ENDIF.

;Post Initial Protocol Server Receive Buffers

IFN FTOPS20,<
	MOVE T1,SB		;Pass SVB address
	CALL PSTBUF		;Post buffers
	  NOP			;Ignore failure
>; END IFN FTOPS20
	SETONE SVIFG,(SB)	;Set Initialize flag
	RETSKP			;Success - RETURN from PSVINI

;END of Routine PSVINI

	SUBTTL LLMOP Local Utility -- PSTBUF - Post Receive Buffer for Protocol Server

;PSTBUF - Routine to allocate and post receive buffer to Data Link
;
;Call:	T1/ SV Block address
;	CALL PSTBUF
;	  Error Return - Failed BUGCHKS's
;	Normal Return
;Changes T1,T2
;Updates SVBPC in SV Block

	RESCD
PSTBUF:	SAVEAC <SB,UN>		;Allocate named AC variables for block pointers
	SAVEAC <MS>		;Save MS so we can use it here
	MOVE SB,T1		;Set up SB
	TMNE SVDLS,(SB)		;Data Link State ON for this channel?
	  RETSKP		;No, just return
	XMOVEI UN,+SV.IXB(SB)	;Set up UN
PSTBF1:	LOAD T1,SVBPC,(SB)	;Get count of receive buffers posted
	OPSTR <CAML T1,>,SVIBN,(SB) ;Need to post receive buffers?
	  RETSKP		;NO, just return
	MOVEI T1,<MD.LEN+UN.LEN+BUFSIZ> ;Storage for MSD, UN and receive buffer
	XCALL (XCDSEC,DNGWDS)	;Allocate a buffer
	IFSKP.			;Got a buffer, post it for receive
	  MOVE MS,T1		;MSD is prepended to buffer
	  STOR MS,UNRID,(UN)	;Save MSD address for receive completion
	  XMOVEI T2,MD.LEN+UN.LEN(MS) ;Get address of receive data buffer
	  STOR T2,UNBFA,+1(UN)	;Store as two word global address
	  MOVX T3,BUFLEN	;Get length of buffer in bytes
	  STOR T3,UNBSZ,(UN)	;Set in UN Block
	  XCALL (XCDSEC,DNGMSI)	;Initialize MSD for raw buffer
	  LOAD T1,MDPTR,(MS)	;Get standard pointer... Make it
	  TXO T1,1B12		; 2 word global, non-zero section
	  TLZ T1,37		; Clear indexing and indirection
	  STOR T1,UNBFA,(UN)	;Store pointer in UN Block
	  MOVX T1,UNA.EV	;Buffer is Exec Virtual
	  STOR T1,UNADS,(UN)	;Indicate to driver
	  MOVEI T1,NU.RCV	;DLL Receive Function code
	  XMOVEI T2,SV.IXB(SB)	;Pass address of UN Block
	  CALL DLLUNI		;Call DLL User to NI Interface Block
	  IFNSK.		;Failed to accept buffer, BUGCHK
	    OPSTRM <AOS>,SVLBC,(SB) ;Bump count of lost buffers
	    LOAD T1,UNRID,(UN)	;Get Buffer address in UN Block
	    XCALLRET (XCDSEC,DNFWDS) ;Release the buffer fail return
	  ELSE.
	    INCRF SVBPC,(SB)	;Bump count of buffers posted to the DLL
	  ENDIF.
	ELSE.			;Failed to allocate buffer
	  OPSTRM <AOS>,SVLBC,(SB) ;Bump count of lost buffers
	  XCT LLMRXF		;Do the BUG.
	  RET			;Fail return
	ENDIF.
	JRST PSTBF1		;Loop back to post buffers

;END of Routine PSTBUF

	SUBTTL LLMOP Local Utility -- NRANDM - Non-Repeating Random Number

;NRANDM - Initialize Ethernet Loopback Protocol Server
;
;Call:	
;	CALL NRANDM
;	Normal Return	T1/ 16 bit Value
;Changes T1

	RESCD
NRANDM:

;Here we initialize the next receipt number to a pseudo-random number.
;This reduces the risk of a reloaded system continuing a maintenance
;operation from before the crash.  We use the high-order 16 bits of
;the time to avoid any similarities in the number due to a similar
;number of seconds since startup.  System time will always start on an
;even second.

IFN FTOPS20,<
	CALL LGTAD		;Get time & date
>; END IFN FTOPS20
IFN FTOPS10,<
	MOVE	T1,DATE##	;Get date
>; END IFN FTOPS10
	ANDI T1,177777		;Pare it down to 16 bits
	RET			;Success - RETURN from NRANDM

;END of Routine NRANDM

	SUBTTL LLMOP Local Utility -- LLMQUE - LLMOP Protocol Server Queue Routine

;LLMQUE - Queue RB for an LLMOP Protocol Server
;
;Call:	T1/ RB address
;	T2/ SVB address
;	CALL LLMQUE
;	Normal Return
;Changes T3

	RESCD
LLMQUE:	ETHLOK			;Interlock the queue structure
	LOAD T3,SVRQT,(T2)	;Get address of RB queue tail
	STOR T1,RBFWD,(T3)	;Make old tail point to new tail
	STOR T1,SVRQT,(T2)	;Make this RB new tail
	SETZRO RBFWD,(T1)	;Ensure this is end of queue
	ETHULK			;Allow access to queue again
	RET			;Success - RETURN from LLMQUE

;END of Routine LLMQUE

	SUBTTL LLMOP Local Utility -- LLMGNQ - LLMOP Protocol Server Get Next RB in Queue

;LLMGNQ - Get address of next RB in Protocol Server Request Queue
;
;Call:	T1/ Address of current RB
;	CALL LLMGNQ
;	 Abnormal return, at end of queue T2/ 0
;	Normal Return T2/ Address of next RB in queue
;Changes T2

	RESCD
LLMGNQ:	ETHLOK			;Interlock the queue structure
	LOAD T2,RBFWD,(T1)	;Get address of next RB in queue
	ETHULK			;Allow access to queue again
	SKIPN T2		;Is this last RB in queue?
	  RET			;Yes, Abnormal return
	RETSKP			;Success - RETURN from LLMGNQ

;END of Routine LLMGNQ

	SUBTTL LLMOP Local Utility -- LLMUNQ - LLMOP Protocol Server Unqueue RB from Queue

;LLMUNQ - Unqueue an RB in Protocol Server Request Queue
;
;Call:	T1/ Address of RB preceding one to be unqueued
;	T2/ Address of RB to be unqueued
;	T3/ SVB Address for this queue
;	CALL LLMUNQ
;	 Error return
;	Normal Return
;Changes T4

	RESCD
LLMUNQ:	SAVEAC <SB>		;Allocate named AC variables for block pointers
	ETHLOK			;Interlock the queue structure
	MOVE SB,T3		;Point to SVB
	OPSTR <CAMN T2,>,RBFWD,(T1) ;This the one to remove?
	IFSKP.			;No..., Take error return
	  ETHULK
	  RET
	ENDIF.
	LOAD T4,RBFWD,(T2)	;Yes..., Get address of RB following
	SKIPE T4		;At end of queue? 
	IFSKP.			;Yes..., One being removed was last
	  STOR T1,SVRQT,(SB)	;Make previous new tail
	ENDIF.
	STOR T4,RBFWD,(T1)	;Link from previous
	SETZRO RBFWD,(T2)	;Clear link field of unqueued RB
	ETHULK			;Allow access to queue again
	RETSKP			;Success - RETURN from LLMUNQ

;END of Routine LLMUNQ

	SUBTTL LLMOP Local Utility -- LPSRMQ - Loopback Protocol Server Remove RB from Queue 

;LPSRMQ - Remove RB from Queue for Loopback Protocol Server
;
;Call:
;	T1/ RB address
;	T2/ SVB address
;	CALL LPSRMQ
;	 Error return, Queue Empty or RB not in queue
;	Normal Return T1/ RB Address
;Changes T1,T2
;Note: BUGCHK's if queue empty or RB not in queue

	RESCD
LPSRMQ:	SAVEAC <SB>		;Allocate named AC variables for block pointers
	ETHLOK			;Interlock the queue structure
	MOVE SB,T2		;Save SVB address
	XMOVEI T2,SV.RQH(SB)	;Get address of queue head
LPSRM1:	SKIPE T3,(T2)		;Get address of next RB in queue
	IFSKP.
	  ETHULK		;Allow access to queue again
	  XCT LLMRQC		;Do the BUG.
	  RET			;Take error return
	ENDIF.
	CAME T1,T3		;This the one to remove?
	IFSKP.			;Yes...
	 LOAD T3,RBFWD,(T3)	;Get address of next
	 SKIPE T3		;Is there another?
	 IFSKP.			;No..., One being removed was last
	  STOR T2,SVRQT,(SB)	;Make previous new tail
	 ENDIF.
	 STOR T3,RBFWD,(T2)	;Link from previous
	 SETZRO RBFWD,(T1)	;Clear link field
	 ETHULK			;Allow access to queue again
	 RETSKP			;Success - RETURN from LPSRMQ
	ENDIF.			;No...
	MOVE T2,T3		;Look at next RB
	JRST LPSRM1

;END of Routine LPSRMQ

	SUBTTL LLMOP Local Utility -- LPSSXQ - Loopback Protocol Server Search Queue

;LPSSXQ - Search RB Queue for Loopback Protocol Server
;
;Call:
;	T1/ Receipt Number
;	T2/ SVB address
;	CALL LPSSXQ
;	 Error return Queue Empty or not found
;	Normal Return T2/ RB Address
;Changes T1,T2

	RESCD
LPSSXQ:	SAVEAC <SB>		;Allocate named AC variables for block pointers
	ETHLOK			;Interlock the queue structure
	MOVE SB,T2		;Save SVB address
	XMOVEI T2,SV.RQH(SB)	;Get address of queue head
	SKIPE (T2)		;Queue Empty?
	IFSKP.			;Yes..., Error return
	  ETHULK
	  RET
	ENDIF.
LPSSX1:				;Top of Loop
	LOAD T2,RBFWD,(T2)	;Get address of next RB in queue
	CAME T1,RB.RNO(T2)	;Receipt Number match?
	IFSKP.
	  ETHULK		;Allow access to queue again
	  RETSKP		;Yes..., return RB address
	ENDIF.
	CAME T2,SV.RQT(SB)	;Is this last RB in queue?
	JRST LPSSX1		;No..., Keep looking
	ETHULK			;Allow access to queue again
	SKIPE T2		;Yes, verify by having null pointer
	RET			;Whoops, BUG!. Tail doesn't have null pointer

	RET			;End of queue - RETURN from LPSSXQ

;END of Routine LPSSXQ

	SUBTTL LLMOP Local Utility -- CNVPTR - Convert User to MSD style pointer

;CNVPTR - Convert pointer in user context to one word local pointer
;	  indexed by T6
;
;Call:
;	T1/ users byte pointer
;	CALL CNVPTR
;	 Error return (illegal pointer)
;	Normal Return T1/ Pointer indexed by T6
;		      T2/ Virtual Address
;Changes T1,T2,T3

	SWAPCD
CNVPTR:
  	LDB T3,[POINT 6,T1,5]	;Get P field
	CAIG T3,44		;P less than 36?
	IFSKP.			;Yes..., One word global byte pointer
	  JSUERR (LLMX03,)	;Illegal! For now, but could convert to local
	ELSE.			;No..., Two word global or Local pointer
	  TLNN T1,40 		;Bit 12 = 1?
	  IFSKP.		;Yes..., 2 word global byte pointer
	    JSUERR (LLMX03,)	;Illegal!
	  ELSE.			;No..., One word local byte pointer 
	    MOVE T2,T1		;Make a copy of pointer
	    TLZ T1,000037	;Clear I & X fields
	    TRZ T1,777777	;Clear Y field
	    LDB T3,[POINT 6,T1,11] ;Get size field
	    CAIE T3,^D8		;Eight bit?
	      RET		;No, error
	    LDB T3,[POINT 6,T1,5] ;Get position field
	    CAIE T3,04		;Pointer to next word?
	    IFSKP.
	      HRLI T1,441000	;Yes, update pointer
	      AOJ T2,		;...
	    ENDIF.
	    MOVEI T3,T6		;Get value of T6
	    DPB T3,[POINT 4,T1,17] ;Make pointer indexed by T6 in T1
            TLZ T2,777740	;Clear P & S fields and Bit 12
	    TXO T2,<XMOVEI T2,>	;Build XMOVEI with users I, X & Y
	    XCTU T2		;Obtain address in T2
	  ENDIF.
	ENDIF.
	RETSKP			;RETURN from CNVPTR

;END of Routine CNVPTR

	SUBTTL LLMOP Local Utility -- CHKCHL - Check and Verify Interrupt Channel Number

;CHKCHL - Verify Interrupt Channel Number to be in range
;
;Call:
;	T1/ Channel Number
;	CALL CHKCHL
;	 Error return, Channel Invalid
;	Normal Return, Channel Valid
;
;Changes T1
;

	SWAPCD
CHKCHL:	CAIG T1,^D36		;Within Range? (0 to 36)
	CAIGE T1,0
	JRST CHKILL		;No
	CAILE T1,^D5		;Within Range 0-5?
	CAIL T1,^D23		;Or Within Range 23-35
	AOSA T1			;Yes. A Good Channel
	JRST CHKILL		;No. Illegal
	RETSKP			;Return Good Value
CHKILL:	JSUERR (ARGX13,)	;Invalid Channel

;END of Routine CHKCHL

	SUBTTL TOPS-10 Specifics


IFN FTOPS10,<
;Routine called to create a monitor buffer for transmit datagrams
;Call:
;	T1/ MSD address
;	    MDBYT:  User byte count
;	    MDAUX:  User byte pointer (P&S portion)
;	    MDALA:  User buffer address
;Returns:
;	CPOPJ on error
;	CPOPJ1 on success

MAKMBF:	SAVEAC <P1,P2,J>	;Save P1, P2 and J
	MOVE P1,T1		;Save MSD address
	LOAD T1,MDBYT,(P1)	;Get user byte count
	JUMPE T1,[SETZRO MDALA,(P1) ;If no allocation, clear address
		  RETSKP]	;And return
	LDB P2,[POINT 3,MD.AUX(P1),2] ;Pick up word alignment
	MOVNS P2		;Negate
	ADDI P2,7(T1)		;Calculate word count
	ASH P2,-2		;...
	MOVE T1,P2		;Get size of monitor buffer
	MOVE J,.CPJOB##		;Get our job number
	XCALL (XCDSEC,DNGWDZ)	;Get core for monitor buffer
	  RET			;Error, return
	LOAD T2,MDALA,(P1)	;Get user address of buffer
	MOVE T3,T1		;Get monitor buffer address
	STOR T1,MDALA,(P1)	;Save address of buffer
	MOVE T1,P2		;Get size of buffer
	XBLTUX <T1>		;Copy user buffer into monitor buffer
	RETSKP			;And return


;Routine called to free up monitor buffer
;Call:
;	T1/ MSD address
;	CALL FREMBF
;Returns:
;	CPOPJ Always

FREMBF:	SAVEAC <P1>		;Save P1
	MOVE P1,T1		;Save MSD address
	SKIPE T1,MD.ALA(P1)	;Get address of monitor buffer
	XCALL (XCDSEC,DNFWDS)	;Release buffer and return
	RET
>; END IFN FTOPS10
IFN FTOPS10,<
;Routine to wait in event wait for a request block to complete
;Call:
;	RB/ Address of request block
;	CALL RBWAIT
;Returns:
;	CPOPJ when request completes

RBWAIT:	SAVEAC <J>		;Save J
	SETONE RBEVW,(RB)	;Mark event wait
RBWAI1:	LOAD T1,RBSTT,(RB)	;Get request state
	CAXN T1,.RQCMP		;Completed?
	RET			;Yes, return
	MOVEI T1,EV.LLM		;Get LLMOP event wait code
	LOAD J,RBJCH,(RB)	;Get JCH
	ANDI J,JOBMSK##		;Mask to job number
	CALL FSLEEP##		;Wait for completion
	JRST RBWAI1		;Loop back till request completes


;Routine to wake up waiting job
;Call:
;	RB/ Address of request block
;	CALL RBWAKE
;Returns:
;	CPOPJ Always

RBWAKE:	SAVEAC <J>		;Save J
	OPSTR <SKIPN>,RBEVW,(RB) ;Job in event wait for this request?
	IFNSK.
	  LOAD J,RBJCH,(RB)	;No, get JCH of job
	  SIGNAL C$LLM		;Signal LLMOP event
	    JFCL		; ...
	  RET			;And return
	ENDIF.
	LOAD T1,RBJCH,(RB)	;Get JCH of job
	CALL CTXEWK##		;Wake it up
	  JFCL			;...
	RET			;Return
>; END IFN FTOPS10
	SUBTTL End of Program

IFN FTOPS20,TNXEND

	END