Google
 

Trailing-Edge - PDP-10 Archives - BB-M081Z-SM - monitor-sources/llmop.mac
There are 26 other files named llmop.mac in the archive. Click here to see a list.
; Edit= 9172 to LLMOP.MAC on 22-Jun-90 by GSCOTT
;Insure the AC save routines in APRSRV are used by always SEARCHing PROLOG
;before any SEARCH of MACSYM so that the proper USRSAV macro (from PROLOG) is
;used in the SAVEAC macro.
; Edit= 9158 to LLMOP.MAC on 8-Mar-90 by GSCOTT
;Don't try to use a zero MSD in DEQMSD. 
; Edit= 8937 to LLMOP.MAC on 23-Aug-88 by LOMARTIRE
;Spell MONITR correctly in ACTION field of BUGs!
; Edit= 8919 to LLMOP.MAC on 18-Aug-88 by LOMARTIRE
;Improve BUG. documentation
; UPD ID= 8662, RIP:<7.MONITOR>LLMOP.MAC.6,  22-Feb-88 18:48:51 by GSCOTT
;TCO 7.1238 - Set LLMRRF and LLMRXF not normally dumpable.
; UPD ID= 8543, RIP:<7.MONITOR>LLMOP.MAC.5,   9-Feb-88 17:04:26 by GSCOTT
;TCO 7.1218 - Update copyright date.
; UPD ID= 8422, RIP:<7.MONITOR>LLMOP.MAC.4,   4-Feb-88 12:58:08 by GSCOTT
;TCO 7.1210 - Set LLMIL1, LLMILF, LLMIR1, LLMLXF, LLMMCF, LLMSCA, LLMSTC, 
; LPRLXF, MOPIFC, and RCSPIS normally not dumpable.  Make a real honest to god
; EMACS generated table of contents.
; UPD ID= 23, RIP:<7.MONITOR>LLMOP.MAC.3,  23-Jun-87 14:32:26 by RASPUZZI
;TCO 7.1013 - Prevent NSKDIS BUGHLTs by moving RCRWAI out of extended
;resident code and into 0/1 resident code.
; *** Edit 7454 to LLMOP.MAC by RASPUZZI on 16-Apr-87, for SPR #21586
; Prevent GLFNF BUGHLTs, SUMNR1 BUGCHKs and UNBFNF BUGCHKs.
; Make sure that the routines that call PSIRQ in this module don't do
; so at interrupt level. The PSI must be queued and done at scheduler
; level. Make the scheduler check the LLMOP PSI queue when there is
; something in this queue (Routine LLQCHK). This will prevent LLMOP
; from getting its fingers into scheduler pie at the wrong time.
; *** Edit 7432 to LLMOP.MAC by MCCOLLUM on 1-Apr-87, for SPR #21552
; Rearrange code and define dummy routine XCKNI so building monitors with
; KNIN=0 will work 
; Edit 7173 to LLMOP.MAC by PALMIERI on 23-Oct-85 (TCO 6.1.1542)
; Move modules NIUSR and LLMOP to an extended section. This required the
; changing of some global routine names in LLMOP; Therefor the changes to
; MEXEC, JSYSA, and FORK. 
; Edit 7168 to LLMOP.MAC by PALMIERI on 22-Oct-85
; Add routine to handle line state change callbacks for the remote console
; server. 
; UPD ID= 2239, SNARK:<6.1.MONITOR>LLMOP.MAC.46,  19-Jun-85 10:57:55 by GROSSMAN
;TCO 6.1.1461 - Make BLDSID generate correct system time.  Make periodic system
;IDs work.  Fix various and sundry things.
; UPD ID= 2100, SNARK:<6.1.MONITOR>LLMOP.MAC.45,   3-Jun-85 15:43:37 by MCCOLLUM
;TCO 6.1.1406  - Update copyright notice.
; UPD ID= 1948, SNARK:<6.1.MONITOR>LLMOP.MAC.44,   9-May-85 17:15:19 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1886, SNARK:<6.1.MONITOR>LLMOP.MAC.43,   4-May-85 14:41:26 by MCCOLLUM
;TCO 6.1.1238 - Fix more BUG. documentation
; UPD ID= 1841, SNARK:<6.1.MONITOR>LLMOP.MAC.42,  29-Apr-85 14:58:19 by GROSSMAN
;TCO 6.1.1348 - Fix SVBPC discrepancy by re-writing LLMRCX.  Seperate out
;counts for unsupported messages and bad messages.  Pass SV block address to
;PSTBUF in AC SB.
; UPD ID= 1839, SNARK:<6.1.MONITOR>LLMOP.MAC.41,  26-Apr-85 15:25:49 by MCCOLLUM
;TCO 6.1.1238 - Fix BUG. documentation
; UPD ID= 1758, SNARK:<6.1.MONITOR>LLMOP.MAC.40,  16-Apr-85 23:18:35 by GROSSMAN
;TCO 6.1.1324 - Fix hundreds of potential bugs - replace INCRF and DECRF with
;INCR and DECR.
; 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


;	COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1976, 1990.
;	ALL RIGHTS RESERVED.
;
;	THIS SOFTWARE IS FURNISHED UNDER A  LICENSE AND MAY BE USED AND  COPIED
;	ONLY IN  ACCORDANCE  WITH  THE  TERMS OF  SUCH  LICENSE  AND  WITH  THE
;	INCLUSION OF THE ABOVE  COPYRIGHT NOTICE.  THIS  SOFTWARE OR ANY  OTHER
;	COPIES THEREOF MAY NOT BE PROVIDED  OR OTHERWISE MADE AVAILABLE TO  ANY
;	OTHER PERSON.  NO  TITLE TO  AND OWNERSHIP  OF THE  SOFTWARE IS  HEREBY
;	TRANSFERRED.
;
;	THE INFORMATION IN THIS  SOFTWARE IS SUBJECT  TO CHANGE WITHOUT  NOTICE
;	AND SHOULD  NOT  BE CONSTRUED  AS  A COMMITMENT  BY  DIGITAL  EQUIPMENT
;	CORPORATION.
;
;	DIGITAL ASSUMES NO  RESPONSIBILITY FOR  THE USE OR  RELIABILITY OF  ITS
;	SOFTWARE ON EQUIPMENT THAT IS NOT SUPPLIED BY DIGITAL.
	SEARCH D36PAR,PROLOG,NIPAR	;[9172]
	SALL

	TTITLE (LLMOP,,< - Low Level Maintenance OPeration Layer of Phase IV DECnet>)
	SUBTTL  By D. C. Gunn 10 January 1983
	Subttl	Table of Contents

;		     Table of Contents for LLMOP
;
;				  Section		      Page
;
;
;    1. Module Comments  . . . . . . . . . . . . . . . . . . .   6
;    2. Symbol Definitions
;        2.1    Register Definitions . . . . . . . . . . . . .   7
;        2.2    Macros $BUILD,$SET,$EOB  . . . . . . . . . . .   8
;        2.3    Macros LSTIN.,LSTOF. . . . . . . . . . . . . .   9
;        2.4    Macros MIN.,MAX.,MAXENT  . . . . . . . . . . .  10
;    3. Data Structure Definitions
;        3.1    Request Block (RB) . . . . . . . . . . . . . .  11
;    4. Symbol Definitions
;        4.1    External Declarations  . . . . . . . . . . . .  12
;        4.2    LLMOP Internal Definitions . . . . . . . . . .  13
;        4.3    LLMOP Protocol . . . . . . . . . . . . . . . .  14
;        4.4    INTERNAL Symbols . . . . . . . . . . . . . . .  15
;    5. Data Structure Definitions
;        5.1    Counters Block (CB)  . . . . . . . . . . . . .  16
;        5.2    Overview . . . . . . . . . . . . . . . . . . .  17
;        5.3    Server Variable Block (SVB)  . . . . . . . . .  19
;        5.4    Identify-self Message Block (IM) . . . . . . .  20
;    6. Storage Allocation
;        6.1    Resident Write-protected . . . . . . . . . . .  21
;    7. LLMOP BUG. Expansions  . . . . . . . . . . . . . . . .  22
;    8. Storage Allocation
;        8.1    Resident Writeable . . . . . . . . . . . . . .  26
;    9. LLMINI - LLMOP Server/Requestor Initialization . . . .  27
;   10. LLMOFF - LLMOP Server/Requestor Reset (Turn OFF) . . .  28
;   11. Loopback Protocol Server
;       11.1    LPSCBR - DLL Callback Routine  . . . . . . . .  29
;       11.2    LPSRCV - Receive Datagram Handler  . . . . . .  30
;       11.3    LPSXTC - Process Transmit Complete . . . . . .  31
;       11.4    LPSRCI - Process Chan State Change . . . . . .  32
;       11.5    LPSSCA - Process Channel Address . . . . . . .  33
;   12. Loop Server
;       12.1    LPSLBK - Process Forward Data Loop Message . .  34
;   13. Loop Requester
;       13.1    LPSRPY - Process Loopback Reply Message  . . .  35
;   14. Remote Console Protocol Server
;       14.1    RCSCBR - DLL Callback Routine  . . . . . . . .  36
;       14.2    RCSXTC - Process Transmit Complete . . . . . .  37
;   15. Remote Console Server
;       15.1    RCSRCI - Process Chan State Change . . . . . .  38
;   16. Remote Console Protocol Server
;       16.1    RCSRCV - Receive Datagram Handler  . . . . . .  39
;   17. Protocol Server
;       17.1    LLMRCV - Common Receive Datagram Processing  .  40
;   18. Remote Console Protocol Server
;       18.1    RCSFCD - MOP Function Code Dispatch  . . . . .  41
	Subttl	Table of Contents (page 2)

;		     Table of Contents for LLMOP
;
;				  Section		      Page
;
;
;   19. Console Server
;       19.1    RCSRID - Process Request ID  . . . . . . . . .  42
;   20. Console Server/Requestor
;       20.1    RCSSID - Process System ID . . . . . . . . . .  45
;   21. Console Server
;       21.1    RCSRCT - Process Request Counters  . . . . . .  46
;   22. Console Requestor
;       22.1    RCSCTR - Process Counters  . . . . . . . . . .  47
;       22.2    RCSRAK - Process Console Response Ack  . . . .  48
;   23. Remote Console Protocol Server
;       23.1    RCSRCC - Process Read Counters Complete  . . .  49
;       23.2    RCSRSC - Process Read Station Complete . . . .  50
;   24. Console Server
;       24.1    XMTRPY - Transmit MOP Reply  . . . . . . . . .  51
;       24.2    BLDSID - Build SYSTEM ID message . . . . . . .  52
;       24.3    QUEMSD - Queue an INPut MSD  . . . . . . . . .  53
;       24.4    DEQMSD - DEQueue an input MSD  . . . . . . . .  54
;       24.5    INFHDR - Build INFO Header . . . . . . . . . .  55
;       24.6    BLDCTR - Build COUNTERS Message  . . . . . . .  56
;       24.7    INPMSD - Initialize INPut MSD  . . . . . . . .  57
;   25. Protocol Server
;       25.1    SETRBS - SET RB State  . . . . . . . . . . . .  58
;   26. LLMOP Requestor
;       26.1    .LLMOP - LLMOP% (Low Level MOP) JSYS Entry . .  59
;   27. Loop Protocol Requestor
;       27.1    LPRDIR - Ethernet Loop Direct  . . . . . . . .  60
;       27.2    LPRAST - Ethernet Loop Assisted  . . . . . . .  61
;       27.3    LPHDRI - Loopback Message Header Initializatio  62
;       27.4    LPHDRF - Loopback Message Header Forward Packe  63
;       27.5    LPHDRN - Loopback Message Header Reply and Req  64
;       27.6    LPRRPY - Read Loop Reply . . . . . . . . . . .  65
;       27.7    LPRAIC - Assign Interrupt Channel  . . . . . .  66
;       27.8    LPRABT - Ethernet Loop Abort . . . . . . . . .  67
;       27.9    LPRSTS - Get Request Status  . . . . . . . . .  68
;       27.10   LRQINI - Request Block Initialization  . . . .  69
	Subttl	Table of Contents (page 3)

;		     Table of Contents for LLMOP
;
;				  Section		      Page
;
;
;   28. Remote Console Protocol Requestor
;       28.1    RCRRID - Read Identity . . . . . . . . . . . .  70
;       28.2    RCRRCT - Read Counters . . . . . . . . . . . .  71
;       28.3    RCRIDS - Identify Self . . . . . . . . . . . .  72
;       28.4    RCRRBT - Remote Boot . . . . . . . . . . . . .  73
;       28.5    RCRRPY - Read Reply  . . . . . . . . . . . . .  74
;       28.6    RCRSTS - Check Request Status  . . . . . . . .  75
;       28.7    RCRADR - Get Addresses . . . . . . . . . . . .  76
;       28.8    RCRRSV - Reserve Remote Console  . . . . . . .  77
;       28.9    RCRREL - Release Remote Console  . . . . . . .  78
;       28.10   RCRSND - Send Console Command  . . . . . . . .  79
;       28.11   RCRPOL - Console Response Poll . . . . . . . .  80
;       28.12   RCRAIC - Assign Interrupt Channel  . . . . . .  81
;       28.13   RCRABT - Abort Request . . . . . . . . . . . .  82
;       28.14   CRQINI - Request Block Initialization  . . . .  83
;       28.15   MSDINI - MSD Request Block Initialization  . .  84
;       28.16   SETRNO - Set Request Receipt Number  . . . . .  85
;       28.17   SCCINI - ASCII Console Cxr Initialization  . .  86
;   29. Loop Protocol Requestor
;       29.1    XMTREQ - Transmit MOP Request Message  . . . .  87
;       29.2    XMTRCM - Transmit MOP Remote Console Message .  88
;   30. LLMOP Local Utility
;       30.1    XMTMSD - Transmit MOP Message using MSD  . . .  89
;   31. LLMOP Global Utility
;       31.1    LLMRSF/LLMRSJ - ReSet for Fork/Job . . . . . .  90
;   32. LLMOP Local Utility
;       32.1    LLMRST - Reset Request Queue . . . . . . . . .  91
;       32.2    PSVINI - Protocol Server Initialization  . . .  92
;       32.3    PSTBUF - Post Receive Buffer for Protocol Serv  93
;       32.4    NRANDM - Non-Repeating Random Number . . . . .  94
;       32.5    LLMQUE - LLMOP Protocol Server Queue Routine .  95
;       32.6    LLMGNQ - LLMOP Protocol Server Get Next RB in   96
;       32.7    LLMUNQ - LLMOP Protocol Server Unqueue RB from  97
;       32.8    LPSRMQ - Loopback Protocol Server Remove RB fr  98
;       32.9    LPSSXQ - Loopback Protocol Server Search Queue  99
;       32.10   CNVPTR - Convert User to MSD style pointer . . 100
;       32.11   CHKCHL - Check and Verify Interrupt Channel Nu 101
;   33. Routine LLPUTQ . . . . . . . . . . . . . . . . . . . . 102
;   34. Routine LLREMQ . . . . . . . . . . . . . . . . . . . . 103
;   35. Routine LLQCHK . . . . . . . . . . . . . . . . . . . . 104
;   36. End of LLMOP . . . . . . . . . . . . . . . . . . . . . 105
	SUBTTL Module Comments

	XRESCD			;[7173] 

;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.


; 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.

	ENTRY LLMINI		;The entry point
				; see procedures for calling sequence
	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.

	DEFAC (WK,Q1)		;Define a preserved general purpose work AC
	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 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&777777>	;[7173] 
	.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
	FIELD AIC,^D1		;Assign Interrupt Channel
	FILLER ^D10
	FIELD ICH,^D6		;Interrupt Channel Number (0 to 35)
	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
	WORD FRK		;Fork Number
	WORD JOB		;Job Number
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

;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 DNCM2U		;Copy message to user buffer
	EXTERN DNCU2M		;Copy user buffer to message
	EXTERN DNGOPS
	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
	LLPILM==<1B<POS(PICHNM)-WID(PICHNM)+DLSCHN>> ;PI Level mask for KLNI
	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
	MSKSTR	LMAIC,.LMREQ,LM%AIC
	MSKSTR	LMICH,.LMREQ,LM%ICH
	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
	FIELD AIC,^D1		;Assign Interrupt Channel
	FILLER ^D11
	FIELD ICH,^D6		;Interrupt Channel Number (0 to 35)
	FILLER ^D2
	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 USF		;Total of unsupported functions received
	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
	WORD CJN		;Configurator Job Number
	WORD CFN		;Configurator Fork Number
	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

; Request block to make CHKR generate a System ID message

BEGSTR RI
	WORD QUE		;Pointer to next item (Must be first!)
	HWORD REC		;Receipt number
	HWORD CHN		;Ethernet channel number
	WORD SAD,2		;Source Ethernet address
ENDSTR
	SUBTTL Storage Allocation -- Resident Write-protected

	RESDT			;[7173] 

;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

	XRESCD			;[7173] 

;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. 

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	FUNCODE - Function code
>)

	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.

Action:	Using the high and low order bits of the Ethernet address, attempt 
	to locate the remote node which is sending the illegal message.

Data:	MSGLEN - The received message length
	HIORD  - The Ethernet address (high order bits)
	LOORD  - The Ethernet address (low order bits)
>,,<DB%NND>)			;[7.1210] 

	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.

Action:	Using the high and low order bits of the Ethernet address, attempt 
	to locate the remote node which is sending the illegal message.

Data:	FUNCOD - The function code
	HIORD  - The Ethernet address of the transmitting node (high order)
	LOORD  - The Ethernet address of the transmitting node (low order)
>,,<DB%NND>)			;[7.1210] 

	BUG. (HLT,LPRIXC,LLMOP,SOFT,<LLMOP Invalid Xmit Complete>,<<T1,RBSTT>,<T2,UNSTA>>,<

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. 

Data:	RBSTT - The current RB state
	UNSTA - The status in the UN block
>)
	BUG. (INF,LLMSTC,LLMOP,SOFT,<LLMOP data link state change>,<<T1,CHANNEL>,<T2,PRTLID>,<T3,STATUS>>,<

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

Data:	CHANNEL - Channel number
	PTRLID  - Portal ID
	STATUS  - Status bits
>,,<DB%NND>)			;[7.1210] 

	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.

Action:	No action is required as this is informational only.

Data:	CHANNEL - Channel number
>,,<DB%NND>)			;[7.1210] 

	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.

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	DLLERC  - The error code returned from the DLL
	STATUS  - The channel status returned from the DLL
	CHANNEL - The channel on which the failure occurred
>,,<DB%NND>)			;[7.1210] 

	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. 

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	FUNCODE - Function code
>)

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

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

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	MSGLEN - Received message length
>,,<DB%NND>)			;[7.1210] 
	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.

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	FUNCODE - Function code
>,,<DB%NND>)			;[7.1210] 

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

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

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	DLLERC  - The error code returned from the DLL
	CHANNEL - The channel on which the failure occurred
>,,<DB%NND>)			;[7.1238] 

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

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

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	DLLERC - The error code returned from the DLL
	CHANNEL - 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.
>,,<DB%NND>)			;[7.1210] 

	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.

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	DLLERC - The error code returned from the DLL
	CHANNEL - The channel on which the failure occurred
>,,<DB%NND>)			;[7.1210] 

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

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

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	DLLERC - The error code returned from the DLL
>)
	BUG. (CHK,LLMMCF,LLMOP,SOFT,<LLMOP Declare Multicast Address Failed>,<<T1,DLLERC>>,<

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

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	DLLERC - The error code returned from the DLL
>,,<DB%NND>)			;[7.1210] 

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

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

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	DLLERC - The error code returned from the DLL
>)

	BUG. (CHK,LLMSB2,LLMOP,SOFT,<LLMOP Specify Receive Buffer Failure>,<<T1,DLLERC>>,<

Cause:	LLMOP could not post a receive buffer to the Data Link Layer.

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	DLLERC - 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.  
	It is also possible that the RB was not on the queue.

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.

Data:	RBADDRESS - Address of RB queue entry
>)

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

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

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.
>,,<DB%NND>)			;[7.1238] 
	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
	$SET (UNPMS,<LLPILM>,SV.IXB) ;PI level at which we call NI Data Link
	$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
	$SET (UNPMS,<LLPILM>,SV.IXB) ;PI level at which we call NI Data Link
	$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 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
	XRESCD			;[7173] 

	INTERN LLMINI		;[7173] 

	XRENT LLMINI		;[7173] 

	SETZM RIQHED		;Reset the head of the Request ID queue
	XMOVEI T1,RIQHED	;Get the address of the head of the queue
	MOVEM T1,RIQLST		;Make the queue ent point to the queue head
	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?
	 RET			;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

;END of Routine LLMINI
	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.
	XSWAPCD			;[7173] 
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 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

	XRESCD			;[7173] 
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

	XRESCD			;[7173] 
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

	CALL DNG2BY		;[7173] Get skip count
	  JRST LPSRCY
	MOVEM T1,SKPCNT		;Save skip count
	CALL DNSKBY		;[7173] Skip past that in message
	  JRST LPSRCY
	CALL DNG2BY		;[7173] 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:	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

	XRESCD			;[7173] 
LPSXTC:	LOAD T1,UNBSZ,(UN)	;Get Transmitted Message length
	INCR 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
	  INCR SVSTC,(SB)	;Bump Loop Server transmit count
	  MOVE T1,MS		;Pass buffer address
	  CALL DNFWDS		;[7173] Release the buffer
	  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
	  TMNE RBFTI,(RB)	;Ensure transmit was initiated
	  IFSKP.		;It's a bug if not
	    LOAD T2,UNSTA,(UN)	;Get UN block status
	    XCT LPRIXC		;Do the BUG.
	  ENDIF.
	  INCR SVRTC,(SB)	;Bump requester transmit count
	  TMNN UNSTA,(UN)	;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
	  LOAD T1,MDALA,+LD.MSD(RB) ;Get physical address
	  LSH T1,-<WID(777)>	;Convert to core page number
	  XCALL (MSEC1,MULKCR)	;[7173] Unlock the page
	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
;	UN/ UN Block address
;	SB/ SV Block address
;	CALL LPSRCI
;	Normal Return
;Changes T1,T2,T3

	XRESCD			;[7173] 
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,<
	XCT LLMSTC		;BUGINF to let someone know what's happened
>
COMRCI:	LOAD T1,UNCAR,(UN)	;[7168] 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)
	LOAD T1,UNEXS,(UN)	;Get external DLL state
	CAIE T1,UNS.RN		;Running?
	IFSKP.
	  SETZRO SVDLS,(SB)	;Yes...
	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

	XRESCD			;[7173] 
LPSSCA:	LOAD T1,UNCHN,+SV.IXB(SB) ;Get channel
	LOAD T2,UNDAD,(UN)	;Get new physical address
	LOAD T3,UNDAD,+1(UN)
IFN FTDEBUG,<
	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)
	LOAD T1,UNEXS,(UN)	;Get external DLL state
	CAIE T1,UNS.RN		;Running?
	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

	XRESCD			;[7173] 
LPSLBK:	INCR SVSRC,(SB)		;Bump received loopback server message count
	CALL DNGENA		;Get forward address in UNDAD format
	  RET
	STOR T1,UNDAD,(UN)	;Set as destination address in UN block
	STOR T2,UNDAD,+1(UN)
	SETZRO UNPTR,(UN)	;Indicate immediate address passed in UNDAD

;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
	CALL DNP2BS		;[7173] 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.
	  INCR SVTTF,(SB)	;Bump count of total transmit failures
	  RET			;Take failure return
	ENDIF.

	INCR 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

	XRESCD			;[7173] 
LPSRPY:	INCR SVRRC,(SB)		;Bump received loopback requestor message count
	CALL 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
	  INCR 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

	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
	CONSO PI,PIPIIP		;[7454] Are we at interrupt level?
	IFSKP.			;[7454] Yes...
	  CALL LLPUTQ		;[7454] (T1,T2/) Queue up the interrupt
	ELSE.			;[7454] No...
	  XCALL (MSEC1,PSIRQ)	;[7454] (T1,T2/) Notify user that request completed
	ENDIF.			;[7454]
	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

	XRESCD			;[7173] 
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) ;[7168] 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

	XRESCD			;[7173] 
RCSXTC:	LOAD T1,UNBSZ,(UN)	;Get Transmitted Message length
	INCR 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
	    INCR SVSTC,(SB)	;Bump server transmit count
	    MOVE T1,MS		;Pass buffer address
	    CALL DNFWDS		;[7173] Release the buffer
	    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
	    TMNE RBFTI,(RB)	;Ensure transmit was initiated
	    IFSKP.		;It's a bug if not
	      LOAD T2,UNSTA,(UN) ;Get UN block status
	      XCT LPRIXC	;Do the BUG.
	    ENDIF.
	    INCR SVRTC,(SB)	;Bump requester transmit count
	    TMNN UNSTA,(UN)	;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
	    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
	    CAIE T2,VMC.NO	;If this was a user page...
	    IFSKP.
	      XCALL (MSEC1,MULKCR) ;[7173] Unlock the page
	    ENDIF.
	    TMNN RBABT,(RB)	;Is this an abortion?  (Yes, it certainly is!)
	    IFSKP.		;Yes.
	      LOAD T1,RBMSI,(RB) ;Get address of input MSD and buffer
	      CAIN T1,0		;An MSD there?
	      IFSKP.		;Yes...
	 	CALL DNFWDS	;[7173] Release the buffer
	      ENDIF.
	      MOVE T1,RB	;Get address of RB
	      CALLRET DNFWDS	;[7173] Release the RB
	    ENDIF.		;End of the abortion
	  ENDIF.
	ELSE.			;MSD - SID Transmitted by Console Requestor
	  INCR SVRTC,(SB)	;Bump requester transmit count
	ENDIF.

	RET			;Success - RETURN from RCSXTC

;END of Routine RCSXTC
	SUBTTL Remote Console Server -- RCSRCI - Process Chan State Change

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

	XRESCD			;[7173]

RCSRCI:	CALLRET COMRCI		;[7168] Join common code for this callback

;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

	XRESCD			;[7173] 
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

	XRESCD			;[7173] 
LLMRCV:	STOR T3,UNSTA,(UN)	;Put receive status in a safe place
	INCR SVRCT,(SB)		;Count receipt of all messages
	DECR SVBPC,(SB)		;Decrement count of receive buffers posted
	CALL PSTBUF		;Post a receive buffer
	  NOP			;Ignore failure
	JN UNSTA,(UN),LLMRCX	;Jump if we got a receive error
	MOVE T1,UN		;Pass UN Block address
	CALL INPMSD		;Set up input MSD
	CALL DNRPOS		;[7173] Get message length
	RETSKP			;Return +2 with length in T1

LLMRCX:				;Common error exit from LLMRCV
	INCR SVTIC,(SB)		;Count Total Invalid receive Counter

FREBUF:	LOAD T1,UNRID,(UN)	;Get buffer address saved when buffer posted
	CALLRET DNFWDS		;[7173] 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

	XRESCD			;[7173] 
RCSFCD:	CALL 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,RCSUSF) ;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,RCSUSF) ;Don't support RESERVE CONSOLE
	MAKENT (FCDDSP,FCRELC-MINFCD,RCSUSF) ;Don't support RELEASE CONSOLE
	MAKENT (FCDDSP,FCCCAP-MINFCD,RCSUSF) ;Don't support CONSOLE COMMAND POLL
	MAKENT (FCDDSP,FCCRAK-MINFCD,RCSRAK) ;Process CONSOLE RESPONSE ACK

RCSUSF:	INCR SVUSF,(SB)			; Count # of times received unsupp fcn
	CALL FREBUF			; Release the buffer
	RETSKP				; And return

;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

	XRESCD			;[7173] 
RCSRID:	SAVEAC Q3
	CALL DNG1BY		;[7173] Get the reserved field
	  RET
	CALL DNG2BY		;[7173] Get the receipt number
	  RET
	MOVE Q3,T1		;Save the receipt number for a moment
	MOVX T1,RI.LEN		;Get length of queue block
	CALL DNGWDS		;[7173] Get some memory
	 RET			; Give error return, couldn't get memory
	EXCH Q3,T1		;Swap the receipt # and the queue entry
	SETZRO RIQUE,(Q3)	;Zero the link pointer
	STOR T1,RIREC,(Q3)	;Save the receipt number
	OPSTR <DMOVE T1,>,UNSAD,(UN) ; Get the source address
	OPSTR <DMOVEM T1,>,RISAD,(Q3) ; Put it into the request block

	MOVE T1,RIQLST		;Get the address of the last block
	STOR Q3,RIQUE,(T1)	;Make last block point to us
	MOVEM Q3,RIQLST		;Make last pointer point to us
	INCR SVSRC,(SB)		;Bump count of server receives
	AOS JB0FLG		;Make CHKR run
	LOAD T1,UNRID,(UN)	;Get the buffer address
	CALL DNFWDS		;[7173] Release the buffer
	RETSKP			;And return success
	INTERN LLMJB0		;[7173] 

	XRENT LLMJB0 		;[7173] Run in extended resident code

	MOVE T1,TODCLK		;[7432]Get the time of day
	CAMGE T1,LLMACT		;[7432]Time to send an ID?
	SKIPE RIQHED		;[7432]Any stuff to do for LLMOP?
	TRNA			;[7432]Yes to either
	RET			;[7432]No
	SAVEAC <Q3,UN,MS,SB>
	TRVAR (<<UNBLOK,UN.LEN>,<RIBLOK,RI.LEN>>)
	XMOVEI UN,UNBLOK	;Get NISRV arg block pointer
	XMOVEI SB,RCSSVB	;Setup server block
	LOAD T1,UNPID,+RCSSVB+SV.IXB ;Get the portal ID
	STOR T1,UNPID,(UN)	;Setup the UN block

LLMJB1:	D36OFF			;No interrupts please
	MOVE Q3,RIQHED		;Get the first item
	LOAD T1,RIQUE,(Q3)	;Get pointer to the next item
	MOVEM T1,RIQHED		;Make that the new first item
	XMOVEI T1,RIQHED	;Get a pointer to the queue head
	SKIPN RIQHED		;Did we just remove the last item?
	 MOVEM T1,RIQLST	; Yes, make last pointer point to Q head
	D36ON			;Enable interrupts
	JUMPE Q3,LLMJB2		;See if periodic ID is required

	MOVE T1,Q3		;Get RI block address
	CALL SNDSID		;Send a System ID
	 NOP			; Ignore errors

	MOVE T1,Q3		;Get the RI block address
	CALL DNFWDS		;[7173] Release the RI block
	JRST LLMJB1		;And jump back for more

; Here to generate a periodic System ID

LLMJB2:	TMNE SVDLS,(SB)		;Data Link State ON for this channel?
	  RET			;No, just return
	MOVE T1,LLMACT		;Get the time for next ID
	CAMLE T1,TODCLK		;Time to generate an ID?
	 RET			; Nope, quit now
	SKIPE T1		;First time?
	IFSKP.			;Yes, setup random timer offset

; Here to setup a random periodic timer offset.  I am basing it on the two low
; order bytes of the software address of the KLNI.

	  SETZRO UNCHN,(UN)	;Use channel 0 for this
	  MOVX T1,NU.RCI	;Get NISRV function code
	  MOVE T2,UN		;Get the NISRV arg block
	  CALL DLLUNI		;Read the channel information
	   NOP
	  LOAD T1,UNCAR,+1(UN)	;Get the last 2 bytes of the soft addr
	  LSH T1,-^D20		;Shift it down a ways
	  IMULI T1,<^D10*^D60*^D1000>/200000 ;10 minutes(in ms)/2^16
	  ADD T1,TODCLK		;Compute when to generate next system ID
	  SUBX T1,^D60*^D10*^D1000 ;Account for subsequent addition
	ENDIF.
	ADDX T1,^D60*^D10*^D1000 ;Add ten minutes to the time
	MOVEM T1,LLMACT		;Setup for next time
	XMOVEI T1,RIBLOK	;Get our fake RI block
	DMOVE T2,[BYTE (8)253,0,0,2,0,0] ;Get the multicast address
	OPSTR <DMOVEM T2,>,RISAD,(T1) ;Setup the destination address
	SETZRO RIREC,(T1)	;No receipt number
	SETZRO RICHN,(T1)	;Use channel # 0
	CALL SNDSID		;Send a System ID
	 NOP
	RET			;And quit
;Send a System ID message

SNDSID:	SAVEAC Q3
	MOVE Q3,T1		;Save RI block address
	MOVX T1,MD.LEN+BUFSIZ	;Get amount of memory to allocate
	CALL DNGWDS		;[7173] Allocate a buffer and an MSD
	 RET			; Couldn't get memory, pass error up
	XMOVEI T2,MD.LEN(T1)	;Get pointer to buffer
	MOVX T3,BUFLEN		;Get length of buffer (in bytes)
	CALL DNGMSI		;[7173] Initialize the MSD (also sets up MS)

	MOVE T1,Q3		;Get RI block for BLDSID
	CALL BLDSID		;Create a System ID
	LOAD T1,RICHN,(Q3)	;Get the Ethernet channel number
	STOR T1,UNCHN,(UN)	;Put it in the arg block
	OPSTR <DMOVE T1,>,RISAD,(Q3) ; Get the dest address
	CALL XMTMSD		;Transmit the reply response
	 TRNA
	  RETSKP		;Return success
	MOVE T1,MS		;Get address of MSD
	CALLRET DNFWDS		;[7173] Release the memory
	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

	XRESCD			;[7173] 
RCSSID:	CALL DNG1BY		;[7173] Ignore Reserved field
	  RET
	CALL DNG2BY		;[7173] Get the receipt number
	  RET
	SKIPE T1		;Is the receipt number zero?
	IFSKP.			;Yes, this is an unsolicited configuration msg
	  OPSTR <SKIPN>,SVCFN,(SB) ;Is there a Configurator Fork?
	  IFSKP.		;Yes..., Notify process requesting SID messages
	  INCR 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
	    CALL DNGWDZ		;[7173] Cleared to zeroes
	      RETBAD (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
	    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
	    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
	    CALL FREBUF		;Release the buffer
	    RETSKP		;And return success
	  ENDIF.
	ELSE.			;No..., Handle response to RC request
	  INCR SVRRC,(SB)	;Bump count of requestor receives
	  MOVE T2,SB		;Pass SVB address
	  CALL LPSSXQ		;Search the request queue for this RB
	  IFNSK.
	    CALL FREBUF		;Request not found - Release the buffer
	    RETSKP		;And return success
	  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
	ENDIF.

	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
	CONSO PI,PIPIIP		;[7454] Are we at interrupt level?
	IFSKP.			;[7454] Yes...
	  CALL LLPUTQ		;[7454] (T1,T2/) Queue up the interrupt
	ELSE.			;[7454] No...
	  XCALL (MSEC1,PSIRQ)	;[7454] (T1,T2/) Notify user that request completed
	ENDIF.			;[7454]
	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

	XRESCD			;[7173] 
RCSRCT:	STKVAR <RCPTNO>
	CALL DNG2BY		;Get the receipt number
	  RET
	MOVEM T1,RCPTNO		;Save receipt number
	INCR SVSRC,(SB)		;Bump count of server receives

	MOVX T1,RB.LEN		;Allocate an RB for this request
	CALL DNGWDZ		;[7173] 
	  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

	XRESCD			;[7173] 
RCSCTR:	CALL DNG2BY		;[7173] Get the receipt number
	  RET
	INCR 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
	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
	CONSO PI,PIPIIP		;[7454] Are we at interrupt level?
	IFSKP.			;[7454] Yes...
	  CALL LLPUTQ		;[7454] (T1,T2/) Queue up the interrupt
	ELSE.			;[7454] No...
	  XCALL (MSEC1,PSIRQ)	;[7454] (T1,T2/) Notify user that request completed
	ENDIF.			;[7454]
	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

	XRESCD			;[7173] 
RCSRAK:	INCR 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
	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
	CONSO PI,PIPIIP		;[7454] Are we at interrupt level?
	IFSKP.			;[7454] Yes...
	  CALL LLPUTQ		;[7454] (T1,T2/) Queue up the interrupt
	ELSE.			;[7454] No...
	  XCALL (MSEC1,PSIRQ)	;[7454] (T1,T2/) Notify user that request completed
	ENDIF.			;[7454]
	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

	XRESCD			;[7173]
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
	CALL DNFWDS		;[7173] 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

	XRESCD			;[7173]
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
;

	XRESCD			;[7173]
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 -- BLDSID - Build SYSTEM ID message

;BLDSID - Build SYSTEM ID message
;
;Call:	T1/ Request ID block address
;	MS/ Addr of MSD
;	CALL BLDSID
;	  Error Return
;	Normal Return
;Changes T1,T2
;

	XRESCD			;[7173]
BLDSID:	SAVEAC <Q3>
	MOVE Q3,T1		;Save the RI block

	MOVEI T1,FCSSID		;Get System ID function code
	CALL DNP1BY		;[7173] Store in message
	MOVEI T1,0		;Store reserved field
	CALL DNP1BY		;[7173] 
	LOAD T1,RIREC,(Q3)	;Get receipt number given us
	CALL DNP2BY		;[7173] Store receipt number in message

;Build MAINTENANCE VERSION in SYSTEM ID message

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

	MOVE T1,MOPVER
	CALL DNP1BY		;[7173] Store maintenance version
	MOVE T1,MOPECO
	CALL DNP1BY		;[7173] Store ECO
	MOVE T1,MOPUEC
	CALL DNP1BY		;[7173] Store User ECO

;Build FUNCTIONS in SYSTEM ID message

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

;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
	CALL DLLUNI		;Call DLL User to NI Interface
	  NOP			;Ignore error
	MOVEI T1,IT.HAD		;Hardware Address
	MOVEI T2,6
	CALL INFHDR		;Build INFO header
	LOAD T1,UNHAD,(UN)	;Get hardware address
	LOAD T2,UNHAD,+1(UN)
	CALL DNPENA		;[7173] 

;Build SYSTEM TIME in SYSTEM ID message

	MOVEI T1,IT.SYT		;System Time
	MOVEI T2,^D10
	CALL INFHDR		;Build INFO header

	SETO T2,		;Get current date and time
	MOVX T4,IC%DSA!IC%UTZ!FLD(0,IC%ADS)!FLD(0,IC%TMZ)
	ODCNV%			;Get GMT without daylight savings

	MOVE Q3,T2		;Save year and month for a moment

	HLRZ T1,T2		;Get year
	IDIVI T1,^D100		;Seperate century and year
	CALL DNP1BY		;[7173] Store CENTURY
	MOVE T1,T2		;Get the year
	CALL DNP1BY		;[7173] Store YEAR

	HRRZ T1,Q3		;Get the month
	ADDI T1,1		;Make it ordinal
	CALL DNP1BY		;[7173] Store MONTH

	HLRZ T1,T3		;Get the day
	CALL DNP1BY		;[7173] Store DAY

	HRRZ T1,T4		;Get the seconds since midnight
	IDIVI T1,^D3600		;Get the hour
	CALL DNP1BY		;[7173] Store HOUR
	MOVE T1,T2		;Get the remainder in seconds
	IDIVI T1,^D60		;Get the minute
	CALL DNP1BY		;[7173] Store MINUTE
	MOVE T1,T2		;Get the remainder in seconds
	CALL DNP1BY		;[7173] Store SECOND

	SETZ T1,		;We don't get the 100'th of a second
	CALL DNP1BY		;[7173] Store 100TH

	MOVX T1,.SFTMZ		;Get function code for TMON%
	TMON%			;Get the local time zone
	MOVE T1,T2		;Get the time zone
	CALL DNP1BY		;[7173] Store TDFH
	MOVX T1,^D0
	CALL DNP1BY		;[7173] Store TDFM

;Build COMMUNICATION DEVICE in SYSTEM ID message

	MOVEI T1,IT.CDV		;Communication Device
	MOVEI T2,1
	CALL INFHDR		;Build INFO header
	MOVX T1,^D15		;Code for KLNI Device
	CALL DNP1BY		;[7173] 

;Build SOFTWARE ID

	MOVX T1,IT.SID		;System ID
	CALL DNP2BY		;[7173] Install the type
	CALL DNRPOS		;[7173] Get the current position
	MOVE Q3,T1		;Remember it for a moment
	CALL DNP1BY		;[7173] Skip over the length

	MOVX T2,<POINT 7,SVN>	;Get byte pointer to system name
	SETZ T3,		;Reset count
	DO.
	  ILDB T1,T2		;Get a byte
	  JUMPE T1,ENDLP.	;Jump if it's a 0
	  CALL DNP1BY		;[7173] Install this byte
	  AOJA T3,TOP.		;Loop over the whole mess
	ENDDO.

	CALL DNRPOS		;[7173] Read the position again
	EXCH T1,Q3		;Get the old pos, save the new one
	CALL DNGOPS		;[7173] Go back to the old position
	MOVE T1,T3		;Get the byte count
	CALL DNP1BY		;[7173] Install the length
	MOVE T1,Q3		;Get the position back
	CALL DNGOPS		;[7173] Put us back at the end of the message

;Build DATA LINK in SYSTEM ID message

	MOVEI T1,IT.DLK		;Data Link
	MOVEI T2,1
	CALL INFHDR		;Build INFO header
	MOVX T1,1
	CALL DNP1BY		;[7173] 

;Build DATA LINK BUFFER SIZE in SYSTEM ID message

	MOVEI T1,IT.DBS		;Data Link Buffer Size
	MOVEI T2,2
	CALL INFHDR		;Build INFO header
	MOVX T1,^D262
	CALLRET DNP2BY		;[7173] 

;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
;

	XRESCD			;[7173]
QUEMSD:	D36OFF			;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.
	D36ON			;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
;

	XRESCD			;[7173]
DEQMSD:	D36OFF			;Interlock the RB
	TMNE RBMSI,(RB)		;Is there an MSD available?
	IFSKP.			;No...
	  D36ON
	  SETZ MS,		;Clear the MSD address
	  RET			;[9158] Kevin O'Kelley says to return at once
	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
	D36ON			;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 TYPE value
;	T2/ INFO LENGTH value
;	CALL INFHDR
;	  Error Return
;	Normal Return
;Changes T1,T2
;

	XRESCD			;[7173]
INFHDR:	CALL DNP2BY		;[7173] Store INFO TYPE in message
	MOVE T1,T2		;Get INFO LENGTH
	CALLRET DNP1BY		;[7173] Store INFO LENGTH in message

;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 
	XRESCD			;[7173]
BLDCTR: ASUBR <RCPTNO,CTRBLK>	;Save receipt number & counter block address
	SAVEAC <CC>
	MOVE T1,T3		;Get MSD Address
	CALL DNPINI		;[7173] Initialize MSD for output
	MOVEI T1,FCCNTR		;Get COUNTERS function code
	CALL DNP1BY		;[7173] Store in message
	MOVE T1,RCPTNO		;Get receipt number given us
	CALL DNP2BY		;[7173] Set receipt number
	MOVE CC,CTRBLK		;Get address of counter block
	LOAD T1,CCSLZ,(CC)	;Pass Seconds since last zeroed
	CALL DNP2BY		;[7173] Output Seconds since last zeroed
	LOAD T1,CCBYR,(CC)	;Pass Bytes received
	CALL DNP4BY		;[7173] Output Bytes Received
	LOAD T1,CCBYS,(CC)	;Pass Bytes sent
	CALL DNP4BY		;[7173] Output Bytes Sent 
	LOAD T1,CCDGR,(CC)	;Pass Datagrams received
	CALL DNP4BY		;[7173] Output Frames Received
	LOAD T1,CCDGS,(CC)	;Pass Datagrams sent
	CALL DNP4BY		;[7173] Output Frames Sent 
	LOAD T1,CCMBR,(CC)	;Pass Multicast bytes received
	CALL DNP4BY		;[7173] Output Multicast Bytes Received
	LOAD T1,CCMDR,(CC)	;Pass Multicast datagrams received
	CALL DNP4BY		;[7173] Output Multicast Frames Received
	LOAD T1,CCDSD,(CC)	;Pass Datagrams sent, initially deferred
	CALL DNP4BY		;[7173] Output Frames Sent, Initially Deferred
	LOAD T1,CCDS1,(CC)	;Pass Datagrams sent, single collision
	CALL DNP4BY		;[7173] Output Frames Sent, Single Collision
	LOAD T1,CCDSM,(CC)	;Pass Datagrams sent multiple collisions
	CALL DNP4BY		;[7173] Output Frames Sent, Multiple Collisions
	LOAD T1,CCSF,(CC)	;Pass Send failures
	CALL DNP2BY		;[7173] Output Send Failure
	LOAD T1,CCSFM,(CC)	;Pass Send failure bit mask
	LSH T1,-4		;Right justify it
	CALL DNP2BY		;[7173] Output Send Failure Reason Bitmap
	LOAD T1,CCRF,(CC)	;Pass Receive failure
	CALL DNP2BY		;[7173] Output Receive Failure
	LOAD T1,CCRFM,(CC)	;Pass Receive failure bit mask
	LSH T1,-4		;Right justify it
	CALL DNP2BY		;[7173] Output Receive Failure Reason Bitmap
	LOAD T1,CCUFD,(CC)	;Pass Unrecognized frame destination
	CALL DNP2BY		;[7173] Output Unrecognized Frame Destination
	LOAD T1,CCDOV,(CC)	;Pass Data overrun
	CALL DNP2BY		;[7173] Output Data Overrun
	LOAD T1,CCSBU,(CC)	;Pass System buffer unavailable
	CALL DNP2BY		;[7173] Output System Buffer Unavailable
	LOAD T1,CCUBU,(CC)	;Pass User buffer unavailable
	CALL DNP2BY		;[7173] 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
;

	XRESCD			;[7173]
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
	CALLRET DNGMSS		;[7173] 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
;

	XRESCD			;[7173]
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

;.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

	XSWAPCD

	INTERN .LLMOP		;[7173] 

	XNENT .LLMOP		;[7173] Run in extended swapable code

	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

FUNTAB:	IFIW <LPRDIR&777777>	;[7173] Ethernet Loop Direct
	IFIW <LPRAST&777777>	;[7173] Ethernet Loop Assisted
	IFIW <LPRRPY&777777>	;[7173] Ethernet Loop Read Reply
	IFIW <LPRAIC&777777>	;[7173] Ethernet Loop Assign Interrupt Channel
	IFIW <LPRABT&777777>	;[7173] Ethernet Loop Abort
	IFIW <LPRSTS&777777>	;[7173] Ethernet Loop Get Request Status
	IFIW <RCRRID&777777>	;[7173] Remote Console Read Identity
	IFIW <RCRRCT&777777>	;[7173] Remote Console Read Counters
	IFIW <RCRIDS&777777>	;[7173] Remote Console Identify Self
	IFIW <RCRRBT&777777>	;[7173] Remote Console Remote Boot
	IFIW <RCRRPY&777777>	;[7173] Remote Console Read Reply
	IFIW <RCRRSV&777777>	;[7173] Reserve Remote Console
	IFIW <RCRREL&777777>	;[7173] Release Remote Console
	IFIW <RCRSND&777777>	;[7173] Send Console Command
	IFIW <RCRPOL&777777>	;[7173] Console Response Poll
	IFIW <RCRAIC&777777>	;[7173] Assign Interrupt channel
	IFIW <RCRABT&777777>	;[7173] Abort Request
	IFIW <RCRSTS&777777>	;[7173] Remote Console Check Request Status
	IFIW <RCRADR&777777>	;[7173] Obtain Ethernet Addresses
	LMTBMX==.-FUNTAB	;[7173] Maximum Table Entry

;END of Routine .LLMOP
	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
;
	XSWAPCD
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
;

	XSWAPCD
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
;

	XSWAPCD
LPHDRI:				;Entry
	;Set skip count to zero

	MOVEI T1,0		;Skip count zero
	CALLRET DNP2BY		;[7173] Write into message & 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
;

	XSWAPCD
LPHDRF:	ASUBR <HIORD,LOORD>	;Subroutine arguments

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

	MOVEI T1,2		;Function code 02
	CALL DNP2BY		;[7173] Write into message

	;Store our Ethernet address as forward address

	MOVE T1,HIORD		;Get Hi Order 4 bytes
	MOVE T2,LOORD		;Get Lo Order 2 bytes
	CALL DNPENA		;[7173] 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
;

	XSWAPCD
LPHDRN:				;Entry

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

	MOVEI T1,1		;Function code 01
	CALL DNP2BY		;[7173] Write into message

	;Set receipt number

	LOAD T1,RBRNO,(RB)	;Get receipt number from RB
	CALL DNP2BY		;[7173] 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

	XSWAPCD
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 

	XSWAPCD
LPRAIC:				;Ethernet Loop Assign Interrupt Channel
	RETBAD (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

	XSWAPCD
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
	  RETBAD (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...
	  CALL DNFWDS		;[7173] Release the buffer
	ENDIF.
	MOVE T1,RB		;Get address of RB
	CALL DNFWDS		;[7173] 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

	XSWAPCD
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
	  RETBAD (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

	XSWAPCD
LRQINI:				;Request Block Initialization
	MOVEI T1,RB.LEN		;Obtain and Initialize a Request Block (RB)
	CALL DNGWDZ		;[7173] Get a clean block for RB
	  RETBAD (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)
	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
				;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
	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

	;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
	MOVE T1,T2		;Make copy of virtual address
	TXO T1,<1B0>		;Set bit 0 to indicate user virtual
	XCALL (MSEC1,MLKMA)	;[7173] Lock 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
	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 

	XSWAPCD
RCRRID:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	CALL SETRNO		;Set up receipt number
	MOVX T1,FCRQID		;Get Request ID function code
	CALL DNP1BY		;[7173] Store function code in message
	MOVX T1,0
	CALL DNP1BY		;[7173] Store reserved byte in message
	LOAD T1,RBRNO,(RB)	;Get Receipt Number of this request
	CALL DNP2BY		;[7173] 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 

	XSWAPCD			;[7173] 
RCRRCT:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	CALL SETRNO		;Set up receipt number
	MOVX T1,FCRQCT		;Get Request Counters function code
	CALL DNP1BY		;[7173] Store function code in message
	LOAD T1,RBRNO,(RB)	;Get Receipt Number of this request
	CALL DNP2BY		;[7173] 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 

	XSWAPCD
RCRIDS:	ITERR ARGX02		;Remote Console Identify Self


;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 

	XSWAPCD
RCRRBT:	SAVEAC <WK>		;Save preserved work AC
	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	MOVX T1,FCBOOT		;Get Remote Boot function code
	CALL DNP1BY		;[7173] Store function code in message
	ULOAD T1,LMPWD,(LM)	;Get Verification Password
	CALL DNPHIO		;[7173] Use this for password bytes 0,1,2,3
	ULOAD T1,LMPWD,+1(LM)	;And bytes 4,5,6,7 also
	CALL DNPHIO		;[7173] 
	ULOAD T1,LMCFB,(LM)	;Get Control Information
	CALL DNP2BY		;[7173] 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)
	  CALL DNCU2M		;[7173] Copy from user buffer to message
	  OPSTR <LDB T1,>,MDPTR,(MS) ;Get the count byte back
	  CAIG T1,^D17		;Ensure C-17 field
	  IFSKP.
	    CALL DNBKBY		;[7173] Back up over count byte
	    MOVX T1,^D17	;Get maximum count
	    CALL DNP1BY		;[7173] Put count in message
	  ENDIF.
	  ULOAD T2,LMDID,(LM)	;Get Device Id (Pointer) again
	  IBP T2		;Bump pointer past count byte
	  CALL DNCU2M		;[7173] Copy from user buffer to message
	ENDIF.
	MOVX T1,1		;Copy just first byte (count)
	ULOAD T2,LMSID,(LM)	;Get Software Id (Pointer)
	CALL DNCU2M		;[7173] 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...
	    CALL DNBKBY		;[7173] Back up over count byte
	    MOVX T1,^D17	;Get maximum count
	    CALL DNP1BY		;[7173] Put count in message
	  ENDIF.
	  ULOAD T2,LMSID,(LM)	;Get Software Id (Pointer) again
	  IBP T2		;Bump pointer past count byte
	  CALL DNCU2M		;[7173] 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

	XSWAPCD
RCRRPY:	ULOAD T1,LMREQ,(LM)	;Get Request Number
	MOVE T2,SB		;Pass address of SVB
	CALL LPSSXQ		;Search RB queue
	  RETBAD (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
	 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(Q3)	;Store RB address for use by SCHED test routine
	 MDISMS			;T1/ Request #,,Routine Addr
	ENDIF.
	CALL DEQMSD		;Dequeue an MSD
	  RETBAD (LLMX99)	;None there...
	CALL DNRPOS		;[7173] 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
	CALL DNCM2U		;[7173] Move data to user
	  RETBAD (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
	  CALL DNFWDS		;[7173] Release the RB
	ENDIF.
	MOVE T1,MS		;Get address of input MSD and receive buffer
	CALL DNFWDS		;[7173] Release the MSD and buffer
	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, Q3 with fork table index

	RESCD			;[7.1013]

RCRWAI:	MOVE T2,FKSTA2(Q3)	;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 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

	XSWAPCD
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
	  RETBAD (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

	XSWAPCD
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
	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 

	XSWAPCD
RCRRSV:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	MOVX T1,FCRSVC		;Get Reserve Console function code
	CALL DNP1BY		;[7173] Store function code in message

	ULOAD T1,LMPWD,(LM)	;Get Verification Password
	CALL DNPHIO		;[7173] Use also for password bytes 0,1,2,3
	ULOAD T1,LMPWD,+1(LM)	;And bytes 4,5,6,7 also
	CALL DNPHIO		;[7173]

	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 

	XSWAPCD
RCRREL:	CALL CRQINI		;Initialize Remote Console ReQuest Block
	  RETBAD
	MOVX T1,FCRELC		;Get Release Console function code
	CALL DNP1BY		;[7173] 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 

	XSWAPCD			;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
	CALL DNPINI		;[7173] Initialize for output
	MOVX T1,FCCCAP		;Get Console Command and Poll function code
	CALL DNP1BY		;[7173] Store function code in message
	ULOAD T1,LMCCF,(LM)	;Get message number and command break flag
	CALL DNP1BY		;[7173] 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 

	XSWAPCD
RCRPOL:				;Console Response Poll
	ULOAD T1,LMREQ,(LM)	;Get Request Number
	MOVE T2,SB		;Pass address of SVB
	CALL LPSSXQ		;Search RB queue
	  RETBAD (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
	 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(Q3)	;Store RB address for use by SCHED test routine
	 MDISMS			;T1/ Request #,,Routine Addr
	ENDIF.
	LOAD MS,RBMSI,(RB)	;Get address of input MSD
	CALL DNG1BY		;[7173] Get control flags byte
	  MOVEI T1,0		;If short message, set flags to zero
	USTOR T1,LMRCF,(LM)	;Store Console Response Control Flags
	CALL DNRPOS		;[7173] 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
	CALL DNCM2U		;[7173] Move data to user
	  RETBAD (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
	CALL DNFWDS		;[7173] Release the MSD and buffer
	MOVE T1,RB		;Get address of RB
	CALL DNFWDS		;[7173] Release the RB
	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

	XSWAPCD
RCRAIC:				;Assign Interrupt Channel
	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.
	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

	XSWAPCD
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
	  RETBAD (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...

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

	LOAD T1,RBMSI,(RB)	;Get address of input MSD and buffer
	CAIN T1,0		;An MSD there?
	IFSKP.			;Yes...
	  CALL DNFWDS		;[7173] Release the buffer
	ENDIF.
	MOVE T1,RB		;Get address of RB
	CALL DNFWDS		;[7173] 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

	XSWAPCD			;Request Block Initialization
CRQINI:	MOVEI T1,RB.LEN		;Obtain and Initialize a Request Block (RB)
	CALL DNGWDZ		;[7173] Get a clean block for RB
	  RETBAD (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)
	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
				;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
	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
				;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:	XSWAPCD			;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
	CALL DNPINI		;[7173] 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

	XSWAPCD			;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

	XSWAPCD			;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
	MOVE T1,T2		;Make copy of virtual address
	TXO T1,<1B0>		;Set bit 0 to indicate user virtual
	XCALL (MSEC1,MLKMA)	;[7173] Lock 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
;
;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
;

	XSWAPCD
XMTREQ:	MOVE T1,RB		;Pass address of RB
	MOVE T2,SB		;Pass address of SVB
	CALL LLMQUE		;Queue RB on protocol server request queue
	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
;

	XSWAPCD
XMTRCM:	MOVX T1,UN.LEN		;Pass length of UN block
	CALL DNGWDZ		;[7173] Allocate a UN block
	  RETBAD (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
	  CALL DNFWDS		;[7173] Release RB
	  MOVE T1,UN		;Get address of UN
	  CALL DNFWDS		;[7173] Release UN
	  RETBAD		;Error - Pass error up
	ENDIF.
	MOVE T1,UN		;Get address of UN block
	CALL DNFWDS		;[7173] 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
;

	XRESCD			;[7173]
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
	SETZRO UNPTR,(UN)	;Indicate UNDAD contains immediate address
	STOR T1,UNDAD,(UN)	;Set Destination Address in UN Block
	STOR T2,UNDAD,+1(UN)
	INCR 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...
	  INCR 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.
	  RETBAD (LLMX01)	;Error - Transmit Failed
	ENDIF.
	RETSKP			;Success - RETURN from XMTMSD

;END of Routine XMTMSD
	SUBTTL LLMOP Global Utility -- LLMRSF/LLMRSJ - ReSet for Fork/Job

;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

	INTERN LLMRSQ,LLMRJB,LLMRFK	;[7173] 

;Entry for call to reset for whole job

	XNENT LLMRSQ		;[7173][7454] LLMRSQ:: and XLLMRS::
	CALLRET LLMRS0		;[7173] Join common code

	XNENT LLMRJB		;[7173][7454] LLMRJB:: and XLLMRJ::

LLMRS0:	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

	XNENT LLMRFK		;[7454][7173] LLMRFK:: and XLLMFR::

	MOVE T1,[LOAD T4,RBFRK,(T2)] ;Instruction to check fork ownership
	MOVE T2,FORKX		;Get this fork's fork index
	CALL LLREMQ		;[7454] (T2/) Remove any entries for this fork from PSI queue

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...
	    D36OFF		;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!?
	    D36ON		;Allow access to queue again

	    PIOFF		; Absolutely, positively, no interrupts
	    LOAD T3,RBSTT,(RB)	; Get state
	    CAIN T3,.RQCMP	; Did this request complete?
	    IFSKP.		; Nope, perform an abortion
	      SETONE RBABT,(RB)	; Abort when NISRV returns the buffer
	      PION		; Enable interrupts
	      JRST LLMRS1	; Loop till done
	    ENDIF.
	    PION		; 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
	      CALL DNFWDS	;[7173] Release buffer
	      EXCH MS,T1	;Get T1 back
	    ENDIF.
	    EXCH T1,RB		;Pass address of RB, save previous
	    CALL DNFWDS		;[7173] 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
	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

	XRESCD			;[7173]
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.
	TMNN UNRUN,(UN)		;[7168] Is channel running?
	IFSKP.
	  SETZRO SVDLS,(SB)	;[7168] Yes...
	ELSE.
	  SETONE SVDLS,(SB)	;[7168] No...
	ENDIF.
	SETZRO UNRSP,(UN)	;Set no completion callback desired
	SETZRO UNPTR,(UN)	;Indicate UNDAD is immediate address
	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

	LOAD T1,SVIBN,(SB)	;Number of buffers to post
	MOVEM T1,LOOPCT		;Keep count
PSVIN1:	CALL PSTBUF		;Post a buffer
	  NOP			;Ignore failure
PSVIN2:	SOSLE LOOPCT		;Loop through for initial maximum
	JRST PSVIN1
	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:	SB/ SV Block address
;	CALL PSTBUF
;	  Error Return - Failed BUGCHKS's
;	Normal Return
;Changes T1,T2
;Updates SVBPC in SV Block

	XRESCD			;[7173]
PSTBUF:	SAVEAC <MS,UN>		;Allocate named AC variables for block pointers
	XMOVEI UN,+SV.IXB(SB)	;Set up UN
	LOAD T1,SVBPC,(SB)	;Get count of receive buffers posted
	OPSTR <CAML T1,>,SVIBN,(SB) ;Need to post receive buffers?
	  RETSKP		;No, return success
	MOVEI T1,<MD.LEN+UN.LEN+BUFSIZ> ;Storage for MSD, UN and receive buffer
	CALL DNGWDS		;[7173] 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
	  CALL DNGMSI		;[7173] 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
	    XCT LLMSB2		;Do the BUG.
	    OPSTRM <AOS>,SVLBC,(SB) ;Bump count of lost buffers
	    LOAD T1,UNRID,(UN)	;Get Buffer address in UN Block
	    CALLRET DNFWDS	;[7173] Release the buffer fail return
	  ELSE.
	    INCR 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.
	RETSKP			;Success - RETURN from PSTBUF

;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

	XRESCD			;[7173]
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.

	CALL LGTAD		;Get time & date
	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

	XRESCD			;[7173]
LLMQUE:	D36OFF			;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
	D36ON			;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

	XRESCD			;[7173]
LLMGNQ:	D36OFF			;Interlock the queue structure
	LOAD T2,RBFWD,(T1)	;Get address of next RB in queue
	D36ON			;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

	XRESCD			;[7173]
LLMUNQ:	SAVEAC <SB>		;Allocate named AC variables for block pointers
	D36OFF			;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
	  D36ON
	  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
	D36ON			;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

	XRESCD			;[7173]
LPSRMQ:	SAVEAC <SB>		;Allocate named AC variables for block pointers
	D36OFF			;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.
	  D36ON			;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
	 D36ON			;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

	XRESCD			;[7173]
LPSSXQ:	SAVEAC <SB>		;Allocate named AC variables for block pointers
	D36OFF			;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
	  D36ON
	  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.
	  D36ON			;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
	D36ON			;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

	XSWAPCD
CNVPTR:
  	LDB T3,[POINT 6,T1,5]	;Get P field
	CAIG T3,44		;P less than 36?
	IFSKP.			;Yes..., One word global byte pointer
	  RETBAD (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
	    RETBAD (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
	    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
;

	XSWAPCD
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:	RETBAD (ARGX13)		;Invalid Channel

;END of Routine CHKCHL
	SUBTTL Routine LLPUTQ

;LLPUTQ - This routine is called at interrupt level. If we need to initiate
;a PSI for some fork doing an LLMOP request, then we must queue up the
;PSI to happen later. This is because we may be interrupting the scheduler
;and calling PSIRQ may do things out from underneath the scheduler. That's
;not nice. This routine help keeps LLMOP out of scheduler pie. [7454]
;
; Call with:
;	T1/ Channel to initiate PSI on
;	T2/ Fork to receive PSI
;	CALL LLPUTQ
;
; Returns:
;	+1 - Always with entry on LLMPSQ for requested fork
;	     Destroys no ACs.

	XRESCD

LLPUTQ:	SAVET			;Destroy no ACs
	STKVAR <FORK,CHAN,TMPT3>;Temporary place for fork and PSI chan
	MOVEM T1,CHAN		;Save channel
	MOVEM T2,FORK		;And fork
	SKIPN T3,LLMPSQ		;Is the queue empty?
	JRST LLPUT2		;Yes.
LLPUT1:	SKIPN (T3)		;Get next entry in queue
	JRST LLPUT2		;We are at the end of the queue
	MOVE T3,.FLPSI(T3)	;Move on to the next queue entry
	JRST LLPUT1
;T3 now has the last entry in the queue
LLPUT2:	MOVEM T3,TMPT3		;This is used by ASGRES
	MOVE T1,[.RESP1,,2]	;Top priority,,we need 2 words
	MOVEI T2,.RESGP		;Get it from the general pool
	XCALL (MSEC1,ASGRES)	;(T1,T2/T1) Get the free space
	 JRST LLPUT3		;No more!
	MOVE T3,TMPT3		;Get T3 back
	SKIPN T3		;Was the queue originally empty?
	 XMOVEI T3,LLMPSQ	;Yes.
	MOVEM T1,.FLPSI(T3)	;Add entry to tail of queue
	SETZM .FLPSI(T1)	;Now this is the tail of the queue
	HRL T2,CHAN		;Get channel in left side
	HRR T2,FORK		;And fork in right side
	MOVEM T2,.CHNFK(T1)	;And put in queue block
	SETZM LLQTIM		;Tell scheduler that we have something
	RET			;Done

LLPUT3:	BUG.(CHK,LLPSIF,LLMOP,SOFT,<LLPUTQ - Couldn't get free space to put an entry on the LLMOP PSI queue>,,<

Cause:  ASGRES was called to get some free space from the general pool
	to queue up a PSI for a fork. Unfortunately, there was no more
	space in the free pool to assign. This is a free space problem
	somewhere.

Action:	If this BUG persists, make it dumpable and submit an SPR with the
	dump and a copy of MONITR.EXE.  If possible, include any known
	method for reproducing the problem and/or the state of the system
	at the time the BUG was observed.
>)
	RET			;Just return - PSI interrupt will be lost
	SUBTTL Routine LLREMQ

;LLREMQ - This routine is called at fork reset time. It will remove
;any outstanding PSI requests from LLMOP for this fork from the LLMOP
;PSI queue. It will also return the block of free space to the pool.
;[7454]
;
; Call with:
;	T2/ Fork number
;	CALL LLREMQ
;
; Returns:
;	+1 - Always with free space block returned.
;	     Destroys no ACs.

	XSWAPCD

LLREMQ:	SAVET			;Be cool
	STKVAR <<QUEPT,2>,FRKNUM> ;Save queue pointers here
	CALL .NIOFF		;Turn that thing off and go NOSKED!
	SKIPN T1,LLMPSQ		;Get entry from queue
	JRST LLREM3		;Queue is empty, so done
	XMOVEI T4,LLMPSQ	;Must keep a pointer one behind current pos.
LLREM1:	HRRZ T3,.CHNFK(T1)	;Get fork number of this entry
	CAMN T3,T2		;Remove this entry?
	IFNSK.			;Yes
	  MOVE T3,.FLPSI(T1)	;Get next in line in the queue
	  MOVEM T3,.FLPSI(T4)	;Now we have removed the entry we want
	  MOVEM T2,FRKNUM	;Save fork number temporarily
	  DMOVEM T3,QUEPT	;Save T3 & T4
	  XCALL (MSEC1,RELRES)	;(T1/) Now return to free space pool
	  DMOVE T3,QUEPT	;Get T3 and T4 back
	  MOVE T2,FRKNUM	;Restore fork number here
	  JRST LLREM2		;Go on to the next one
	ENDIF.
	MOVE T4,T1		;Save this entry as previous position
LLREM2:	SKIPE T1,.FLPSI(T4)	;Get next entry
	JRST LLREM1		;And go on
LLREM3:	CALL .NION		;(/) Let this come back to life and go OKSKED
	RET			;Fini
	SUBTTL Routine LLQCHK

;LLQCHK - This routine scans the LLMOP PSI queue and initiates a software
;interrupt for each fork that is waiting for one. It is called by the
;scheduler when it is handling each entry in the CLK2CL table. It empties
;one entry off the queue at a time. This prevents lost software interrupts.
;If there are more than 1 in the queue, then we will handle subsequent
;entries every 100 ms. [7454]
;
; Call with:
;	no arguments
;	XCT CLK2CL(P4)
;
; Returns:
;	+1 - always

	XRENT (LLQCHK,G)	;LLQCHK:: and XLLQCH::
				;Called by scheduler, must be resident
	STKVAR <QUENT>		;Place to save queue entry
	CALL .NIOFF		;(/) Shut off the NI
	SKIPE T1,LLMPSQ		;Anything on the queue?
	IFSKP.			;The queue is empty
	  CALL .NION		;(/) Turn NI back on
	  MOVX T1,<.INFIN>	;Get a very large number
	  MOVEM T1,LLQTIM	;Reset timer
	  RET			;Not much to do when the queue is empty
	ENDIF.
	MOVE T2,.FLPSI(T1)	;Get next entry in queue
	MOVEM T2,LLMPSQ		;Make it the first entry
	CALL .NION		;(/) Turn NI back on
	MOVEM T1,QUENT		;Save queue entry for later
	HRRZ T2,.CHNFK(T1)	;Get fork number
	HLRZ T1,.CHNFK(T1)	;And now the channel
	XCALL (MSEC1,PSIRQ)	;(T1,T2/) Now initiate the PSI for the fork
	MOVE T1,QUENT		;Get address of free space block
	XCALL (MSEC1,RELRES)	;(T1/) Return it
	MOVEI T1,^D100		;Come back here in 100 ms
	MOVEM T1,LLQTIM		;Save countdown
	RET			;Done
	SUBTTL End of LLMOP
	TNXEND

	END