Google
 

Trailing-Edge - PDP-10 Archives - DECNET-20_V2.1_2020_7-20-82 - decnet/ncp.mac
There are 2 other files named ncp.mac in the archive. Click here to see a list.
;<JENNESS.NETCON>NCP.MAC.2, 31-Jan-80 13:27:46, Edit by JENNESS
; Update copyright date
;<JENNESS>NCP.MAC.3, 19-Dec-79 09:25:32, Edit by PLATUKIS
; Fix STATUS/STATE keyword conflict in SET/SHOW commands.
;<JENNESS>NCP.MAC.17, 16-Nov-79 15:13:43, Edit by JENNESS
; Change "FROM" keyword in LOAD CONTROLLER kdp_0 FROM to a guide word.
;<JENNESS>NCP.MAC.15,  7-Nov-79 11:58:05, Edit by JENNESS, PLATUKIS
; Fix RCVTOP to call UPDNOD to remove deleted nodes from monitor node list.
;<JENNESS>NCP.MAC.14,  1-Nov-79 10:54:40, Edit by JENNESS, PLATUKIS
; Fix to SETNOD to release the node name block after used.
;<JENNESS>NCP.MAC.11, 30-Oct-79 10:40:35, Edit by JENNESS
; Add code to release topology table if a new one is made (call to ADVTOP).
;<JENNESS>NCP.MAC.10, 22-Oct-79 14:02:29, Edit by JENNESS
; Add code to GETFRE and RELFRE to record in an extra word (allocated before
; block) the address of who allocated it.
;<JENNESS>NCP.MAC.9, 12-Oct-79 11:16:21, Edit by JENNESS
; Fix PRSNOD to give an error return if the node name string has no characters
;  in it.
;<JENNESS>NCP.MAC.7, 11-Oct-79 15:47:34, Edit by JENNESS
; Add code in CHKNIC, QUENCU and DEQNIC to destroy a request that hangs
;  around too long.
;<JENNESS>NCP.MAC.4,  2-Oct-79 11:32:18, Edit by JENNESS
; Add the code to do TOPOLOGY updates every once in a while, when a TIMER
;  interrupt goes off.
;<JENNESS>NCP.MAC.3,  2-Oct-79 10:35:52, Edit by JENNESS
; Fix DOJFD so that it properly checks for an error code before going to the
;  service routine for a message.  Formerly it was just checking to see if
;  there were anymore bytes in the header string (of course there were).
;<JENNESS>NCP.MAC.2,  1-Oct-79 15:00:45, Edit by JENNESS
; Fix PIDINT to release the page and queue entry if no IPCF message was
;  found after MRECV was executed.
;<SROBINSON.NETCON>NCP.MAC.21, 26-Sep-79 18:13:24, Edit by JENNESS
; Fix REQLST routine to know about loopback line status'.
;<SROBINSON.NETCON>NCP.MAC.17, 26-Sep-79 15:30:24, Edit by JENNESS
; TCO 4.2488  Remove AOBJP at PRSPRT.  The routines such as PRSLID
; already increment automatically along the ORION command message.
; This now allows the "SET LOCAL LOOPBACK ENABLE/DISABLE line-id" to work.
;<SROBINSON.NETCON>NCP.MAC.15, 20-Sep-79 14:00:39, Edit by JENNESS
; TCO 4.2478  Fix TOPINI for 2020 to ignore lines that are "ON" but
;   don't go anywhere.
;<SROBINSON.NETCON>NCP.MAC.12,  7-Sep-79 14:21:54, Edit by JENNESS
; Another superficial fix to RELFRE.
;<4.UTILITIES>NCP.MAC.176, 27-Aug-79 17:08:51, Edit by JENNESS
; Fix RELRQI to release links that have been aborted.
;<4.UTILITIES>NCP.MAC.175, 26-Aug-79 12:28:11, Edit by JENNESS
; Add recording for free page allocation/deallocation.
;<4.UTILITIES>NCP.MAC.174, 8-Aug-79 10:40:14, Edit by JENNESS
; Change any error returned from RELFRE to be fatal.
;<4.UTILITIES>NCP.MAC.173, 1-Aug-79 15:51:25, Edit by JENNESS
; Clean up readability of block memory managment code, add sequence checking.
;<4.UTILITIES>NCP.MAC.172, 24-Jul-79 15:37:05, Edit by SROBINSON
;<4.UTILITIES>NCP.MAC.171, 23-Jul-79 15:32:25, Edit by JENNESS
;Change CPYASC to always shift to upper case during string copy.
;<4.UTILITIES>NCP.MAC.170, 22-Jul-79 13:08:22, Edit by SROBINSON
;ADD CODE TO PROCESS DISCONNECTS ON THE NCP LINKS CORRECTLY
;<4.UTILITIES>NCP.MAC.169, 22-Jul-79 09:06:44, Edit by SROBINSON
;ADD CODE TO SET PAGE ACCESSES TO READ/EXECUTE ONLY
;<4.UTILITIES>NCP.MAC.168, 15-Jul-79 14:40:13, Edit by SROBINSON
;ADD CODE TO REESTABLISH NODE LIST UPON INITIALIZATION
;<4.UTILITIES>NCP.MAC.167, 20-Jun-79 16:08:16, EDIT BY KIRSCHEN
;ADD EVENT LOGGING COMMANDS
;<4.UTILITIES>NCP.MAC.166, 16-May-79 08:25:55, EDIT BY KIRSCHEN
;USE CORRECT SYMBOL IN PREVIOUS EDIT
;<4.UTILITIES>NCP.MAC.165, 14-May-79 13:22:51, EDIT BY KIRSCHEN
;DISCARD SPURIOUS IPCF MESSAGES FROM ORION SAYING OPR DISAPPEARED
;<4.UTILITIES>NCP.MAC.164, 17-Mar-79 14:52:03, EDIT BY KIRSCHEN
;ADD .ERR29
;<4.UTILITIES>NCP.MAC.163, 10-Mar-79 14:30:22, EDIT BY KONEN
;UPDATE COPYRIGHT FOR RELEASE 4
;<4.UTILITIES>NCP.MAC.162,  4-Mar-79 08:37:27, EDIT BY ENGEL
;FIX AUTO DUMP/LOAD WHEN EXECUTOR SET INCORRECTLY
;<4.UTILITIES>NCP.MAC.160,  4-Feb-79 22:05:35, EDIT BY KIRSCHEN
;FIX SPURIOUS "?INTERNAL NETCON ERROR" MESSAGE
;<4.UTILITIES>NCP.MAC.159, 31-Jan-79 11:05:27, EDIT BY KIRSCHEN
;FIX TOPOLOGY REPORTING BUGS AT TOPINT AND UPDNOD
;<4.UTILITIES>NCP.MAC.158, 30-Jan-79 16:41:53, EDIT BY KIRSCHEN
;FIX SETUP FOR NODE JSYS IN MONDEL
;<4.UTILITIES>NCP.MAC.157, 30-Jan-79 16:25:33, EDIT BY KIRSCHEN
;FIX OBTAINING NODE NAME IN UPDNOD
;<4.UTILITIES>NCP.MAC.156, 30-Jan-79 09:09:27, EDIT BY KIRSCHEN
;ADD CODE TO STORE KDP REGISTERS ON EVENT LOG MESSAGES
;<4.UTILITIES>NCP.MAC.155, 19-Jan-79 20:42:10, EDIT BY KIRSCHEN
;STORE EXECUTOR NODE CORRECTLY IN SNDNIC
;<4.UTILITIES>NCP.MAC.154, 19-Jan-79 15:55:32, EDIT BY KIRSCHEN
;RELEASE PAGE BY ADDRESS NOT PAGE NUMBER AT RTPINX
;<4.UTILITIES>NCP.MAC.153, 14-Jan-79 21:18:48, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.152, 14-Jan-79 20:45:02, EDIT BY KIRSCHEN
;UPDATE NODE JSYS SYMBOLS; RELEASE OLD JFN AT TOPINX
;<4.UTILITIES>NCP.MAC.151, 12-Jan-79 21:12:48, EDIT BY KIRSCHEN
;PROCESS ENTIRE NICE QUEUE ON EVERY PASS
;<4.UTILITIES>NCP.MAC.150,  8-Jan-79 22:02:08, EDIT BY KIRSCHEN
;remove initiate monitoring command; automate topology reporting
;<4.UTILITIES>NCP.MAC.149,  4-Jan-79 13:07:46, EDIT BY KIRSCHEN
;PASS NODE NAME AND HOST ON DOWN LINE LOADS
;<4.UTILITIES>NCP.MAC.148, 27-Dec-78 10:24:02, EDIT BY ENGEL
;FIX SET EXECUTOR BUG
;<4.UTILITIES>NCP.MAC.147, 22-Dec-78 10:13:29, EDIT BY ENGEL
;ADD AUTO DUMP/LOAD CODE
;<4.UTILITIES>NCP.MAC.146, 21-Dec-78 11:08:17, EDIT BY ENGEL
;add .err26
;<4.UTILITIES>NCP.MAC.145, 20-Dec-78 12:10:51, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.144, 18-Dec-78 22:33:16, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.143, 18-Dec-78 22:16:10, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.142, 18-Dec-78 21:43:49, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.141, 18-Dec-78 21:37:41, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.140, 18-Dec-78 21:04:02, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.139, 18-Dec-78 21:01:17, EDIT BY KIRSCHEN
;ADD SET LINE STATE USING NICE PROTOCOL
;<4.UTILITIES>NCP.MAC.138,  5-Dec-78 14:02:59, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.137,  5-Dec-78 11:31:05, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.136,  5-Dec-78 09:32:41, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.135,  1-Dec-78 10:50:32, EDIT BY KIRSCHEN
;FIX OUTPUT FORMATTING BUG
;<4.UTILITIES>NCP.MAC.134,  1-Dec-78 09:44:18, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.133, 27-Nov-78 14:39:25, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.132, 22-Nov-78 16:17:55, EDIT BY ENGEL
;<4.UTILITIES>NCP.MAC.131, 15-Nov-78 10:14:47, EDIT BY ENGEL
;FIX ERROR RETURNS IN DOJFD'S CALL TO SHOTAB
;<4.UTILITIES>NCP.MAC.130, 15-Nov-78 08:44:42, EDIT BY ENGEL
;ELIMINATE BKJFN IN SHOW STATE KNOWN LINES 
;<4.UTILITIES>NCP.MAC.129, 13-Nov-78 14:24:21, EDIT BY ENGEL
;ADD SHOW STATE KNOWN LINES
;<4.UTILITIES>NCP.MAC.128, 10-Nov-78 11:23:20, EDIT BY KIRSCHEN
;FIX TOPOLOGY NOTIFICATION BUGS
;<4.UTILITIES>NCP.MAC.127,  9-Nov-78 08:51:07, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.126,  9-Nov-78 08:46:46, EDIT BY KIRSCHEN
;DON'T GET NEW SERVER LINK IN MONINI
;<4.UTILITIES>NCP.MAC.125,  8-Nov-78 20:58:01, EDIT BY KIRSCHEN
;DO NOT RELEASE BLOCK CONTAINING NODE NAME IN INIMON
;<4.UTILITIES>NCP.MAC.124,  7-Nov-78 15:55:30, EDIT BY KIRSCHEN
;BUG FIXES
;<4.UTILITIES>NCP.MAC.123,  6-Nov-78 16:12:05, EDIT BY KIRSCHEN
;WAIT FOR CONNECT ACCEPT IN TOPLNK
;<4.UTILITIES>NCP.MAC.122,  3-Nov-78 10:52:18, EDIT BY ENGEL
;MAKE SAVT GLOBAL
;<4.UTILITIES>NCP.MAC.121,  2-Nov-78 13:21:07, EDIT BY ENGEL
;MAKE SAVQ GLOBAL
;<4.UTILITIES>NCP.MAC.120,  2-Nov-78 10:11:17, EDIT BY KIRSCHEN
;FIX OUTPUT FORMATS
;<4.UTILITIES>NCP.MAC.118,  1-Nov-78 16:28:09, EDIT BY ENGEL
;FIX  LOOP WITH XXX 
;<4.UTILITIES>NCP.MAC.117,  1-Nov-78 14:23:06, EDIT BY KIRSCHEN
;FIX FORMATTING OF OUTPUT TO OPR
;<4.UTILITIES>NCP.MAC.116,  1-Nov-78 10:12:58, EDIT BY ENGEL
;FIX COUNT REPORTING IN LOPTST:
;<4.UTILITIES>NCP.MAC.115, 31-Oct-78 09:46:49, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.114, 31-Oct-78 09:06:05, EDIT BY KIRSCHEN
;ADD CODE TO HANDLE ERROR MESSAGES FROM ORION
;<4.UTILITIES>NCP.MAC.113, 30-Oct-78 11:53:27, EDIT BY KIRSCHEN
;MAKE OPRMES EXTERNAL
;<4.UTILITIES>NCP.MAC.112, 25-Oct-78 11:00:56, EDIT BY ENGEL
;ADD LOOP COMMAND
;<4.UTILITIES>NCP.MAC.111, 25-Oct-78 09:37:22, EDIT BY KIRSCHEN
;USE HEADER INSTEAD OF TEXT WHEN ADVISING OPR OF FORK TERMINATIONS
;<4.UTILITIES>NCP.MAC.110, 24-Oct-78 09:17:01, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.109, 23-Oct-78 18:02:00, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.108, 23-Oct-78 17:45:08, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.107, 19-Oct-78 12:06:22, EDIT BY KIRSCHEN
;FIX SHOTAB - SHOULD HAVE ADDRESSES, NOT RETS
;<4.UTILITIES>NCP.MAC.106, 18-Oct-78 12:11:24, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.105, 18-Oct-78 11:10:56, EDIT BY ENGEL
;FIX ERROR IN COMMUNICATION VERSIONS
;<4.UTILITIES>NCP.MAC.104, 16-Oct-78 13:21:59, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.103, 16-Oct-78 11:55:05, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.102, 16-Oct-78 10:23:52, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.101, 16-Oct-78 10:07:15, EDIT BY KIRSCHEN
;PROVIDE RESOURCE MASK IN CALL TO EDLOCK
;<4.UTILITIES>NCP.MAC.100, 13-Oct-78 21:45:16, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.99, 13-Oct-78 15:23:08, EDIT BY KIRSCHEN
;
; GENERATIONS NCP.MAC.59 THRU NCP.MAC.99 WERE CONTINUING EDITS
; TO IMPLEMENT THE TOPOLOGY CHANGE MECHANISM
;CODE TO PROCESS TOPOLOGY CHANGE MESSAGES
;<4.UTILITIES>NCP.MAC.58, 19-Sep-78 15:20:58, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.57, 19-Sep-78 13:40:36, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.56, 19-Sep-78 11:42:55, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.55, 19-Sep-78 11:29:14, EDIT BY KIRSCHEN
;<4.UTILITIES>NCP.MAC.54, 19-Sep-78 10:31:11, EDIT BY KIRSCHEN
;ADD CODE TO INITIALIZE TOPOLOGY MONITORING
;<4.UTILITIES>NCP.MAC.52, 18-Sep-78 16:17:39, EDIT BY KIRSCHEN
;ADD CODE TO PARSE INITIATE MONITORING
;<4.UTILITIES>NCP.MAC.51,  6-Sep-78 13:46:33, EDIT BY KIRSCHEN
;FIX BUG IN DMPRMD CODE
;<4.UTILITIES>NCP.MAC.49,  5-Sep-78 16:50:12, EDIT BY KIRSCHEN
;CHANGE ALL .KY SYMBOLS TO .DN SYMBOLS
;<4.UTILITIES>NCP.MAC.48,  5-Sep-78 14:29:29, EDIT BY KIRSCHEN
;UPDATE MESSAGE FORMATS FOR RELEASE 4 ORION
;<4.UTILITIES>NCP.MAC.46, 16-Aug-78 11:10:30, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.45, 16-Aug-78 11:04:04, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.44, 16-Aug-78 09:11:11, Edit by KIRSCHEN
;BEGIN EDITS TO UPGRADE TO RELEASE 4 OPR
;<4.UTILITIES>NCP.MAC.43,  3-Aug-78 14:17:28, Edit by KIRSCHEN
;MAKE PSIINI ACCEPTS CHANNELS AS ARGUMENT
;<4.UTILITIES>NCP.MAC.42, 21-Jul-78 13:08:51, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.41, 21-Jul-78 10:09:50, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.40, 21-Jul-78 10:01:06, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.39, 21-Jul-78 09:49:07, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.38, 21-Jul-78 09:45:40, Edit by KIRSCHEN
;GET SYSTEM NAME ON STARTUP
;<4.UTILITIES>NCP.MAC.37, 21-Jul-78 08:58:56, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.36, 20-Jul-78 15:42:40, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.35, 20-Jul-78 14:49:14, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.34, 20-Jul-78 13:50:48, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.33, 20-Jul-78 10:06:20, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.31, 19-Jul-78 11:07:28, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.30, 19-Jul-78 09:10:19, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.29, 18-Jul-78 16:51:21, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.28, 18-Jul-78 11:26:55, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.27, 18-Jul-78 11:25:46, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.26, 18-Jul-78 11:13:34, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.25, 17-Jul-78 13:37:45, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.24, 17-Jul-78 13:24:25, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.23, 17-Jul-78 12:01:30, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.22, 17-Jul-78 11:50:41, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.21, 17-Jul-78 11:09:32, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.20, 17-Jul-78 09:21:29, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.19, 17-Jul-78 09:12:41, Edit by KIRSCHEN
;PROVIDE POINTER ON CALL TO GET NODE NAME IN REMSTS
;<4.UTILITIES>NCP.MAC.18, 14-Jul-78 14:45:54, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.17, 14-Jul-78 11:47:44, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.16, 14-Jul-78 11:38:28, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.15, 13-Jul-78 15:12:04, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.14, 13-Jul-78 13:47:24, Edit by KIRSCHEN
;<4.UTILITIES>NCU.MAC.12, 13-Jul-78 13:26:22, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.12, 13-Jul-78 11:45:33, Edit by KIRSCHEN
;ADD SHOW STATE NODE NODE-NAME
;<4.UTILITIES>NCP.MAC.11, 13-Jul-78 11:09:51, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.10, 13-Jul-78 10:57:20, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.9, 13-Jul-78 10:48:20, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.8, 13-Jul-78 10:35:17, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.7, 13-Jul-78 10:33:27, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.6, 13-Jul-78 10:02:26, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.5, 13-Jul-78 09:54:39, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.4, 13-Jul-78 09:44:50, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.3, 13-Jul-78 09:35:21, Edit by KIRSCHEN
;<4.UTILITIES>NCP.MAC.2, 13-Jul-78 09:24:06, Edit by KIRSCHEN
;THE NEXT SEVERAL EDITS REFLECT CONTINUED ATTEMPTS TO RESOLVE THE
; VARIOUS SYMBOL CONFLICTS DUE TO BREAKING APART THE SOURCE CODE.
;<4.UTILITIES>NCP.MAC.1, 13-Jul-78 09:15:07, Edit by KIRSCHEN
;BREAK NETCON INTO TWO MODULES, NCU.MAC AND THIS MODULE, NCP.MAC
;<4.UTILITIES>NETCON.MAC.28, 13-Jul-78 09:05:55, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.27, 12-Jul-78 16:03:44, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.26, 12-Jul-78 15:56:10, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.25, 12-Jul-78 15:40:32, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.24, 12-Jul-78 15:13:55, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.23, 12-Jul-78 15:01:17, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.21, 12-Jul-78 11:40:36, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.20, 12-Jul-78 11:19:08, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.19, 12-Jul-78 11:03:54, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.18, 12-Jul-78 10:55:54, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.16, 12-Jul-78 09:34:29, Edit by KIRSCHEN
;COMPLETE SHOW STATE LINE
;<4.UTILITIES>NETCON.MAC.15, 12-Jul-78 08:44:43, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.14, 12-Jul-78 08:19:01, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.13, 12-Jul-78 08:14:46, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.21, 12-Jul-78 08:10:12, Edit by KIRSCHEN
;BREAK OUT DEFINITIONS INTO NCPPAR.MAC
;<4.UTILITIES>NETCON.MAC.20, 11-Jul-78 16:45:55, Edit by KIRSCHEN
; ADD SHOW STATE
;<4.UTILITIES>NETCON.MAC.19, 11-Jul-78 16:18:33, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.18, 11-Jul-78 16:05:03, Edit by KIRSCHEN
;ADD LINE STATUS SERVER
;<4.UTILITIES>NETCON.MAC.17, 11-Jul-78 15:17:10, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.16, 11-Jul-78 14:23:38, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.15, 11-Jul-78 13:32:34, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.14, 11-Jul-78 13:20:26, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.13, 11-Jul-78 13:13:05, Edit by KIRSCHEN
;SAVE NICE FUNCTION AND OPTION CODES ACROSS THE COMMAND
;<4.UTILITIES>NETCON.MAC.11, 11-Jul-78 09:49:43, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.10, 29-Jun-78 12:03:14, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.9, 29-Jun-78 09:18:16, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.8, 28-Jun-78 14:48:03, Edit by KIRSCHEN
;SUBROUTINIZE RETURNING LINE COUNTERS AT DOJFD
;<4.UTILITIES>NETCON.MAC.7, 27-Jun-78 11:29:18, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.6, 27-Jun-78 11:13:28, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.5, 27-Jun-78 11:11:09, Edit by KIRSCHEN
;ADD SHOW EXECUTOR COMMAND
;<3A.UTILITIES>NETCON.MAC.22, 22-Jun-78 10:29:27, Edit by KIRSCHEN
;<3A.UTILITIES>NETCON.MAC.21, 22-Jun-78 10:15:02, Edit by KIRSCHEN
;<3A.UTILITIES>NETCON.MAC.20, 21-Jun-78 10:12:30, Edit by KIRSCHEN
;FIX LINE STATISTICS ENTRIES
;<4.UTILITIES>NETCON.MAC.3, 16-Jun-78 11:05:14, Edit by KIRSCHEN
;CHECK FOR ANOTHER NETCON ALREADY RUNNING
;<3A.UTILITIES>NETCON.MAC.19, 12-Jun-78 13:09:55, Edit by KIRSCHEN
;FIX PIDINT TO UNDERSTAND ABOUT SPURIOUS INTERRUPTS
;<3A.UTILITIES>NETCON.MAC.18,  7-Jun-78 14:57:08, Edit by KIRSCHEN
;FIX BUG IN LIDPRT
;<3A.UTILITIES>NETCON.MAC.17,  6-Jun-78 11:21:05, Edit by KIRSCHEN
;<3A.UTILITIES>NETCON.MAC.16,  6-Jun-78 10:54:07, Edit by KIRSCHEN
;<3A.UTILITIES>NETCON.MAC.15,  6-Jun-78 10:09:03, Edit by KIRSCHEN
;LINE STATISTICS SYSERR ENTRY FIXES
;<3A.UTILITIES>NETCON.MAC.14,  2-Jun-78 10:05:44, Edit by KIRSCHEN
;<3A.UTILITIES>NETCON.MAC.13,  2-Jun-78 09:37:46, Edit by KIRSCHEN
;USE ASCLIN INSTEAD OF MAKLID ROUTINE TO CONVERT LINE ID TO TEXT
;<3A.UTILITIES>NETCON.MAC.12, 31-May-78 15:44:10, Edit by KIRSCHEN
;MORE SET EXECUTOR FIXES
;<3A.UTILITIES>NETCON.MAC.11, 31-May-78 15:15:30, Edit by KIRSCHEN
;PARSE NODE NAME NOT FIELD IN SET EXECUTOR
;<3A.UTILITIES>NETCON.MAC.10, 31-May-78 14:29:52, Edit by KIRSCHEN
;CLEAN UP LISTING
;<3A.UTILITIES>NETCON.MAC.9, 30-May-78 12:00:16, Edit by KIRSCHEN
;<3A.UTILITIES>NETCON.MAC.8, 30-May-78 11:47:21, Edit by KIRSCHEN
;CAUSE LOGGING-INTERVAL CHANGE TO TAKE EFFECT IMMEDIATELY
;<3A.UTILITIES>NETCON.MAC.7, 26-May-78 09:19:26, Edit by KIRSCHEN
;UPDATE SYSERR ENTRY FORMATS FOR RELEASE 3A
;<KIRSCHEN>NETCON.MAC.6, 15-May-78 13:40:18, Edit by KIRSCHEN
;<3A.UTILITIES>NETCON.MAC.6,  8-May-78 13:16:08, Edit by MCCLURE
; Zero counters for 2020 KDP's
;<3A.UTILITIES>NETCON.MAC.5,  4-May-78 23:47:50, Edit by MCCLURE
; Add CABLE-LOOPBACK & CONTROLLER-LOOPBACK
;<3A.UTILITIES>NETCON.MAC.4, 19-Apr-78 11:11:08, Edit by KIRSCHEN
;REDUCE WAIT TIME FOR PROTOCOL INIT ON DTE20; ADD NEW ERROR CODES
;<3A.UTILITIES>NETCON.MAC.3, 13-Apr-78 08:52:38, Edit by MCCLURE
; Add 2020 stuff
;<4.UTILITIES>NETCON.MAC.36, 20-Mar-78 12:35:08, Edit by KIRSCHEN
;TERMINATE PROTOCOL BEFORE INITIATING A DUMP OVER A DTE20
;<4.UTILITIES>NETCON.MAC.35,  7-Mar-78 15:07:58, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.34,  7-Mar-78 12:49:01, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.33,  6-Mar-78 16:44:16, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.32,  6-Mar-78 14:50:01, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.31,  6-Mar-78 09:30:13, Edit by KIRSCHEN
;PERMIT LOGGING OF LINE COUNTERS WITHOUT HAVING DONE A DOWN LINE LOAD
;<4.UTILITIES>NETCON.MAC.30,  1-Mar-78 15:09:10, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.29,  1-Mar-78 10:27:33, Edit by KIRSCHEN
;ZERO COUNTERS AFTER LOGGING THEM
;<4.UTILITIES>NETCON.MAC.27, 28-Feb-78 09:08:26, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.25,  6-Feb-78 12:06:22, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.24,  6-Feb-78 11:54:57, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.23,  6-Feb-78 11:41:59, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.22,  6-Feb-78 11:33:40, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.21,  3-Feb-78 12:07:19, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.20,  3-Feb-78 11:56:52, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.19,  2-Feb-78 16:24:48, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.18,  2-Feb-78 15:48:51, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.17,  2-Feb-78 13:05:51, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.16,  1-Feb-78 14:41:50, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.15,  1-Feb-78 14:27:16, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.14,  1-Feb-78 14:12:23, Edit by KIRSCHEN
;<4.UTILITIES>NETCON.MAC.13, 23-Jan-78 11:59:52, EDIT BY KIRSCHEN
;<4.UTILITIES>NETCON.MAC.12, 23-Jan-78 09:47:54, EDIT BY KIRSCHEN
;<4.UTILITIES>NETCON.MAC.11, 19-Jan-78 16:25:00, EDIT BY KIRSCHEN
;<4.UTILITIES>NETCON.MAC.10, 19-Jan-78 12:14:14, EDIT BY KIRSCHEN
;<4.UTILITIES>NETCON.MAC.9, 19-Jan-78 12:07:58, EDIT BY KIRSCHEN
;<4.UTILITIES>NETCON.MAC.8, 19-Jan-78 11:00:33, EDIT BY KIRSCHEN
;FIX FAILURE TO RELEASE LOGICAL LINK ON FAILING TO GET LINE COUNTERS
;<4.UTILITIES>NETCON.MAC.7, 11-Jan-78 14:33:46, EDIT BY KIRSCHEN
;ADD CODE TO NOTE THAT LOGGING IS REQUIRED FOR A LINE
;<4.UTILITIES>NETCON.MAC.3, 10-Jan-78 10:33:23, EDIT BY KIRSCHEN
;RELEASE JFN IF OPENF FAILS IN GETLNK ROUTINE
;<4.UTILITIES>NETCON.MAC.2,  5-Jan-78 16:33:49, EDIT BY KIRSCHEN
;SET UP SCRATCH AREA FOR LOGGING PROCESS
TITLE NCP - TOPS20 NETWORK CONTROL PROGRAM (NCP)
SUBTTL	D. KIRSCHEN/P. HURLEY	FEBRUARY, 1977


	SEARCH NETPAR
	SEARCH MONSYM,MACSYM,ORNMAC,GLXMAC,MACTEN
	.REQUIRE SYS:MACREL
;	SALL


;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
;  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976,1977,1978,1979,1980 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
SUBTTL	EXTERNAL Definitions

; ALL OF THE FOLLOWING SYMBOLS ARE DEFINED IN THE MODULE NCU.MAC

EXTERN	LEV1PC, LEV2PC, LEV3PC
EXTERN	L1SAV1, L1SAV2, L1SAV3, L1SAV4, L1SAVC
EXTERN	L2SAV1, L2SAV2, L2SAV3, L2SAV4, L2SAVC
EXTERN	L3SAV1, L3SAV2, L3SAV3, L3SAV4, L3SAVC
EXTERN	EXCUTR, LOGTIM, ERRSTR, OURNAM, OURNUM, PGMTAB
EXTERN	BEGFRE, LSTFRE, NODTAB, NXTNIB, NXTLIN
EXTERN	GETNIB, CVTDEV, NCU, ASCLIN, SYRNCU, LOGGER, ADVTOP
EXTERN	MAKTWO, MAKIMB, MAKIMA, MAKNAM, MAKNUM, MAKNOD, MAKLIN
EXTERN	MAKSLN, MAKHST, MAKENA, MAKENL, MAKDSL, MAKDIS
EXTERN	GETTWO, GETLIN, GETEXB, GETNUM, GETNOD, GETIMA, TOPFRE
SUBTTL	Table of Contents
;
;
;               TABLE OF CONTENTS FOR NETCON
;
;
;                        SECTION                                   PAGE
;    1. Table of Contents.........................................   3
;    2. Macro Definitions.........................................   4
;    3. NICE Process Data Area Offset Definitions.................   7
;    4. Symbol Definitions........................................   8
;    5. Data Structure Definitions................................  13
;    6. Network Control Program (NCP).............................  17
;    7. NCP
;         7.1   SET Command.......................................  22
;         7.2   LOAD Command......................................  33
;         7.3   DUMP Command......................................  43
;         7.4   SHOW Command......................................  49
;         7.5   INITIATE and TERMINATE Commands...................  52
;         7.6   Miscellaneous Routines............................  58
;    8. Network Information and Control Exchange (NICE) Process... 104
;    9. NICE Process
;         9.1   Down-Line Load.................................... 107
;         9.2   Up Line Dump...................................... 118
;         9.3   Return Line Counts................................ 121
;         9.4   Zero Line Counters................................ 122
;         9.5   Line Service Handler.............................. 123
;   10. Routines to Default Information from the Configuration Database 139
;   11. Routines to Extract Fields from NICE Messages............. 144
;   12. Routines to Assemble NICE Messages........................ 162
;   13. Routines to Manipulate DTE-20's........................... 181
;   14. I/O Subroutines........................................... 186
;   15. SYSERR Routines........................................... 198
;   16. Utility Routines.......................................... 212
;   17. Constants and Tables...................................... 224
;   18. Variable Data Storage..................................... 225
;Assembly switches

	ND TRACE,0		; Memory pool tracing normally off (0)

;FREE PAGES - THESE ARE UNMAPPED AT PROGRAM START UP

	NCUFFP==400		;FIRST PAGE OF NCU LOCAL STORAGE AREA
	NNCUPG==10		;NUMBER OF PAGES PER NCU
	NCUNFP==NJFN*NNCUPG	;NUMBER OF PAGES FOR NCU STORAGE SPACE

	FFP==500		;FIRST FREE PAGE IN POOL
	NFP==100		;NUMBER OF FREE PAGES
	FPRCD==477000		;Base address of free pool recording page


;FREE SPACE POOL

	FSP==600		;FIRST FREE SPACE PAGE
	NFSP==100		;SIZE OF FREE SPACE POOL
	FSADR==600*1000		;FREE SPACE ADR
	FSLEN==100*1000		;LENGTH OF FREE SPACE POOL

;Offsets into free space pool header

	.FHFFB==0		; LH points to first free block
	.FHCNT==1		; Count of free words in pool
	.FHCBS==2		; Most common block size in pool
	.FHADR==3		; Pool addresses (top,,bottom)
	.FHBFS==4		; Best fit size (so far) during allocation
	.FHBFA==5		; Address of best fit block

;	Each block on the free chain (list) has a header of:
;
;	Word 0/	Next-block,,length
;
;	If the next-block link is zero then the end of the free chain has
;	been found.  All of the blocks on the free pool chain are sorted
;	by ascending address.  When a block is freed it is checked for
;	continguousness with previous and next blocks on the chain.  If
;	so they are compressed into a single block.
SUBTTL	Variable Data Storage

PDL:	BLOCK PDLEN		;TOP FORK PUSH DOWN LIST
REQADR:	BLOCK 1			;ADDRESS OF CURRENT REQUEST
REQCOD:	BLOCK 1			;CODE USED IN RETURNING ACK TO OPR
QUEUE:	BLOCK 1			;POINTER TO THE FIRST ITEM ON QUEUE
NICQUE:	BLOCK 1			;POINTER TO FIRST ITEM ON NICE QUEUE
LOGFRK:	BLOCK 1			;HANDLE OF LOGGING FORK
TOPTAB:	BLOCK 1			;TOPOLOGY TABLE
TOPSRV:	BLOCK 1			;TOPOLOGY SERVER LINK JFN
JFNTAB:	BLOCK NJFN		;TABLE OF OPEN NCU JFNS
FRKTAB:	BLOCK NJFN		;TABLE OF PROCESS HANDLES
FRKFLG:	BLOCK NJFN		;FLAGS PER FORK
REQTAB:	BLOCK NJFN		;REQUEST NUMBERS
JFDTAB:	BLOCK NJFN		;JFN'S FOR SENDING NICE MESSAGES
REQMES:	BLOCK NJFN		;POINTERS TO MESSAGES
REQXTR:	BLOCK NJFN		;EXECUTOR STRING ADDRESSES
FCNTAB:	BLOCK NJFN		;NICE FUNCTION,,OPTION CODES

REQNUM:	0			;NEXT REQUEST NUMBER

PID:	0			;OUR PID FOR ORION COMMUNICATION
OPRPID:	0			;PID OF ORION

FRELOK:	0			;GETFRE/RELFRE LOCK WORD
PAGLOK:	0			;ASGPAG/RELPAG LOCK WORD

FRSHDR:	BLOCK 6			;FREE SPACE HEADER
FPTBL:	BLOCK <NFP+^D35>/^D36	;FREE PAGE TABLE - BIT=1 MEANS PAGE FREE

SYSNAM::BLOCK 100		;SYSTEM NAME TEXT

NIBTAB::BLOCK NIBSIZ*MAXNOD	;ALLOCATE ONE NIB PER NODE
ADJTAB:	BLOCK MAXNOD*LINSIZ	;MAX # OF NODES * SIZE OF EACH LINE TABLE
START:
NETCON::RESET			;START FRESH
	MOVE P,[IOWD PDLEN,PDL]	;INIT THE PUSH DOWN POINTER
	CALL DUPTST		;ANOTHER NETCON ALREADY RUNNING ?
	 JRST [	HALTF		;YES, GIVE UP.
		JRST START ]	;IF CONTINUED, START OVER
	CALL NETINI		;INITIALIZE EVERYTHING
	 FATAL.ERROR		;FAILED, GO TYPE OUT REASON FOR FAILURE

;BACKGROUND LOOP - EXECUTES REQUESTS FROM ORION

BGLOOP:	MOVEI T1,^D60*^D1000	;SET UP FOR A 1 MINUTE DISMS
	MOVEI T2,0		;ASSUME WAIT JSYS
	SKIPE NICQUE		;ANYTHING IN THE NICE MSSAGE QUEUE?
	MOVEI T2,1		;YES, USE A DISMS JSYS
	SKIPN QUEUE		;ANYTHING TO DO?
BGWAIT:	XCT WATINS(T2)		;NO, WAIT UNTIL SOMETHING COMES ALONG
BGWTPC:	 JFCL			;PC OF WAIT STATE IS HERE
	PIOFF			;TURN OFF INTERRUPTS WHILE TOUCHING QUEUE
	MOVE T1,QUEUE		;GET FIRST ENTRY ON THE QUEUE
	JUMPE T1,[PION		;NOTHING TO BE DONE
		JRST BGLOP1]	;GO WAIT FOR SOMETHING TO DO
	LOAD T2,QUEPNT,(T1)	;GET ADDRESS OF NEXT ENTRY ON QUEUE
	MOVEM T2,QUEUE		;TAKE THE TOP ENTRY OFF QUEUE
	PION			;QUEUE ENTRY IS NOW IN AC T1
	MOVEM T1,REQADR		;SAVE THIS FOR LATER
	CALL DOREQ		;GO PROCESS THIS REQUEST
	 TDZA T2,T2		;FAILED
	SETO T2,		;SUCCESS
	MOVE T3,REQADR		;GET ADDRESS OF REQUEST AGAIN
	CALL FINREQ		;FINISH THIS REQUEST
	 NON.FATAL.ERROR	;FAILED, TYPE OUT MESSAGE
BGLOP1:	CALL CHKNIC		;SEE IF ANY NICE MESSAGES TO BE SENT
	JRST BGLOOP		;GO GET NEXT REQUEST TO BE DONE


WATINS:	WAIT			;INIFINITE BLOCK
	DISMS			;SLEEP FOR 1 MINUTE
;ROUTINE TO WAKE UP THE BACKGROUND LEVEL
;CAN BE CALLED FROM ANY INTERRUPT LEVEL

WAKBKG:	MOVEI T1,.FHSLF		;GET THE ACTIVE LEVELS
	RWM
	TDNE T2,[40000,,40000] ;LEVEL 3 ACTIVE?
	JRST [	MOVEI T1,LEV3PC	;YES, USE THIS PC
		JRST WAKBK1]
	TDNE T2,[100000,,100000] ;LEVEL 2 ACTIVE
	JRST [	MOVEI T1,LEV2PC	;YES
		JRST WAKBK1]
	TDNN T2,[200000,,200000] ;LEVEL 1 ACTIVE?
	RET			;NO, MUST BE BACKGROUND
	MOVEI T1,LEV1PC		;YES
WAKBK1:	HRRZ T2,0(T1)		;GET ADDRESS OF BACKGROUND PROCESS
	CAIE T2,BGWAIT		;IS THIS IN THE WAIT STATE?
	CAIN T2,BGWTPC		;...
	SKIPA			;YES, WAKE IT UP
	RET			;NO, NO NEED TO WAKE IT NOW
	MOVEI T2,BGLOOP		;CAUSE IT TO WAKE UP
	MOVEM T2,0(T1)		;STORE NEW PC IN DISMS ADDRESS
	RET			;DONE
;ROUTINE TO PARSE COMMANDS FROM OPR
;ACCEPTS IN T1/	ADR OF THE QUEUE ENTRY
;	CALL DOREQ
;RETURNS +1:	ERROR IN REQUEST
;	 +2:	SUCCESSFULLY PARSED AND EXECUTED

DOREQ:	SAVEPQ			;SAVE THE PERMANENT ACS
	LOAD T2,QUETYP,(T1)	;GET TYPE OF THIS QUEUE ENTRY
	CAIL T2,DODSPL		;LEGAL VALUE?
	FATAL.ERROR (.ERR14)	;NO
	MOVE T2,DODSP(T2)	;GET DISPATCH ADDRESS
	JRST (T2)		;DISPATCH...

DODSP:	DOMES			;MESSAGE
	DOFKT			;FORK TERMINATION
	DOJFD			;NCP DATA OR DISCONNECT
	DMPLOD			;TOPOLOGY CHANGE INTERRUPT
DODSPL==.-DODSP
	SUBTTL	IPCF message proccessing routine

DOMES:	LOAD P1,QUEMES,(T1)	;KEEP THE ADDRESS OF THE MESSAGE IN P1
	LOAD T2,MS.TYP,.MSTYP(P1) ;GET MESSAGE TYPE
	CAIN T2,MT.TXT		;IS THIS SOME TYPE OF ERROR ?
	JRST [	LOAD T1,MF.SUF,.MSFLG(P1) ;GET SIXBIT ERROR CODE FROM ORION
		CAIN T1,'ODE'	;DID OPR DISAPPEAR ?
		RETSKP		;YES, ALL DONE
		HRROI T1,[ASCIZ/
? NETCON: Error message received from ORION:
	/]			;GET INITIAL PART OF ERROR STRING
		PSOUT		;OUTPUT FIRST PART OF STRING
		HRROI T1,.OHDRS+ARG.DA(P1) ;GET POINTER TO ERROR TEXT
		PSOUT		;OUTPUT ERROR TEXT
		HRROI T1,[ASCIZ/
/]				;GET FINAL CRLF
		PSOUT		;AND TYPE ON TERMINAL
		RETSKP ]	;IGNORE THIS COMMAND
	CAIN T2,.OMHAC		;ACK OF INITIAL HELLO MESSAGE ?
	JRST [	MOVX T4,QF%NOA	;GET "DON'T ACKNOWLEDGE" FLAG
		STOR T4,QUEFLG,(T1) ;NOTE THAT NO ACK NEEDED
		RETSKP ]	;AND DONE
	CAIE T2,.OMCMD		;LOOKING FOR A COMMAND FROM OPR
	JRST [	NON.FATAL.ERROR (.ERR18)
		RETBAD (.ERR18)]
	MOVE T1,.MSCOD(P1)	;GET CODE NEEDED TO RETURN ACK TO OPR
	MOVEM T1,REQCOD		;SAVE REQUEST CODE
	MOVE T1,COM.PB(P1)	;GET ADDRESS OF PARSER BLOCK
	MOVE P2,P1		;GET BASE ADDRESS OF IPCF MESSAGE
	ADD P2,T1		;COMPUTE ADDRESS OF PARSER BLOCK
	CALL PRSKEY		;GO GET FIRST KEYWORD
	 RETBAD (.ERR14)	;FAILED
	MOVEI T2,LV1REQ		;LOOK UP THE DISPATCH ADDRESS
	MOVEI T3,LV1RQL		;  IN THE FIRST LEVEL DISPATCH TABLE
	CALL FNDDSP		;GET NEXT PHASE OF THE COMMAND
	 JRST DOREQE		;UNKNOWN KEYWORD TYPE
	JRST (T1)		;DISPATCH...

DOREQE:	RETBAD (.ERR13)		;ILLEGAL NETCON COMMAND

LV1REQ:	.DNSET,,SETREQ		;SET
	.DNDMP,,DMPREQ		;DUMP
	.DNINI,,INIREQ		;INITIATE
	.DNLOA,,LOAREQ		;LOAD
	.DNLOP,,LOPREQ		;LOOP
	.DNSHW,,SHOREQ		;SHOW
	.DNTRM,,TRMREQ		;TERMINATE
	.DNDSL,,DISREQ		;DISABLE
	.DNENA,,ENAREQ		;ENABLE
LV1RQL==.-LV1REQ
;ROUTINE TO SEARCH A DISPATCH TABLE LOOKING FOR A KEYWORD VALUE
;ACCEPTS IN T1/	KEYWORD VALUE FROM MESSAGE
;	    T2/	ADDRESS OF THE DISPATCH TABLE
;	    T3/	LENGTH OF THE DISPATCH TABLE
;	CALL FNDDSP
;RETURNS +1:	NOT FOUND
;	 +2:	T1/	ADR TO DISPATCH TO

FNDDSP::HLRZ T4,0(T2)		;GET THE NEXT ENTRY VALUE FROM TABLE
	CAMN T1,T4		;FOUND A MATCH?
	JRST FNDDS1		;YES
	AOS T2			;NO, STEP TO THE NEXT ENTRY
	SOJG T3,FNDDSP
	RET			;RAN OUT OF ENTRIES, NOT FOUND

FNDDS1:	HRRZ T1,0(T2)		;GET THE DISPATCH ADDRESS INTO T1
	RETSKP			;AND GIVE SUCCESSFUL RETURN


;ROUTINE TO FIND A "NIB" FOR A NODE OR CREATE ONE IF ONE DOESNT EXIST

;ACCEPTS IN T1/	POINTER TO ASCIZ NODE NAME
;	CALL FOCNIB
;RETURNS +1:	COULD NOT CREATE A NIB
;	 +2:	T1/	ADR OF NIB

FOCNIB:	ASUBR <FOCNAM>
	CALL GETNIB		;GO LOOK FOR NODE NAME
	 SKIPA T1,FOCNAM	;DID NOT FIND IT
	RETSKP
	CALLRET ADDNOD		;GO ADD NODE NAME AND CREATE A NIB
SUBTTL	NCP -- ENABLE Command

ENAREQ:	STKVAR <<ENALID,2>,ENAKEY,<ENAMSG,20>>
	CALL PRSKEY		;PARSE A KEYWORD
	 RET			;FAILED
	MOVEI T2,ENARTB		;GET ADDRESS OF DISPATCH TABLE
	MOVEI T3,ENARTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 RET			;FAILED
	JRST (T1)		;DISPATCH TO PROPER PARSING ROUTINE

ENARTB:	.DNELG,,EVTLOG		;EVENT-LOGGING

ENARTL==.-ENARTB



; ENABLE EVENT-LOGGING

EVTLOG:	CALL PRSCFM		;END OF COMMAND AT THIS POINT ?
	 JRST EVTRQ1		;NO, SEE IF PROPER KEYWORD FOLLOWS
	JRST ENANOD		;YES, ENABLE FOR ENTIRE NODE

EVTRQ1:	CALL PRSKEY		;PARSE NEXT KEYWORD
	 RET			;FAILED
	MOVEI T2,ENALTB		;GET ADDRESS OF DISPATCH TABLE
	MOVEI T3,ENALTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 RET			;FAILED
	JRST (T1)		;DISPATCH TO PROPER PARSING ROUTINE


ENALTB:	.DNSLI,,ENALIN		;LINE line-id
	.DNKNO,,ENAKNO		;KNOWN LINES

ENALTL==.-ENALTB
ENALIN:	CALL PRSLID		;PARSE A LINE ID
	 RET			;FAILED
	DMOVEM T1,ENALID	;SAVE LINE ID
	JRST ENAFIN		;GO FINISH PARSING COMMAND

ENAKNO:	CALL PRSKEY		;PARSE A KEYWORD
	 RET			;FAILED
	MOVEI T2,ENAKTB		;GET ADDRESS OF DISPATCH TABLE
	MOVEI T3,ENAKTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 RET			;FAILED
	JRST (T1)		;DISPATCH TO PROPER PARSING ROUTINE


ENAKTB:	.DNSKL,,ENALNS		;KNOWN LINES

ENAKTL==.-ENAKTB


ENALNS:	SETOM ENALID		;INDICATE KNOWN LINES
	JRST ENAFIN		;GO FINISH PARSING COMMAND
; HERE TO FINISH PARSING COMMAND LINE

ENAFIN:	CALL PRSCFM		;PARSE CONFIRMATION
	 RET			;FAILED
	DMOVE T1,ENALID		;GET LINE ID
	MOVEI T3,ENAMSG		;GET DESTINATION ADDRESS FOR MESSAGE
	CALL MAKENL		;ASSEMBLE A NICE SET PARAMETERS MESSAGE
	 RETBAD ()		;FAILED
	MOVE T4,[.NCSET,,.NCNLS] ;GET NICE FUNCTION CODE,,OPTION CODE
	MOVE T3,T2		;COPY COUNT
	MOVE T2,T1		;COPY POINTER TO START OF MESSAGE
	MOVE T1,P1		;GET ADR OF MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;DONE, RETURN SUCCESS


; NOW ASSEMBLE THE NICE "SET" MESSAGE TO DO THE ENABLE
; HERE ON "ENABLE EVENT-LOGGING" COMMAND FOR ENTIRE NODE

ENANOD:	CALL MAKENA		;GO ASSEMBLE NICE "SET PARAMETER" MSG
	 RETBAD ()		;FAILED
	MOVE T4,[.NCSET,,.NCNLS] ;GET NICE FUNCTION CODE,,OPTION CODE
	MOVE T3,T2		;COPY COUNT
	MOVE T2,T1		;COPY POINTER TO START OF MESSAGE
	MOVE T1,P1		;GET ADR OF MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;DONE, RETURN SUCCESS
SUBTTL	NCP -- DISBLE Command

DISREQ:	STKVAR <<DISLID,2>,DISKEY,<DISMSG,20>>
	CALL PRSKEY		;PARSE A KEYWORD
	 RET			;FAILED
	MOVEI T2,DISRTB		;GET ADDRESS OF DISPATCH TABLE
	MOVEI T3,DISRTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 RET			;FAILED
	JRST (T1)		;DISPATCH TO PROPER PARSING ROUTINE

DISRTB:	.DNELG,,DISLOG		;EVENT-LOGGING

DISRTL==.-DISRTB



; DISBLE EVENT-LOGGING

DISLOG:	CALL PRSCFM		;END OF COMMAND AT THIS POINT ?
	 JRST EVTRQ2		;NO, SEE IF PROPER KEYWORD FOLLOWS
	JRST DISNOD		;YES, DISBLE FOR ENTIRE NODE

EVTRQ2:	CALL PRSKEY		;PARSE NEXT KEYWORD
	 RET			;FAILED
	MOVEI T2,DISLTB		;GET ADDRESS OF DISPATCH TABLE
	MOVEI T3,DISLTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 RET			;FAILED
	JRST (T1)		;DISPATCH TO PROPER PARSING ROUTINE


DISLTB:	.DNSLI,,DISLIN		;LINE line-id
	.DNKNO,,DISKNO		;KNOWN LINES

DISLTL==.-DISLTB
DISLIN:	CALL PRSLID		;PARSE A LINE ID
	 RET			;FAILED
	DMOVEM T1,DISLID	;SAVE LINE ID
	JRST DISFIN		;GO FINISH PARSING COMMAND

DISKNO:	CALL PRSKEY		;PARSE A KEYWORD
	 RET			;FAILED
	MOVEM T1,DISKEY		;SAVE KEYWORD CODE
	CALL PRSCFM		;PARSE END OF COMMAND
	 RET			;FAILED
	MOVE T1,DISKEY		;RESTORE KEYWORD CODE
	MOVEI T2,DISKTB		;GET ADDRESS OF DISPATCH TABLE
	MOVEI T3,DISKTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 RET			;FAILED
	JRST (T1)		;DISPATCH TO PROPER PARSING ROUTINE


DISKTB:	.DNSKL,,DISLNS		;KNOWN LINES

DISKTL==.-DISKTB


DISLNS:	SETOM DISLID		;INDICATE KNOWN LINES
	JRST DISFIN		;GO FINISH PARSING COMMAND
; HERE TO FINISH PARSING COMMAND LINE

DISFIN:	CALL PRSCFM		;PARSE CONFIRMATION
	 RET			;FAILED
	DMOVE T1,DISLID		;GET LINE ID
	MOVEI T3,DISMSG		;GET DESTINATION ADDRESS FOR MESSAGE
	CALL MAKDSL		;ASSEMBLE A NICE SET PARAMETERS MESSAGE
	 RETBAD ()		;FAILED
	MOVE T4,[.NCSET,,.NCNLS] ;GET NICE FUNCTION CODE,,OPTION CODE
	MOVE T3,T2		;COPY COUNT
	MOVE T2,T1		;COPY POINTER TO START OF MESSAGE
	MOVE T1,P1		;GET ADR OF MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;DONE, RETURN SUCCESS


; NOW ASSEMBLE THE NICE "SET" MESSAGE TO DO THE ENABLE
; HERE ON "DISBLE EVENT-LOGGING" COMMAND FOR ENTIRE NODE

DISNOD:	CALL MAKDIS		;GO ASSEMBLE NICE "SET PARAMETER" MSG
	 RETBAD ()		;FAILED
	MOVE T4,[.NCSET,,.NCNLS] ;GET NICE FUNCTION CODE,,OPTION CODE
	MOVE T3,T2		;COPY COUNT
	MOVE T2,T1		;COPY POINTER TO START OF MESSAGE
	MOVE T1,P1		;GET ADR OF MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;DONE, RETURN SUCCESS
SUBTTL 	NCP -- SET Command

SETREQ:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,SETRTB		;GET ADR OF DISPATCH TABLE
	MOVEI T3,SETRTL		;AND LENGTH OF TABLE
	CALL FNDDSP		;GET THE DISPATCH ADR
	 JRST DOREQE		;NOT FOUND, UNKNOWN KEYWORD
	JRST (T1)		;DISPATCH

SETRTB:	.DNSEX,,SETEX		;SET EXECUTOR
	.DNLGI,,SETLGI		;SET LOGGING-INTERVAL
	.DNLPH,,SETHST		;SET HOST
	.DNSLO,,SETLCL		;SET LOCAL
	.DNSMO,,SETMON		;SET MONITORING
	.DNNOD,,SETNOD		;SET NODE
	.DNSPW,,SETPSW		;SET PASSWORD
	.DNSSD,,SETSDF		;SET SECONDARY-DUMP-FILE
	.DNSSL,,SETSLF		;SET SECONDARY-LOAD-FILE
	.DNSST,,SETSTA		;SET STATE
	.DNSTD,,SETTDF		;SET TERTIARY-DUMP-FILE
	.DNSTL,,SETTLF		;SET TERTIARY-LOAD-FILE
SETRTL==.-SETRTB
;SET EXECUTOR

SETEX:	CALL PRSNOD		;PARSE A NODE NAME
	 JRST DOREQE		;FAILED
	HRRZ T4,EXCUTR		;GET CURRENT EXECUTOR
	MOVEM T1,EXCUTR		;SAVE STRING POINTER TO EXECUTOR
	MOVE T1,T4		;GET POINTER TO PREVIOUS EXECUTOR
	CALL RELFRE		;RELEASE OLD STRING BLOCK
	 FATAL.ERROR		;ISSUE ERROR MESSAGE
	RETSKP





;SET HOST

SETHST:	JRST DOREQE
;SET LOCAL LOOPBACK ENABLED/DISABLED LINE-ID

SETLCL:	STKVAR <LCLSCD,LCLPRT>
	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	CAIE T1,.DNLPB		;WAS IT LOOPBACK ?
	JRST DOREQE		;NO SO REJECT
	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,.NDSLP		;IN CASE ENABLING
	CAIN T1,.DNEAB		;WANT TO ENABLE LINE ?
	JRST DOLPB		;ENABLE THE LINE
	MOVEI T2,.NDCLP		;CODE TO CLEAR ENABLE
	CAIE T1,.DNDAB		;WANT TO DISABLE LINE ?
	JRST DOREQE		;NO FAIL
DOLPB:	MOVEM T2,LCLSCD		;SAVE CODE
	CALL PRSPRT		;PARSE THE LINE-ID INTO NSP PORT
	 RETBAD (.ERR23)	;<Invalid line-id>
	MOVEM T1,LCLPRT		;SAVE PORT #
	CALL PRSCFM		;PARSE END OF COMMAND
	 JRST DOREQE		;LOSE
	MOVE T1,LCLSCD		;GET ENABLE/DISABLE CODE
	MOVEI T2,T3		;POINT TO ARGUMENT BLOCK
	MOVE T3,LCLPRT		;GET PORT #
	NODE			;SET/CLEAR LOOPBACK
	 ERJMP [MOVEI T1,.ERR19	;JSYS error
		RET ]
	RETSKP			;DONE
;SET LOGGING INTERVAL

SETLGI:	CALL PRSNOI		;PARSE NOISE WORD
	CALL PRSKEY		;PARSE KEYWORD
	 JRST DOREQE		;FAILED, RETURN ERROR
	CAIE T1,.DNLCT		;LINE-COUNTERS ?
	JRST DOREQE		;NO, FAIL
	CALL PRSNUM		;GET # OF MINUTES
	 JRST DOREQE		;FAILED
	IMULI T1,^D60*^D1000	;CONVERT MINUTES TO MILLISECONDS
	MOVEM T1,LOGTIM		;SAVE NEW LOGGING INTERVAL
	CALL LOGINI		;GO START LOGGING WITH NEW INTERVAL
	 JRST DOREQE		;FAILED, ISSUE ERROR MESSAGE
	RETSKP			;DONE, RETURN
;SET NODE

SETNOD:	CALL PRSNOD		;PARSE A NODE NAME
	 JRST DOREQE		;FAILED, NOT A NODE NAME
	MOVE P3,T1		;Save address of node name block
	CALL FOCNIB		;FIND OR CREATE THE ASSOCIATED NIB
	 JRST [MOVE T1,P3	;Failed to create a NIB
	       CALL RELFRE	; Release node name block
		FATAL.ERROR
	       JRST DOREQE]
	EXCH P3,T1		;Swap node name block for NIB address
	CALL RELFRE		;Release node name block
	 FATAL.ERROR		; Can't release it .. die.
	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,SETNTB		;SET UP TO FIND DISPATCH ADR
	MOVEI T3,SETNTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET DISPATCH ADR
	 JRST DOREQE		;NOT FOUND, UNKNOWN COMMAND
	JRST (T1)		;DISPATCH

SETNTB:	.DNSNB,,SETNBP		;SET NODE BOOT-PASSWORD
	.DNSNF,,SETNDF		;SET NODE DUMP-FILE
	.DNSNL,,SETNLF		;SET NODE LOAD-FILE
	.DNPRM,,SETNLP		;SET NODE LOAD-PARAMETERS
	.DNSNS,,SETNSV		;SET NODE SERVER
	.DNSNT,,SETNPT		;SET NODE PROTOCOL-TYPE
	.DNADM,,SETADM		;SET NODE AUTO-DUMP
	.DNALD,,SETALD		;SET NODE AUTO-LOAD
SETNTL==.-SETNTB


; SET NODE PROTOCOL-TYPE

SETNPT:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,SETPTB		;GET PROTOCOL TABLE ADDRESS
	MOVEI T3,SETPTL		;AND TABLE LENGTH
	CALL FNDDSP		;FIND PROTOCOL IN TABLE
	 JRST DOREQE		;FAILED, NOTE ERROR
	STOR T1,NDPRO,(P3)	;STORE PROTOCOL VERSION TYPE
	SETONE NDPST,(P3)	;NOTE THAT PROTOCOL TYPE HAS BEEN SET
	RETSKP			;DONE, RETURN


SETPTB:	.DNRQP,,.VN20F		;RSX20F QUEUED PROTOCOL
	.DNNSP,,.VNMCB		;NETWORK SERVICES PROTOCOL (NSP)

SETPTL==.-SETPTB		;LENGTH OF TABLE
;SET NODE DUMP/LOAD FILE

SETNDF:	STKVAR <SDFFIL>
	CALL PRSOFI		;PARSE AN OUTPUT FILE SPEC
	 JRST DOREQE		;FAILED
	MOVEM T1,SDFFIL		;SAVE POINTER TO OUTPUT FILE SPEC
	CALL PRSCFM		;PARSE END OF COMMAND
	 JRST DOREQE		;FAILED
	LOAD T1,NDDMP,(P3)	;GET POINTER TO OLD FILE
	JUMPN T1,[CALL RELFRE	;RELEASE THE OLD BLOCK
		   FATAL.ERROR	;FAILED, ISSUE MESSAGE AND CONTINUE
		  JRST .+1]	;CONTINUE
	SETONE NDDOK,(P3)	;TELL AUTO DUMP - WE CONTROL THIS NIB
	MOVE T1,SDFFIL		;GET NEW FILE SPEC POINTER
	STOR T1,NDDMP,(P3)	;SAVE POINTER TO NEW FILE SPEC
	RETSKP			;DONE, RETURN SUCCESS



SETNLF:	STKVAR <SLFFIL>
	CALL PRSIFI		;PARSE AN INPUT FILE SPEC
	 JRST DOREQE		;FAILED
	MOVEM T1,SLFFIL		;SAVE POINTER TO INPUT FILE SPEC
	CALL PRSCFM		;PARSE END OF COMMAND
	 JRST DOREQE		;FAILED
	LOAD T1,NDLOD,(P3)	;GET POINTER TO OLD FILE
	JUMPN T1,[CALL RELFRE	;RELEASE THE OLD BLOCK
		   FATAL.ERROR	;FAILED, ISSUE MESSAGE AND CONTINUE
		  JRST .+1]	;CONTINUE
	SETONE NDLOK,(P3)	;TELL AUTO LOAD - WE CONTROL THIS NIB
	MOVE T1,SLFFIL		;GET NEW FILE SPEC POINTER
	STOR T1,NDLOD,(P3)	;SAVE POINTER TO NEW FILE SPEC
	RETSKP			;DONE, RETURN SUCCESS


; SET NODE BOOT PASSWORD

SETNBP:	JRST DOREQE		;NOT SUPPORTED YET
;SET NODE SERVER

SETNSV:	STKVAR <SNSNOD>
	LOAD T1,NDSRV,(P3)	;GET POINTER TO SERVER NODE NAME
	JUMPN T1,[CALL RELFRE	;RELEASE THE OLD BLOCK
		   FATAL.ERROR	;FAILED, ISSUE MESSAGE AND CONTINUE
		  JRST .+1]	;CONTINUE
	CALL PRSNOD		;PARSE NODE NAME
	 JRST DOREQE		;FAILED, RETURN ERROR
	MOVEM T1,SNSNOD		;SAVE POINTER TO NODE NAME
	CALL PRSLID		;PARSE A LINE ID
	 JRST DOREQE		;FAILED
	STOR T1,NDSL1,(P3)	;STORE SERVER LINE ID IN
	STOR T2,NDSL2,(P3)	; TARGET NODE NIB
	MOVE T1,SNSNOD		;GET POINTER TO NODE NAME
	STOR T1,NDSRV,(P3)	;PUT POINTER TO STRING IN NIB
	LOAD T1,NDSRV,(P3)	;GET POINTER TO ASCIZ SERVER NODE NAME
	CALL FOCNIB		;GO GET ADDRESS OF SERVER'S NIB
	 JRST DOREQE		;FAILED
	LOAD T2,NDSL1,(P3)	;GET FIRST PART OF SERVER LINE ID
	LOAD T3,NDSL2,(P3)	;GET SECOND PART OF SERVER LINE ID
	CALL FOCLIN		;FIND OR CREATE ENTRY FOR THIS LINE
	 JRST DOREQE		;FAILED
	STOR P3,LTNIB,(T1)	;STORE NIB ADR OF TARGET NODE IN LINE TABLE
	RETSKP
;SET NODE LOAD-PARAMETERS

SETNLP:	CALL PRSCMA		;PARSED A COMMA ?
	 JFCL			;NO, TRY NEXT ARG TYPE
	CALL PRSCFM		;PARSE END OF COMMAND
	RETSKP			;YES, DONE
	CALL PRSKEY		;PARSE A KEYWORD
	JRST DOREQE		;NOT FOUND
	MOVEI T2,SETLPT		;GET ADR OF THE DISPATCH TABLE
	MOVEI T3,SETLPL		;AND ITS LENGTH
	CALL FNDDSP		;FIND THE DISPATCH ADDRESS
	 JRST DOREQE		;FAILED TO FIND IT
	JRST (T1)		;DISPATCH

SETLPT:	.DNLPH,,SETNHS		;SET NODE LOAD-PARAMETERS HOST
	.DNLPN,,SETNNM		;SET NODE LOAD-PARAMETERS NAME
	.DNLP1,,SETNNU		;SET NODE LOAD-PARAMETERS NUMBER
	.DNNON,,SETNON		;SET NODE LOAD-PARAMETERS NONE
SETLPL==.-SETLPT


;SET NODE LOAD-PARAMETERS NONE

SETNON:	LOAD T1,NDPNA,(P3)	;GET POINTER TO NODE NAME
	SETZRO NDPNA,(P3)	;CLEAR IT
	HRRZS T1		;GET ADR OF STRING
	JUMPE T1,SETNO1		;ANYTHING THERE?
	CALL RELFRE		;YES, RELEASE THE SPACE
	 FATAL.ERROR
SETNO1:	LOAD T1,NDPHT,(P3)	;GET POINTER TO HOST NAME
	SETZRO NDPHT,(P3)	;ZERO THE ENTRY
	HRRZS T1		;GET JUST THE ADDRESS
	JUMPE T1,SETNO2		;ANYTHING THERE?
	CALL RELFRE		;YES, RELEASE THE SPACE
	 FATAL.ERROR
SETNO2:	SETZRO NDPNU,(P3)	;CLEAR THE NUMBER
	RETSKP			;RETURN
;SET NODE LOAD-PARAMETERS NAME

SETNNM:	STKVAR <NNMNOD>
	CALL PRSNOD		;PARSE A NODE NAME
	 RETBAD ()		;FAILED
	MOVEM T1,NNMNOD		;SAVE POINTER TO NODE NAME
	LOAD T1,NDPNA,(P3)	;GET PREVIOUS NAME
	JUMPN T1,[CALL RELFRE	;RELEASE THE OLD BLOCK
		   FATAL.ERROR	;FAILED, ISSUE MESSAGE AND CONTINUE
		  JRST .+1]	;CONTINUE
	MOVE T1,NNMNOD		;GET NEW NODE NAME
	STOR T1,NDPNA,(P3)	;STORE NEW NAME IN NIB
	JRST SETNLP		;LOOP BACK FOR ANY OTHER PARAMETERS



;SET NODE LOAD-PARAMETERS HOST

SETNHS:	STKVAR <NHSNOD>
	CALL PRSNOD		;PARSE A NODE NAME
	 RETBAD ()		;FAILED
	MOVEM T1,NHSNOD		;SAVE POINTER TO NODE NAME
	LOAD T1,NDPHT,(P3)	;GET POINTER TO SERVER NODE NAME
	JUMPN T1,[CALL RELFRE	;RELEASE THE OLD BLOCK
		   FATAL.ERROR	;FAILED, ISSUE MESSAGE AND CONTINUE
		  JRST .+1]	;CONTINUE
	MOVE T1,NHSNOD		;GET NEW NODE NAME
	STOR T1,NDPHT,(P3)	;PUT POINTER TO STRING IN NIB
	JRST SETNLP		;LOOP BACK FOR ANY OTHER PARAMETERS



;SET NODE LOAD-PARAMETERS NUMBER

SETNNU:	CALL PRSNUM		;PARSE NODE NUMBER
	 RETBAD ()		;FAILED
	STOR T1,NDPNU,(P3)	;STORE THE NUMBER
	JRST SETNLP		;LOOP BACK FOR ANY OTHER PARAMETERS
SETSDF:	MOVX Q1,.PTSDM		;SET SECONDARY-DUMP-FILE
	JRST SETFIL		;GO STORE FILESPEC

SETSLF:	MOVX Q1,.PTSLD		;SET SECONDARY-LOAD-FILE
	JRST SETFIL		;GO STORE FILESPEC

SETTDF:	MOVX Q1,.PTTDM		;SET TERTIARY-DUMP-FILE
	JRST SETFIL		;GO STORE FILESPEC

SETTLF:	MOVX Q1,.PTTLD		;SET TERTIARY-LOAD FILE
	JRST SETFIL		;GO STORE FILESPEC
; SETFIL - ROUTINE TO SET UP DUMP OR LOAD FILE SPECS
;
;ACCEPTS IN Q1/	PROGRAM TYPE

SETFIL:	STKVAR <SFLFIL>
	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,SETDVT		;GET POINTER TO DEVICE TABLE
	MOVEI T3,SETDVL		;AND LENGTH OF TABLE
	CALL FNDDSP		;FIND DEVICE TYPE
	 JRST DOREQE		;NOT FOUND
	MOVE Q2,T1		;SAVE DEVICE TYPE
	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,SETCPT		;GET POINTER TO CPU TABLE
	MOVEI T3,SETCPL		;AND ITS LENGTH
	CALL FNDDSP		;GET CPU TYPE CODE
	 JRST DOREQE		;NOT FOUND
	MOVE Q3,T1		;SAVE CPU TYPE
	MOVE T1,Q2		;NOW FIND THE PGM TABLE ENTRY FOR THIS
	MOVE T2,Q3		;SET UP DEVICE TYPE AND CPU TYPE
	MOVE T3,Q1		;AND PROGRAM TYPE
	CALL FOCPGM		;GO GET A PGM TABLE ENTRY
	 RETBAD (.ERR15)	;NO MORE SPACE FOR A NEW ENTRY
	MOVE Q2,T1		;SAVE THE ADDRESS OF THE ENTRY
	CALL PRSFIL		;PARSE A FILE-SPEC
	 RETBAD ()		;FAILED, RETURN ERROR
	MOVEM T1,SFLFIL		;SAVE FILE SPEC
	CALL PRSCFM		;PARSE COMMAND CONFIRMATION
	 RETBAD ()		;FAILED
	LOAD T1,PGFIL,(Q2)	;GET OLD FILE SPEC
	JUMPN T1,[CALL RELFRE	;RELEASE THE OLD BLOCK
		   FATAL.ERROR	;FAILED, ISSUE MESSAGE AND CONTINUE
		  JRST .+1]	;CONTINUE
	MOVE T1,SFLFIL		;GET FILE SPEC
	STOR T1,PGFIL,(Q2)	;STORE THE NEW FILE SPEC
	RETSKP			;DONE
SETFTB:	.DNSSD,,.PTSDM		;SET SECONDARY-DUMP-FILE
	.DNSSL,,.PTSLD		;SET SECONDARY-LOAD-FILE
	.DNSTD,,.PTTDM		;SET TERTIARY-DUMP-FILE
	.DNSTL,,.PTTLD		;SET TERTIARY-LOAD-FILE
SETFTL==.-SETFTB

SETDVT:	.DND11,,.DTP11		;DP11
	.DNKDP,,.DTKDP		;KMC-DUP
	.DNKDZ,,.DTKDZ		;KMC-DZ
	.DNU11,,.DTU11		;DU11
	.DNL1E,,.DTL1E		;DL11E
	.DNQ11,,.DTQ11		;DQ11
	.DNA11,,.DTA11		;DA11A
	.DNDUP,,.DTDUP		;DUP11
	.DNDMC,,.DTDMC		;DMC11
	.DNDLV,,.DTDLV		;DLV11
	.DNL1A,,.DTL1A		;DL11A
	.DNDTE,,.DTDTE		;DTE-20
	.DNDV1,,.DTDV1		;DV11
SETDVL==.-SETDVT

SETCPT:	.DNP8,,.CP8		;PDP-8
	.DNP11,,.CP11		;PDP-11
	.DND20,,.CP20		;DEC-20
SETCPL==.-SETCPT
;SET STATE LINE LINE-ID OFF/ON

SETSTA:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;FAILED, NOT A KEYWORD
	CAIE T1,.DNSLI		;IS THIS LINE ?
	JRST DOREQE		;NOT FOUND
	CALL PRSLID		;PARSE THE LINE-ID
	 RETBAD (.ERR23)	;<Invalid line-id>
	DMOVE Q1,T1		;SAVE LINE ID
	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;FAILED, NOT A KEYWORD
	MOVE Q3,T1		;COPY LINE STATE KEYWORD
	CALL PRSCFM		;PARSE CONFIRMATION
	 JRST DOREQE		;FAILED
	MOVE T1,Q3		;GET LINE STATE CODE FROM COMMAND
	MOVEI T2,LSTTAB		;GET ADDRESS OF LINE STATE TABLE
	MOVEI T3,LSTLEN		;GET LENGTH OF TABLE
	CALL FNDDSP		;GET NICE PROTOCOL LINE STATE CODE
	 RETBAD ()		;FAILED
	DMOVE T2,Q1		;GET LINE ID
	CALL LINSET		;GO SEND MSG TO SET LINE STATE
	 RETBAD ()		;FAILED
	RETSKP			;DONE


; TABLE OF LINE STATE CODE MAPPINGS

LSTTAB:	.DNSSO,,.LSTON
	.DNSSF,,.LSTOF
	.DNCNL,,.LSTCN
	.DNCBL,,.LSTCB
	.DNMNT,,.LSTMN

LSTLEN==.-LSTTAB
;SET NODE node AUTO-DUMP 

SETADM:	CALL PRSKEY		;GET THE NEXT KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,SETDDL		;GET DISPATCH TABLE ADDRESS
	MOVEI T3,SETDLN		; AND LENGTH OF TABLE
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 JRST DOREQE		;WRONG TYPE
	JRST (T1)

SETDDL:	.DNEAB,,SETDEN		;SET NODE node AUTO-DUMP ENABLED
	.DNDAB,,SETDDA		;SET NODE node AUTO-DUMP DISABLED
SETDLN==.-SETDDL

; SET NODE node AUTO-DUMP ENABLED

SETDEN:	SETONE NDFRD,(P3)	;TURN ON AUTO DUMPING
	RETSKP

;SET NODE node AUTO-DUMP DISABLED

SETDDA:	SETZRO NDFRD,(P3)	;TURN OFF AUTO DUMPING
	RETSKP
;SET NODE node AUTO-LOAD 

SETALD:	CALL PRSKEY		;GET THE NEXT KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,SETLDL		;GET DISPATCH TABLE ADDRESS
	MOVEI T3,SETLLN		; AND LENGTH OF TABLE
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 JRST DOREQE		;WRONG TYPE
	JRST (T1)

SETLDL:	.DNEAB,,SETLEN		;SET NODE node AUTO-LOAD ENABLED
	.DNDAB,,SETLDA		;SET NODE node AUTO-LOAD DISABLED
SETLLN==.-SETLDL

; SET NODE node AUTO-LOAD ENABLED

SETLEN:	SETONE NDFRL,(P3)	;TURN ON AUTO LOADING
	RETSKP

;SET NODE node AUTO-LOAD DISABLED

SETLDA:	SETZRO NDFRL,(P3)	;TURN OFF AUTO LOADING
	RETSKP
;LINSET - ROUTINE TO ASSEMBLE AND SEND A NICE "SET PARAMETERS" MSG
;	    TO SET A LINE STATE
;
;ACCEPTS IN T1/	LINE STATE
;	    T2-T3/ STANDARD NICE LINE ID
;		CALL LINSET
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, MESSAGE SENT

LINSET:	STKVAR <<LNSMSG,50>>
	MOVEI T4,LNSMSG		;GET ADDRESS WHERE MESSAGE IS TO GO
	CALL MAKSLN		;GO ASSEMBLE A NICE "SET PARAMETER" MESSAGE
	 RETBAD ()		;FAILED, RETURN ERROR
	MOVE T4,[.NCSET,,.NCSLN] ;GET NICE FUNCTION CODE,,OPTION CODE
	MOVE T3,T2		;COPY COUNT
	MOVE T2,T1		;COPY POINTER TO START OF MESSAGE
	MOVE T1,P1		;GET ADR OF MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;DONE, RETURN SUCCESS
SUBTTL	NCP -- LOAD Command

LOAREQ:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;FAILED, NOT A KEYWORD
	MOVEI T2,LOARTB		;GET DISPATCH ADDRESS
	MOVEI T3,LOARTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET ADDRESS TO DISPATCH TO
	 JRST DOREQE		;NOT FOUND
	JRST (T1)		;DISPATCH

LOARTB:	.DNSLI,,LOALIN		;LOAD LINE
	.DNNOD,,LOAREM		;LOAD REMOTE
	.DNVIA,,LOAVIA		;LOAD VIA
LOARTL==.-LOARTB
;LOAD LINE-ID (from) FILESPEC
LOALIN:	STKVAR <<BTLBLK,14>,<BTLPAG,2>,BTLFIL>
	CALL PRSKDP		;GET KMC11 ADR
	 RETBAD (.ERR23)	;<Invalid line-id>
	MOVEM T1,.BTKMC+BTLBLK	;SAVE ADR OF KMC11 TO LOAD
;	CALL PRSKEY		;PARSE KEYWORD
;	 RETBAD ()		;FAILED
;	CAIE T1,.DNLFR		;KEYWORD "FROM" ?
;	JRST DOREQE		;NO, UNIMPLEMENTED COMMAND
	CALL PRSIFI		;PARSE AN INPUT FILE
	 RETBAD ()		;FAILED
	MOVEM T1,BTLFIL		;SAVE POINTER TO FILE SPEC FOR LATER
	CALL PRSCFM		;PARSE END OF COMMAND
	 RETBAD ()		;FAILED
	MOVE T2,BTLFIL		;COPY POINTER TO FILESPEC
	MOVX T1,GJ%OLD!GJ%SHT	;FILE FOR INPUT USE, SHORT CALL
	GTJFN			;GET A JFN FOR INPUT FILE
	 RETBAD (.ERR24)	;<Could not open file>
	HRRZM T1,BTLFIL		;SAVE JFN
	MOVE T2,[070000,,OF%RD]	;7-BIT BYTES, READ ACCESS ONLY
	OPENF			;OPEN THE FILE
	 JRST [	MOVEI T4,.ERR24 ;<Could not open file>
		JRST LOAKD6 ]
	CALL ASGPAG		;GET A PAGE ADR FOR CRAM DATA
	 JRST [	MOVE T4,T1	;COPY ERROR CODE
		JRST LOAKD6 ]
	MOVEM T2,BTLPAG		;SAVE ADR OF FIRST WORD IN PAGE
	SETZM (T2)		;CLEAR FIRST WORD IN PAGE
	HRLI T1,(T2)		;MAKE BLT POINTER
	HRRI T1,1(T2)
	BLT T1,777(T2)		;CLEAR THE PAGE
	CALL ASGPAG		;GET A PAGE ADR FOR DRAM DATA
	 JRST [	MOVE T4,T1	;COPY ERROR CODE
		JRST LOAKD5 ]
	MOVEM T2,1+BTLPAG	;SAVE ADR OF FIRST WORD IN PAGE
	SETZM (T2)		;CLEAR FIRST WORD IN PAGE
	HRLI T1,(T2)		;MAKE BLT POINTER
	HRRI T1,1(T2)
	BLT T1,777(T2)		;CLEAR THE PAGE
	SETZM .BTKSA+BTLBLK	;NO STARTING ADDRESS YET
	MOVE T1,BTLFIL		;GET FILE JFN
LOAKD1:	BIN			;GET NEXT BYTE
	ERJMP LOAKD3		;IN CASE EOF
	CAIN T2,"C"		;IS THIS CRAM DATA ?
	JRST LDKMC1		;LOADING THE CRAM
	CAIN T2,"D"		;IS THIS DRAM DATA ?
	JRST LDKMD1		;LOADING THE DRAM
	CAIE T2,15		;IS THIS A CARRIAGE RETURN ?
	CAIN T2,12		;OR A LINE FEED ?
	JRST LOAKD1		;YES SO LOOK FOR COMMAND TYPE
	CAIN T2,14		;OR A FORM FEED ?
	JRST LOAKD1		;YES SO LOOK FOR TYPE OF COMMAND
	CAIE T2,";"		;IS THIS A COMMENT LINE ?
	JRST LOAKMX		;Bad data in load file
LOAKD2:	BIN			;GET NEXT CHARACTER
	ERJMP LOAKD3
	CAIE T2,12		;IS THIS A LINE FEED ?
	CAIN T2,14		;OR A FORM FEED
	JRST LOAKD1		;YES SO LOOK FOR COMMAND CHARACTER
	JRST LOAKD2		;KEEP FLUSHING LINE

LOAKD3:	SETZM .BTKER+BTLBLK	;INITIALIZE FLAGS
	MOVE T1,BTLPAG		;GET ADR OF PAGE
	HRLI T1,(POINT 16,)	;MAKE INTO BYTE POINTER
	MOVEM T1,.BTKCP+BTLBLK
	MOVEI T1,2000		;COUNT FOR CRAM
	MOVEM T1,.BTKCC+BTLBLK
	MOVE T1,1+BTLPAG	;GET ADR OF PAGE
	HRLI T1,(POINT 8,)	;MAKE INTO BYTE POINTER
	MOVEM T1,.BTKDP+BTLBLK
	MOVEI T1,2000		;COUNT FOR DRAM
	MOVEM T1,.BTKDC+BTLBLK
	SETZM .BTKRC+BTLBLK	;NOT LOADING REGISTERS
	MOVEI T1,.BTKML		;WANT TO LOAD THE KMC11
	MOVEI T2,BTLBLK		;POINT TO BLOCK
	BOOT
	 ERJMP [MOVEI T4,.ERR19	;JSYS error
		JRST LOAKD4 ]
	SETZ T4,		;LOAD WON
LOAKD4:	MOVE T1,1+BTLPAG	;GET ADR OF FIRST WORD IN PAGE
	CALL RELPGA		;RELEASE THE PAGE
	 MOVE T4,T1		;COPY ERROR CODE
LOAKD5:	MOVE T1,BTLPAG		;GET ADR OF FIRST WORD IN PAGE
	CALL RELPGA		;RELEASE THE PAGE
	 MOVE T4,T1		;COPY ERROR CODE
LOAKD6:	MOVE T1,BTLFIL		;GET FILE JFN
	RLJFN			;RELEASE THE JFN
	 ERJMP .+1
	SKIPE T1,T4		;WAS THERE AN ERROR ?
	 RET			;YES SO LOSE RETURN
	RETSKP
	JRST DOREQE		;CAN'T DO IT
;HERE TO READ CRAM DATA TO LOAD IN KMC11
LDKMC1:	MOVE T2,BTLPAG		;GET ADR OF PAGE
	HRLI T2,(POINT 16,)	;MAKE POINTER TO AREA
	CALL LDKMCX		;GET THE DATA
	 JRST LOAKMX		;LOST
	SKIPE T2		;WAS THIS A STARTING ADDRESS ?
	MOVEM T2,.BTKSA+BTLBLK	;SAVE STARTING ADDRESS
	JRST LOAKD1		;ON TO NEXT LINE

;HERE TO READ DRAM DATA TO LOAD IN KMC11
LDKMD1:	MOVE T2,1+BTLPAG	;GET ADR OF PAGE
	HRLI T2,(POINT 8,)	;MAKE POINTER TO DATA
	CALL LDKMCX		;GET THE DATA
	 JRST LOAKMX		;LOST
	JUMPE T2,LOAKD1		;ON TO NEXT LINE
LOAKMX:	MOVEI T4,.ERR25		;Bad data in load file
	JRST LOAKD4

LDKMCX:	SAVEQ			;SAVE THE Q REGISTERS
	MOVE Q1,T2		;SAVE POINTER
	BIN			;GET SPACE
	ERJMP R			;LOSE ON EOF
	SETZ T4,		;ACCUMULATE THE CHECKSUM HERE
	CAIN T2,40		;IS THIS A SPACE ?
	CALL LOAKMN		;GET WORD COUNT FROM THE FILE
	 RET			;LOST
	SKIPL Q2,T2		;SAVE COUNT
	CALL LOAKMN		;GET ADDRESS FROM THE FILE
	 RET			;LOST
	SKIPG T3,Q2		;COPY COUNT
	JRST [	MOVEM T2,Q1	;SAVE STARTING ADDRESS
		CALL LOAKMN	;GET THE CHECKSUM
		 RET		;LOST
		MOVE T2,Q1	;PICK UP STARTING ADDRESS
		HRLI T2,(BT%KSA) ;THIS IS A STARTING ADDRESS
		JUMPE T4,RSKP	;IF CHECKSUM OK WE WON
		RET ]
	ADDI T3,T2
	CAILE T3,2000		;IS THIS REASONABLE ?
	RET
	CAIA
	IBP Q1			;ADVANCE BYTE POINTER
	SOJGE T2,.-1		;LOOP TILL HIT RIGHT BYTE
	CALL LOAKMN		;GET NEXT DATA BYTE
	 RET
	IDPB T2,Q1		;PUT BYTE INTO DATA
	SOJG Q2,.-3
	CALL LOAKMN		;GET THE CHECKSUM
	 RET
	SETZ T2,
	JUMPE T4,RSKP		;IF CHKSUM IS 0 WE WON
	RET
;HERE TO GET A NUMBER FROM A LOAD FILE
LOAKMN:	SAVEQ			;SAVE THE Q REGISTERS
	SETZB Q2,Q3		;BUILD NUMBER HERE
LOAKM2:	BIN			;GET 
	ERJMP R
	CAIL T2,75		;IS THIS ENCODED DATA ?
	CAILE T2,174
	JRST [	IMULI Q3,6	;MAKE HOW MUCH TO ROTATE BACK
		ROTC Q1,(Q3)
		MOVE T2,Q2	;COPY DATA
		ADD T4,Q2	;INCLUDE IN CHECKSUM
		ANDI T4,177777	;STRIP OVERFLOW
		RETSKP ]
	ANDI T2,77		;STRIP EXTRA BITS
	ADDI Q2,(T2)		;INCLUDE IN NUMBER
	ROTC Q1,-6		;POSITION OLD BITS
	AOJA Q3,LOAKM2		;GET NEXT CHARACTER
	RET
LOAVIA:	JRST DOREQE		;LOAD VIA NOT YET SUPPORTED





LOAREM:	STKVAR <<LOARMS,24>,<LOARBP,2>,LOARMC,LOARFS,LOARHO,LOARSV,LOARSL,LOARNM,LOARNU,LOARNO,LOARCT,LOARSP>
	SETZM LOARBP		;NO BOOT
	SETZM 1+LOARBP		; PASSWORD YET
	SETZM LOARHO		;NO HOST YET
	SETZM LOARNM		;NO NAME YET
	SETZM LOARNO		;HAVE NOT SEEN "NONE" YET
	SETOM LOARNU		;NO NUMBER YET
	SETZM LOARFS		;NO FILE SPEC YET
	SETZM LOARSV		;NO SERVER SPECIFICATION
	SETZM LOARSL		;NOR A SERVER LINE
	CALL PRSNOD		;PARSE A NODE NAME
	 JRST DOREQE		;FAILED, NOT A NODE NAME
	CALL FOCNIB		;GET A NIB ADDRESS FOR THIS NODE
	 RETBAD ()		;NOT FOUND
	MOVE Q2,T1		;SAVE THE ADDRESS OF THE NODE NIB
LOARML:	CALL PRSCFM		;END OF COMMAND ?
	SKIPA			;NO, GO ON
	JRST LOARMD		;YES, GO SEND NICE LOAD REQ MESSAGE
	CALL PRSKEY		;PARSE A KEYWORD
	 RETBAD ()		;FAILED
	MOVEI T2,LORMTB		;GET DISPATCH TABLE ADDRESS
	MOVEI T3,LORMTL		;AND ITS LENGTH
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 JRST DOREQE		;UNKNOWN KEYWORD
	JRST 0(T1)		;DISPATCH

LORMTB:	.DNLFR,,LOARFR		;LOAD REMOTE FROM
	.DNVIA,,LOARVI		;LOAD REMOTE VIA
	.DNPRM,,LOARPR		;LOAD REMOTE PARAMETERS
LORMTL==.-LORMTB
;LOAD REMOTE <NODE> FROM

LOARFR:	CALL PRSIFI		;PARSE AN INPUT FILE SPEC
	 RETBAD ()		;FAILED
	MOVEM T1,LOARFS		;SAVE POINTER TO FILE SPEC FOR LATER
	JRST LOARML		;LOOP BACK TIL <CR>


;LOAD REMOTE <NODE> VIA

LOARVI:	JRST DOREQE		;NOT SUPPORTED YET


;LOAD REMOTE <NODE> PARAMETERS

LOARPR:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;FAILED, NOT A KEYWORD
	MOVEI T2,LOARPT		;GET ADR OF DISPATCH TABLE
	MOVEI T3,LOARPL		;AND ITS LENGTH
	CALL FNDDSP		;GET DISPATCH
	 JRST DOREQE		;UNKNOWN KEYWORD
	JRST (T1)		;DISPATCH

LOARPT:	.DNLPH,,LORPHO		;LOAD REMOTE PARAM HOST
	.DNLPN,,LORPNM		;LOAD REMOTE PARAM NAME
	.DNLP1,,LORPNU		;LOAD REMOTE PARAM NUMBER
	.DNNON,,LORPNO		;LOAD REMOTE PARAM NONE
LOARPL==.-LOARPT


;LOAD REMOTE <NODE> PARAMETERS HOST

LORPHO:	CALL PRSNOD		;PARSE A NODE NAME
	 RETBAD ()		;FAILED
	MOVEM T1,LOARHO		;SAVE NODE NAME POINTER
	CALL FOCNIB		;GET POINTER TO NIB FOR THIS NODE
	 JRST [	MOVE T1,LOARHO	;FAILED, GET NODE NAME POINTER
		CALL RELFRE	;RELEASE FREE SPACE
		 FATAL.ERROR	;IGNORE FAILURE
		RETBAD () ]	;RETURN ERROR
	EXCH T1,LOARHO		;SAVE ADR OF NIB OF HOST
	CALL RELFRE		;RELEASE FREE BLOCK
	 FATAL.ERROR		;RELEASE FAILED, GO ON
	JRST LOARML		;LOOP BACK FOR OTHER KEYWORDS
;LOAD REMOTE <NODE> PARAMETERS NAME

LORPNM:	CALL PRSNOD		;PARSE A NODE NAME
	 RETBAD ()		;FAILED
	MOVEM T1,LOARNM		;SAVE NODE NAME POINTER
	CALL FOCNIB		;GET POINTER TO NIB FOR THIS NODE
	 JRST [	MOVE T1,LOARNM	;FAILED, GET NODE NAME POINTER
		CALL RELFRE	;RELEASE FREE SPACE
		 FATAL.ERROR	;IGNORE FAILURE
		RETBAD () ]	;RETURN ERROR
	EXCH T1,LOARNM		;SAVE ADR OF NIB OF HOST
	CALL RELFRE		;RELEASE FREE BLOCK
	 FATAL.ERROR		;RELEASE FAILED, GO ON
	JRST LOARML		;LOOP BACK FOR OTHER KEYWORDS


;LOAD REMOTE <NODE> PARAMETERS NUMBER

LORPNU:	CALL PRSNUM		;PARSE A NUMBER
	 RETBAD ()		;FAILED
	MOVEM T1,LOARNU		;SAVE THE NUMBER
	JRST LOARML		;LOOP BACK TIL CONFIRMATION


;LOAD REMOTE <NODE> PARAMETERS NONE

LORPNO:	SETZM LOARNU		;ZERO NUMBER
	SETZM LOARNM		;ZERO THE NMAE
	SETZM LOARHO		;ZERO THE HOST
	SETOM LOARNO		;MARK THAT "NONE" WAS SPECIFIED
	JRST LOARML		;LOOP BACK TIL <CR> SEEN
;LOAD REMOTE COMMAND FINISHED

LOARMD:	HRLI T1,(POINT 8,)	;FORM POINTER TO WHERE
	HRRI T1,LOARMS		; MESSAGE IS TO BE ASSEMBLED
	SETZM T2		;ZERO COUNT OF CHARACTERS IN NICE MESSAGE
	MOVEI T4,.NCRQL		;START BY MARKING THIS AS A "LOAD" 
	IDPB T4,T1		;   REQUEST MESSAGE
	ADDI T2,1		;INCREMENT COUNT OF CHARS IN MESSAGE
	MOVEI T4,0		;START WITH NO OPTIONS
	MOVX T3,.LOPTH		;ASSUME SERVER SPECIFICATION GIVEN IN COMMAND
	SKIPN LOARSV		;ANY SERVER SPECIFIED?
	MOVX T3,.LOTGT		;NO SERVER, BUT TARGET GIVEN IN COMMAND
	STOR T3,LO%TGT,T4	;ADD TARGET SPECIFICATION TO OPTION FIELD
	MOVX T3,.LOTBD		;TRIGGER BOOTSTRAP, ASSUME DEFAULT BOOT PASSWORD
	SKIPN LOARBP		;BOOT PASSWORD GIVEN IN COMMAND ?
	SKIPE 1+LOARBP		;...
	MOVX T3,.LOTBP		;YES, USE PASSWORD FROM COMMAND
	STOR T3,LO%ROM,T4	;STORE ROM BOOT FIELD IN OPTIONS
	SKIPE LOARFS		;IS THERE A FILE SPEC?
	TXO T4,LO%OPS		;YES, REMEMBER THAT
	TXO T4,LO%PAR		;at least host and node name parameters
				;  are always specified in message
	IDPB T4,T1		;STORE OPTION BITS
	ADDI T2,1		;INCREMENT COUNT OF CHARS IN MESSAGE
	; ..
	; ..

; ADD TARGET AND SERVER INFORMATION TO MESSAGE

	LOAD T3,NDNAM,(Q2)	;GET POINTER TO ASCIZ NAME OF TARGET NODE
	CALL MAKNOD		;GO ADD TARGET NODE NAME TO MESSAGE
	 JRST DOREQE		;FAILED, PUNT
	SKIPE LOARSV		;SERVER NODE SPECIFIED IN COMMAND ?
	JRST [	MOVE T3,LOARSV	;YES, GET POINTER TO ASCIZ SERVER NODE NAME
		CALL MAKNOD	;GO ASSEMBLE NODE NAME IN MESSAGE
		 JRST DOREQE	;FAILED, PUNT
;**** WHEN LOAD REMOTE VIA IS DONE, ADD LINE TO MESSAGE HERE
		JRST .+1]	;DONE WITH SERVER, GO DO NEXT FIELD
	SKIPN LOARBP		;BOOT PASSWORD GIVEN IN COMMAND ?
	SKIPE 1+LOARBP		;...
	JRST [	MOVEM T2,LOARMC	;YES, SAVE CURRENT BYTE COUNT
		MOVX T2,MBPWSZ	;GET SIZE OF BOOT PASSWORDS
		DMOVE T3,LOARBP	;GET BOOT PASSWORD TO ADD TO MESSAGE
		CALL MAKIMB	;GO ADD IMAGE BINARY FIELD TO MESSAGE
		MOVE T2,LOARMC	;RESTORE MESSAGE SIZE
		ADDI T2,MBPWSZ	;ACCOUNT FOR BOOT PASSWORD
		JRST .+1]	;GO ON TO NEXT FIELD IN MESSAGE

	SKIPE LOARFS		;FILE TO LOAD GIVEN IN COMMAND ?
	JRST [	MOVEM T2,LOARMC		;SAVE CURRENT MESSAGE SIZE
		MOVE T3,LOARFS	;YES, GET POINTER TO FILESPEC
		MOVEI T2,^D255	;FILESPEC CAN BE AS LONG AS LARGEST IMAGE FIELD
		CALL MAKIMA	;GO ADD IMAGE ASCII FIELD TO MESSAGE
		 JRST DOREQE	;FAILED, PUNT
		ADD T2,LOARMC	;GET UPDATED MESSAGE SIZE
		JRST .+1]	;RETURN TO MAINLINE CODE
	; ..
	; ..
	SKIPE LOARNO		;parameters "none" specified ?
	JRST LOD100		;YES, GO SEND NICE LOAD REQUEST MESSAGE
	MOVEM T2,LOARCT		;SAVE CURRENT BYTE COUNT
	SETZM T2		;INITIALIZE COUNT OF BYTES IN PARAMETERS
	MOVEM T1,LOARSP		;SAVE POINTER TO WHERE PARAMETER COUNT GOES
	IBP T1			;SKIP OVER PARAMETER COUNT BYTE
	LOAD T3,NDPNA,(Q2)	;GET POINTER TO DEFAULT NAME PARAM
	SKIPE LOARNM		;WAS NAME PARAMETER GIVEN IN COMMAND ?
	MOVE T3,LOARNM		;YES, GET POINTER TO NAME IN LOAD CMD
	JUMPE T3,LOD010		;IF NO NAME, GO CHECK DEFAULT HOST
	CALL MAKNAM		;GO ADD NODE NAME PARAMETER TO MESSAGE
	 JRST DOREQE		;FAILED
lod010:	LOAD T3,NDPHT,(Q2)	;GET POINTER TO DEFAULT HOST
	SKIPE LOARHO		;HOST SPECIFIED IN LOAD COMMAND ?
	MOVE T3,LOARHO		;YES, USE SPECIFIED HOST
	jumpe t3,lod020		;if no host, go check node number
	CALL MAKhst		;GO ADD HOST NODE NAME TO MESSAGE
	 JRST DOREQE		;FAILED
lod020:	LOAD T3,NDPNU,(Q2)	;GET DEFAULT NODE NUMBER PARAMETER
	SKIPL LOARNU		;NODE NUMBER GIVEN IN COMMAND ?
	MOVE T3,LOARNU		;YES, USE VALUE IN LOAD COMMAND
	SKIPL T3		;IF NO NUMBER DO NOT ADD TO MESSAGE
	CALL MAKNUM		;GO ASSEMBLE NODE NUMBER PARAMETER
	MOVX T3,.PVEND		;GET "END OF PARAMETERS" MARK
	IDPB T3,T1		;ADD END MARK TO MESSAGE
	ADDI T2,1		;ACCOUNT FOR END MARK IN BYTE COUNT
	IDPB T2,LOARSP		;STORE TOTAL BYTE COUNT FOR PARAMETERS
	ADDI T2,1		;ACCOUNT FOR PARAMETER COUNT BYTE
	ADD T2,LOARCT		;compute total byte count for message
; here when message completely assembled - send to nice process

LOD100:	SETONE NDLIP,(Q2)	;SET  LOAD IN PROGRESS
	MOVE T3,T2		;COPY COUNT
	MOVE T1,P1		;GET ADR OF MESSAGE
	MOVEI T2,LOARMS		;GET POINTER TO NICE MESSAGE
	HRLI T2,(POINT 8,0)	;SET UP BYTE POINTER
	HRLI T1,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	JE NDLOK,(Q2),LOD200	;JUMP IF NOT IN CHARGE OF LOADING THIS NODE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	HRROI T3,OURNAM		;SHOW WHAT EXECUTOR WE WANT
LOD200:	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;ALL DONE
SUBTTL	NCP -- DUMP Command

; DUMP NODE NODE-NAME

DMPREQ:	call prskey		;parse a keyword
	 jrst doreqe		;failed, not a keyword
	MOVEI T2,DMPRTB		;GET DISPATCH ADDRESS
	MOVEI T3,DMPRTL		;GET LENGTH OF DISPATCH TABLE
	CALL FNDDSP		;GET ADDRESS TO DISPATCH TO
	 JRST DOREQE		;NOT FOUND
	JRST (T1)		;DISPATCH

DMPRTB:	.DNSLI,,DMPLIN		;DUMP LINE
	.DNNOD,,DMPREM		;DUMP REMOTE
	.DNVIA,,DMPVIA		;DUMP VIA
DMPRTL==.-DMPRTB

DMPVIA:	JRST DOREQE		;DUMP VIA NOT YET SUPPORTED
;DUMP LINE-ID TO FILESPEC
DMPLIN:	TRVAR <<BTDBLK,14>,<BTDPAG,2>,BTDFIL>
	CALL PRSKDP		;GET KMC11 ADR
	 RETBAD (.ERR23)	;<Invalid line-id>
	MOVEM T1,.BTKMC+BTDBLK	;SAVE ADR OF KMC11
	CALL PRSKEY		;PARSE KEYWORD
	 RETBAD ()		;FAILED
	CAIE T1,.DNDR2		;KEYWORD "TO" ?
	JRST DOREQE		;NO, UNIMPLEMENTED COMMAND
	CALL PRSOFI		;PARSE OUTPUT FILESPEC
	 RETBAD ()		;FAILED
	MOVEM T1,BTDFIL		;SAVE POINTER TO FILE SPEC FOR LATER
	CALL PRSCFM		;PARSE CONFIRMATION
	 RETBAD ()		;FAILED
	MOVE T2,BTDFIL		;COPY POINTER TO FILESPEC
	MOVX T1,GJ%FOU!GJ%SHT	;FILE FOR OUTPUT USE, SHORT CALL
	GTJFN			;GET A JFN FOR OUTPUT FILE
	 RETBAD (.ERR24)	;<Could not open file>
	HRRZM T1,BTDFIL		;SAVE JFN
	MOVE T2,[070000,,OF%WR]	;7-BIT BYTES, WRITE ACCESS ONLY
	OPENF			;OPEN THE FILE
	 JRST [	MOVEI T4,.ERR24 ;<Could not open file>
		JRST DMPLN9 ]
	CALL ASGPAG		;GET A PAGE ADR FOR CRAM DUMP
	 JRST [	MOVE T4,T1	;COPY ERROR CODE
		JRST DMPLN9 ]	;CLEAN UP AND LEAVE
	MOVEM T2,BTDPAG		;SAVE ADR OF FIRST WORD IN PAGE
	CALL ASGPAG		;GET A PAGE ADR FOR DRAM & REG DUMP
	 JRST [	MOVE T4,T1	;COPY ERROR CODE
		JRST DMPLN8 ]	;CLEAN UP AND LEAVE
	MOVEM T2,1+BTDPAG	;SAVE ADR OF FIRST WORD IN PAGE
	MOVEI T1,20		;NUMBER OF REGISTERS TO GET
	MOVEM T1,.BTKRC+BTDBLK
	ADD T2,[POINT 16,400]	;GET 16 BIT BYTES
	MOVEM T2,.BTKRP+BTDBLK	;WHERE TO PUT REGISTERS
	MOVEI T1,2000		;NUMBER OF DRAM BYTES TO GET
	MOVEM T1,.BTKDC+BTDBLK
	MOVE T2,1+BTDPAG	;GET ADR OF PAGE AGAIN
	HRLI T2,(POINT 8,)	;8 BIT BYTES FOR DRAM
	MOVEM T2,.BTKDP+BTDBLK
	MOVEI T1,2000		;NUMBER OF CRAM LOCATIONS TO GET
	MOVEM T1,.BTKCC+BTDBLK	;NUMBER OF CRAM WORDS TO GET
	MOVE T2,BTDPAG		;GET ADR OF PAGE
	HRLI T2,(POINT 16,)	;16 BIT BYTES FOR CRAM
	MOVEM T2,.BTKCP+BTDBLK
	MOVEI T1,.BTKMD		;WANT TO DUMP THE KMC11
	MOVEI T2,BTDBLK		;POINT TO ARGUMENT BLOCK
	BOOT
	 ERJMP [MOVEI T4,.ERR19	;<JSYS error>
		JRST DMPLN8 ]	;NOW EXIT
	;..
	;..
	MOVE T1,BTDFIL
	HRROI T2,[ASCIZ \	Register data\]
	MOVEI T3,20		;NUMBER OF REGISTERS WE ASKED FOR
	SUB T3,.BTKRC+BTDBLK	;MAKES NUMBER OF REGISTERS WE GOT
	MOVE T4,1+BTDPAG	;POINT TO REGISTER DATA
	ADD T4,[POINT ^D16,400]	;16 BIT BYTES
	CALL DMPLDT		;DUMP THE REGISTERS
	HRROI T2,[ASCIZ \	DRAM data\]
	MOVEI T3,2000		;NUMBER OF DRAM WE ASKED FOR
	SUB T3,.BTKDC+BTDBLK	;MAKES NUMBER OF DRAM WE GOT
	MOVE T4,1+BTDPAG	;POINT TO DRAM DATA
	HRLI T4,(POINT 8,)	;8 BIT BYTES
	CALL DMPLDT		;DUMP THE DRAM
	HRROI T2,[ASCIZ \	CRAM data\]
	MOVEI T3,2000		;NUMBER OF CRAMS WE ASKED FOR
	SUB T3,.BTKCC+BTDBLK	;MAKES NUMBER OF CRAMS WE GOT
	MOVE T4,BTDPAG		;POINT TO CRAM DATA
	HRLI T4,(POINT 16,)	;16 BIT BYTES
	CALL DMPLDT		;DUMP THE CRAMS
	SETZ T4,		;DUMP WON
DMPLN7:	MOVE T1,1+BTDPAG	;ADR OF FIRST WORD IN PAGE
	CALL RELPGA		;RELEASE THE PAGE
	 MOVE T4,T1		;COPY THE ERROR CODE
DMPLN8:	MOVE T1,BTDPAG		;ADR OF FIRST WORD IN PAGE
	CALL RELPGA		;RELEASE THE PAGE
	 MOVE T4,T1		;COPY THE ERROR CODE
DMPLN9:	HRRZ T1,BTDFIL		;GET DUMP JFN
	CLOSF			;CLOSE FILE
	 RETBAD (.ERR24)	;<Could not open file>
	SKIPE T1,T4		;WAS THERE AN ERROR ?
	RET
	RETSKP			;HAVE MADE DUMP
DMPLDT:	MOVEM T3,.BTKRC+BTDBLK	;SAVE COUNT OF DATA
	MOVEM T4,.BTKRP+BTDBLK	;SAVE POINTER TO DATA
	MOVEM T2,.BTKERR+BTDBLK	;SAVE TYPE OF DATA
	HRROI T2,[ASCIZ \Dump of KDP_\]
	SETZ T3,
	SOUT
	MOVE T2,.BTKMC+BTDBLK	;GET KMC11 ADR
	SUB T2,[3,,760540]	;MAKE RELATIVE KMC ADR
	LSH T2,-3		;MAKE UNIT NUMBER
	MOVEI T3,^D8		;OCTAL
	NOUT
	 ERJMP .+1
	HRROI T2,[ASCIZ \ made on \]
	SETZ T3,
	SOUT
	SETO T2,		;CURRENT DATE AND TIME
	SETZ T3,		;FORMAT
	ODTIM
	MOVE T2,.BTKERR+BTDBLK	;GET TYPE OF DATA
	SETZ T3,
	SOUT
	SETZ T4,		;FIRST ADR TO DUMP
DMPLD2:	TRNE T4,7		;TIME FOR A CR/LF ?
	JRST DMPLD4		;NO
	CALL DMPCRL		;PUT OUT A CR/LF
	TRNN T4,37		;TIME FOR AN EXTRA CR/LF
	CALL DMPCRL		;PUT OUT A CR/LF
	MOVE T2,T4		;CURRENT LOCATION NUMBER
	MOVE T3,[NO%LFL+6B17+10] ;OCTAL
	NOUT			;PUT CURRENT LOCATION NUMBER
	ERJMP .+1
	MOVEI T2,"/"
	BOUT
DMPLD4:	ILDB T2,.BTKRP+BTDBLK	;GET NEXT PIECE OF DATA
	MOVE T3,[NO%LFL+10B17+^D8] ;LEADING FILLER
	NOUT			;PRINT DATA
	JFCL
	SOSLE .BTKRC+BTDBLK	;ANY LEFT ?
	AOJA T4,DMPLD2		;ON TO NEXT LOCATION
	CALL .+1		;ADD CR/LF
	CALL DMPCRL		;END WITH A CR/LF
	;RET			;ALL DONE

;HERE TO PUT OUT A CR/LF
DMPCRL:	HRROI T2,[BYTE (7)15,12,0] ;CR/LF
	SETZ T3,
	SOUT
	RET
;HERE TO GET KDP_#
PRSKDP:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;FAILED, NOT A KEYWORD
	CAIE T1,.DNKDP		;AND IS IT KDP ?
	 RET
	MOVX T1,"_"		;GET EXPECTED TOKEN
	CALL PRSTOK		;PARSE THE TOKEN
	 RETBAD ()		;FAILED
	CALL PRSNUM		;PARSE THE NUMBER
	 RETBAD ()		;FAILED
	CAIL T1,3		;POSSIBLE ?
	 RET
	IMULI T1,10		;CONVERT UNIT NUMBER TO OFFSE
	ADD T1,[3,,760540]	;MAKES ADR OF KMC11
	RETSKP
; DUMP NODE NODE-NAME

DMPREM:	STKVAR <DMPRFS,<DMPRMS,100>,DMPRMC>
	SETZM DMPRFS		;ASSUME NO FILESPEC GIVEN
	CALL PRSNOD		;PARSE A NODE NAME
	 RETBAD ()		;FAILED
	MOVEM T1,Q2		;SAVE ADDRESS OF BLOCK
	CALL FOCNIB		;GET A NIB ADDRESS FOR THIS NODE
	 JRST [	MOVE T1,Q2	;GET BLOCK ADDRESS
		CALL RELFRE	;RELEASE THE BLOCK
		 FATAL.ERROR
		RETBAD ()]	;NOT FOUND
	EXCH Q2,T1		;SAVE THE ADDRESS OF THE NODE NIB
	CALL RELFRE		;RELEASE FREE BLOCK
	 FATAL.ERROR		;FAILED
DMPRML:	CALL PRSCFM		;END OF COMMAND ?
	SKIPA			;NO, PARSE SOME MORE
	JRST DMPRMD		;YES, DONE WITH THE PARSING
	CALL PRSKEY		;PARSE A KEYWORD
	 RETBAD ()		;FAILED
	MOVEI T2,DMRMTB		;GET DISPATCH TABLE ADDRESS
	MOVEI T3,DMRMTL		;AND ITS LENGTH
	CALL FNDDSP		;GET DISPATCH ADDRESS
	 RETBAD ()		;FAILED
	JRST 0(T1)		;DISPATCH

DMRMTB:	.DNDR2,,DMPRFR		;DUMP REMOTE FROM
DMRMTL==.-DMRMTB
;DUMP REMOTE <NODE> TO FILE-SPEC

DMPRFR:	CALL PRSOFI		;PARSE OUTPUT FILE
	 RETBAD ()		;FAILED
	MOVEM T1,DMPRFS		;SAVE POINTER TO FILE SPEC FOR LATER
	JRST DMPRML		;LOOP BACK TIL <CR>


; HERE ON END OF DUMP COMMAND

DMPRMD:	HRLI T1,(POINT 8,)	;FORM POINTER TO WHERE
	HRRI T1,DMPRMS		; MESSAGE IS TO BE ASSEMBLED
	SETZM T2		;ZERO COUNT OF CHARACTERS IN NICE MESSAGE
	MOVEI T4,.NCRQD		;START BY MARKING THIS AS A "DUMP" 
	IDPB T4,T1		;   REQUEST MESSAGE
	ADDI T2,1		;INCREMENT COUNT OF CHARS IN MESSAGE
	SETZM T4		;ASSUME NO OPTIONS
	SKIPE DMPRFS		;WAS A FILESPEC SPECIFIED ?
	TXO T4,DO%FIL		;YES, SET OPTION BIT
	IDPB T4,T1		;STORE OPTION BITS
	ADDI T2,1		;INCREMENT COUNT OF CHARS IN MESSAGE

; ADD TARGET AND FILESPEC INFORMATION TO MESSAGE

	LOAD T3,NDNAM,(Q2)	;GET POINTER TO ASCIZ NAME OF TARGET NODE
	CALL MAKNOD		;GO ADD TARGET NODE NAME TO MESSAGE
	 JRST DOREQE		;FAILED, PUNT
	SKIPE DMPRFS		;FILE TO LOAD GIVEN IN COMMAND ?
	JRST [	MOVEM T2,DMPRMC		;SAVE CURRENT MESSAGE SIZE
		MOVE T3,DMPRFS	;YES, GET POINTER TO FILESPEC
		MOVEI T2,^D255	;FILESPEC CAN BE AS LONG AS LARGEST IMAGE FIELD
		CALL MAKIMA	;GO ADD IMAGE ASCII FIELD TO MESSAGE
		 JRST DOREQE	;FAILED, PUNT
		ADD T2,DMPRMC	;GET UPDATED MESSAGE SIZE
		JRST .+1]	;RETURN TO MAINLINE CODE
	SETONE NDDIP,(Q2)	;SET DUMP IN PROGRESS
	MOVE T3,T2		;COPY COUNT
	MOVE T1,P1		;GET ADR OF MESSAGE
	MOVEI T2,DMPRMS		;GET POINTER TO NICE MESSAGE
	HRLI T2,(POINT 8,0)	;SET UP BYTE POINTER
	HRLI T1,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	JE NDDOK,(Q2),DMP200	;JUMP IF NOT IN CHARGE OF DUMPING THIS NODE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	HRROI T3,OURNAM		;SHOW WHAT EXECUTOR WE WANT
DMP200:	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;ALL DONE
SUBTTL	NCP -- SHOW Command

SHOREQ:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;FAILED, RETURN ERROR
	MOVEI T2,SHORTB		;GET DISPATCH TABLE ADR
	MOVEI T3,SHORTL		;AND LENGTH
	CALL FNDDSP		;GET DISPATCH ADR
	 JRST DOREQE		;FAILED
	JRST 0(T1)		;DISPATCH

SHORTB:	.DNSCT,,SHOCNT		;SHOW COUNTS
	.DNSEX,,SHOEXE		;SHOW EXECUTOR
	.DNQUE,,SHOQUE		;SHOW QUEUE
	.DNSTS,,SHOSTA		;SHOW STATUS
SHORTL==.-SHORTB




; SHOW EXECUTOR

SHOEXE:	CALL PRSCFM		;PARSE CONFIRMATION
	 JRST DOREQE		;NO SO FAILED
	STKVAR <<EXESTR,20>>
	HRROI T1,EXESTR		;GET POINTER TO WHERE REPLY WILL GO
	HRROI T2,[ASCIZ/	Current EXECUTOR is node /]
	SETZM T3		;TERMINATE ON NULL
	SOUT			;ASSEMBLE INITIAL PART OF REPLY
	MOVE T2,EXCUTR		;GET POINTER TO CURRENT EXECUTOR
	SOUT			;ADD NODE NAME
	SETZM T1		;NO TEXT, JUST HEADER
	HRRI T2,EXESTR		;GET ADDRESS OF REPLY MESSAGE
	HRLI T2,(POINT 7,)	;FORM POINTER TO REPLY
	CALL OPRMES		;SEND REPLY TO OPERATOR
	 JRST DOREQE		;FAILED, ISSUE MESSAGE
	RETSKP			;DONE, RETURN
;SHOW COUNTS LINE LINE-ID
SHOCNT:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;FAILED, NOT A KEYWORD
	CAIE t1,.DNSLI		;WHICH SHOULD BE LINE
	JRST DOREQE		;INVALID REQUEST
	CALL PRSLID		;PARSE THE LINE-ID
	 RETBAD (.ERR23)	;<Invalid line-id>
	STKVAR <<CNTMSG,100>>
	DMOVEM T1,T3		;SAVE LINE-ID
	CALL PRSCFM		;PARSE CONFIRMATION
	 RETBAD ()		;FAILED

; COMMAND PARSED - SAVE REQUEST TYPE IN QUEUE ENTRY AND SEND NICE MESSAGE

	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVEI T1,CNTMSG		;ADR OF MESSAGE
	HRLI T1,441000		;MAKE POINTER TO MESSAGE
	MOVEI T2,.NCRED		;READ INFORMATION
	IDPB T2,T1
	MOVEI T2,.RDLCT		;GET LINE COUNTERS
	IDPB T2,T1
	MOVEI T2,2		;NUMBER OF BYTES IN MESSAGE SO FAR
	CALL MAKLIN		;PUT LINE-ID INTO MESSAGE
	MOVE T1,P1		;GET ADR OF MESSAGE
	MOVE T3,T2		;COPY COUNT OF BYTES IN MESSAGE
	MOVEI T2,CNTMSG		;ADR OF MESSAGE
	HRLI T2,441000		;MAKE POINTER TO MESSAGE
	HRLI T4,.NCRED		;GET NICE PROTOCOL "READ INFORMATION" FUNCTION
	HRRI T4,.RDLCT		;GET OPTION FOR "READ LINE COUNTERS"
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;ALL DONE
; SHOW STATE LINE LINE-ID

SHOSTA:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;FAILED, NOT A KEYWORD
	MOVEI T2,STATAB		;GET DISPATCH TABLE ADR
	MOVEI T3,STALEN		;AND LENGTH
	CALL FNDDSP		;GET DISPATCH ADR
	 JRST DOREQE		;FAILED
	JRST 0(T1)		;DISPATCH

STATAB:	.DNSLO,,SHSLCL		;SHOW STATE LOCAL
	.DNSLI,,SHSLIN		;SHOW STATE LINE LINE-ID
	.DNKNO,,SHSKNO		;SHOW STATE KNOWN LINES/NODES
	.DNNOD,,SHSNOD		;SHOW STATE NODE NODE-NAME

STALEN==.-STATAB
; SHOW STATE LOCAL

SHSLCL:	STKVAR <<SLSMSG,50>>
	CALL PRSCFM		;PARSE CONFIRMATION
	 RETBAD ()		;FAILED
	HRRI T1,SLSMSG		;GET ADDRESS OF NICE MESSAGE
	HRLI T1,(POINT 8,)	;FORM POINTER TO NICE MESSAGE
	MOVX T4,.NCRED		;GET NICE "READ INFORMATION" FUNCTION
	IDPB T4,T1		;PUT FUNCTION CODE IN MESSAGE
	MOVX T4,.RDLNS		;GET "LOCAL NODE STATUS" OPTION CODE
	IDPB T4,T1		;ADD OPTION TO MESSAGE
	HRLI T4,.NCRED		;GET READ INFORMATION FUNCTION CODE
	HRRI T4,.RDLNS		;GET "LOCAL NODE STATUS" OPTION
	MOVX T3,2		;GET NUMBER OF BYTES IN NICE MESSAGE
	HRRI T2,SLSMSG		;GET ADDRESS OF NICE MESSAGE
	HRLI T2,(POINT 8,)	;FORM POINTER TO NICE MESSAGE
	MOVE T1,P1		;GET ADR OF ORION MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;PUT MSG ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;DONE, RETURN SUCCESS
; SHOW STATE KNOWN REMOTES

SHSKNO:	CALL PRSKEY		;PARSE A KEYWORD
	 RETBAD ()		;FAILED
	MOVEI T2,KNOTAB		;GET DISPATCH TABLE ADR
	MOVEI T3,KNOLEN		;AND LENGTH
	CALL FNDDSP		;GET DISPATCH ADR
	 JRST DOREQE		;FAILED
	JRST 0(T1)		;DISPATCH


KNOTAB:	.DNNDS,,SHNNDS		;SHOW STATE KNOWN NODES
	.DNskl,,SHNLNS		;SHOW STATE KNOWN LINES

KNOLEN==.-KNOTAB




; SHOW STATE KNOWN NODES

SHNNDS:	STKVAR <<SHDMSG,50>>
	CALL PRSCFM		;PARSE CONFIRMATION
	 RETBAD ()		;FAILED
	HRRI T1,SHDMSG		;GET ADDRESS OF NICE MESSAGE
	HRLI T1,(POINT 8,)	;FORM POINTER TO NICE MESSAGE
	MOVX T4,.NCRED		;GET NICE "READ INFORMATION" FUNCTION
	IDPB T4,T1		;PUT FUNCTION CODE IN MESSAGE
	MOVX T4,.RDRNS		;GET "REMOTE NODE STATUS" OPTION CODE
	IDPB T4,T1		;ADD OPTION TO MESSAGE
	MOVX T4,0		;USE A LENGTH OF 0 TO IMPLY READ STATE OF
	IDPB T4,T1		;  ALL KNOWN NODES
	HRLI T4,.NCRED		;GET READ INFORMATION FUNCTION CODE
	HRRI T4,.RDRNS		;GET "REMOTE NODE STATUS" OPTION
	MOVX T3,3		;GET NUMBER OF BYTES IN NICE MESSAGE
	HRRI T2,SHDMSG		;GET ADDRESS OF NICE MESSAGE
	HRLI T2,(POINT 8,)	;FORM POINTER TO NICE MESSAGE
	MOVE T1,P1		;GET ADR OF ORION MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;PUT MSG ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;DONE, RETURN SUCCESS
; SHOW STATE NODE node

SHSNOD:	STKVAR <<SHNMSG,50>,SHNNOD>
	CALL PRSNOD		;PARSE A NODE NAME
	 RETBAD ()		;FAILED
	MOVEM T1,SHNNOD		;SAVE NODE NAME POINTER
	CALL PRSCFM		;PARSE CONFIRMATION
	 JRST SHSNDX		;FAILED, GO RELEASE FREE SPACE
	HRRI T1,SHNMSG		;GET ADDRESS OF NICE MESSAGE
	HRLI T1,(POINT 8,)	;FORM POINTER TO NICE MESSAGE
	MOVX T4,.NCRED		;GET NICE "READ INFORMATION" FUNCTION
	IDPB T4,T1		;PUT FUNCTION CODE IN MESSAGE
	MOVX T4,.RDRNS		;GET "REMOTE NODE STATUS" OPTION CODE
	IDPB T4,T1		;ADD OPTION TO MESSAGE
	MOVE T3,SHNNOD		;GET POINTER TO NODE NAME
	MOVX T2,NNAMSZ		;MAX SIZE OF NODE NAMES
	CALL MAKIMA		;ADD NODE NAME TO MESSAGE
	 JRST SHSNDX		;FAILED, GO RELEASE FREE SPACE
	ADDI T2,2		;ACCOUNT FOR FUNCTION AND OPTION CODES
	HRLI T4,.NCRED		;GET READ INFORMATION FUNCTION CODE
	HRRI T4,.RDRNS		;GET "REMOTE NODE STATUS" OPTION
	MOVE T3,T2		;GET NUMBER OF BYTES IN NICE MESSAGE
	HRRI T2,SHNMSG		;GET ADDRESS OF NICE MESSAGE
	HRLI T2,(POINT 8,)	;FORM POINTER TO NICE MESSAGE
	MOVE T1,P1		;GET ADR OF ORION MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;PUT MSG ON NICE QUEUE
	 JRST SHSNDX		;FAILED, GO RELEASE FREE SPACE
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	MOVE T1,SHNNOD		;GET FREE BLOCK ADDRESS
	CALL RELFRE		;RELEASE THE BLOCK
	 FATAL.ERROR		;FAILD
	RETSKP			;DONE, RETURN SUCCESS

; HERE ON AN ERROR

SHSNDX:	EXCH T1,SHNNOD		;GET FREE BLOCK ADDRESS
	CALL RELFRE		;RELEASE THE BLOCK
	 FATAL.ERROR		;FAILD
	MOVE T1,SHNNOD		;RESTORE ERROR CODE
	RETBAD ()		;FAIL
; SHOW STATE LINE line-id

SHSLIN:	STKVAR <<SHOMSG,100>,<SHLLID,2>>
	CALL PRSLID		;PARSE THE LINE-ID
	 RETBAD (.ERR23)	;<Invalid line-id>
	DMOVEM T1,SHLLID	;SAVE LINE-ID
	CALL PRSCFM		;PARSE END OF COMMAND
	 RETBAD ()		;FAILED

; COMMAND PARSED - SAVE REQUEST TYPE IN QUEUE ENTRY AND SEND NICE MESSAGE

	MOVEI T1,SHOMSG		;ADR OF MESSAGE
	HRLI T1,441000		;MAKE POINTER TO MESSAGE
	MOVEI T2,.NCRED		;READ INFORMATION
	IDPB T2,T1
	MOVEI T2,.RDLST		;GET LINE STATE
	IDPB T2,T1
	MOVEI T2,2		;NUMBER OF BYTES IN MESSAGE SO FAR
	DMOVE T3,SHLLID		;GET LINE ID
	CALL MAKLIN		;PUT LINE-ID INTO MESSAGE
	MOVE T1,P1		;GET ADR OF MESSAGE
	MOVE T3,T2		;COPY COUNT OF BYTES IN MESSAGE
	MOVEI T2,SHOMSG		;ADR OF MESSAGE
	HRLI T2,441000		;MAKE POINTER TO MESSAGE
	HRLI T4,.NCRED		;GET NICE PROTOCOL "READ INFORMATION" FUNCTION
	HRRI T4,.RDLST		;GET OPTION FOR "READ LINE STATE"
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;ALL DONE
; shnlns - show status known lines

shnlns:	stkvar <<snlmsg,100>>

; parse end of command

	call prscfm		;parse end of command
	 retbad ()		;failed

; assemble nice protocol message to read information

	MOVEI T1,snlMSG		;ADR OF MESSAGE
	HRLI T1,441000		;MAKE POINTER TO MESSAGE
	MOVEI T2,.NCRED		;READ INFORMATION
	IDPB T2,T1
	MOVEI T2,.RDLST		;GET LINE STATE
	IDPB T2,T1
	movx t2,.ltall		;get "all lines" line id
	idpb t2,t1		;add line id to message
	MOVE T1,P1		;GET ADR OF MESSAGE
	MOVx T3,3		;there are three bytes in the message
	MOVEI T2,SNLMSG		;ADR OF MESSAGE
	HRLI T2,441000		;MAKE POINTER TO MESSAGE
	HRLI T4,.NCRED		;GET NICE PROTOCOL "READ INFORMATION" FUNCTION
	HRRI T4,.RDLST		;GET OPTION FOR "READ LINE STATE"
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;STORE THIS MESSAGE ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;ALL DONE
;SHOW QUEUE (OF) NCP-REQUESTS

SHOQUE:	CALL PRSNOI		;PARSE NOISE WORDS
	CALL PRSKEY		;PARSE KEYWORD
	 RETBAD ()		;FAILED
	MOVEI T2,SHOQTB		;GET ADR OF DISPATCH TABLE
	MOVEI T3,SHOQTL		;AND ITS LENGTH
	CALL FNDDSP		;GET DISPATCH
	 JRST DOREQE		;NOT FOUND
	JRST 0(T1)		;DISPATCH

SHOQTB:	.DNNCR,,SHONCP		;SHOW QUEUE (OF) NCP-REQUESTS
SHOQTL==.-SHOQTB

SHONCP:	STKVAR <SQNPAG>
	CALL ASGPAG		;GET A PAGE TO USE FOR THE TEXT
	 RETBAD ()		;FAILED
	MOVEM T1,SQNPAG		;SAVE PAGE NUMBER
	LSH T1,9		;FORM ADDRESS OF TEXT DESTINATION
	HRLI T1,(POINT 7,0,35)	;FORM DESTINATION POINTER
	MOVE Q1,T1		;SAVE STARTING BYTE POINTER
	CALL BLDACT		;LIST THE ACTIVE COMMANDS
	CALL BLDQUE		;THEN THE QUEUED COMMANDS
	 HRROI T2,[ASCIZ/	There are no outstanding NCP requests.
/]
	SETZM T3		;TERMINATE ON NULL
	CAMN T1,Q1		;DID THE BYTE POINTER CHANGE?
	SOUT			;ADD STRING TO TEXT
	MOVE T1,SQNPAG		;GET PAGE ADDRESS OF TEXT
	LSH T1,9		;FORM ADDRESS
	HRLI T1,(POINT 7,0,35)	;FORM POINTER TO TEXT TO BE OUTPUT
	MOVE T2,[POINT 7,[ASCIZ//]]
	CALL OPRMES		;TELL OPERATOR QUEUE IS EMPTY
	 JRST [	EXCH T1,SQNPAG	;GET PAGE ADDRESS
		CALL RELPAG	;RELEASE THE PAGE
		 NON.FATAL.ERROR
		MOVE T1,SQNPAG	;RESTORE ERROR CODE
		RETBAD () ]	;FAILED
	MOVE T1,SQNPAG		;GET PAGE ADDRESS
	CALL RELPAG		;RELEASE THE PAGE
	 NON.FATAL.ERROR
	RETSKP			;AND EXIT
SUBTTL 	NCP -- LOOP Command

LOPREQ:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,LOPRTB		;GET ADR OF DISPATCH TABLE
	MOVEI T3,LOPRTL		;AND LENGTH OF TABLE
	CALL FNDDSP		;GET THE DISPATCH ADR
	 JRST DOREQE		;NOT FOUND, UNKNOWN KEYWORD
	JRST (T1)		;DISPATCH

LOPRTB:	.DNSLI,,LOPLIN		;LOOP LINE
LOPRTL==.-LOPRTB

; LOOP LINE line-id

LOPLIN:	STKVAR <LOPBYT,<LOPMSG,50>,<LOPLID,2>,LOPCNT,LOPLNG,LOPWTH>
	CALL PRSLID		;PARSE THE LINE-ID
	 RETBAD (.ERR23)	;<Invalid line-id>
	DMOVEM T1,LOPLID	;SAVE LINE-ID
	MOVEI T1,1		;DEFAULT COUNT
	MOVEM T1,LOPCNT
	MOVEI T1,^D128		;DEFAULT LENGTH
	MOVEM T1,LOPLNG
	MOVEI T1,.DOMXD		;DEFAULT DATA MODE
	MOVEM T1,LOPWTH
LOPLST:	CALL PRSCFM		;END OF COMMAND?
	SKIPA			;NO - PARSE THE KEYWORD
	JRST DOLOOP		;GO DO THE LOOP COMMAND
	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,LINRTB		;GET ADR OF DISPATCH TABLE
	MOVEI T3,LINRTL		;AND LENGTH OF TABLE
	CALL FNDDSP		;GET THE DISPATCH ADR
	 JRST DOREQE		;NOT FOUND, UNKNOWN KEYWORD
	JRST (T1)		;DISPATCH

LINRTB:	.DNDRC,,LINDRC		;LOOP LINE line-id COUNT
	.DNLNG,,LINLNG		;LOOP LINE line-id LENGTH
	.DNWTH,,LINWTH		;LOOP LINE line-id WITH
LINRTL==.-LINRTB
; LOOP LINE line-id COUNT n

LINDRC::	CALL PRSCFM		;END OF COMMAND?
	SKIPA			;NO - PARSE THE KEYWORD
	JRST DOLOOP		;GO DO THE LOOP COMMAND
	CALL PRSNUM		;GET THE BLOCK COUNT
	JRST DOREQE		;FAILED
	MOVEM T1,LOPCNT		;SAVE
	JRST LOPLST		;GET MORE KEYWORDS

; LOOP LINE line-id LENGTH n

LINLNG:	CALL PRSCFM		;END OF COMMAND?
	SKIPA			;NO - PARSE THE KEYWORD
	JRST DOLOOP		;GO DO THE LOOP COMMAND
	CALL PRSNUM		;GET THE BLOCK LENGTH
	JRST DOREQE		;FAILED
	SKIPG T1		;MUST >0 AND <256
	RETBAD (ARGX04)		;TELL USER BLOCK TOO SMALL
	CAIL T1,^D256
	RETBAD (ARGX05)		;TELL USER BLOCK TOO LONG
	MOVEM T1,LOPLNG		;SAVE
	JRST LOPLST		;GET MORE KEYWORDS

; LOOP LINE line-id WITH [MIXED/ZEROES/ONES]

LINWTH:	CALL PRSCFM		;END OF COMMAND?
	SKIPA			;NO - PARSE THE KEYWORD
	JRST DOLOOP		;GO DO THE LOOP COMMAND
	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,WTHRTB		;GET ADR OF DISPATCH TABLE
	MOVEI T3,WTHRTL		;AND LENGTH OF TABLE
	CALL FNDDSP		;GET THE DISPATCH ADR
	 JRST DOREQE		;NOT FOUND, UNKNOWN KEYWORD
	MOVEM T1,LOPWTH		;SAVE THE CODE VALUE
	JRST LOPLST		;KEEP PARSING

WTHRTB:	.DNMXD,,.DOMXD		;LOOP LINE line-id WITH MIXED
	.DNONS,,.DOONS		;LOOP LINE line-id WITH ONES
	.DNZRO,,.DOZRO		;LOOP LINE line-id WITH ZEROES
WTHRTL==.-WTHRTB
	;...
	;...

DOLOOP:	SETZM LOPBYT		;ZERO BYTE COUNT
	HRRI T1,LOPMSG		;GET ADDRESS OF NICE MESSAGE
	HRLI T1,(POINT 8,)	;FORM POINTER TO NICE MESSAGE
	MOVX T4,.NCTST		;GET NICE "DO LOOPBACK" FUNCTION
	IDPB T4,T1		;PUT FUNCTION CODE IN MESSAGE
	AOS LOPBYT		;BUMP BYTE COUNT
	MOVX T4,.DOLIN		;GET "LINE TYPE TEST" OPTION CODE
	IDPB T4,T1		;ADD OPTION TO MESSAGE
	AOS LOPBYT		;BUMP BYTE COUNT
	MOVEI T2,6		;MOVE EXECUTOR NAME INTO NICE MSG
	MOVE T3,EXCUTR
	CALL MAKIMA		;PUT EXECUTOR IN IMAGE FIELD
	 RETBAD			;ERROR - FAIL
	ADDM T2,LOPBYT		;ADD  COUNT TO TOTAL 
	DMOVE T3,LOPLID		;PUT LINE ID INTO NICE MESSAGE
	MOVE T2,LOPBYT		;GIVE IT COUNT
	CALL MAKLIN		;ROUTINE PUTS LINE ID INTO NICE MESSAGE
	MOVEM T2,LOPBYT		;STORE COUNT
	MOVE T2,LOPCNT		;GET COUNT OF BLOCKS TO LOOP
	CALL MAKTWO		;SAVE THE TWO BYTE NUMBER
	AOS LOPBYT		;BUMP BYTE COUNT
	AOS LOPBYT		;BUMP BYTE COUNT
	MOVE T2,LOPWTH		;GET DATA TYPE
	IDPB T2,T1		;AND MOVE INTO RECORD
	AOS LOPBYT		;BUMP BYTE COUNT
	MOVE T2,LOPLNG		;GET THE BLOCK LENGTH
	CALL MAKTWO		;PUT TWO BYTE NUMBER IN MESSAGE
	AOS LOPBYT		;BUMP BYTE COUNT
	AOS LOPBYT		;BUMP BYTE COUNT
	HRLI T4,.NCTST		;SET "TEST" FUNCTION
	HRRI T4,.DOLIN		;GET "LOCAL NODE STATUS" OPTION
	MOVE T3,LOPBYT		;GET NUMBER OF BYTES IN NICE MESSAGE
	HRRI T2,LOPMSG		;GET ADDRESS OF NICE MESSAGE
	HRLI T2,(POINT 8,)	;FORM POINTER TO NICE MESSAGE
	MOVE T1,P1		;GET ADR OF ORION MESSAGE
	HRL T1,T3		;MOVE COUNT INTO PARAM REG
	MOVE T3,EXCUTR		;SHOW WHAT EXECUTOR WE WANT
	CALL STONIC		;PUT MSG ON NICE QUEUE
	 RETBAD ()		;FAILED
	MOVE T1,REQADR		;GET ADR OF THIS QUEUE ENTRY
	MOVX T2,QF%NOA		;MARK THAT THIS MESSAGE NOT TO BE ACK'D YET
	STOR T2,QUEFLG,(T1)
	RETSKP			;DONE, RETURN SUCCESS
SUBTTL	NCP -- INITIATE and TERMINATE Commands

TRMREQ:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,TRMRTB		;GET ADR OF DISPATCH TABLE
	MOVEI T3,TRMRTL		;AND LENGTH OF TABLE
	CALL FNDDSP		;GET THE DISPATCH ADR
	 JRST DOREQE		;NOT FOUND, UNKNOWN KEYWORD
	JRST (T1)		;DISPATCH

TRMRTB:	.DNLGI,,TRMLOG		;TERMINATE LOGGING

TRMRTL==.-TRMRTB




INIREQ:	CALL PRSKEY		;PARSE A KEYWORD
	 JRST DOREQE		;WRONG TYPE
	MOVEI T2,INIRTB		;GET ADR OF DISPATCH TABLE
	MOVEI T3,INIRTL		;AND LENGTH OF TABLE
	CALL FNDDSP		;GET THE DISPATCH ADR
	 JRST DOREQE		;NOT FOUND, UNKNOWN KEYWORD
	JRST (T1)		;DISPATCH

INIRTB:	.DNLOG,,INILOG		;INITIATE LOGGING

INIRTL==.-INIRTB
INILOG:	TDZA T4,T4		;NOTE INITATE
TRMLOG:	SETOM T4		;NOTE TERMINATE
	STKVAR <IRQERR,IRQFLG,IRQNOD>
	MOVEM T4,IRQFLG		;SAVE INITIATE/TERMINATE FLAG
	CALL PRSNOI		;SKIP NOISE FIELD
	CALL PRSKEY		;PARSE KEYWORD
	 RETBAD ()		;FAILED
	CAIE T1,.DNLCT		;LINE-COUNTERS ?
	JRST DOREQE		;NO, FAIL
	CALL PRSNOI		;SKIP NOISE
	CALL PRSLID		;GO PARSE A LINE ID
	 JRST DOREQE		;FAILED, NOTE ERROR
	DMOVEM T1,Q1		;SAVE LINE ID
	CALL PRSNOI		;PARSE NOISE FIELD
	CALL PRSNOD		;PARSE NODE NAME
	 RETBAD ()		;FAILED
	MOVEM T1,IRQNOD		;SAVE FREE BLOCK ADDRESS
	CALL FOCNIB		;FIND OR CREATE THE ASSOCIATED NIB
	 JRST INIRQX		;FAILED, RELEASE FREE SPACE
	MOVE T3,T1		;GET THE NIB ADDRESS
	DMOVE T1,Q1		;RESTORE LINE ID
	SETZM IRQERR		;INITIALIZE ERROR CELL
	MOVE T4,[SETLIN]	;GET ADDRESS OF ROUTINE TO CALL
	SKIPE IRQFLG		;TERMINATING ?
	MOVE T4,[CLRLIN]	;YES, USE THAT ROUTINE
	CALL (T4)		;PERFORM THE FUNCTION
	 SKIPA			;FAILED, ISSUE ERROR MESSAGE
	JRST INIRQ5		;DONE, RELEASE FREE BLOCK
	HRROI T1,[ASCIZ/? NETCON: Could not set logging for specified line
/]				;GET STRING POINTER
	SETZM T2		;NO HEADER
	CALL OPRMES		;SEND MESSAGE TO OPERATOR
INIRQ5:	MOVE T1,IRQNOD		;GET FREE BLOCK ADDRESS
	CALL RELFRE		;RELEASE THE BLOCK
	 FATAL.ERROR		;FAILD
	RETSKP			;DONE

; HERE ON AN ERROR

INIRQX:	EXCH T1,IRQNOD		;GET FREE BLOCK ADDRESS
	CALL RELFRE		;RELEASE THE BLOCK
	 FATAL.ERROR		;FAILD
	MOVE T1,IRQNOD		;RESTORE ERROR CODE
	RETBAD ()		;FAIL
;SETLIN/CLRLIN - ROUTINE TO MODIFY DATABASE TO NOTE THAT LOGGING SHOULD
;		 OR SHOULD NOT BE DONE FOR THE INDICATED LINE.
;	  FOR SPECIFIED LINE.
;
;ACCEPTS IN  T1-T2/ LINE ID
;		T3/ NIB ADDRESS
;		CALL SETLIN/CLRLIN
;RETURNS: +1	 FAILED, ERROR CODE IN T1
;	  +2	SUCCESS, DATABASE MODIFIED

SETLIN:	TDZA T4,T4		;NOTE THAT LOGGING SHOULD BE TURNED ON
CLRLIN:	SETOM T4		;NOTE THAT LOGGING SHOULD BE TURNED OFF
	STKVAR <<STLLID,2>,STLFLG,STLNIB>
	MOVEM T4,STLFLG		;SAVE FLAG TO NOTE ON OR OFF
	DMOVEM T1,STLLID	;SAVE LINE ID
	MOVEM T3,STLNIB		;SAVE NIB ADDRESS
	MOVE T1,STLNIB		;GET NIB ADDRESS
	DMOVE T2,STLLID		;GET LINE ID
	CALL FOCLIN		;FIND OR CREATE THE ENTRY FOR THIS LINE
	 RETBAD ()		;FAILED, RETURN ERROR
	SKIPE STLFLG		;TURNING LOGGING OFF ?
	JRST [SETZRO LTLOG,(T1)	;YES, TURN IT OFF
	      RETSKP ]		;AND DONE. RETURN SUCCESS
	SETONE LTLOG,(T1)	;NOTE THAT LOGGING IS REQUIRED FOR THIS LINE
	RETSKP			;DONE, RETURN SUCCESS
;PRSPRT - ROUTINE TO PARSE A LINE-ID INTO A NSP PORT NUMBER
;
;ACCEPTS IN P2/	CURRENT POINTER INTO IPCF MESSAGE
;		CALL PRSPRT
;RETURNS: +1	LOST, INVALID LINE-ID
;	  +2	WIN, PORT NUMBER IN T1
PRSPRT:	CALL PRSLID		;GET LINE-ID
	 RET			;LOST ALREADY
LIDPRT::STKVAR	<<PRTSAV,2>,<PRTLID,2>>
	DMOVE T2,T1		;COPY LINE ID
	MOVEI T1,PRTLID		;ADR OF ASCII DEVICE NAME
	HRLI T1,440700		;MAKE INTO BYTE POINTER
	CALL ASCLIN		;CONVERT LINE-ID TO TEXT STRING
	 RETBAD (.NRILN)	;INVALID LINE ID
	HRROI T4,PRTLID		;ADR OF ASCIZ LINE-ID
	HRLI T4,440700		;TEMPORARY
	MOVEI T1,.BTCLI		;CONVERT LINE-ID TO NSP PORT NUMBER
	MOVEI T2,T3		;ARGUMENT BLOCK
	BOOT
	 ERJMP [RETBAD (.NRILN)] ;FAILED, RETURN INVALID LINE ID
	HRRZ T1,T3		;GET PORT NUMBER FROM ARGUMENT BLOCK
	RETSKP
SUBTTL	NCP -- Miscellaneous Routines

;ROUTINE TO BUILD A LIST OF THE ACTIVE REQUESTS
;ACCEPTS IN T1/	BYTE POINTER TO WHERE TO PUT THE LIST
;	CALL BLDACT
;RETURNS +1:	ALWAYS - UPDATED BYTE POINTER IN T1

BLDACT:	SAVEQ
	MOVSI Q1,-NJFN		;SEE IF THERE ARE ANY ACTIVE REQUESTS
BLDAC0:	SKIPE REQTAB(Q1)	;THIS ONE ACTIVE?
	JRST BLDAC2		;YES
	AOBJN Q1,BLDAC0		;NO, LOOP BACK
	RET			;NONE ACTIVE

BLDAC2:	HRROI T2,[ASCIZ/
NCP requests in progress:
/]
	SETZ T3,
	SOUT
	MOVSI Q1,-NJFN		;SET UP TO LOOK AT ACTIVE REQUESTS
BLDACL:	SKIPN REQTAB(Q1)	;THIS ONE ACTIVE?
	JRST BLDAC1		;NO
	HRROI T2,[ASCIZ/   # /]
	SETZ T3,
	SOUT
	MOVE T2,REQTAB(Q1)	;GET THE REQUEST NUMBER
	MOVEI T3,^D10		;DECIMAL
	NOUT
	 JFCL
	HRROI T2,[ASCIZ/ - /]
	SETZ T3,
	SOUT
	MOVE T2,REQXTR(Q1)	;GET ADDRESS OF EXECUTOR NODE NAME
	HRLI T2,(POINT 7,)	;FORM POINTER TO NAME STRING
	SOUT			;ADD EXECUTOR NAME TO DISPLAY
	HRROI T2,[ASCIZ/ - /]
	SETZ T3,
	SOUT
	MOVE T2,REQMES(Q1)	;GET THE ADR OF THE ORION MESSAGE
	CALL BLDCOM		;PUT IN THE REQUEST
	HRROI T2,[ASCIZ/
/]
	SETZ T3,
	SOUT
BLDAC1:	AOBJN Q1,BLDACL		;LOOP FOR ALL REQUESTS
	RET
;ROUTINE TO BUILD A LIST OF THE QUEUED REQUESTS
;ACCEPTS IN T1/	BYTE POINTER TO WHERE TO STORE LIST
;	CALL BLDQUE
;RETURNS +1:	ALWAYS - UPDATED BYTE POINTER IN T1

BLDQUE:	SAVEQ
	SKIPN NICQUE		;ANY REQUESTS ON QUEUE?
	RET			;NO
	HRROI T2,[ASCIZ/
NCP requests on the queue but not yet started:
/]
	SETZ T3,
	SOUT
	MOVEI Q1,NICQUE		;GET POINTER TO START OF NICE QUEUE
BLDQUL:	LOAD Q1,NQPNT,(Q1)	;STEP TO NEXT ENTRY ON QUEUE
	JUMPE Q1,R		;IF 0, THEN DONE
	HRROI T2,[ASCIZ/   # /]
	SETZ T3,
	SOUT
	LOAD T2,NQNUM,(Q1)	;GET THE REQUEST NUMBER
	MOVEI T3,^D10		;DECIMAL
	NOUT
	 JFCL
	HRROI T2,[ASCIZ/ - /]
	SETZ T3,
	SOUT
	LOAD T2,NQXTR,(Q1)	;GET ADDRESS OF EXECUTOR STRING
	HRLI T2,(POINT 7,)	;FORM POINTER TO NODE NAME STRING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;ADD EXECUTOR NODE TO STRING
	HRROI T2,[ASCIZ/ - /]
	SETZ T3,
	SOUT
	LOAD T2,NQMES,(Q1)	;GET ADR OF ORION MESSAGE
	CALL BLDCOM		;THROW IN THE COMMAND
	HRROI T2,[ASCIZ/
/]
	SETZ T3,
	SOUT
	JRST BLDQUL		;LOOP BACK FOR ALL ENTRIES ON QUEUE
;ROUTINE TO STORE A NICE MESSAGE ON THE NICE QUEUE
;ACCEPTS IN T1/ COUNT OF CHARS IN NICE MSG,,ADDRESS OF MESSAGE FROM ORION
;	    T2/	BYTE POINTER TO NICE MESSAGE
;	    T3/	BYTE POINTER OF EXECUTOR
;	    T4/	NICE FUNCTION CODE,,NICE SUB-OPTION
;	CALL STONIC
;RETURNS +1:	FAILED
;	 +2:	NICE MESSAGE IS ON REAR OF NICE QUEUE

STONIC:	ASUBR <STONIM,STONIT,STONIN,STONIF>
	LOAD T2,MS.CNT,.MSTYP(T1) ;GET SIZE OF ORION MESSAGE
	ADDI T2,.MSTYP(T1)	;GET ADDRESS OF END OF ORION MESSAGE
	HRLI T2,(POINT 8,0)	;SET UP BYTE POINTER
	MOVE T1,STONIT		;GET POINTER TO NICE MESSAGE
	MOVEM T2,STONIT		;SAVE NEW POINTER TO NICE MESSAGE
	HLRZ T3,STONIM		;GET THE COUNT OF CHARACTERS
	MOVN T3,T3		;GET NEG COUNT OF CHARS IN MESSAGE
	SIN			;MOVE THE MESSAGE TO A PERMANENT PLACE
	MOVE T2,STONIT		;GET POINTER TO NICE MESSAGE
	HLRZ T1,STONIM		;GET NICE MESSAGE COUNT
	AOS T1			;INSURE SPACING BETWEEN MESSAGES
	ADJBP T1,T2		;POINT PAST END
	AOS T1			;MOVE TO NEXT WORD
	MOVE T4,T1		;SAVE THE ADDRESS
	HRRO T1,T1		;MAKE INTO SEVEN BIT BYTE POINTER
	MOVE T2,STONIN		;GET THE EXECUTOR STRING
	SETZ T3,		;COPY WHOLE STRING
	SOUT
	HRRZ T1,STONIM		;GET ADR OF ORION MESSAGE AGAIN
	HRL T1,T4		;ADD EXECUTOR STRING ADDRESS
	HRRZ T2,STONIT		;GET ADR OF NICE MESSAGE WITHIN ORION MESS
	HLRZ T3,STONIM		;AND GET COUNT OF CHARS IN NICE MESSAGE
	AOS T4,REQNUM		;GET A REQUEST NUMBER FOR THIS REQUEST
	HRL T3,T4		;GET REQ ,, COUNT
	MOVE T4,STONIF		;GET NICE FUNCTION CODE AND OPTION
	CALL QUENCR		;QUEUE UP THIS MESSAGE
	 RETBAD ()		;FAILED
	RETSKP
;ROUTINE TO SEND A NICE MESSAGE

;ACCEPTS IN T1/	ADDRESS OF EXECUTOR STRING,,ADDRESS OF ORION MESSAGE
;	    T2/	POINTER TO NICE MESSAGE
;	    T3/	REQ NUMBER ,, COUNT OF CHARACTERS IN NICE MESSAGE
;	    T4/	NICE FUNCTION CODE,,NICE OPTION
;	CALL SNDNIC
;RETURNS +1:	ERROR, MESSAGE NOT SENT
;	 +2:	SUCCESSFUL

SNDNIC:	SAVEQ			;SAVE SOME PERMANENT ACS
	ASUBR <SNDNIM,SNDNIT,SNDNIN,SNDNIF>
	HLRZ T1,SNDNIN		;GET REQUEST NUMBER
	CALL GETRQI		;GET A REQUEST INDEX
	 RETBAD ()		;NONE LEFT
	MOVE Q1,T1		;REMEMBER THE INDEX VALUE
	HRRZ T2,SNDNIM		;GET ORION MESSAGE POINTER
	MOVEM T2,REQMES(Q1)	;SAVE IT FOR LATER
	MOVEI T1,JFDCHN(Q1)	;GET CHANNEL NUMBER
	HLRZ T2,SNDNIM		;PASS EXECUTOR ADDRESS
	MOVEM T2,REQXTR(Q1)	;SAVE ADDRESS OF EXECUTOR NODE NAME
	CALL GETSRJ		;GET A JFN TO NCU
	 JRST [	EXCH T1,Q1	;SAVE THE ERROR CODE
		CALL RELRQI	;RELEASE THE INDEX
		MOVE T1,Q1	;GET BACK THE ERROR CODE
		RETBAD ()]
	MOVEM T1,JFDTAB(Q1)	;SAVE THE JFN
	MOVE T2,SNDNIF		;GET NICE FUNCTION AND OPTION
	MOVEM T2,FCNTAB(Q1)	;SAVE NICE FUNCTION AND OPTION
	MOVE T2,SNDNIT		;GET PONTER TO NICE MESSAGE
	HRRZ T3,SNDNIN		;GET COUNT
	MOVNS T3		;NEED NEGATIVE COUNT FOR SOUTR
	SOUTR			;OUTPUT THE MESSAGE
	 ERJMP [MOVE T1,Q1	;RELEASE THE INDEX BLOCK
		CALL RELRQI	;...
		MOVEI T1,.FHSLF	;GET ERROR CODE
		GETER
		HRRZ T1,T2
		RETER2()]
	RETSKP			;DONE
;ROUTINE TO GET AN AVAILABLE REQUEST INDEX
;ACCEPTS IN T1/	REQUEST NUMBER

GETRQI:	MOVSI T4,-NJFN		;SET UP TO LOOP THROUGH ALL INDEXES
GETRQ0:	SKIPE REQTAB(T4)	;THIS SLOT FREE?
	JRST GETRQ1		;NO
	MOVEM T1,REQTAB(T4)	;SAVE NUMBER IN TABLE
	HRRZ T1,T4		;RETURN THE INDEX IN T1
	RETSKP

GETRQ1:	AOBJN T4,GETRQ0		;LOOP BACK FOR ALL ENTRIES
	RETBAD (.ERR16)		;NO MORE SLOTS LEFT


;ROUTINE TO RELEASE A REQUEST INDEX

RELRQI:	SAVEQ
	MOVE Q1,T1		; Save index in permanent AC
	SKIPN T1,JFDTAB(Q1)	; Any JFN here?
	JRST RELRQ2		;  No .. just clear up and return
	CLOSF			; Yes .. close it
	 SKIPA T1,JFDTAB(Q1)	;  Close failed
	JRST RELRQ1		; Success .. go clear stored JFN

	TXO T1,CZ%ABT		; Insure that link will go away
	CLOSF			; by closing an aborted link properly
	 JFCL			;  Should never fail here
RELRQ1:	SETZM JFDTAB(Q1)	; Clear the JFN for the DCN:

RELRQ2:	SETZM REQMES(Q1)
	SETZM REQTAB(Q1)	; Clear this slot
	RET			; Done
;ROUTINE TO GET A JFN TO NCU
;ACCEPTS IN T1/	CHANNEL NUMBER TO PUT JFN ON
;	    T2/ ADDRESS OF EXECUTOR STRING
;	CALL GETSRJ
;RETURNS +1:	FAILED
;	 +2:	T1/	JFN

GETSRJ:	STKVAR <GETSRC,GETSRH,<GETSRT,20>>
	MOVEM T1,GETSRC		;SAVE CHANNEL NUMBER
	HRLI T2,(POINT 7,)	;MAKE EXECUTOR ADDRESS INTO BYTE POINTER
	MOVEM T2,GETSRH		;SAVE
	HRROI T1,GETSRT		;GET POINTER TO WHERE TO BUILD STRING
	SETZ T3,
	HRROI T2,[ASCIZ/DCN:/]	;BUILD GTJFN STRING TO DCN:NODE-NCU
	SOUT			;PUT IN DEVICE NAME
	SKIPE T2,GETSRH		;ANY EXECUTOR?
	SOUT			;YES, ADD IN NODE NAME OF EXECUTOR
	HRROI T2,[ASCIZ/-NCU;PASSWORD:NCU;CHARGE:NCU;USERID:NCU/] ;-NCU
	SOUT
	MOVX T1,GJ%SHT		;NOW GET A LINK TO THAT NCU
	HRROI T2,GETSRT		;POINTER TO STRING JUST BUILT
	GTJFN
	 RETER2 ()		;FAILED TO GET A JFN
	MOVEM T1,GETSRH		;SAVE JFN
	MOVE T2,[^D8B5+OF%RD+OF%WR]
	OPENF			;OPEN THE LINK
	 JRST GETSR1		;FAILED, GO CLEAN UP
	MOVE T2,GETSRC		;GET CHANNEL #
	STOR T2,MO%DAV,T3	;DATA AVAILABLE INTERRUPT
	MOVEI T2,.MOCIA		;CLEAR INTERRUPT
	STOR T2,MO%CDN,T3	;FOR CONNECT
	STOR T2,MO%INA,T3	;AND INTERRUPT MESSAGE
	MOVEI T2,.MOACN		;SET UP INTERRUPT CONDITIONS
	MTOPR
	 ERJMP GETSR1		;FAILED
	MOVE T1,GETSRH		;GET BACK THE JFN
	RETSKP			;AND RETURN

GETSR1:	MOVEM T1,GETSRC		;SAVE THE ERROR CODE
	MOVE T1,GETSRH		;GET JFN
	CLOSF			;CLOSE IT
	 SKIPA T1,GETSRH	;FAILED, TRY TO RELEASE IT
	SKIPA
	RLJFN			;RELEASE JFN
	 JFCL
	MOVE T1,GETSRC		;GET ERROR CODE AGAIN
	RETER2 ()
;SET MONITORING

SETMON:	JRST DOREQE

;SET PASSWORD

SETPSW:	JRST DOREQE
;ROUTINE TO HANDLE FORK TERMINATIONS

DOFKT:	STKVAR <<DOFKTS,40>>
	MOVSI Q3,-NJFN		;SET UP TO LOOK AT ALL FORKS
	SETZ Q2,		;INITIALIZE ERROR REGISTER
DOFKTL:	SKIPN T1,FRKTAB(Q3)	;ANY FORK HERE?
	JRST DOFKT1		;NO, SKIP IT
	RFSTS			;YES, GET ITS STATUS
	 ERJMP DOFKT0		;IF ERROR, GO DELETE THIS FORK
	TLC T1,-1		;IS THE FORK EXISTENT?
	TLCN T1,-1		;LH = -1 MEANS NOT EXISTENT
	JRST DOFKT0		;NOT EXISTENT, GO DELETE IT
	LDB T1,[POINT 17,T1,17]	;GET THE CODE
	CAIE T1,.RFSLP		;SLEEPING?
	CAIN T1,.RFWAT		;OR IO WAIT?
	JRST DOFKT1		;YES, SKIP THIS ONE
	CAIE T1,.RFRUN		;RUNNING
	CAIN T1,.RFIO		;OR IO WAIT?
	JRST DOFKT1		;YES, SKIP THIS ONE
	CAIN T1,.RFFPT		;FORCED TERMINATION?
	JRST [	MOVEI T1,.ERR17	;YES, FORK CRASHED
		HRROI T2,DOFKTS	;GET POINTER TO STRING TO GET ERROR MES
		MOVE T3,FRKTAB(Q3)
		CALL ERRORB	;BUILD ERROR STRING FOR THIS FORK'S ERROR
		SETZM T1	;NO TEXT
		HRROI T2,DOFKTS	;NOW TELL THIS TO THE OPR
		CALL OPRMES
		 NON.FATAL.ERROR
		JRST .+1]
	MOVE T1,FRKTAB(Q3)	;FORK HAS STOPPED
	KFORK			;KILL IT
	 ERJMP .+1
DOFKT0:	SETZM FRKTAB(Q3)	;ZERO THE HALDLE
	MOVE T1,JFNTAB(Q3)	;GET THE JFN
	CLOSF			;CLOSE IT
	 SKIPA T1,JFNTAB(Q3)	;FAILED, RELEASE IT
	SKIPA
	RLJFN
	 JFCL
	SETZM JFNTAB(Q3)	;NO MORE JFN
	PIOFF
	MOVEI T1,JFNCHN(Q3)	;GET CHANNEL NUMBER FOR THIS JFN
	CALL GETJFN		;GO CREATE A NEW JFN
	 JRST [	PION
		MOVEI T1,Q2	;SAVE THE ERROR CODE
		JRST DOFKT1]	;LOOP FOR ALL OTHER FORKS
	MOVEM T1,JFNTAB(Q3)	;SAVE THE JFN NUMBER
	PION
DOFKT1:	AOBJN Q3,DOFKTL		;LOOP BACK FOR ALL FORKS
	SKIPN T1,Q2		;ANY ERRORS HAPPEN?
	RETSKP			;NO, DONE
	RETBAD ()		;YES
;ROUTINE TO HANDLE A DATA INTERRUPT OR DISCONNECT INTERRUPT FROM
;	A JFN

DOJFD:	STKVAR <<DOJFDM,200>,DORMSG,DORCTr,dortxt,DOJHLD>
	LOAD Q1,QUEMES,(T1)	;GET THE JFN INDEX
	SKIPN T1,JFDTAB(Q1)	;GET JFN
	 RETSKP			;AND IGNORE THE REQUEST IF NO JFN ASSIGNED
	SIBE			;ANY CHARACTERS THERE?
	 CAIA			;YES
	JRST [MOVE T1,JFDTAB(Q1) ;NO, CHECK FOR DISCONNECT OF LINK
	      MOVX T2,.MORLS	;READ LINK STATUS
	      MTOPR
	      ERJMP [SETZ Q2,	;ERROR FAILURE
		     JRST DOJFD1] ;JOIN COMMON CODE
	      TXNE T3,MO%CON	;STILL CONNECTED?
	      RETSKP		;YES, JUST IGNORE REQUEST
	      MOVX Q2,.NRNCE	;NO,SHOW AS NETWORK COMM ERROR
	      JRST DOJFD1]	;JOIN COMMON CODE
		 
	MOVE T1,JFDTAB(Q1)	;GET JFN
	MOVEI T2,DORMSG		;ADR OF NICE MESSAGE BUFFER
	HRLI T2,(POINT 8,)	;MAKE INTO BYTE POINTER
	MOVNI T3,3		;MAXIMUM MESSAGE SIZE
	SINR			;READ ANSWER BYTE INTO T4
	 ERJMP [SETZ Q2,	;IF FAILED
		JRST DOJFD1 ]	; SEND FAILURE CODE 0
	MOVEI T3,2(T3)		;MAKES NUMBER OF BYTES IN MESSAGE
	MOVEM T3,DORCTR		;REMEMBER HOW MANY BYTES LEFT
	MOVE T4,DORMSG		;GET FIRST BYTE FROM MSCDGE(LEFT JUSTIFIED)
	ASH T4,-^D28		;SIGN EXTEND THE ERROR CODE
	MOVE Q2,T4		;SAVE THE ERROR CODE
DOJFD1:	HRROI T1,DOJFDM		;GET POINTER TO MESSAGE SPACE
	HRROI T2,[ASCIZ/NCP request # /]
	SETZ T3,
	SOUT			;BUILD THE RESPONSE MESSAGE
	MOVE T2,REQTAB(Q1)	;GET THE REQUEST NUMBER
	MOVEI T3,^D10		;DECIMAL NUMBER
	NOUT			;PUT NUMBER INTO STRING
	 JFCL
	HRROI T2,[ASCIZ/ [/]
	SETZ T3,
	SOUT			;NOW TYPE OUT THE OPR COMMAND
	MOVE T2,REQMES(Q1)	;GET THE ADR OF THE ORION MESSAGE
	CALL BLDCOM		;ADD THE OPR COMMAND TO THE STRING
	HRROI T2,[ASCIZ/]/]
	SETZ T3,
	SOUT
	IBP T1			;SKIP OVER THE NULL
	MOVEM T1,DORTXT		;SAVE POINTER TO START OF TEXT
	MOVE T3,DORCTR		;Get count of bytes left in header string
	JUMPL Q2,DOJFD6		;If an error code was found, go say so.
	MOVEI T2,DORMSG		;GET ADDRESS OF MESSAGE
	HLRZ T4,FCNTAB(Q1)	;GET NICE FUNCTION CODE
	CAILE T4,SHOLEN		;WITHIN RANGE ?
	JRST DOJFD6		;NO, JUST FINISH UP
	HRRZ Q3,FCNTAB(Q1)	;GET NICE OPTION CODE
	MOVEM T1,DOJHLD		;SAVE STRING POINTER IN CASE OF FAILURE
	;..
	;..

	CALL @SHOTAB(T4)	;GO DO REQUEST
	 JRST [	MOVE T1,DOJHLD	;GET STRING POINTER
		SETZM DOJHLD	;INDICATE WHICH ERROR MESSAGE
		JRST .+1]
; HERE TO ASSEMBLE TEXT REPLY AND SEND IT TO OPR

DOJFD6:	HRROI T2,[ASCIZ/	  /] ;GET SPACING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;ADD PUNCTUATION TO STRING
	JUMPG Q2,DOJFD7		;SUCCESSFUL REQUEST ?
	HRROI T2,[ASCIZ/? Request failed, /]
	SETZM T3		;TERMINATE ON NULL
	SOUT			;PRECEDE MESSAGE WITH ERROR INDICATION
DOJFD7:	ADDI Q2,JFDMSO		;ADD IN OFFSET 
	SKIPL Q2		;LEGAL ERROR CODE
	CAIL Q2,JFDMSL
	SKIPA T2,[-1,,[ASCIZ/? Unknown NICE error code/]]
	HRRO T2,JFDMES(Q2)	;GET THE ANSWER STRING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;PUT THE TEXT STRING IN THE MESSAGE
	HRROI T2,DOJFDM		;GET A POINTER TO THE MESSAGE
	MOVE T1,DORTXT		;GET POINTER TO TEXT
	CALL OPRMES		;SEND THE ANSWER BACK TO THE OPR
	 NON.FATAL.ERROR
	MOVE T1,REQMES(Q1)	;GET THE ADDRESS OF THE ORION MESSAGE
	CALL RELPGA		;RELEASE IT
	 NON.FATAL.ERROR
	MOVE T1,Q1		;NOW RELEASE THE REQUEST BLOCK
	CALL RELRQI		;...
	RETSKP			;DONE
; TABLE OF ROUTINES TO HANDLE REPLIES FROM NICE PROCESSES

SHOTAB:	R			;ILLEGAL
	R			;ILLEGAL
	R			;ILLEGAL
	R			;ILLEGAL
	R			;ILLEGAL
	R			;ILLEGAL
	LOPTST			;.NCTST - RESPONSE TO A NICE TEST REQUEST
	R			;ILLEGAL
	@REDTAB(Q3)		;READ INFORMATION BASED ON OPTION

SHOLEN==.-SHOTAB


; TABLE OF ROUTINES TO HANDLE REPLIES TO READ INFORMATION REQUESTS

REDTAB:	R			;LOCAL NODE COUNTERS
	LCLSTS			;LOCAL NODE STATUS
	R			;REMOTE NODE COUNTERS
	REMSTS			;REMOTE NODE STATUS
	LINCTR			;LINE COUNTERS
	LINSTS			;LINE STATUS

REDLEN==.-REDTAB
;LOPTST - ROUTINE TO SHOW EFFECTS OF LOOP COMMAND

LOPTST:	STKVAR <LOPHLD>
	MOVEM T1,LOPHLD		;SAVE THE STRING POINTER
	MOVE T1,T2		;T1<= NICE MESSAGE POINTER
	HRLI T1,(POINT 8,)	;IT'S THE SECOND BYTE IN THE MESSAGE
	IBP T1
	MOVE T2,T3		;GET NUMBER OF BYTES LEFT IN NICE MSG
	CALL GETTWO		;GET COUNT OF BLOCKS NOT PROCESSED
	 RETBAD			;ERROR - RETURN
	MOVE T1,LOPHLD		;GET ANSWER STRING POINTER
	MOVEM T3,LOPHLD		;SAVE THE BLOCK COUNT
	HRROI T2,[ASCIZ\Count of blocks not looped = \]
	SETZ T3,		;WRITE WHOLE STRING
	SOUT
	 ERJMP [RETBAD]		;ERROR RETURN	
	MOVE T2,LOPHLD		;GET THE COUNT
	MOVEI T3,^D10		;WRITE IT OUT IN  DECIMAL
	NOUT
	 ERJMP [RETBAD]
	HRROI T2,[ASCIZ/.
/]
	SOUT
	MOVE T2,T1		;BACKUP POINTER 
	HRROI T1,-1
	ADJBP T1,T2
	RETSKP
	
;LCLSTS - ROUTINE TO RETURN LOCAL NODE STATUS

LCLSTS:	STKVAR <LNJPTR,LNJCTR,<LNRMSG,100>,LNRCTR,LNJNUM,<LNJSYS,10>,<LNJRVR,3>,<LNJCVR,3>,LNJSTA,<LNJHST,2>,LNJLEN>
	MOVEM T1,LNJPTR		;SAVE POINTER TO RESPONSE MESSAGE
	MOVE T1,T2		;COPY ADDRESS OF NICE MESSAGE
	HRLI T1,341000		;POINT TO 2ND BYTE IN MESSAGE
	MOVE T2,T3		;GET NUMBER OF BYTES LEFT IN NICE MSG
	CALL GETTWO		;GET NUMBER OF RESPONSE MESSAGES
	 RET			;FAILED
	MOVEM T3,LNRCTR		;SAVE NUMBER OF BLOCKS TO FOLLOW
	EXCH T1,LNJPTR		;GET RESPONSE MESSAGE POINTER
	HRROI T2,[ASCIZ \
Status of local node as of \]
	SETZ T3,
	SOUT
	 ERJMP R		;FAIL
	SETOM T2		;CURRENT DATE AND TIME
	MOVE T3,[OT%SCL]
	ODTIM			;ADD TIME AND DATE
	 ERJMP R		;FAIL
	HRROI T2,[ASCIZ/

Node Name is /]
	SETZ T3,
	SOUT
	 ERJMP R		;FAIL
	MOVEM T1,LNJPTR		;SAVE MESSAGE POINTER
	MOVE T1,JFDTAB(Q1)	;GET JFN FOR MESSSAGES
	MOVEI T2,LNRMSG		;POINT TO MESSAGE BUFFER
	HRLI T2,(POINT 8,)	;MAKE IT INTO A BYTE POINTER
	MOVNI T3,4*100		;MAXIMUM SIZE OF MESSAGE
	SINR			;READ NEXT BLOCK
	 ERJMP R		;FAIL
	MOVEI T1,LNRMSG		;POINT TO MESSAGE BUFFER
	HRLI T1,(POINT 8,)	;MAKE IT INTO A BYTE POINTER
	MOVEI T2,4*100(T3)	;MAKES NUMBER OF BYTES WE READ
	ILDB T3,T1		;GET CODE
	CAIN T3,.RDLNS		;WAS THIS LOCAL STATUS ?
	SOSGE T2		;ADJUST COUNT
	 RET			;NOT ENOUGH BYTES
	MOVE T3,LNJPTR		;GET TEXT POINTER
	CALL GETIMA		;EXTRACT NODE NAME FROM MESSAGE
	 RET			;FAILED, RETURN ERROR
	MOVEM T1,LNJPTR		;SAVE POINTER INTO NICE MESSAGE
	MOVEM T2,LNJCTR		;SAVE NUMBER OF BYTES LEFT
	MOVE T1,T3		;GET TEXT POINTER
	BKJFN			;OVERWRITE THE NULL
	 ERJMP R		;FAILED
	HRROI T2,[ASCIZ/, # /]	;AND TEXT TO OUTPUT
	SETZM T3		;TERMINATE NULL
	SOUT			;OUTPUT THE TEXT
	EXCH T1,LNJPTR		;GET NICE POINTER AGAIN, SAVE TEXT PTR
	MOVE T2,LNJCTR		;AND COUNT
	CALL GETNUM		;GET NODE NUMBER FROM NICE MESSAGE
	 RET			;FAILED
	MOVEM T4,LNJNUM		;SAVE NODE NUMBER
	SUBI T2,3		;AT LEAST ANOTHER 3 BYTES LEFT ?
	JUMPL T2,R		;NO, FAIL
	ILDB T4,T1		;YES, GET NODE STATE
	MOVEM T4,LNJSTA		;SAVE STATE
	ILDB T4,T1		;GET MAINTENANCE LOGGING STATE
	ILDB T4,T1		;AND OPERATOR LOGGING STATE
	HRRI T3,LNJHST		;GET ADDRESS WHERE HOST NAME GOES
	HRLI T3,(POINT 7,)	;AND FORM POINTER TO HOST NAME
	CALL GETIMA		;GET DEFAULT HOST NAME
	 RET			;FAILED
	MOVEM T4,LNJLEN		;SAVE LENGTH OF HOST NAME
	SUBI T2,6		;ENOUGH BYTES LEFT FOR VERSIONS ?
	JUMPL T2,R		;NO, FAIL
	ILDB T4,T1		;GET A VERSION BYTE
	MOVEM T4,LNJRVR		;SAVE FIRST BYTE
	ILDB T4,T1		;GET A BYTE
	MOVEM T4,1+LNJRVR	;SAVE IT
	ILDB T4,T1		;GET LAST BYTE
	MOVEM T4,2+LNJRVR	;SAVE LAST BYTE
	ILDB T4,T1		;GET FIRST COMM VER BYTE
	MOVEM T4,LNJCVR		;SAVE IT
	ILDB T4,T1		;GET NEXT BYTE
	MOVEM T4,1+LNJCVR	;SAVE IT
	ILDB T4,T1		;GET LAST BYTE
	MOVEM T4,2+LNJCVR	;SAVE LAST VERSION BYTE
	HRRI T3,LNJSYS		;GET ADDRESS WHERE SYS NAME GOES
	HRLI T3,(POINT 7,)	;FORM POINTER TO NAME
	CALL GETIMA		;GET SYSTEM ID
	 RET			;FAILED
	EXCH T1,LNJPTR		;GET BACK TEXT POINTER
	MOVEM T2,LNJCTR		;SAVE COUNT OF BYTES LEFT IN MESSAGE
	MOVE T2,LNJNUM		;GET BINARY NODE NUMBER
	MOVX T3,^D10		;USE DECIMAL
	NOUT			;ADD NODE NUMBER TO RESPONSE
	 ERJMP R		;FAILED, RETURN ERROR
	HRROI T2,[ASCIZ/, System = /] ;GET MORE TEXT
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT TEXT
	HRROI T2,LNJSYS		;GET ADDRESS OF SYSTEM NAME
	SOUT			;OUTPUT SYSTEM NAME
	HRROI T2,[ASCIZ/
Routing Version = /]		;OUTPUT VERSION
	SOUT			;OUTPUT TEXT
	MOVE T2,LNJRVR		;GET FIRST VERSION NUMBER BYTE
	MOVX T3,^D10		;USE DECIMAL
	NOUT			;OUTPUT VERSION BYTE
	 ERJMP R		;FAILED
	MOVX T2,"."		;GET PUNCTUATION
	BOUT			;OUTPUT A PERIOD
	MOVE T2,1+LNJRVR	;GET NEXT PART OF VERSION
	NOUT			;OUTPUT VERSION BYTE
	 ERJMP R		;FAILED
	MOVX T2,"."		;GET PUNCTUATION
	BOUT			;OUTPUT A PERIOD
	MOVE T2,2+LNJRVR	;GET NEXT PART OF VERSION
	NOUT			;OUTPUT VERSION BYTE
	 ERJMP R		;FAILED
	HRROI T2,[ASCIZ/, Communications Version = /]
	SETZM T3		;TERMINATE ON NULL
	SOUT			;OUTPUT HEADING
	MOVX T3,^D10		;USE DECIMAL
	MOVE T2,LNJCVR		;GET FIRST PART OF VERSION
	NOUT			;OUTPUT THE BYTE
	 ERJMP R		;FAILED
	MOVX T2,"."		;GET PUNCTUATION
	BOUT			;OUTPUT A PERIOD
	MOVE T2,1+LNJCVR	;GET NEXT PART OF VERSION
	NOUT			;OUTPUT VERSION BYTE
	 ERJMP R		;FAILED
	MOVX T2,"."		;GET PUNCTUATION
	BOUT			;OUTPUT A PERIOD
	MOVE T2,2+LNJCVR	;GET NEXT PART OF VERSION
	NOUT			;OUTPUT LAST BYTE OF VERSION
	 ERJMP R		;FAILED
	HRROI T2,[ASCIZ/
State is /]				;get text
	SETZM T3		;SOUT
	SOUT			;OUTPUT TEXT
	HRROI T2,[ASCIZ/Unknown,  Default Host = /] ;ASSUME UNKOWN
	MOVE T4,LNJSTA		;GET STATE
	CAIN T4,.NSON		;NODE ON ?
	HRROI T2,[ASCIZ/On,  Default Host = /] ;YES
	CAIN T4,.NSOFF		;OFF ?
	HRROI T2,[ASCIZ/Off,  Default Host = /] ;YES
	CAIN T4,.NSSHT		;SHUT ?
	HRROI T2,[ASCIZ/Shut,  Default Host = /] ;YES
	SOUT			;OUTPUT STATE
	HRROI T2,[ASCIZ/Unknown/]
	SKIPE LNJLEN		;ANY HOST SPECIFIED ?
	HRROI T2,LNJHST		;GET POINTER TO HOST NAME
	SOUT			;OUTPUT HOST NAME
	HRROI T2,[ASCIZ/

/]				;GET BLANK LINES
	SOUT			;AND FINAL TEXT
	RETSKP			;DONE
;REMSTS - ROUTINE TO RETURN REMOTE NODE STATUS
;
;ACCEPTS IN T1/	POINTER TO DESTINATION FOR TEXT
;	    T2/	ADDRESS OF RESPONSE MESSAGE FROM NICE PROCESS
;		CALL REMSTS
;RETURN: +1	 FAILED
;	 +2	SUCCESS, WITH T1/ UPDATED POINTER

REMSTS:	STKVAR <RSJPTR,RSJCNT>
	MOVEM T1,RSJPTR		;SAVE POINTER TO RESPONSE MESSAGE
	MOVE T1,T2		;COPY ADDRESS OF NICE MESSAGE
	HRLI T1,341000		;POINT TO 2ND BYTE IN MESSAGE
	MOVE T2,T3		;GET NUMBER OF BYTES LEFT IN NICE MSG
	CALL GETTWO		;GET NUMBER OF RESPONSE MESSAGES
	 RET			;FAILED
	MOVEM T3,RSJCNT		;SAVE NUMBER OF BLOCKS TO FOLLOW
	EXCH T1,RSJPTR		;GET RESPONSE MESSAGE POINTER
	HRROI T2,[ASCIZ \
	Status as of \]
	SETZ T3,
	SOUT
	 ERJMP R		;FAIL
	SETOM T2		;CURRENT DATE AND TIME
	MOVE T3,[OT%SCL]
	ODTIM			;ADD TIME AND DATE
	 ERJMP R		;FAIL
	HRROI T2,[ASCIZ/

	Node Name	Node Number		State

	/]				;OUTPUT TITLE
	SETZ T3,
	SOUT
	 ERJMP R		;FAIL
	MOVE T2,RSJCNT		;PASS COUNT OF INCOMING MESSAGES
	CALL REQSTS		;GO REQUEST NODE STATUS
	 RET			;FAILED
	RETSKP			;DONE, RETURN SUCCESS
;REQSTS - ROUTINE TO REQUEST REMOTE NODE STATUS
;
;ACCEPTS IN T1/	POINTER TO DESTINATION FOR TEXT
;		CALL REQSTS
;RETURNS: +1	 FAILED
;	  +2	SUCCESS

REQSTS:	STKVAR <RSRCNT,RSRPTR,RSRCTR,<RSRMSG,100>>

	MOVEM T2,RSRCNT		;SAVE COUNT OF COMING MESSAGES
STSLOP:	movem t1,rsrptr		;save text destination pointer
	MOVE T1,JFDTAB(Q1)	;GET JFN FOR MESSSAGES
	MOVEI T2,RSRMSG		;POINT TO MESSAGE BUFFER
	HRLI T2,(POINT 8,)	;MAKE IT INTO A BYTE POINTER
	MOVNI T3,4*100		;MAXIMUM SIZE OF MESSAGE
	SINR			;READ NEXT BLOCK
	 ERJMP R		;FAIL
	MOVEI T1,RSRMSG		;POINT TO MESSAGE BUFFER
	HRLI T1,(POINT 8,)	;MAKE IT INTO A BYTE POINTER
	MOVEI T2,4*100(T3)	;MAKES NUMBER OF BYTES WE READ
	ILDB T3,T1		;GET CODE
	CAIN T3,.RDRNS		;WAS THIS REMOTE STATUS ?
	SOSGE T2		;ADJUST COUNT
	 RET			;NOT ENOUGH BYTES
	MOVE T3,RSRPTR		;GET TEXT POINTER
	CALL GETIMA		;EXTRACT NODE NAME FROM MESSAGE
	 RET			;FAILED, RETURN ERROR
	MOVX T4,.CHTAB		;GET A TAB
	DPB T4,T3		;ADD PUNCTUATION TO TEXT
	IDPB T4,T3		;AND ANOTHER TAB
	MOVEM T3,RSRPTR		;SAVE TEXT POINTER AGAIN
	CALL GETNUM		;GET NODE NUMBER FROM NICE MESSAGE
	 RET			;FAILED
	EXCH T1,RSRPTR		;GET BACK TEXT POINTER
	MOVEM T2,RSRCTR		;SAVE COUNT OF BYTES LEFT IN MESSAGE
	MOVE T2,T4		;GET BINARY NODE NUMBER
	MOVX T3,^D10		;USE DECIMAL
	NOUT			;ADD NODE NUMBER TO RESPONSE
	 ERJMP R		;FAILED, RETURN ERROR
	MOVX T2,.CHTAB		;GET A TAB
	BOUT			;ADD PUNCTUATION
	BOUT			;AND ANOTHER TAB
	BOUT			;AND YET ANOTHER
	EXCH T1,RSRPTR		;GET BACK PTR TO NICE MESSAGE
	SOSGE RSRCTR		;AT LEAST ONE BYTE LEFT IN MESSAGE ?
	RET			;NO, FAIL
	ILDB T4,T1		;YES, GET NODE STATE
	EXCH T1,RSRPTR		;GET BACK PTR TO NICE MESSAGE
	HRROI T2,[ASCIZ/Unknown

/]				;ASSUME STATE IS UNKNOWN
	CAIN T4,.NSON		;NODE ON ?
	HRROI T2,[ASCIZ/On

/]				;YES, USE ON TEXT
	CAIN T4,.NSOFF		;NODE OFF ?
	HRROI T2,[ASCIZ/Off

/]				;YES, SAY OFF
	CAIN T4,.NSSHT		;NODE IN SHUT STATE ?
	HRROI T2,[ASCIZ/Shut
/]				;YEP, SAY SO
	SETZM T3		;TERMINATE ON NULL
	SOUT			;ADD STATE TO TEXT
	MOVE T2,RSRCNT		;GET COUNT OF MESSAGE TO PROCESS
	SOS T2			;ACCOUNT FOR WORK JUST DONE
	JUMPN T2,[ MOVEM T2,RSRCNT	;KEEP GOING IF  NON-ZERO (SAVE COUNT)
		   HRROI T2,[ASCIZ/	/] ;KEEP GOING IF NON-ZERO
		   SOUT		;PUT TABS FOR NEXT LINE
		   JRST STSLOP]	;BUILD NEXT LINE
	RETSKP			;DONE, RETURN
;LINCTR - ROUTINE TO RETURN ASCII LINE COUNTERS
;
;ACCEPTS IN T1/	POINTER TO RESPONSE MESSAGE
;	    T2/	ADDRESS OF RESPNSE MESSAGE FROM NICE PROCESS
;		CALL LINCTR
;RETURN: +1	 FAILED
;	 +2	SUCCESS, WITH T1/ UPDATED POINTER

LINCTR:	STKVAR <LCJPTR,LCJCTR,<LCRMSG,100>,LCRCTR,LCRTYP>
	MOVEM T1,LCJPTR		;SAVE POINTER TO RESPONSE MESSAGE
	MOVE T1,T2		;COPY ADDRESS OF NICE MESSAGE
	HRLI T1,341000		;POINT TO 2ND BYTE IN MESSAGE
	MOVE T2,T3		;GET NUMBER OF BYTES LEFT IN NICE MSG
	CALL GETTWO		;GET NUMBER OF RESPONSE MESSAGES
	 RET			;FAILED
	MOVEM T3,LCRCTR		;SAVE NUMBER OF BLOCKS TO FOLLOW
DOJFD2:	EXCH T1,LCJPTR		;GET RESPONSE MESSAGE POINTER
	HRROI T2,[ASCIZ \Counts for line \]
	SETZ T3,
	SOUT
	EXCH T1,LCJPTR		;SAVE MESSAGE POINTER
	MOVE T1,JFDTAB(Q1)	;GET JFN FOR MESSSAGES
	MOVEI T2,LCRMSG		;POINT TO MESSAGE BUFFER
	HRLI T2,441000		;MAKE IT INTO A BYTE POINTER
	MOVNI T3,4*100		;MAXIMUM SIZE OF MESSAGE
	SINR			;READ NEXT BLOCK
	 ERJMP R		;FAIL
	MOVEI T1,LCRMSG		;POINT TO MESSAGE BUFFER
	HRLI T1,441000		;MAKE IT INTO A BYTE POINTER
	MOVEI T2,4*100(T3)	;MAKES NUMBER OF BYTES WE READ
	ILDB T3,T1		;GET CODE
	CAIN T3,.RDLCT		;WAS THIS A LINE COUNT ?
	SOSGE T2		;ADJUST COUNT
	 JRST DOJFD5		;BAD CODE OR OUT OF DATA
	CALL GETLIN		;GET LINE NAME IN STANDARD FORMAT
	 JRST [ MOVE Q2,T1	;GET ERROR CODE
		JRST DOJFD5 ]
	EXCH T1,LCJPTR		;SWAP POINTERS
	EXCH T2,LCJCTR
	DMOVE T2,T3		;GET LINE ID
	CALL ASCLIN		;PUT LINE-ID IN TEXT
	 JRST DOJFD5		;LOSE
	HRROI T2,[ASCIZ \, as of \]
	SOUT
	SETOM T2		;CURRENT DATE AND TIME
	MOVE T3,[OT%SCL]
	ODTIM			;ADD TIME AND DATE
DOJFD3:	HRROI T2,[BYTE(7)15,12,0]
	SETZ T3,
	SOUT
	EXCH T1,LCJPTR		;SWAP POINTERS
	EXCH T2,LCJCTR		;AND COUNTERS
	JUMPL T2,DOJFD5		;ANY MORE COUNTERS ?
	CALL GETEXB		;GET COUNTER TYPE
	 JRST DOJFD5
	MOVEM T4,LCRTYP		;SAVE TYPE CODE
	CALL GETTWO		;GET TWO BYTE FIELD
	 JRST DOJFD5
	EXCH T1,LCJPTR		;SWAP POINTERS
	EXCH T2,LCJCTR		;AND COUNTERS
	SKIPL T4,LCRTYP
	CAIL T4,NLCTMX		;IS TYPE IN RANGE ?
	SKIPA T2,[-1,,[ASCIZ \ *** unknown ***	\]]
	HRRO T2,NICLCT(T4)
	MOVEM T3,T4		;SAVE COUNTER
	SETZ T3,		;FOR SOUT
	SOUT
	MOVE T2,T4		;PUT COUNTER IN RIGHT REG
	MOVE T3,[NO%LFL+10B17+12]
	NOUT
	 JFCL
	JRST DOJFD3
DOJFD5:	SOSLE LCRCTR		;HAVE WE DONE ALL BLOCKS YET ?
	JRST DOJFD2		;LOOP BACK FOR REST OF BLOCKS
	MOVE T1,LCJPTR		;GET RESPONSE MESSAGE POINTER
	RETSKP			;DONE, RETURN
NICLCT:	[ASCIZ \Seconds since zeroed	\]
	[ASCIZ \Blocks received		\]
	[ASCIZ \Blocks sent		\]
	[ASCIZ \Retran, line errors	\]
	[ASCIZ \Received line errors	\]
	[ASCIZ \Retran, not line errors	\]
	[ASCIZ \Receive timeouts	\]
	[ASCIZ \Receive select errors	\]
	[ASCIZ \Resource errors		\]
	NLCTMX==.-NICLCT




JFDMES:
	[ASCIZ /NCU process not available/]	;-21
	[ASCIZ /No room for new entry/]		;-20
	[ASCIZ /Network Communications Error/]	;-19
	[ASCIZ\File I/O error\]			;-18
	[ASCIZ/Line protocol error/]		;-17
	[ASCIZ/Invalid parameter value/]	;-16
	[ASCIZ/Resource error/]			;-15
	[ASCIZ/Configuration data base error/]	;-14
	[ASCIZ/Invalid file/]			;-13
	[ASCIZ/Invalid server id/]		;-12
	[ASCIZ/Invalid node id/]		;-11
	[ASCIZ/Line communications error/]	;-10
	[ASCIZ/Line in wrong state/]		;-9
	[ASCIZ/Invalid line id/]		;-8
	[ASCIZ/Unknown NICE error code/]	;-7
	[ASCIZ/Unknown NICE error code/]	;-6
	[ASCIZ/NICE Process program error/]	;-5
	[ASCIZ/NICE Protocol Error/]		;-4
	[ASCIZ/Insufficient status/]		;-3
	[ASCIZ/Invalid message format/]		;-2
	[ASCIZ/Invalid function or option/]	;-1

	JFDMSO==.-JFDMES		;NUMBER OF KNOWN NICE ERROR CODES

	[ASCIZ/NSP link died/]			;0
	[ASCIZ/Function completed successfully/];1

	JFDMSL==.-JFDMES
;LINSTS - ROUTINE TO RETURN ASCII LINE STATUS
;
;ACCEPTS IN T1/	POINTER TO RESPONSE MESSAGE
;	    T2/	ADDRESS OF RESPNSE MESSAGE FROM NICE PROCESS
;		CALL LINSTS
;RETURN: +1	 FAILED
;	 +2	SUCCESS, WITH T1/ UPDATED POINTER

LINSTS:	STKVAR <lsrPTR,LSrCTR>
	MOVEM T1,LSrPTR		;SAVE POINTER TO RESPONSE MESSAGE
	MOVE T1,T2		;COPY ADDRESS OF NICE MESSAGE
	HRLI T1,341000		;POINT TO 2ND BYTE IN MESSAGE
	MOVE T2,T3		;GET NUMBER OF BYTES LEFT IN NICE MSG
	CALL GETTWO		;GET NUMBER OF RESPONSE MESSAGES
	 RET			;FAILED
	MOVEM T3,LSRCTR		;SAVE NUMBER OF BLOCKS TO FOLLOW
	move T1,lsrPTR		;GET RESPONSE MESSAGE POINTER
	HRROI T2,[ASCIZ \
	Status as of \]
	SETZ T3,
	SOUT
	 ERJMP R		;FAIL
	SETOM T2		;CURRENT DATE AND TIME
	MOVE T3,[OT%SCL]
	ODTIM			;ADD TIME AND DATE
	 ERJMP R		;FAIL
	HRROI T2,[ASCIZ/

	Line ID		State		Adjacent Node

	/]				;OUTPUT TITLE
	SETZ T3,
	SOUT
	 ERJMP R		;FAIL
	MOVE T2,LSRCTR		;PASS COUNT OF MESSAGE TO COME
	CALL REQLST		;go request line status
	 RET			;failed
	RETSKP			;done, success
;reqlst - request line status

REQLST:	STKVAR <LSJCNT,<lsjmsg,100>,lsjctr,<lsjlin,2>,lsjptr>
	MOVEM T2,LSJCNT		;SAVE THE COUNT OF INCOMING MESSAGES
LSTLOP:	movem T1,lsjptr		;SAVE MESSAGE POINTER
	MOVE T1,JFDTAB(Q1)	;GET JFN FOR MESSSAGES
	MOVEI T2,lsjmsg		;POINT TO MESSAGE BUFFER
	HRLI T2,(POINT 8,)	;MAKE IT INTO A BYTE POINTER
	MOVNI T3,4*100		;MAXIMUM SIZE OF MESSAGE
	SINR			;READ NEXT BLOCK
	 ERJMP R		;FAIL
	MOVEI T1,lsjmsg		;POINT TO MESSAGE BUFFER
	HRLI T1,(POINT 8,)	;MAKE IT INTO A BYTE POINTER
	MOVEI T2,4*100(T3)	;MAKES NUMBER OF BYTES WE READ
	ILDB T3,T1		;GET CODE
	CAIN T3,.RDLST		;WAS THIS LINE STATUS ?
	SOSGE T2		;ADJUST COUNT
	 RET			;NOT ENOUGH BYTES
	CALL GETLIN		;GET LINE NAME IN STANDARD FORMAT
	 RET			;BAD MESSAGE FORMAT
	DMOVEM T3,lsjlin	;SAVE LINE ID
	EXCH T1,LSJPTR		;SWAP POINTERS
	MOVEM T2,LSJCTR
	DMOVE T2,lsjlin		;RESTORE LINE ID
	CALL ASCLIN		;OUTPUT LINE ID AGAIN
	 RET			;FAILED
	MOVX T2,.CHTAB		;GET A TAB
	BOUT			;AND OUTPUT PUNCTUATION
	EXCH T1,LSJPTR		;SWAP POINTERS
	EXCH T2,LSJCTR		;AND COUNTERS
	JUMPL T2,R		;ANY MORE BYTES ?
	ILDB T4,T1		;GET LINE STATE
	SUBI T2,1		;ACCOUNT FOR STATE BYTE
	EXCH T1,LSJPTR		;SAVE POINTER
	EXCH T2,LSJCTR		;SAVE COUNT
	HRROI T2,[ASCIZ/Unknown	/] ;ASSUME UNKNOWN STATE
	CAIN T4,.LSTON		;IS LINE ON ?
	HRROI T2,[ASCIZ/On		/] ;YES,  LINE IS ON
	CAIN T4,.LSTOFF		;IS LINE OFF ?
	HRROI T2,[ASCIZ/Off		/] ;YES, GET CORRECT STATE STRING
	CAIN T4,.LSTMN		;MAINTENANCE ?
	HRROI T2,[ASCIZ/Maintenance	/]
	CAIN T4,.LSTCN		;Controller loopback?
	HRROI T2,[ASCIZ/Controller loopback/]
	CAIN T4,.LSTCB		;Cable loopback?
	HRROI T2,[ASCIZ/Cable loopback	/]
	SETZ T3,		;END ON NULL
	SOUT			;COMPLETE LINE
	EXCH T1,LSJPTR		;GET BACK POINTER TO NICE MSG
	EXCH T2,LSJCTR		;AND RESTORE COUNT
	SUBI T2,2		;SKIP OVER USELESS STATES
	IBP T1			; LOGGING STATES ARE NOT
	IBP T1			;  USED
	JUMPLE T2,R		;MUST BE AT LEAST ONE BYTE LEFT
	ILDB T4,T1		;GET COUNT FIELD FOR NODE NAME
	CAMLE T4,T2		;AT LEAST THAT MANY BYTES LEFT ?
	RET			;NO, DONE
	MOVE T2,LSJPTR		;GET POINTER TO TEXT REPLY
LINST5:	SOJL T4,LINST7		;IF DONE ALL CHARACTERS, RETURN SUCCESS
	ILDB T3,T1		;GET A CHARACTER FROM NODE NAME
	IDPB T3,T2		;STORE CHARACTER IN OUTPUT STRING
	JRST LINST5		;AND DO ALL CHARACTERS IN NAME

LINST7:	MOVE T1,T2		;COPY POINTER TO REPLY TEXT
	HRROI T2,[ASCIZ /
/]				;OUTPUT CRLF
	SETZM T3		;TERMINATE ON NULL
	SOUT			;END THE OUTPUT
	MOVE T2,LSJCNT		;GET COUNT OF MESSAGE TO PROCESS
	SOS T2			;ACCOUNT FOR WORK JUST DONE
	JUMPN T2,[ MOVEM T2,LSJCNT	;KEEP GOING IF  NON-ZERO (SAVE COUNT)
		   HRROI T2,[ASCIZ/	/] ;KEEP GOING IF NON-ZERO
		   SOUT		;PUT TABS FOR NEXT LINE
		   JRST LSTLOP]	;BUILD NEXT LINE
	RETSKP
SUBTTL	Routines to Parse and Rebuild Commands from OPR

; PRSKEY - PARSE A KEYWORD


PRSKEY:	LOAD T1,PBTYP		;GET ARGUMENT TYPE
	CAIE T1,.CMKEY		;KEYWORD ?
	RET			;NO, FAIL
	LOAD T1,PBVAL		;GET KEYWORD VALUE TO RETURN
	LOAD T2,PBLEN		;YES, GET LENGTH
	ADD P2,T2		;POINT TO NEXT ARGUMENT
	RETSKP			;DONE


; PRSCFM - PARSE COMMAND CONFIRMATION

PRSCFM:	LOAD T1,PBTYP		;GET ARGUMENT TYPE
	CAIE T1,.CMCFM		;CONFIRMATION ?
	RET			;NO, FAIL
	RETSKP			;YES, RETURN SUCCESS


; PRSNOD - PARSE A NODE NAME

PRSNOD:	LOAD T1,PBTYP		;GET ARGUMENT TYPE
	CAIE T1,.CMNOD		;NODE ?
	JRST [	CAIE T1,.CMFLD	;OR FIELD SPECIFICATION ?
		RET		;NO, FAIL
		JRST .+1]	;YES, ALL SET
	SETZM T1		;NO OLD BLOCK
	HRRI T2,.PBVAL(P2)	;GET ADDRESS OF NODE NAME STRING
	HRLI T2,(POINT 7,)	;FORM POINTER TO STRING
	MOVEI T3,NODLEN		;GET LENGTH OF NODE NAME STRING
	CALL CPYASC		;COPY STRING
	 RETBAD			;ILLEGAL NODE NAME
	CAIL T3,NODLEN*^D5	;Check if any bytes copied
	JRST [CALL RELFRE	;No .. release block
	       FATAL.ERROR	;Release failed
	      RETBAD]		;Give error return .. null node name
	LOAD T2,PBLEN		;YES, GET LENGTH
	ADD P2,T2		;POINT TO NEXT ARGUMENT
	RETSKP			;DONE
; PRSFIL - PARSE ANY TYPE OF FILE SPEC

PRSFIL:	CALL PRSIFI		;TRY INPUT FILE FIRST
	 JRST [	CALL PRSOFI	;FAILED, TRY OUTPUT FILE
		 RET		;NEITHER, RETURN ERROR
		RETSKP ]	;RETURN OUTPUT FILE
	RETSKP			;RETURN INPUT FILE



; PRSIFI - PARSE AN INPUT FILE NAME
; PRSOFI - PARSE AN OUTPUT FILE NAME

PRSOFI:	SKIPA T4,[.CMOFI]	;GET COMMAND JSYS FUNCTION CODE
PRSIFI:	MOVX T4,.CMIFI		;GET COMMAND JSYS CODE FOR INPUT FILE
	LOAD T1,PBTYP		;GET ARGUMENT TYPE
	CAME T1,T4		;RIGHT FILE ?
	RET			;NO, FAIL
	SETZM T1		;NO OLD BLOCK
	HRRI T2,.PBVAL(P2)	;GET ADDRESS OF NODE NAME STRING
	HRLI T2,(POINT 7,)	;FORM POINTER TO STRING
	LOAD T3,PBLEN		;GET LENGTH OF ARG FIELD
	CALL CPYASC		;COPY STRING
	 RETBAD			;FAILED, RETURN ERROR
	LOAD T2,PBLEN		;YES, GET LENGTH
	ADD P2,T2		;POINT TO NEXT ARGUMENT
	RETSKP			;DONE


; PARSE A NUMBER

PRSNUM:	LOAD T1,PBTYP		;GET ARGUMENT TYPE
	CAIE T1,.CMNUM		;NUMBER ?
	RET			;NO, FAIL
	LOAD T1,PBVAL		;GET VALUE TO RETURN
	LOAD T2,PBLEN		;YES, GET LENGTH
	ADD P2,T2		;POINT TO NEXT ARGUMENT
	RETSKP			;DONE



; PARSE NOISE WORDS

PRSNOI:	LOAD T1,PBTYP		;GET ARGUMENT TYPE
	CAIE T1,.CMNOI		;NOISE WORDS ?
	RET			;NO, FAIL
	LOAD T2,PBLEN		;YES, GET LENGTH
	ADD P2,T2		;POINT TO NEXT ARGUMENT
	RET			;DONE
; PARSE A TOKEN

PRSTOK:	MOVE T4,T1		;SAVE EXPECTED TOKEN
	LOAD T1,PBTYP		;GET ARGUMENT TYPE
	CAIE T1,.CMTOK		;TOKEN ?
	RET			;NO, FAIL
	LDB T1,[POINT 7,.PBVAL(P2),6] ;GET THE TOKEN
	CAME T1,T4		;CORRECT TOKEN ?
	RET			;NO, FAIL
	LOAD T2,PBLEN		;YES, GET LENGTH OF THIS ARGUMENT
	ADD P2,T2		;POINT TO NEXT ARGUMENT
	RETSKP			;DONE, RETURN SUCCESS



; PRSCMA - PARSE A COMMA


PRSCMA:	LOAD T1,PBTYP		;GET ARGUMENT TYPE
	CAIE T1,.CMCMA		;COMMA ?
	RET			;NO, FAIL
	LOAD T1,PBVAL		;GET VALUE TO RETURN
	LOAD T2,PBLEN		;YES, GET LENGTH
	ADD P2,T2		;POINT TO NEXT ARGUMENT
	RETSKP			;DONE
;PRSLID - ROUTINE TO PARSE A LINE ID
;
;ACCEPTS IN P2/	CURRENT POINTER INTO IPCF MESSAGE
;		CALL PRSLID
;RETURNS: +1	 FAILED, INVALID LINE ID
;	  +2	SUCCESS, WITH T1-T2/ LINE ID

PRSLID:	STKVAR <PLIDEV,PLICTL,PLIUNI,PLISTN>
	SETZM PLICTL		;INITIALIZE THE VARIOUS VALUES
	SETZM PLIUNI		; IN THE LINE ID.
	SETZM PLIDEV
	SETZM PLISTN

; PARSE DEVICE TYPE

	CALL PRSKEY		;PARSE A KEYWORD FOR DEVICE TYPE
	 RET			;FAILED
	MOVEI T2,SETDVT		;GET ADDRESS OF DEVICE TABLE
	MOVEI T3,SETDVL		;AND TABLE LENGTH
	CALL FNDDSP		;GET DEVICE TYPE
	 RET			;NOT FOUND, RETURN FAILURE
	MOVEM T1,PLIDEV		;SAVE DEVICE TYPE

; PARSE PUNCTUATION

	MOVX T1,"_"		;EXPECT AN UNDERSCORE
	CALL PRSTOK		;PARSE A TOKEN
	 RET			;FAILED

; PARSE CONTROLLER NUMBER (REQUIRED)

	CALL PRSNUM		;PARSE CONTROLLER NUMBER
	 RET			;FAILED
	MOVEM T1,PLICTL		;SAVE CONTROLLER NUMBER

; DETERMINE IF UNIT WAS SPECIFIED - IF SO PARSE PUNCTUATION

	MOVX T1,"_"		;POSSIBLY A TOKEN NEXT
	CALL PRSTOK		;PARSE A TOKEN
	 JRST PRS500		;NONE, GO RETURN LINE ID

; PARSE UNIT NUMBER

	CALL PRSNUM		;PARSE UNIT NUMBER
	 RET			;FAILED
	MOVEM T1,PLIUNI		;SAVE CONTROLLER NUMBER

; HERE ON COMPLETED PARSE - RETURN LINE ID

PRS500:	HRL T1,PLIDEV		;GET DEVICE TYPE
	HRR T1,PLICTL		;GET CONTROLLER NUMBER
	HRL T2,PLIUNI		;GET UNIT NUMBER
	HRR T2,PLISTN		;GET STATION ADDRESS
	RETSKP			;DONE
;ROUTINE TO REBUILD A COMMAND TYPED TO OPR
;ACCEPTS IN T1/	STRING POINTER TO WHERE COMMAND IS TO BE PUT
;	    T2/	ADR OF ORION MESSAGE
;	CALL BLDCOM
;RETURNS +1:	ALWAYS - UPDATED STRING POINTER IN T1

BLDCOM:	SAVEPQ			;SAVE THE PERMANENT ACS
	MOVE P1,T2		;SAVE ADR OF START OF MESSAGE
	MOVE T4,COM.PB(P1)	;GET OFFSET TO PARSER BLOCK
	MOVE P2,P1		;GET BASE ADDRESS OF IPCF MESSAGE
	ADD P2,T4		;COMPUTE ADDRESS OF PARSER BLOCK
BLDCML:	LOAD T2,PBTYP		;GET NEXT FIELD
	LOAD T3,PBVAL		;GET VALUE INTO T3
	CAIGE T2,BLDTBL		;IS THIS A KNOWN TYPE?
	XCT BLDTAB(T2)		;YES, EXECUTE IT
	MOVE T3,T1		;WITHOUT UPDATING THE POINTER
	MOVEI T2,0		;END WITH A NULL
	IDPB T2,T3		;...
	LOAD T2,PBLEN		;GET LENGTH OF THIS ARGUMENT
	ADD P2,T2		;COMPUTE ADDRESS OF NEXT ARG
	JRST BLDCML		;LOOP OVER EACH ARGUMENT

BLDTAB:	CALL BLDKEY		;.CMKEY
	CALL BLDNUM		;.CMNUM
	JFCL			;.CMNOI
	CALL BLDSWI		;.CMSWI
	CALL BLDFIL		;.CMIFI
	CALL BLDFIL		;.CMOFI
	CALL BLDFIL		;.CMFIL
	CALL BLDTXT		;.CMFLD
	JRST BLDCMD		;.CMCFM
	CALL BLDDIR		;.CMDIR
	CALL BLDDIR		;.CMUSR
	CALL BLDCMA		;.CMCMA
	JFCL			;.CMINI
	CALL BLDFLT		;.CMFLT
	CALL BLDDEV		;.CMDEV
	CALL BLDTXT		;.CMTXT
	CALL BLDTAD		;.CMTAD
	CALL BLDTXT		;.CMQST
	CALL BLDTXT		;.CMUQS
	CALL BLDTXT		;.CMTOK
	CALL BLDNUM		;.CMNUX
	CALL BLDTXT		;.CMACT
	CALL BLDNOD		;.CMNOD
BLDTBL==.-BLDTAB

BLDCMD:	MOVNI T2,1		;BACK UP OVER THE SPACE
	ADJBP T2,T1
	MOVE T1,T2		;RETURN THE UPDATED BYTE POINTER
	MOVEI T3,0		;PUT A NULL AT THE END OF THE STRING
	IDPB T3,T2		;...
	RET			;DONE
BLDKEY:	HRRO T2,KYTAB(T3)	;GET POINTER TO KEYWORD TEXT
	SETZ T3,
	SOUT			;COPY KEYWORD TO STRING
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	RET

BLDNUM:	MOVE T2,1(P2)		;GET THE NUMBER
	SKIPN T3,2(P2)		;IF ANY
	MOVEI T3,10		;ASSUME OCTAL IF NONE
	NOUT			;OUTPUT THE NUMBER
	 JFCL
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	RET

BLDSWI:	MOVEI T2,"/"		;SWITCH
	BOUT			;START WITH A SLASH
	HRRO T2,SWTAB(T3)	;GET SWITCH TEXT
	SETZ T3,
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	SOUT
	RET

BLDFIL:
BLDTXT:
BLDNOD:	HRRI T2,.PBVAL(P2)	;GET ADDRESS OF NODE NAME STRING
	HRLI T2,(POINT 7,)	;FORM POINTER TO STRING
	SETZ T3,
	SOUT
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	RET

BLDDIR:	MOVE T2,T1		;SAVE STRING POINTER
	DIRST			;TRANSLATE IT TO A STRING
	 MOVE T1,T2		;GET BACK STRING POINTER IF ERROR
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	RET

BLDCMA:	MOVEI T2,","		;ADD COMMA TO STRING
	BOUT
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	RET

BLDFLT:	MOVE T2,T3		;GET THE NUMBER
	MOVEI T3,0		;STANDARD FORMAT
	FLOUT
	 JFCL
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	RET
BLDDEV:	MOVE T2,T1		;SAVE STRING POINTER
	MOVE T2,T3		;COPY DEVICE DESIGNATOR
	DEVST
	 MOVE T1,T2		;FAILED, GET BACK STRING POINTER
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	RET

BLDTAD:	MOVE T2,T3		;GET THE DATE
	SETZ T3,
	ODTIM			;OUTPUT THE STRING
	 ERJMP .+1
	MOVEI T2," "		;FOLLOW EACH FIELD WITH A SPACE
	BOUT			;...
	RET
DEFINE X(A,B)<
	[ASCIZ\A\]>

KYTAB:	;EXECUTE THE KEYWORD MACRO FROM ORNMAC
	XLIST
	KEYWORD
	LIST

SWTAB:	;EXECUTE THE SWITCH MACRO FROM ORNMAC
	XLIST
	SWITCH
	LIST



;ROUTINE TO FINISH A REQUEST AND CLEAN UP FREE SPACE

;ACCEPTS IN T1/	ERROR CODE (IF FAILURE OCCURED)
;	    T2/	-1 = SUCCESS,  0 = FAILURE
;	    T3/	ADDRESS OF THE REQUEST

;RETURNS +1:	FAILED TO FINISH CORRECTLY
;	 +2:	OK

FINREQ:	ASUBR <FINRQE,FINRQC,FINRQA,FINRQF>
	SAVEQ
	LOAD T4,QUEFLG,(T3)	;GET THE MESSAGE FLAGS
	MOVEM T4,FINRQF		;SAVE THE FLAGS FOR LATER
	LOAD T4,QUETYP,(T3)	;GET MESSAGE TYPE
	CAIL T4,FREQDL		;LEGAL?
	FATAL.ERROR (.ERR14)	;NO
	MOVE Q1,FREQDT(T4)	;GET DISPATCH ADDRESS
	LOAD T4,QUEMES,(T3)	;GET ADDRESS OF MESSAGE
	MOVEM T4,FINRQA		;SAVE THIS ADDRESS
	MOVEI T1,QUEHLN		;NOW RELEASE THIS BLOCK
	MOVEM T1,(T3)		;SAVE THE CORRECT BLOCK LENGTH
	MOVE T1,T3		;GET ADDRESS OF BLOCK
	CALL RELFRE		;RELEASE THE BLOCK
	 FATAL.ERROR
	JRST (Q1)		;DISPATCH TO THE MESSAGE DEPENDENT CODE

FREQDT:	FINMES			;ORION MESSAGE
	FINFKT			;FORK TERMINATION
	FINJFD			;DATA OR DISCONNECT
	FINDML			;AUTO DUMP/LOAD
FREQDL==.-FREQDT
FINMES:	STKVAR <<FINMSM,200>>
	SETZM FINMSM		;START WITH A NULL MESSAGE
	MOVE T1,FINRQF		;GET THE MESSAGE FLAGS
	TXNE T1,QF%TXT		;IS THERE TEXT TO BE RETURNED?
	JRST [	MOVE T2,FINRQA	;YES, BUILD A POINTER TO IT
		LOAD T1,MS.CNT,.MSTYP(T2)
		ADDI T1,.MSTYP(T2)
		HRLI T1,(POINT 7,0)
		JRST FINMS2]	;GO SEND IT TO OPR
	TXNE T1,QF%NOA		;IS THIS MESSAGE TO BE ACK'D NOW?
	JRST FINMSD		;NO
	SKIPE FINRQC		;WAS THERE AN ERROR IN THE REQUEST?
	JRST FINMS1		;NO
	MOVE T1,FINRQE		;YES, GET THE ERROR CODE
	HRROI T2,FINMSM		;SET UP A POINTER TO THE TEXT AREA 
	MOVEI T3,.FHSLF		;THIS FORK
	CALL ERRORB		;BUILD THE MESSAGE
	setzm t1		;no text, just header
	hrroi t2,finmsM		;get pointer to messaGe
	call oprmes		;output the error text
	 jfcl			;ignore failure
FINMS1:	HRROI T1,FINMSM		;SET UP TO ACK ORION
FINMS2:	MOVE T1,FINRQA		;RELEASE THE MESSAGE PAGE
	CALL RELPGA		;...
	 NON.FATAL.ERROR
FINMSD:	RETSKP			;DONE


FINFKT:	RETSKP			;NO WORK TO BE DONE ON FORK TERMINATION

FINDML:	RETSKP			;DONE


FINJFD:	RETSKP			;DONE
;ROUTINE TO CHECK FOR ANY NICE MESSAGES WAITING TO BE SENT
;  IF ANY ARE FOUND, AN ATTEMPT IS MADE TO SEND THEM.
;  IF THE NICE MESSAGE CANNOT BE SENT, IT IS LEFT ON THE QUEUE
;  TO BE TRIED LATER.

;	CALL CHKNIC
;RETURNS +1:	ALWAYS - NOTING MORE TO DO AT THIS TIME

CHKNIC:	STKVAR <CHKNIM,CHKNIN,CHKNIT,CHKNIF>
CHKNIL:	CALL DEQNIC		;GET A NICE MESSAGE TO SEND
	 RET			;NO MORE ON QUEUE
	MOVEM T1,CHKNIM		;SAVE ADR OF MESSAGE
	MOVEM T2,CHKNIT		;SAVE ADDRESS OF NICE MESSAGE TEXT
	MOVEM T3,CHKNIN		;SAVE NUMBER OF CHARS IN NICE MESSAGE
	MOVEM T4,CHKNIF		;SAVE FUNCTION AND OPTION
	TXZE T2,NQ%REQ		;HAS THIS ENTRY ALREADY BEEN RE-QUEUED ?
	JRST CHKNI2		;YES, DONE WITH THIS PASS THRU QUEUE
	HRLI T2,(POINT 8,)	;NO, FORM POINTER TO NICE MESSAGE
	CALL SNDNIC		;TRY TO SEND THIS NICE MESSAGE
	 JRST CHKNI1		;COULD NOT SEND IT, GO REQUEUE IT
	JRST CHKNIL		;LOOP BACK FOR REST OF REQUESTS

CHKNI1:	MOVE T1,CHKNIM		;GET BACK MESSAGE ADR
	MOVE T2,CHKNIT		;GET BACK ADR OF NICE TEXT
	CALL RQCHK		;Check if request is too old
	JRST CHKNIL		;Yes .. don't requeue it
	TXO T2,NQ%REQ		;NOTE THAT THIS ENTRY REQUEUED
	MOVE T3,CHKNIN		;AND NUMBER OF CHARACTERS
	MOVE T4,CHKNIF		;RESTORE NICE FUNCTION AND OPTION
	CALL QUENCR		;QUEUE IT ON REAR OF QUEUE
	 NON.FATAL.ERROR
	JRST CHKNIL		;GO PROCESS NEXT ENTRY ON QUEUE

; HERE WHEN FOUND AN ALREADY PROCESSED QUEUE ENTRY

CHKNI2:	MOVE T1,CHKNIM		;GET BACK MESSAGE ADR
	MOVE T2,CHKNIT		;GET BACK ADR OF NICE TEXT
	TXZ T2,NQ%REQ		;RESET "ENTRY REQUEUED" FLAG
	MOVE T3,CHKNIN		;AND NUMBER OF CHARACTERS
	MOVE T4,CHKNIF		;RESTORE NICE FUNCTION AND OPTION
	CALL QUENCF		;QUEUE IT ON FRONT OF QUEUE
	 NON.FATAL.ERROR
	RET			;DONE WITH THIS PASS, RETURN
;Routine to check age of a NICE request

;ACCEPTS in T2/ Time of entry,,anything
;
;Returns +1: if request is too old
;	 +2: if request should be requeued

RQCHK:	SAVET			;Save some registers
	HLRZ	T1,T2		;Get time entry was made
	CALL	QUETIM		;Get current time (minutes since midnight)
	CAIG	T2,RQMAX	;Check for midnight wrap around
	ADDI	T2,^D24*^D60	;Yes .. add midnight
	SUBI	T2,RQMAX	;Subtract threshold time
	CAMGE	T2,T1		;Check if entry is too old (lss current-RQMAX)
	RETSKP			;No .. give skip .. entry is still good
	RET			;Nonskip .. entry is ancient
;ROUTINE TO QUEUE NICE MESSAGES ONTO THE NICE QUEUE

;ACCEPTS IN T1/	ADDRESS OF EXECUTOR STRING,,ADDRESS OF MESSAGE FROM ORION
;	    T2/	ADDRESS OF NICE MESSAGE
;	    T3/	REQ NUMBER ,, COUNT OF CHARACTERS IN NICE MESSAGE
;	    T4/	NICE FUNCTION CODE,,NICE SUB-OPTION
;	CALL QUENCF		;QUEUE TO FRONT OF NICE QUEUE
;	    OR
;	CALL QUENCR		;QUEUE TO REAR OF NICE QUEUE
;RETURNS +1:	FAILED
;	 +2:	SUCCESSFUL

QUENCR:	SAVEQ
	SETZM Q2		;MARK THAT REQUEST IS FOR END OF QUEUE
	JRST QUENCU		;GO ADD ENTRY TO QUEUE
QUENCF:	SAVEQ
	SETOM Q2		;PUT ENTRY ON FRONT OF THE QUEUE
	JRST QUENCU		;GO ADD ENTRY TO QUEUE

QUENCU:	ASUBR <QUENCM,QUENCT,QUENCN,QUEFCN>
	MOVEI T1,NQLEN		;GET A HEADER TO HOLD THIS INFO
	CALL GETFRE		;...
	 RETBAD ()		;COULD NOT GET SPACE NOW
	MOVE Q1,T1		;SAVE ADR OF FREE SPACE
	HRRZ T2,QUENCM		;GET ADDRESS OF MESSAGE
	STOR T2,NQMES,(Q1)	;SAVE IN QUEUE ENTRY
	HLRZ T2,QUENCM		;GET ADDRESS OF EXECUTOR STRING
	STOR T2,NQXTR,(Q1)	;SAVE
	MOVE T2,QUENCT		;GET FLAGS AND POINTER TO NICE MESSAGE
	TXZE T2,NQ%REQ		;IS THIS ENTRY BEING RE-QUEUED ?
	JRST [SETONE NQREQ,(Q1)	;YES, NOTE SO
	      JRST .+1]		;AND CONTINUE
	STOR T2,NQTXT,(Q1)
	HLRZS T2		;Get time of first time entry was q'd
	SKIPN T2		;If time not defined..
	CALL QUETIM		;get current time
	STOR T2,NQRQT,(Q1)	;Put into q entry as time initally q'd
	HRRZ T2,QUENCN		;GET NUMBER OF CHARACTERS IN NICE MES
	STOR T2,NQCHR,(Q1)
	HLRZ T2,QUENCN		;GET REQUEST NUMBER
	STOR T2,NQNUM,(Q1)	;SAVE IT
	HLRZ T2,QUEFCN		;GET NICE FUNCTION CODE
	STOR T2,NQFCN,(Q1)	;SAVE NICE FUNCTION CODE
	HRRZ T2,QUEFCN		;GET NICE OPTION (SUBFUNCTION)
	STOR T2,NQOPT,(Q1)	;SAVE NICE OPTION
	SETZRO NQPNT,(Q1)	;INITIALIZE POINTER LOCATION
	PIOFF			;GUARD AGAINST INTERRUPTS
	SKIPE Q2		;PUT THIS ENTRY ON FRONT OF QUEUE ?
	JRST [	MOVE T1,NICQUE	;YES, GET CURRENT FIRST ENTRY
		STOR T1,NQPNT,(Q1) ;MAKE THE NEW ONE POINT DOWN THE LIST
		MOVEM Q1,NICQUE	;PUT THE NEW ENTRY AT FRONT OF LIST
		PION
		RETSKP]		;DONE
	MOVEI T2,NICQUE		;PUT ENTRY AT END OF LIST
QUENC1:	LOAD T3,NQPNT,(T2)	;GET POINTER TO NEXT ITEM ON LIST
	JUMPE T3,QUENC2		;FOUND THE END YET?
	MOVE T2,T3		;NO, STEP TO THE NEXT ENTRY
	JRST QUENC1		;LOOP TIL END OF LIST FOUND

QUENC2:	STOR Q1,NQPNT,(T2)	;PUT THE NEW ENTRY AT END OF LIST
	PION
	RETSKP			;DONE
;ROUTINE TO PULL AN ENTRY OFF THE NICE MESSAGE QUEUE

;	CALL DEQNIC
;RETURNS +1:	NONE LEFT
;	 +2:	T1/	ADDRESS OF EXECUTOR STRING,,ADDRESS OF ORION MESSAGE
;		T2/	ADDRESS OF NICE MESSAGE
;		T3/	REQ NUMBER ,, NUMBER OF CHARACTERS IN NICE MESSAGE
;		T4/	FUNCTION,,OPTION

DEQNIC:	SAVEPQ
	PIOFF			;GUARD AGAINST INTERRUPTS
	SKIPN T1,NICQUE		;ANYTHING ON THE QUEUE
	JRST [	PION		;NO
		RET]		;NONE THERE
	LOAD T2,NQPNT,(T1)	;GET POINTER TO SECOND ENTRY
	MOVEM T2,NICQUE		;MAKE IT BE THE FIRST ENTRY
	PION
	LOAD Q1,NQMES,(T1)	;GET ADDRESS OF ORION MESSAGE
	LOAD Q3,NQXTR,(T1)	;GET EXECUTOR STRING ADDRESS
	HRL Q1,Q3		; INTO IT'S REG
	LOAD Q2,NQTXT,(T1)	;GET ADR OF NICE MESSAGE
	LOAD Q3,NQRQT,(T1)	;Get time entry was initially q'd
	HRL Q2,Q3		;Save for left half of T2 on return
	JN NQREQ,(T1),[	TXO Q2,NQ%REQ ;NOTE THAT THIS ENTRY HAS BEEN
			JRST .+1]     ; REQUEUED IF SO
	LOAD Q3,NQCHR,(T1)	;GET CHARACTER COUNT
	LOAD T2,NQNUM,(T1)	;GET REQUEST NUMBER
	HRL Q3,T2		;GET REQ NUMBER ,, COUNT
	LOAD P1,NQOPT,(T1)	;GET NICE OPTION
	LOAD T2,NQFCN,(T1)	;GET NICE FUNCTION CODE
	HRL P1,T2		;FORM FUNCTION,,OPTION
	MOVEI T2,NQLEN		;NOW RELEASE THE QUEUE ENTRY
	MOVEM T2,0(T1)		;SET UP THE CORRECT LENGTH
	CALL RELFRE		;RELEASE THE BLOCK
	 FATAL.ERROR
	DMOVE T1,Q1		;SET UP THE ANSWERS
	MOVE T3,Q3
	MOVE T4,P1		;GET NICE FUNCTION AND OPTION
	RETSKP			;AND RETURN
;Routine to get time since midnight in minutes
;
;Accepts anything
;
;Returns +1:	Always with time in T2

QUETIM:	SAVEQ			;Save some registers
	MOVE Q1,T1		;Put T's where we can get at them
	DMOVE Q2,T3

	SETO T2,		;Say that current time is wanted
	SETZ T4,		;Say that no screwy conversions are to be done
	ODCNV			;Get time
	HRRZ T2,T4		;Get seconds since midnight
	IDIVI T2,^d60		;Convert to minutes
	DMOVE T3,Q2		;Get the registers back
	MOVE T1,Q1
	RET			;Restore rest of them and return
;ROUTINE TO COPY AN ASCIZ STRING FROM A MESSAGE TO A FREE BLOCK
;
; Warning: This routine shifts any lower case characters to 
;	   upper case.

;ACCEPTS IN T1/	ADDRESS OF OLD STRING BLOCK
;	    T2/	BYTE POINTER TO COPY FROM
;	    T3/	MAXIMUM LENGTH IN WORDS OF STRING
;	CALL CPYASC
;RETURNS +1:	FAILED, STRING TOO LONG OR NO FREE SPACE
;	 +2:	T1/	ADDRESS OF BLOCK WITH STRING IN IT

CPYASC::ASUBR <CPYADR,CPYFRM,CPYLEN>
	HRRZS T1		;RELEASE THE OLD BLOCK
	JUMPE T1,CPYAS1		;ANYTHING THERE?
	CALL RELFRE		;YES, RELEASE IT
	 FATAL.ERROR
CPYAS1:	MOVE T1,CPYLEN		;NOW GET SOME SPACE
	AOS T1			;PLUS ONE WORD FOR HEADER
	CALL GETFRE		;GET SPACE
	 RETBAD			;NO MORE SPACE LEFT
	HRLI T1,(POINT 7,0,35)	;SET UP BYTE POINTER
	MOVEM T1,CPYADR		;SAVE IT FOR LATER
	MOVE T2,CPYFRM		;GET ADR OF STRING
	MOVE T3,CPYLEN		;GET LENGTH OF STRING
	IMULI T3,5		;GET LENGTH IN CHARACTERS

CPYAS2:	ILDB T4,T2		;Get character from string
	CAIG T4,"z"		;Check for above lower case
	CAIGE T4,"a"		;or below lower case
	 CAIA			; Yes .. ignore
	  SUBI T4,"a"-"A"	;  No .. so shift to upper case
	IDPB T4,T1		;Stuff into destination string
	JUMPE T4,[MOVE T1,CPYADR ;If zero byte at end of string .. get address
		  RETSKP]	; and give a successfull return
	SOJG T3,CPYAS2		;If room left in destination .. continue copy

	HRRZ T1,CPYADR		;GET ADDRESS OF BLOCK AGAIN
	CALL RELFRE		;RELEASE THIS BLOCK
	 FATAL.ERROR
	RETBAD (.ERR13)		;ILLEGALLY FORMATTED MESSAGE
;ROUTINE TO RECEIVE A MESSAGE FROM ORION AND PUT IT ON THE QUEUE

PIDINT:	ENTINT (\PIDLVL)	;ENTER INTERRUPT
	SAVEQ			;SAVE PERMANENT ACS USED HERE
	STKVAR <<RCVPDB,7>>	;GET SPACE FOR PID DESCRIPTOR BLOCK
PDINT1:	MOVEI T1,QUEHLN		;GET SOME FREE SPACE FOR QUEUE ENTRY
	CALL GETFRE		;...
	 FATAL.ERROR		;RAN OUT OF FREE SPACE
	MOVE Q1,T1		;SAVE ADDRESS OF QUEUE ENTRY
	MOVEI T1,.QTMES		;MARK THIS AS A MESSAGE ENTRY
	STOR T1,QUETYP,(Q1)	;...
	CALL ASGPAG		;NOW GET A PAGE TO RECEIVE THE MESSAGE
	 FATAL.ERROR		;NO MORE FREE PAGES
	STOR T2,QUEMES,(Q1)	;STORE THE ADDRESS OF THE PAGE IN QUEUE
	MOVEM T1,.IPCFP+RCVPDB	;SET UP TO RECEIVE THE MESSAGE
	MOVEI T1,1000		;SET UP THE LENGTH
	HRLM T1,.IPCFP+RCVPDB	;NOW HAVE LEN,,ADR
	MOVX T1,IP%CFB!IP%CFV	;FIRST TRY TO READ WITH PAGE MODE
	MOVEM T1,.IPCFL+RCVPDB	;STORE THE FLAGS IN DESCRIPTOR BLOCK
	MOVE T1,PID		;GET OUR PID
	MOVEM T1,.IPCFR+RCVPDB	;STORE IN DESCRIPTOR BLOCK
	MOVEI T1,6		;LENGTH = 6
	MOVEI T2,RCVPDB		;POINTER TO DESCRIPTOR BLOCK
	MRECV			;RECEIVE THE MESSAGE
	 JRST [	MOVX T1,IP%CFB	;FAILED, TRY NON-PAGE MODE
		MOVEM T1,.IPCFL+RCVPDB
		LOAD T1,QUEMES,(Q1)	;GET ADR OF MESSAGE
		HRRM T1,.IPCFP+RCVPDB	;SAVE IN IPCF BLOCK
		MOVEI T1,6		;LENGTH
		MRECV			;TRY TO RECEIVE IT AGAIN
		 ERJMP [CAIE T1,IPCFX2  ;FAILED. ERROR NO MESSAGE FOR THIS PID ?
			FATAL.ERROR     ;NO, COULD NOT GET IT STILL
			JRST PDINT2] 	;YES, release memory and dismiss
		JRST .+1]	;CONTINUE ON
	MOVE T1,.IPCFS+RCVPDB	;GET PID OF SENDER
	CAME T1,OPRPID		;IS THIS ORION'S PID ?
	CAMN T1,PID		;NO - IS IT OUR PID?
	SKIPA			;YES - OK THEN
	JRST PDINT2		;NO
	SETZRO QUEPNT,(Q1)	;PUT THIS ENTRY AT END OF QUEUE
	MOVE T1,Q1		;GET ADR OF THE ENTRY
	CALL QUEQUE		;QUEUE UP THIS REQUEST
	CALL WAKBKG		;WAKE UP THE BACKGROUND JOB
	; ..
	; ..

; HERE TO SEE IF THERE ARE ANY MORE MESSAGES

PDINT3:	MOVEI T1,6		;NOW SEE IF THERE ARE MORE MESSAGES
	MOVEI T2,RCVPDB
	MOVEI T3,.MUQRY		;QUERY THE PID QUEUE
	MOVEM T3,RCVPDB		;STORE FUNCTION CODE
	MOVE T3,PID		;GET OUR PID
	MOVEM T3,1+RCVPDB	;SEE IF ANY MESSAGES FOR THIS PID
	MUTIL			;...
	 JRST [	CAIE T1,IPCFX2	;ANY MESSAGES?
		 FATAL.ERROR	;SOME OTHER ERROR
		RET]		;NO MORE MESSAGES, DISMIS THE INTERRUPT
	JRST PDINT1		;LOOP BACK FOR ALL MESSAGES

; HERE IF NOT FROM ORION

PDINT2:	LOAD T1,QUEMES,(Q1)	;GET ADR OF PAGE CONTAINING MESSAGE
	CALL RELPGA		;RELEASE THE PAGE
	 NON.FATAL.ERROR	;FAILED
	MOVE T1,Q1		;GET ADR OF HEADER
	CALL RELFRE		;RELEASE THE BLOCK
	 FATAL.ERROR		;FAILED
	JRST PDINT3		;LOOP BACK FOR REMAINING MESSAGES
;ROUTINE TO QUEUE AN ENTRY ONTO THE QUEUE

;ACCEPTS IN T1/	ADR OF QUEUE ENTRY

QUEQUE:	SETZRO QUEPNT,(T1)	;MAKE SURE THIS IS THE END OF THE LIST
	PIOFF			;PUT THIS ENTRY ON THE QUEUE
	MOVEI T2,QUEUE		;GET POINTER TO FIRST ENTRY
QUEQU1:	LOAD T3,QUEPNT,(T2)	;GET POINTER TO NEXT ITEM ON QUEUE
	JUMPE T3,QUEQU2		;IF AT END, THEN DONE
	MOVE T2,T3		;STEP TO NEXT ENTRY
	JRST QUEQU1		;LOOP BACK TIL END OF LIST IS FOUND

QUEQU2:	STOR T1,QUEPNT,(T2)	;PUT THIS BLOCK AT THE END OF THE QUEUE
	PION			;FINISHED PUTTING IT ON THE QUEUE
	RET			;RETURN
;ROUTINES TO HANDLE CONNECT INTERRUPTS TO NCU JFNS

DEFINE JFNENT (A,B) <
JFN'A:	ENTINT (B)
	MOVEI T4,A
	JRST JFNINT>

	ZZ==0
REPEAT NJFN,<	LALL
		JFNENT (\ZZ,\JFNLVL)
		SALL
		ZZ==ZZ+1>
DEFINE JFDENT (A,B) <
JFD'A:	ENTINT (B)
	MOVEI T4,A
	JRST JFDINT>

	ZZ==0
REPEAT NJFN,<	LALL
		JFDENT (\ZZ,\JFDLVL)
		SALL
		ZZ==ZZ+1>


DEFINE TOPENT (A,B) <
TOP'A:	ENTINT (B)
	MOVEI T1,A
	JRST TOPINT>

	ZZ==0
REPEAT TOPMAX,<	LALL
		TOPENT (\ZZ,\TOPLVL)
		SALL
		ZZ==ZZ+1>

HCKINT: ENTINT (\HCKLVL)
	CALL TOPI.1
	 RET
	RET

ATO0:	ENTINT(\TOPLVL)
	JRST SETATO
;SETATO - SET AUTO DUMP/LOAD

SETATO:	MOVEI T1,QUEHLN		;GET SPACE FOR THIS ENTRY
	CALL GETFRE		;...
	 FATAL.ERROR
	MOVEI T2,.QTTOP		;QUEUE A DUMP/LOAD REQUEST
	STOR T2,QUETYP,(T1)	;STORE IN QUEUE ENTRY
	CALL QUEQUE		;QUEUE UP THIS ENTRY
	CALL WAKBKG		;WAKE UP THE BACKGROUND
	RET
JFNINT:	SAVEQ			;SAVE ACS USED HERE
	MOVX T1,CR%MAP!CR%CAP	;CREATE A FORK FOR NCU
	CFORK			;SHARES SAME MAP
	 FATAL.ERROR		;COULD NOT GET A FORK
	MOVEM T1,FRKTAB(T4)	;SAVE FORK HANDLE
	SETZM FRKFLG(T4)	;CLEAR THE FLAGS WORD
	HRLI T1,.PRAST		;NOW SET UP THE PRARG BLOCK
	MOVEI T2,Q1		;POINTER TO ARG BLOCK
	MOVEI T3,2		;LENGTH
	MOVE Q1,JFNTAB(T4)	;FIRST ARG = JFN OF NCU
	MOVE Q2,T4		;SECOND ARG = LENGTH ,, ADR
	IMULI Q2,NNCUPG*1000	;GET OFFSET INTO NCU AREA
	ADDI Q2,NCUFFP*1000	;GET START ADR OF REGION
	HRLI Q2,NNCUPG*1000	;GET LENGTH
	PRARG			;SET UP THE ARGUMENT BLOCK
	 ERJMP [FATAL.ERROR]	;FAILED
	MOVE T1,FRKTAB(T4)	;NOW START THE NCU PROCESS
	MOVEI T2,NCU		;START ADDRESS
	SFORK
	RET			;DISMISS THE INTERRUPT



JFDINT:	STKVAR <JFDNUM>
	MOVEM T4,JFDNUM		;SAVE THE INDEX
	MOVEI T1,QUEHLN		;GET SPACE FOR A QUEUE ENTRY
	CALL GETFRE
	 FATAL.ERROR
	MOVEI T2,.QTJFD		;DATA OR DISCONNECT TYPE
	STOR T2,QUETYP,(T1)
	MOVE T2,JFDNUM		;GET JFN INDEX
	STOR T2,QUEMES,(T1)	;PUT IT IN THE QUEUE HEADER
	CALL QUEQUE		;QUEUE IT
	CALL WAKBKG		;WAKE UP THE BACKGROUND LEVEL
	RET			;AND DEBRK


;ROUTINE TO QUEUE UP A FORK TERMINATION REQUEST

FRKTER:	ENTINT (\FKTLVL)	;ENTER INTERRUPT LEVEL
	MOVEI T1,QUEHLN		;GET SPACE FOR THIS ENTRY
	CALL GETFRE		;...
	 FATAL.ERROR		;FATAL IF NO MORE SPACE
	MOVEI T2,.QTFKT		;MARK THIS AS A FORK TERMINATION
	STOR T2,QUETYP,(T1)	;STORE IN QUEUE ENTRY
	CALL QUEQUE		;QUEUE UP THIS ENTRY
	CALL WAKBKG		;WAKE UP THE BACKGROUND LEVEL
	RET			;AND DEBRK
;TOPOLOGY CHANGE INTERRUPT ROUTINE
;
;CALL:	CALL TOPINT
;RETURNS: +1	 FAILED
;	  +2	SUCCESS

TOPINT:	STKVAR <<TPIHST,2>,TPIPAG,TPIERR>

; GET ASCIZ NAME OF THE DN20 NODE SENDING THE MESSAGE

	HRROI T3,TPIHST		;POINTER TO WHERE  TO STORE STRING
	MOVEI T2,.MORHN		;READ THE HOST NAME
	MOVE T1,TOPSRV		;GET TOPOLOGY SERVER LINK JFN
	MTOPR			;DO THE JSYS
	 ERJMP R		;FAILED

; ASSIGN A PAGE INTO WHICH TOPOLOGY DATA CAN BE READ

	CALL ASGPAG		;ASSIGN A PAGE
	 RETBAD ()		;FAILED
	MOVEM T2,TPIPAG		;SAVE ADDRESS

; READ THE TOPOLOGY CHANGE PROTOCOL MESSAGE

	MOVE T1,TOPSRV		;GET TOPOLOGY SERVER LINK JFN
	HRRZ T2,TPIPAG		;GET PAGE NUMBER FOR INPUT
	HRLI T2,(POINT 8,)	;FORM POINTER TO DESTINATION
	MOVNI T3,4000		;MAX ONE PAGE OF INFO
	SINR			;READ TOPOLOGY INFO
	 ERJMP TOPINX		;FAILED, RELEASE PAGE AND RETURN ERROR

; CHECK FOR CORRECT MESSAGE TYPE AND ADVISE MONITOR OF TOPOLOGY

	MOVEI T2,4000(T3)	;GET NUMBER OF BYTES INPUT
	HRRZ T1,TPIPAG		;GET PAGE NUMBER FOR INPUT
	HRLI T1,(POINT 8,)	;FORM POINTER TO DESTINATION
	SOSGE T2		;AT LEAST ONE BYTE IN MESSAGE ?
	JRST TOPINX		;NO, RELEASE PAGE AND FAIL
	ILDB T4,T1		;YES, GET MESSAGE TYPE CODE
	CAIE T4,.TPCHG		;TOPOLOGY CHANGE MESSAGE ?
	JRST TOPINX		;NO, FAIL
	MOVEI T3,TPIHST		;GET ADDRESS OF NODE NAME
	HRLI T3,(POINT 7,)	;FORM POINTER TO NODE NAME
	CALL ADVTOP		;ADVISE MONITOR OF NEW NODES IN NETWORK
	 JRST TOPINX		;FAILED
	PUSH P,T1		;Save address of node topology table
	CALL UPDNOD		;UPDATE MONITOR'S LIST FOR DELETED NODES
	 JRST [POP P,T1		; Get node table address
	       CALL TOPFRE	; Release topology table
	       JRST TOPINX]	; Failed to update monitor's list
	POP P,T1		;Get node table address back
	CALL TOPFRE		;Release the topology table
; RELEASE PAGE AND RETURN

	MOVE T1,TPIPAG		;GET ADDRESS OF PAGE USED FOR MESSAGE
	CALL RELPGA		;RELEASE THE PAGE
	 NON.FATAL.ERROR	;FAILED
	MOVE T1,TOPSRV		;GET SERVER JFN
	CLOSF			;CLEAN UP THE USED LINK
	 NON.FATAL.ERROR	;FAILED
	CALL TOPSET		;SETUP ANOTHER TOPOLOGY SERVER
	 FATAL.ERROR (.ERR28)	;FAILED
	RET			;DONE, RETURN SUCCESS

; HERE ON AN ERROR - RELEASE PAGE AND RETURN FAILURE

TOPINX:	MOVEM T1,TPIERR		;SAVE ERROR CODE
	MOVE T1,TPIPAG		;GET ADDRESS OF PAGE USED FOR MESSAGE
	CALL RELPGA		;RELEASE THE PAGE
	 NON.FATAL.ERROR	;FAILED
	MOVE T1,TOPSRV		;GET SERVER JFN
	TXO T1,CZ%ABT		;ABORT CLOSE, PITCH ANY DATA LEFT
	CLOSF			;CLEAN UP THE USED LINK
	 NON.FATAL.ERROR	;FAILED
	CALL TOPSET		;SETUP ANOTHER TOPOLOGY LINK
	 FATAL.ERROR (.ERR28)	;FAILED
	MOVE T1,TPIERR		;RESTORE ERROR CODE
	RET			;FAIL
; Routine to assign space in free storage region
;
; CALL:	T1/ Size of block needed
;	CALL GETFRE
;
; RETURNS: +1	ERROR, not enough space
;	   +2	SUCCESS, T1/ Location of the block
;			     First word of block contains -1,,length
;
; Clobbers T1, T2, T3, and T4
;
; Free storage header format:
;
; FRSHDR+.FHFFB/	; LH points to first free block
; 	+.FHCNT/	; Words free in free pool
;	+.FHCBS/	; Most common block size
;	+.FHADR/	; LH top addrs of free pool, RH bottom addrs
;	+.FHBFS/	; Best free block size found (closest fit for GETFRE)
;	+.FHBFA/	; Address of best free block

	ENTRY GETFRE		; Globalize so that NCU can find it

GETFRE:	MOVE T2,T1		; Get size into T2 of requested block
IFN TRACE,<AOS T2>		; Increment for tracing word
	MOVEI T1,FRSHDR		; Get address of free space header
	PIOFF			; Turn off interrupts
	LOCK FRELOK		; Lock up the free pool memory management
	CALL GETFR0		; Go get space
	 RETBAD (,<UNLOCK FRELOK
			PION>)	;  No more space, propagate error back
	UNLOCK FRELOK		; Unlock memory management code 
	PION			; Turn interrupts back on
IFN TRACE,<
	AOS T1			; Increment past trace word
	HRRZ T2,-1(T1)		; Get size of block allocated
	SOS T2			; Subtract trace word from size
	HRROM T2,0(T1)		; Put into first word of block going to caller
	HRRZ T2,0(P)		; Get return address
	HRLM T2,-1(T1)		; Put into left half of trace word
    > ;End if TRACE
	RETSKP			; Success return

GETFR0:	CAMLE T2,.FHCNT(T1)	; Enough words left in the pool?
	RET			;  No, return immediately
	PUSH P,T2		; Save desired block size
	HRLOI T2,377777
	MOVEM T2,.FHBFS(T1)	; Initial best block size (max positive number)
	SETZM .FHBFA(T1)	; Initial location of best block (none)
	MOVE T2,T1		; Start with the header block

GETFR1:	HLRZ T3,0(T2)		; Get pointer to next free block
	JUMPE T3,GETFR2		; No more free blocks to examine (null link)
	CAIG T3,0(T2)		; Check to see if next block sorted correctly
	JRST [POP P,T2		;  No, clean up the stack
	      RETBAD (.ERR30)]	; and give a free list sequencing error
	HRRZ T4,0(T3)		; Get size of the next block
	CAMN T4,0(P)		; Is it the size requested?
	JRST [HLL T4,0(T3)	;  Yes, get address of next block in chain
	      HLLM T4,0(T2)	;  Point last block to next (close up chain)
	      JRST GETFR5]	;  Go zero the block; return address
	CAML T4,0(P)		; Too small?
	CAML T4,.FHBFS(T1)	; or bigger than the best so far?
	JRST GETFR4		;  Yes, ignore it
	MOVEM T4,.FHBFS(T1)	; This is the best bigger fit found so far
	MOVEM T2,.FHBFA(T1)	; so save address and size
GETFR4:	MOVE T2,T3		; Step to the next block in chain
	JRST GETFR1		; and repeat
GETFR2:	SKIPN T2,.FHBFA(T1)	; Did we find anything that was bigger?
	JRST [POP P,T2		;  No, get the size of block back
		 RETBAD (.ERR8)];  and say no block on list is big enough
	MOVE T4,0(P)		; Get desired size
	HLRZ T3,0(T2)		; Get pointer to block to be used
	HRRM T4,0(T3)		; Convert to desired size in header of block
	ADD T4,T3		; Address of remainder of block
	HRLM T4,0(T2)		; Point previous block in chain to remainder
	HLLZ T2,0(T3)		; Get address of next block in chain
	HLLM T2,0(T4)		; Point remainder to it
	MOVE T2,.FHBFS(T1)	; Get size of block we just split
	SUB T2,0(P)		; Calculate size of remainder
	HRRM T2,0(T4)		; Save in header of remainder

GETFR5:	MOVN T2,0(P)		; Get minus the requested block size
	ADDM T2,.FHCNT(T1)	; Reduce count of space left in free pool
	MOVEI T1,0(T3)		; Get origin of block just allocated
	HRROS (T1)		; Set LH to ones in first word of block
	CAMN T2,[-1]		; Is this a block of one word?
	JRST GETFR6		;  Yes, don't zero anything
	HRRZ T2,(T1)		; Get RH (should contain length of block)
	HRRZI T3,2(T1)		; Address of 3rd word in block
	SETZM -1(T3)		; Zero 2nd word
	HRLI T3,1(T1)		; Address of 2nd word in block, making BLT word
	ADD T2,T1		; Last word+1 in block (end of zero BLT)
	HRRZS T2		; Clear any crap in left half
	CAILE T2,(T3)		; Check for only two words
	BLT T3,-1(T2)		;  No, so zero the block
GETFR6:	POP P,T2		; Restore T2
	RETSKP			; Successful return
; Routine to release free storage block
; Lifted from monitor module FREE, routine RELFRE
;
; CALL:	T1/ Location of the block to be returned
;	    First word of returned block contains length of block in RH
;
;	CALL RELFRE
;
; RETURNS: +1	ERROR, can't release the block
;	   +2	SUCCESS, block released
;
; Clobbers T2, T3, and T4

	ENTRY RELFRE		; Globalize so that NCU can find it

RELFRE:	HRRZ T2,T1		; Get adr of block into T2
	MOVEI T1,FRSHDR		; Get adr of free space header
IFN TRACE,<
	SOS T2			; Move back to actual start of block w/trace
    > ;End if TRACE
	PIOFF			; Turn off interrupts
	LOCK FRELOK		; Lock up access to memory manager
	CALL RELFRW		; Go do the work (release the block)
	 RETBAD (,<UNLOCK FRELOK
			PION>)	;  Failed, propagate the error back
	UNLOCK FRELOK		; Unlock the memory manager
	PION			; Turn interrupts back on
	RETSKP			; Sucessful return

RELFRW:	PUSH P,T1		; Save location of free storage header
	HLRZ T4,.FHADR(T1)	; Get top address of free pool
	HRRZ T1,.FHADR(T1)	; Get bottom address of free pool
	CAILE T4,0(T2)		; Is block to be freed above the top of pool
	CAILE T1,0(T2)		; or below the bottom?
	JRST [POP P,T1		;  Yes, block out of range
	      RETBAD (.ERR9)]	;  Return saying outside of pool space
	MOVE T1,0(P)		; Get pool header location back again
	PUSH P,T2		; Save location of block to free
	MOVE T2,-1(P)		; Get address of header

RELFR1:	HLRZ T3,0(T2)		; Get location of next block in chain
	JUMPE T3,RELFR2		; Check for end of list
	CAIG T3,0(T2)		; Check for next block sorted correctly
	JRST [POP P,T2		;  No .. chain is out of order
	      POP P,T1		;  Clean up the stack
	      RETBAD (.ERR30)]	;  and return a free list sequencing error
	CAML T3,0(P)		; Is block being freed above block on chain
	JRST RELFR2		;  Yes .. block being freed sorts in here.
	MOVE T2,T3		; No .. set last block equal to current block
	JRST RELFR1		; and try next entry on chain
RELFR2:	CAMN T3,0(P)		; Current block addrs match block being freed?
	JSP CX,RLFRX2		;  Yes .. this block is already free
	CAIN T1,0(T2)		; Is previous block addrs the free pool header?
	JRST RELFR6		;  Yes, then this will be first block on chain
	HRRZ T4,0(T2)		; Get size of previous block and
	ADD T4,T2		; compute end of previous block
	CAMLE T4,0(P)		; Previous block overlap one being released?
	 JSP CX,RLFRX2		;  Yes, can't do that .. already free
RELFR6:	JUMPE T3,RELFR7		; At end of free list chain?
	HRRZ T4,@0(P)		; No, compute end of block being freed
	ADD T4,0(P)		; by adding address to length
	CAMLE T4,T3		; Overlaps next block on free list?
	JSP CX,RLFRX2		;  Yes, error .. already free
RELFR7:	HRRZ T4,@0(P)		; Get length of block being freed
	ADDM T4,.FHCNT(T1)	; Augment count of remaining free space
	ADD T4,0(P)		; Get end of block being returned
	CAIE T4,0(T3)		; Does block being freed butt to next block
	JRST [HRLM T3,@0(P)	;  No, point returned block to successor
	      JRST RELFR5]	;  and continue releasing it.
	HRRZ T4,0(T3)		; Get length of following block
	ADDM T4,@0(P)		; Add sizes of the two blocks
	HLLZ T4,0(T3)		; Get address of successor of successor
	HLLM T4,@0(P)		; Point to him as the next block after this one
RELFR5:	MOVE T3,0(P)		; Get address of block being freed
	HRLM T3,0(T2)		; Make predecessor point to it
	HRRZ T4,0(T2)		; Get length of predecessor
	ADD T4,T2		; Calculate end of predecessor
	CAME T4,T3		; Does it abut the block being freed?
	JRST RELFR4		;  No, done
	MOVE T3,0(T3)		; Yes .. get header word in block being fred
	HLLM T3,0(T2)		; Point predecessor to next block in chain
	HRRZS T3		; Get size of block being freed
	ADDM T3,0(T2)		; Make one big block out of them
RELFR4:	POP P,T2		; Restore some registers
	POP P,T1
	RETSKP			; Good return

RLFRX2:	POP P,T2		; Bad block being released
	POP P,T1
	RETBAD (.ERR10)		; Error - attempt to release already free space
; Routine to build free space header at initialization
;  for calls to GETFRE and RELFRE
;
;	CALL FSHDR
; RETURNS: +1	ALWAYS

FSHDR:	SETO T1,		; Zero all the free space
	MOVSI T2,.FHSLF		; Point to this process
	HRRI T2,FSP		; Starting at first page
	MOVE T3,[PM%CNT+NFSP]	; Unmap all pages in free pool
	PMAP
	MOVEI T1,FSADR		; Start adr of free space
	HRLOM T1,FRSHDR+.FHFFB	; Put into free pool header block
	MOVEI T1,FSLEN		; Set up length of first block
	MOVEM T1,FSADR		; Make the first block contain all space
	MOVEM T1,FRSHDR+.FHCNT	; Set up length in header
	MOVE T1,[FSADR+FSLEN,,FSADR] ; Get upper and lower bounds
	MOVEM T1,FRSHDR+.FHADR	; and set in free space header
	RET			; Only return .. hope it worked.
;ROUTINE TO ASSIGN A FREE PAGE

;RETURNS +1:	NONE LEFT
;	 +2:	T1/	PAGE #
;		T2/	ADDRESS OF FIRST WORD IN PAGE

ASGPAG::PIOFF			;PREVENT INTERRUPTS
	LOCK PAGLOK		;LOCK UP THE DATA BASE
	MOVSI T4,-NFP		;SET UP TO SEARCH FOR A PAGE
	MOVE T3,[POINT 1,FPTBL]
ASGPGL:	ILDB T2,T3		;GET NEXT PAGE BIT
	JUMPN T2,ASGPGF		;FOUND A FREE ONE YET?
	AOBJN T4,ASGPGL		;NO, LOOP BACK FOR REST OF PAGES
	UNLOCK PAGLOK		;NONE FOUND
	PION
	RETBAD .ERR5		;NO MORE FREE PAGES LEFT

ASGPGF:	MOVEI T2,0		;MARK THAT THE PAGE IS NOW IN USE
	DPB T2,T3		;...
	UNLOCK PAGLOK		;RELEASE LOCKS
	PION
	MOVE T1,0(P)		;Get return address
	HRLZM T1,FPRCD(T4)	;Store who got this page in left half
	MOVEI T1,FFP(T4)	;GET PAGE NUMBER
	MOVE T2,T1		;GET PAGE ADDRESS
	LSH T2,9		;...
	HRLZ T3,T2		;GET STARTING ADDRESS
	HRRI T3,1(T2)		;GET DESTINATION ADDRESS
	SETZM (T2)		;CLEAR FIRST WORD
	BLT T3,777(T2)		;CLEAR THE PAGE
	RETSKP			;RETURN SUCCESSFUL
;ROUTINES TO RELEASE PAGES

;RELPGA - RELEASE PAGE ADDRESS
;	T1/	ADDRESS OF FIRST WORD IN PAGE

;RELPAG - RELEASE PAGE
;	T1/	PAGE NUMBER

;RETURNS +1:	ERROR
;	 +2:	SUCCESSFUL

RELPGA::LSH T1,-9		;GET PAGE NUMBER FROM ADDRESS
RELPAG:	PIOFF			;LOCK UP
	LOCK PAGLOK
	SUBI T1,FFP		;GET PAGE NUMBER WITHIN POOL
	SKIPL T1		;IS THIS A LEGAL PAGE?
	CAIL T1,NFP		;...
	RETBAD (.ERR6,<UNLOCK PAGLOK
			PION>)	;ILLEGAL PAGE ADDRESS
	MOVE T2,0(P)		;Get return address
	HRRM T2,FPRCD(T1)	;Save who returned this page.
	MOVE T2,[POINT 1,FPTBL]
	ADJBP T1,T2		;GET POINTER TO PAGE BIT
	ILDB T3,T1		;SEE IF THE PAGE IS IN USE
	SKIPE T3		;...
	RETBAD (.ERR7,<UNLOCK PAGLOK
			PION>)	;PAGE WAS ALREADY FREE
	MOVEI T3,1		;NOW FREE UP THE PAGE
	DPB T3,T1
	UNLOCK PAGLOK		;FREE UP THE LOCKS
	PION
	RETSKP			;DONE
; LOKNOD - ROUTINE TO LOCK A NODE TO PREVENT MULTIPLE ACCESS
;
;ACCEPTS IN T1/	ADDRESS OF NIB TO LOCK
;	    T2/	RESOURCE MASK (RM%XXX)
;		CALL LOKNOD
;RETURNS: +1 ALWAYS, WITH NODE LOCKED

LOKNOD::STKVAR <<LKNMSK,2>>

	MOVEM T2,1+LKNMSK	;SAVE RESOURCE CLASS
	MOVX T2,2		;GET COUNT FOR RESOURCE MASK BLOCK
	MOVEM T2,LKNMSK		;SAVE COUNT
	MOVEI T3,LKNMSK		;GET ADDRESS OF RESOURCE MASK
	MOVE T2,[ENQ]		;GET LOCKING JSYS
	HRLI T1,NODLEV		;GET LEVEL FOR NODE LOCKING
	CALLRET EDLOCK		;LOCK THE RESOURCE



; ULKNOD - ROUTINE TO UNLOCK A LOCKED NODE
;
;ACCPETS IN T1/	ADDRESS OF NIB TO UNLOCK
;	    T2/	RESOURCE MASK
;		CALL ULKNOD
;RETURNS: +1 ALWAYS, WITH NODE UNLOCKED

ULKNOD::STKVAR <<ULNMSK,2>>

	MOVEM T2,1+LKNMSK	;SAVE RESOURCE CLASS
	MOVX T2,2		;GET COUNT FOR RESOURCE MASK BLOCK
	MOVEM T2,LKNMSK		;SAVE COUNT
	MOVEI T3,ULNMSK		;GET ADDRESS OF RESOURCE MASK
	MOVE T2,[DEQ]		;GET UNLOCK JSYS
	HRLI T1,NODLEV		;LEVEL FOR NODE LOCKING
	CALLRET EDLOCK		;UNLOCK THE NODE
;ROUTINES TO LOCK AND UNLOCK DATA BASE LOCKS

;CALLED BY THE "LOCK" AND "UNLOCK" MACROS
;ALL ACS ARE PRESERVED

ELOCK::	PUSH P,T1		;SAVE ALL ACS BY HAND
	MOVE T1,CX		; SINCE CX CONTAINS THE ARGUMENT
	PUSH P,T2		;SAVE ANOTHER AC
	PUSH P,T3
	MOVE T2,[ENQ]		;GET TYPE OF OPERATION TO DO
	SETZM T3		;NO GROUP SPECIFICATION
	CALL EDLOCK		;GO DO IT
	POP P,T3		;CLEAN UP
	POP P,T2
	POP P,T1
	RET			;ALL DONE

DLOCK::	PUSH P,T1		;SAVE ALL ACS BY HAND
	MOVE T1,CX		; SINCE CX CONTAINS THE ARGUMENT
	PUSH P,T2		;SAVE ANOTHER AC
	PUSH P,T3
	SETZM T3		;NO RESOURCE MASK
	MOVE T2,[DEQ]		;GET TYPE OF OPERATION TO DO
	CALL EDLOCK		;GO DO IT
	POP P,T3
	POP P,T2		;CLEAN UP
	POP P,T1
	RET			;ALL DONE


EDLOCK:	STKVAR <EDLCKI,<EDLCKB,6>>
	MOVEM T2,EDLCKI		;SAVE THE INSTRUCTION TO BE DONE
	HRRZ T2,T1		;GET THE ADDRESS BEING LOCKED
	TXO T2,5B2		;MAKE IT INTO A NUMBER FOR ENQ/DEQ
	MOVEM T2,.ENQUC+EDLCKB	;SAVE LOCK VALUE
	HRRI T1,-1		;JOB WIDE LOCK (LEVEL NUMBER IN LH)
	MOVEM T1,.ENQLV+EDLCKB
	MOVE T1,[1,,6]		;SET UP REST OF LOCK BLOCK
	MOVEM T1,.ENQLN+EDLCKB	;NUMBER OF LOCKS ,, LENGTH
	MOVEM T3,.ENQMS+EDLCKB	;RESOURCE MASK
	SETZM .ENQID+EDLCKB	;ID
	SETZM .ENQRS+EDLCKB	;GROUP #
	MOVEI T1,.ENQBL		;BLOCKING ENQ / DEQ LOCK FUNCTION
	MOVEI T2,EDLCKB		;ADR OF LOCK BLOCK
	XCT EDLCKI		;DO IT
	 JRST CRUMP		;FAILED
	RET			;RETURN
;ROUTINES TO TURN OFF AND ON THE INTERRUPT SYSTEM
;ALL ACS ARE PRESERVED

PIOFF.:	PUSH P,T1		;SAVE ALL ACS
	MOVEI T1,.FHSLF		;THIS FORK
	DIR			;DISABLE INTERRUPT SYSTEM
	POP P,T1		;RESTORE AC
	RET			;AND RETURN

PION.:	PUSH P,T1		;SAVE ALL ACS
	MOVEI T1,.FHSLF		;THIS FORK
	EIR			;ENABLE INTERRUPTS AGAIN
	POP P,T1		;RESTORE AC
	RET			;AND RETURN


;ROUTINE TO SAVE ALL THE T ACS

SAVT::	PUSH P,T1		;SAVE THE ACS
	PUSH P,T2
	PUSH P,T3
	CALL 0(CX)		;RETURN TO CALLER
RESTT:	 SKIPA			;NON-SKIP RETURN
	AOS -3(P)		;SKIP RETURN
	POP P,T3		;RESTORE ACS
	POP P,T2
	POP P,T1
	RET			;AND RETURN
;ROUTINE TO SAVE ALL THE Q ACS

SAVQ::	PUSH P,Q1		;SAVE THE ACS
	PUSH P,Q2
	PUSH P,Q3
	CALL 0(CX)		;RETURN TO CALLER
RESTQ:	 SKIPA			;NON-SKIP RETURN
	AOS -3(P)		;SKIP RETURN
	POP P,Q3		;RESTORE ACS
	POP P,Q2
	POP P,Q1
	RET			;AND RETURN


SAVPQ::	PUSH P,Q1		;SAVE ALL P'S AND Q'S
	PUSH P,Q2
	PUSH P,Q3
	PUSH P,P1
	PUSH P,P2
	PUSH P,P3
	PUSH P,P4
	PUSH P,P5
	PUSH P,P6
	CALL 0(CX)		;CALL BACK TO ROUTINE
RESTPQ:	 SKIPA
	AOS -11(P)		;SKIP RETURN
	POP P,P6
	POP P,P5
	POP P,P4
	POP P,P3
	POP P,P2
	POP P,P1
	POP P,Q3
	POP P,Q2
	POP P,Q1
	RET
;ROUTINE TO TYPE OUT AN ERROR ON THE TTY
;ACCEPTS IN T1/	NETCON ERROR NUMBER
;RETURNS +1:	ALWAYS

ERROR::	TDZA T4,T4		;NOTE THAT THIS IS AN ERROR
WRNING::SETOM T4		;NOTE THAT THIS IS A WARNING
	MOVEI T3,.FHSLF		;THIS FORK
	HRROI T2,ERRSTR		;SET UP STRING POINTER FOR ERROR STRING
	CALL ERRORB		;BUILD THE ERROR STRING
	HRROI T1,ERRSTR		;GET POINTER TO STRING
	PSOUT			;TYPE OUT THE MESSAGE
	SETZM T1		;NO HEADER
	HRROI T2,ERRSTR		;GET POINTER TO STRING AGAIN
	CALL OPRMES		;SEND THE MESSAGE TO THE OPERATOR
	 SKIPA			;FAILED
	RET			;DONE
	HRROI T2,ERRSTR		;SET UP A POINTER TO WHERE TO PUT THE STRING
	MOVEI T3,.FHSLF		;THIS FORK
	CALL ERRORB		;GET THE REASON FOR THE SEND FAILURE
	PSOUT			;JUST TYPE THIS MESSAGE OUT
	RET			;AND EXIT


;ROUTINE TO SET UP THE ERROR CODE IN T1
;CALLED BY THE RETER2 MACRO
;LEAVES T1/	MONITOR ERROR CODE ,, NETCON ERROR CODE

STOERC:	TLNE T1,-1		;LEGAL ERROR CODE?
	MOVEI T1,.ERR19		;NO, GET ERROR CODE WITH GETER
	CAIGE T1,600000		;NETCON ERROR CODE IN T1?
	JRST STOER1		;YES
	HRLZS T1		;NO, STORE MONITOR ERROR CODE IN LH
	HRRI T1,.ERR19		;STANDARD ERROR MESSAGE "JSYS ERROR"
	RET			;RETURN

STOER1:	PUSH P,T2		;SAVE ALL ACS
	PUSH P,T1		;SAVE ERROR CODE
	MOVEI T1,.FHSLF		;NOW GET LAST ERROR CODE
	GETER
	POP P,T1		;GET BACK NETCON ERROR CODE
	HRL T1,T2		;PUT MONITOR ERROR CODE IN LH
	POP P,T2		;RESTORE ACS
	RET			;GIVE NON-SKIP RETURN
;ROUTINE TO BUILD AN ERROR MESSAGE STRING

;ACCEPTS IN T1/	NETCON ERROR CODE
;	    T2/	POINTER TO WHERE TO PUT THE STRING
;	    T3/	FORK HANDLE

;RETURNS +1:	T2/	UPDATED STRING POINTER

ERRORB:	STKVAR <ERRORC,ERRORH>
	MOVEM T1,ERRORC		;SAVE THE NETCON ERROR NUMBER
	MOVEM T3,ERRORH		;SAVE FORK HANDLE
	MOVE T1,T2		;SET UP POINTER TO ERROR STRING
	HRROI T2,[ASCIZ/
? NETCON: /]
	SKIPE T4		;WARNING INSTEAD OF ERROR ?
	HRROI T2,[ASCIZ/
% NETCON: /]
	SETZ T3,
	SOUT			;OUTPUT THE TEXT
	HRRZ T2,ERRORC		;NOW TYPE THE ERROR MESSAGE
	SUBI T2,ERRCD0		;GET OFFSET INTO ERROR CODE TABLE
	SKIPL T2		;ERROR?
	CAIL T2,ERRTBL		;IS ERROR CODE IN CORRECT RANGE?
	SKIPA T2,[-1,,[ASCIZ/Unknown NETCON error/]]
	HRRO T2,ERRTAB(T2)	;YES, GET POINTER TO ERROR STRING
	SOUT			;TYPE OUT THE ERROR MESSAGE
	HLRZ T4,ERRORC		;GET THE MONITOR ERROR CODE
	JUMPE T4,ERORB1		;IF NONE, DONT TYPE ANY MORE
	HRROI T2,[ASCIZ/
	(/]
	SETZ T3,
	SOUT			;NOW PRINT OUT THE LAST ERROR
	HRLZ T2,ERRORH		;GET FORK HANDLE
	HLR T2,ERRORC		;GET MONITOR ERROR CODE
	SETZ T3,		;NO LENGTH LIMIT
	ERSTR			;TYPE OUT MESSAGE
	 JFCL
	 JRST [	HRROI T2,[ASCIZ/No error message for error code: /]
		SOUT
		HLRZ T2,ERRORC	;NOW TYPE OUT ERROR CODE IN OCTAL
		MOVEI T3,10
		NOUT
		 JFCL
		JRST .+1]
	MOVEI T2,")"		;FINISH MESSAGE WITH CLOSE PAREN
	BOUT
ERORB1:	HRROI T2,[ASCIZ/
/]
	SETZ T3,
	SOUT			;FINISH THE MESSAGE
	MOVE T2,T1		;RETURN WITH UPDATED POINTER IN T2
	RET			;AND RETURN
;ROUTINE TO SEND A TEXT MESSAGE TO OPR
;ACCEPTS IN T1/	POINTER TO THE TEXT STRING
;	    T2/ POINTER TO HEADER TEXT

OPRMES::SAVEQ			;SAVE PERMANENT ACS
	STKVAR <OPRMSS,OPRMSA,<OPRMSB,4>,OPRMSH>
	MOVEM T2,OPRMSH		;SAVE HEADER TEXT POINTER
	MOVEM T1,OPRMSS		;SAVE ADDRESS OF TEXT STRING
	CALL ASGPAG		;GET A PAGE FOR THE IPCF MESSAGE
	 RETBAD			;FAILED
	MOVEM T2,OPRMSA		;SAVE THE PAGE ADDRESS
	HRLI T1,1000		;SET UP POINTER TO THE PAGE FOR MSEND
	MOVEM T1,.IPCFP+OPRMSB	;SAVE POINTER IN PACKET DESCRIPTOR BLOCK
	MOVX T1,IP%CFP!IP%CFV	;PAGE MODE SEND
	MOVEM T1,.IPCFL+OPRMSB
	MOVE T1,PID		;SET UP PID OF SENDER (US)
	MOVEM T1,.IPCFS+OPRMSB
	MOVE T1,OPRPID		;GET PID OF ORION
	MOVEM T1,.IPCFR+OPRMSB	;SAVE THE PID OF THE RECEIVER
	MOVE T4,OPRMSA		;GET ADDRESS OF MESSAGE
	MOVE T1,REQCOD		;GET CODE OF OPR ORIGINATING THIS REQUEST
	MOVEM T1,.MSCOD(T4)	;STORE ACK CODE
	MOVX T2,0		;INITIALIZE ARG COUNT
	SKIPE OPRMSS		;ANY TEXT ?
	ADDI T2,1		;YES
	SKIPE OPRMSH		;ANY HEADER ?
	ADDI T2,1		;YES, ACCOUNT FOR IT
	MOVEM T2,.OARGC(T4)	;STORE ARG COUNT
	MOVX T2,WT.NDA!WT.SJI!WT.NFO ;NO FORMATTING
	MOVEM T2,.OFLAG(T4)	;STORE FLAGS
	ADDI T4,.OHDRS		;POINT TO START OF ARG AREA
	HRROI T1,ARG.DA(T4)	;PUT THE STRING INTO THE MESSAGE
	SKIPN OPRMSH		;ANY HEADER PRESENT ?
	JRST OPRMS5		;NO, GO DO TEXT
	MOVX T2,.WTTYP		;GET TYPE OF ARGUMENT (PLAIN TEXT)
	STOR T2,AR.TYP,ARG.HD(T4) ;STORE ARG TYPE
	MOVE T2,OPRMSH		;GET POINTER TO THE STRING
	SETZ T3,
	SOUT			;PUT TEXT INTO THE MESSAGE
	HRRZ T3,T1		;KEEP JUST THE FINAL ADDRESS
	SUBI T3,-1(T4)		;COMPUTE NUMBER OF WORDS STORED
	STOR T3,AR.LEN,ARG.HD(T4) ;STORE LENGTH OF STRING
	ADD T4,T3		;COMPUTE ADDRESS OF NEXT ARG
	; ..
	; ..

; HERE TO ADD TEXT ARG AND SEND MESSAGE TO OPR

OPRMS5:	SKIPN OPRMSS		;ANY TEXT ?
	JRST OPRMS8		;NO, GO SEND MESSAGE
	MOVX T2,.WTTXT		;GET TYPE OF ARGUMENT (PLAIN TEXT)
	STOR T2,AR.TYP,ARG.HD(T4) ;STORE ARG TYPE
	HRROI T1,ARG.DA(T4)	;FORM POINTER TO WHERE ARG DATA GOES
	MOVE T2,OPRMSS		;GET TEXT POINTER
	SETZM T3		;TERMINATE ON NULL
	SOUT			;ADD THIS ARG TO MESSAGE
	HRRZ t3,T1		;KEEP JUST THE FINAL ADDRESS
	SUBI t3,-1(T4)		;COMPUTE NUMBER OF WORDS STORED
	STOR t3,AR.LEN,ARG.HD(T4) ;STORE LENGTH OF STRING
OPRMS8:	HRRZ T1,T1		;KEEP JUST FINAL ADDRESS
	SUB T1,OPRMSA		;COMPUTE SIZE OF MESSAGE
	ADDI T1,6		;COMPUTE TOTAL MESSAGE LENGTH
	MOVE T2,OPRMSA		;GET MESSAGE ADDRESS AGAIN
	HRLM T1,(T2)		;STORE LENGTH IN HEADER
	MOVX T1,.OMACK		;GET ACK MESSAGE CODE
	HRRM T1,(T2)		;STORE MESSAGE CODE
	MOVE T1,.MSCOD(T2)	;DON'T SEND IF MSCOD=0. SPECIAL CASE FOR NETCON
	JUMPE T1,OPRMS9		; GENERATED MSG'S. SEE AUTO DUMP/LOAD
	MOVEI T1,4		;NOW SEND THE MESSAGE
	MOVEI T2,OPRMSB
	MSEND
	 RETER2 (.ERR12,<MOVE T1,OPRMSA
			CALL RELPGA
			 NON.FATAL.ERROR ()>)
OPRMS9:	MOVE T1,OPRMSA		;FINISH UP BY RELEASING THE FREE PAGE
	CALL RELPGA
	 NON.FATAL.ERROR
	RETSKP			;FINISHED SUCCESSFULLY
;ROUTINE TO INITIALIZE NETCON

;RETURNS +1:	ERROR
;	 +2:	SUCCESSFUL

NETINI:	CALL	PACINI		;INIT PAGE ACCESSES
	CALL FREINI		;INIT THE FREE SPACE
	MOVE T1,ONCHNS		;GET MASK OF CHANNELS TO ENABLE
	CALL PSIINI		;TURN ON ALL CHANNELS
	CALL JFNINI		;GO OPEN ALL NCU SERVOR JFNS
	 RETBAD ()		;FAILED
	CALL PIDINI		;GO OPEN THE COMM CHANNEL TO ORION
	 RETBAD ()		;FAILED
	CALL HELLO		;SEND "HELLO" MESSAGE TO ORION
	 RETBAD ()		;COULD NOT SEND IT
	CALL NAMINI		;GO SET UP EXECUTR NODE NAME
	CALL SYRNCU		;MAKE A "NETCON-STARTED" SYSERR ENTRY
	SETZM LOGFRK		;INITIALIZE HANDLE OF LOGGING FORK
	CALL LOGINI		;GO SET UP LOGGING TASK
	 NON.FATAL.ERROR (.ERR22)
	CALL TOPINI		;INITIALIZE TOPOLOGY MONITORING DATABASE
	 NON.FATAL.ERROR (.ERR27)
	CALL ATOINI		;INITIALIZE AUTO DUMP/LOAD MONITORING 
	 NON.FATAL.ERROR (.ERR26)
	RETSKP			;DONE



;LOGINI - ROUTINE CALLED JUST AFTER NETCON IS STARTED TO START UP
;	    THE LOGGING PROCESS.
;
;CALL:		CALL LOGINI
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, LOGGING IN PROGRESS

LOGINI:	SKIPE T1,LOGFRK		;ANY PREVIOUS LOGGING FORK ?
	KFORK			;YES, KILL IT
	MOVX T1,CR%MAP!CR%CAP!CR%ST ;PASS CAPABILITIES, USE SAME MAP
	HRRI T1,LOGGER		;GET STARTING ADDRESS OF LOGGING TASK
	CFORK			;CREATE THE LOGGING PROCESS
	 RETBAD ()		;FAILED
	HRRZM T1,LOGFRK		;SAVE ID OF LOGGING FORK
	RETSKP			;SUCCESS, DONE
;TOPINI - ROUTINE TO INITIALIZE TOPOLOGY MONITORING DATABASE

TOPINI:	SAVEQ			;SAVE A FEW REGISTERS
	STKVAR	<TOPVR0>	;LOCAL VARIABLE(S)
	CALL TOPSET		;SET UP TOPLOGY SERVER LINKS
	 FATAL.ERROR (.ERR28)	;FAILED, COULD NOT SET UP TOPOLOGY SERVERS
	JRST TOPI.2		;Continue on

TOPI.1:	SAVEQ			; Save a few registers here also
	STKVAR <DMMY>		; Fix up the stack for an alternate entry point

TOPI.2:	MOVE	T1,[.FHSLF,,.TIMEL] ;Elapsed time type interrupt
	MOVX	T2,TOPTIM	; For the topology polling interval
	MOVX	T3,HCKCHN	; Channel for timer interrupt
	TIMER			; Set it all up
	 JFCL			;  Ignore any errors

	CALL	ASGPAG		;USE A PAGE FOR NODE JSYS
	 RETBAD	()		;OOPS!
	MOVEM	T2,TOPVR0	;SAVE PAGE ADDRESS
	MOVEI	T3,1000		;SOME WORDS IN THAT PAGE
	HRRZM	T3,.NDNLN(T2)	;SAVE FOR NODE JSYS
	MOVEI	T1,.NDGLI	;GET LOCAL LINE INFORMATION
	NODE
	 ERJMP	[RETBAD ()]	;THE JSYS IS TOO CUTE!
	MOVE	Q2,TOPVR0	;OBTAIN START OF PAGE
	HLRZ	T4,.NDNLN(Q2)	;NUMBER OF LINE BLOCKS RETURNED
	SKIPN	T4		;ANY?
	 RETSKP			;IF 0, WE CAN'T DO ANYTHING ABOUT IT
	AOS	T4		;PREPARE FOR AOBJP
	MOVNS	T4		;
	HRL	Q2,T4		;WE HAVE AOBJP POINTER IN Q2
TOPINL:	AOBJP	Q2,TOPOUT	;LOOP ON UNTIL DONE
	MOVE	Q1,0(Q2)	;GET ADDRESS OF LINE BLOCK
	MOVE	T2,.NDLST(Q1)	;WHAT IS THE LINE STATUS?
	CAIE	T2,.NDLON	;LINE-ON?
	 JRST	TOPINL		;NO, TRY ANOTHER LINE
	MOVE	T1,.NDLND(Q1)	;YES, GET  POINTER TO NODE NAME
	ILDB	T1,T1		;Get first byte of node name
	JUMPE	T1,TOPINL	;If none .. go onto next line
	MOVE	T1,.NDLND(Q1)	;Get pointer to node name again
	CALL	MONINI		;TRY MONITORING THE TOPOLOGY
	 JFCL			;DON'T REALLY CARE IF IF FAILS
	JRST	TOPINL		;CONTINUE LOOP
TOPOUT:	MOVE	T1,TOPVR0	;RETURN PAGE OF MEMORY
	CALL	RELPGA		;
	 RETBAD			;OOPS, CANT RETURN PAGE!
	RETSKP			;DONE, SO EXIT THE ROUTINE
; TOPSET - ROUTINE TO SET UP SERVER LINKS FOR TOPOLOGY CHANGE INTERRUPTS
;
;CALL:		CALL TOPSET
;RETURNS: +1	 FAILED
;	  +2	SUCCESS

TOPSET:	MOVX T1,GJ%SHT		;SHORT FORM CALL
	HRROI T2,[ASCIZ/SRV:.TOPOL/] ;TOPOLOGY SERVER
	GTJFN			;GET JFN FOR NEW LINK
	 ERJMP R		;FAILED
	MOVE T2,[100000,,300000] ;READ AND WRITE ACCESS
	OPENF			;OPEN THE LINK
	 ERJMP R		;FAILED, RETURN ERROR
	MOVEM T1,TOPSRV		;SAVE TOPOLOGY SERVER LINK JFN

; ENABLE FOR INTERRUPTS FROM FUTURE TOPOLOGY CHANGES

	MOVEI T3,0		;CLEAR UNUSED BITS
	MOVX T2,TOPCHN		;GET CHANNEL FOR TOPOLOGY INTERRUPTS
	STOR T2,MO%CDN,T3	;STORE CHANNEL NUMBER
	MOVX T2,.MOACN		;GET "ASSIGN CHANNEL" FUNCTION
	MTOPR			;ASSIGN CHANNEL FOR CONNECT INTERRUPTS
	 ERJMP R		;FAILED
	MOVX T1,.FHSLF		;GET OUR FORK HANDLE
	MOVX T2,1b<TOPCHN>!1b<HCKCHN> ;Channels for all types of topology chng.
	AIC			;ACTIVATE THE CHANNELs

; DONE, RETURN SUCCESS

	RETSKP			;DONE, RETURN TO CALLER

;ATOINI - ROUTINE TO INITIALIZE AUTO DUMP/LOAD MONITORING

ATOINI:	STKVAR <ATOHLD>
	MOVX T1,ATOCHN		;GET CHANNEL NUMBER 
	MOVEM T1,ATOHLD		;INTO PARAM BLOCK
	MOVEI T1,.NDSIC		;TELL MONITOR TO INTERRUPT US
	MOVEI T2,ATOHLD		;POINT TO BLOCK
	NODE
	 ERJMP [RETBAD]
	RETSKP
;SETUP APPROPRIATE PAGE ACCESSES FOR NETCON
;
; PACINI - SETUP PAGE ACCESSES
;
; RETURNS +1:	ALWAYS

PACINI:	MOVEI T1,<<NETCON+777>/1000> ;FIRST PAGE THAT DOESN'T HAVE
				; DATA FOR SURE
	MOVEI T3,<<BEGFRE-1000>/1000> ;LAST PAGE BEFORE DATA AREA
	SUB T3,T1		;NUMBER OF PAGES
	HRLI T1,.FHSLF		;SETUP T1 FOR RPACS AND SPACS
PACTOP:	RPACS			;SEE IF PAGE THERE FIRST
	TXNE T2,PA%PEX		;PAGE EXISTS?
	JRST [MOVX T2,PA%RD!PA%EX ;YES, SET READ AND EXECUTE ACCESS
	      SPACS		;     SET PAGE ACCESS
	      JRST .+1]		;     JOIN CODE
	AOS T1			;NO, ADVANCE TO NEXT PAGE
	SOJG T3,PACTOP		;DONE IF ZERO
	RET			;EXIT FROM ROUTINE
;ROUTINE TO INIT THE FREE SPACE

;RETURNS +1:	ALWAYS

FREINI:	MOVE T1,[BEGFRE,,BEGFRE+1]
	SETZM BEGFRE		;ZERO THE VARIABLE AREA
	BLT T1,LSTFRE		;FROM FIRST THRU LAST LOCATION
	SETO T1,		;UNMAP ALL NCU PAGES
	MOVSI T2,.FHSLF		;THIS FORK
	HRRI T2,NCUFFP		;START AT FIRST NCU PAGE
	MOVE T3,[PM%CNT+NCUNFP]	;UNMAP ALL NCU PAGES
	PMAP
	SETO T1,		;UNMAP ALL FREE PAGES
	MOVSI T2,.FHSLF		;THIS FORK
	HRRI T2,FFP		;START AT FIRST FREE PAGE
	MOVE T3,[PM%CNT+NFP]	;UNMAP ALL FREE PAGES
	PMAP
	MOVE T1,[POINT 1,FPTBL]	;NOW INITIALIZE THE FREE PAGE TABLE
	MOVEI T2,1		;MAKE ALL PAGES AVAILABLE
	MOVEI T3,NFP
FREIN1:	IDPB T2,T1		;MARK THE PAGE AS FREE
	SOJG T3,FREIN1		;LOOP BACK FOR ALL PAGES
	CALL FSHDR		;GO INITIALIZE THE FREE SPACE HEADER
	MOVE T4,[-MAXPGM,,PGMTAB]
	MOVX T1,.PGFRE		;INITIALIZE THE PGM TABLE TO ALL FREE
FREIN2:	STOR T1,PGLDV,(T4)	;MARK THIS ENTRY AS FREE
	ADDI T4,PGLEN-1		;STEP TO NEXT ENTRY
	AOBJN T4,FREIN2		;LOOP BACK FOR ALL ENTRIES IN PGM TABLE
	MOVE T1,[0,,MAXNOD]	;GET INITIAL HEADER FOR KNOWN NODE TABLE
	MOVEM T1,NODTAB		;INITIALIZE NODE TABLE
	SETOM NXTNIB		;INITIALIZE POINTER TO FIRST NIB
	SETOM NXTLIN		;INITIALIZE POINTER TO NEXT LINTAB ENTRY
	RET			;DONE
;DUPTST - ROUTINE TO TEST FOR DUPLICATE NETCON'S RUNNING
;
;CALL:		CALL DUPTST
;RETURNS: +1	 FAILED, ANOTHER NETCON IS RUNNING
;	  +2	SUCCESS, OK TO CONTINUE

DUPTST:	STKVAR <<ENQJFB,5>,<ENQJFS,3>,<ENQJFU,10>>
	MOVX T1,-2		;USE GLOBAL LOCK
	HRRZM T1,.ENQLV+ENQJFB	;SAVE THE LOCK TYPE 
	MOVE T1,[1,,5]		;SET UP ENQ BLOCK
	MOVEM T1,.ENQLN+ENQJFB
	SETZM .ENQID+ENQJFB	;ID = 0
	HRROI T1,[ASCIZ/NETCON/] ;UNIQUE IDENTIFICATION
	MOVEM T1,.ENQUC+ENQJFB	;UNIQUE CODE
	SETZM .ENQRS+ENQJFB	;EXCLUSIVE LOCK
	MOVEI T1,.ENQAA		;ASK FOR LOCK
	MOVEI T2,ENQJFB
	ENQ
	 SKIPA			;NOT AVAILABLE
	RETSKP			;GOT IT LOCKED
	CAIE T1,ENQX6		;ALREADY IN USE?
	RET			;NO, ERROR
	MOVEI T1,.ENQCS		;NOW GET JOB NUMBER OF OWNER
	MOVEI T2,ENQJFB
	MOVEI T3,ENQJFS		;GET ADR OF STATUS BLOCK
	ENQC			;GET STATUS INFO
	 RET			;FAILED
	HRRZ T1,ENQJFS		;GET JOB NUMBER OF OWNER
	HRROI T2,T4		;GET USER NUMBER OF JOB
	MOVEI T3,.JIUNO
	GETJI
	 RET			;FAILED
	MOVEI T1,.PRIOU
	TMSG <NETCON: Another NETCON already in use by >
	HRROI T1,ENQJFU		;GET USER NAME
	MOVE T2,T4		;GET USER NUMBER
	DIRST
	 SKIPA T2,[-1,,[ASCIZ/user/]]
	HRROI T1,ENQJFU		;GET USER NAME STRING
	PSOUT			;OUTPUT THE USER NAME STRING
	TMSG < on job >
	MOVX T1,.PRIOU		;OUTPUT TO PRIMARY JFN
	HRRZ T2,ENQJFS		;NOW OUTPUT THE JOB NUMBER
	MOVEI T3,^D10		;IN DECIMAL
	NOUT			;OUTPUT JOB NUMBER
	 JFCL
	RET			;RETURN FAILURE
;ROUTINE TO INIT THE PSI SYSTEM
;
;ACCEPTS IN T1/	MASK OF CHANNELS TO ENABLE

;RETURNS +1:	ALWAYS

PSIINI::MOVE T4,T1		;SAVE CHANNELS TO ENABLE
	CIS			;CLEAR THE INTERRUPT SYSTEM
	MOVEI T1,.FHSLF		;THIS FORK
	MOVE T2,[LVTTAB,,CHTTAB]
	SIR			;SET UP LEVTAB AND CHNTAB
	MOVE T2,T4		;GET MASK OF CHANNELS TO ENABLE
	AIC			;ACTIVATE THE CHANNELS
	EIR			;ENABLE THE PI SYSTEM FOR INTERRUPTS
	RET			;DONE


;ROUTINE TO OPEN THE SERVOR JFNS FOR THE NCU

;RETURNS +1:	ERROR
;	 +2:	SUCCESSFUL

JFNINI:	SAVEQ
	MOVSI Q1,-NJFN		;GET THE NUMBER OF JFNS DESIRED
JFNLOP:	MOVEI T1,JFNCHN(Q1)	;GET CHANNEL NUMBER FOR THIS JFN
	CALL GETJFN		;GET A JFN
	 JRST JFNERR		;FAILED
	MOVEM T1,JFNTAB(Q1)	;STORE THE JFN
	AOBJN Q1,JFNLOP		;LOOP FOR ALL JFNS
	RETSKP			;DONE

JFNERR:	TRNN Q1,-1		;WERE ANY JFNS OPENED OK?
	RETBAD .ERR1		;NO, GIVE ERROR RETURN
	RETSKP			;YES, USE THE ONES THAT WERE OPENED
;ROUTINE TO GET A JFN TO SRV:NCU
;ACCEPTS IN T1/	CHANNEL NUMBER TO ENABLE

GETJFN:	STKVAR <GETJFJ,GETJFC>
	MOVEM T1,GETJFC		;SAVE THE CHANNEL NUMBER
	MOVX T1,GJ%SHT		;GET A JFN FOR NCU
	HRROI T2,[ASCIZ/SRV:NCU/]
	GTJFN
	 RETER2 ()		;FAILED
	MOVEM T1,GETJFJ		;SAVE THE JFN
	MOVE T2,[^D8B5+OF%RD+OF%WR]
	OPENF			;OPEN THE LINK
	 JRST GETJF1		;FAILED
	MOVE T2,GETJFC		;GET INTERRUPT CHANNEL NUMBER
	STOR T2,MO%CDN,T3	;SET UP CONNECT CHANNEL NUMBER
	MOVEI T2,.MOCIA		;CLEAR THE UNWANTED INTERRUPTS
	STOR T2,MO%INA,T3	;INTERRUPT MESSAGES
	STOR T2,MO%DAV,T3	;AAND DATA AVAILABLE
	MOVEI T2,.MOACN		;NOW CONNECT THE JFN TO AN INTERRUPT
	MTOPR
	 ERJMP GETJF1		;FAILED
	MOVE T1,GETJFJ		;GET THE JFN
	RETSKP			;AND RETURN

GETJF1:	EXCH T1,GETJFJ		;GET JFN AGAIN
	MOVE T2,T1		;SAVE JFN
	CLOSF			;CLOSE IT
	 SKIPA T1,T2		;FAILED
	SKIPA
	RLJFN			;RELEASE IT
	 JFCL
	MOVE T1,GETJFJ		;GET ERROR CODE
	RETER2 ()
;ROUTINE TO GET A PID FOR COMMUNICATION WITH ORION

;RETURNS +1:	FAILED
;	 +2:	OK

PIDINI:	SAVEQ			;PRESERVE THE PERMANENT ACS
	MOVEI T1,3		;FIRST, GET THE PID QUOTA
	MOVEI T2,Q1
	MOVEI Q1,.MUFPQ
	SETO Q2,		;FOR THIS JOB
	MUTIL			;READ PID QUOTA
	 JRST PIDIN1		;FAILED, DONT TRY TO SET IT
	AOS Q3			;RAISE THE QUOTA BY ONE
	MOVEI Q1,.MUSPQ		;NOW SET THE QUOTA
	MUTIL
	 JFCL			;IGNORE ERRORS AT THIS STEP
PIDIN1:	MOVEI T1,3		;NOW CREATE A PID
	MOVEI T2,Q1
	MOVEI Q1,.MUCRE		;THIS PID IS FOR NETCON TO
	MOVEI Q2,.FHSLF		;  COMMUNICATE WITH ORION
	MUTIL
	 RETER2 (.ERR2)		;FAILED TO GET A PID
	MOVEM Q3,PID		;SAVE THIS PID
	MOVEI Q1,.MUPIC		;NOW PUT THE PID ON A CHANNEL
	MOVE Q2,PID
	MOVEI Q3,PIDCHN
	MUTIL			;NOW WILL GET INTERRUPTED BY ORION
	 RETER2 (.ERR4)		;COULD NOT PUT IT ON A CHANNEL
	RETSKP			;DONE
;NAMINI - ROUTINE TO SET UP NODE NAME, NODE NUMBER, SYSTEM NAME, ETC.

NAMINI:	DMOVE T4,[ASCIZ/TOPS20/] ;GET DEFAULT NAME
	DMOVEM T4,OURNAM	;SET UP OUR LOCAL NODE NAME
	SETZM T1		;NO OLD BLOCK TO RELEASE
	MOVE T2,[POINT 7,[ASCIZ/TOPS20/]] ;GET DEFAULT NAME
	MOVX T3,NODLEN		;GET MAX LENGTH OF NAMES
	CALL CPYASC		;ASSIGN STRING BLOCK
	 FATAL.ERROR (.ERR8)	;IF NO RESOURCES SO SOON, MUST FAIL
	MOVEM T1,EXCUTR		;SAVE POINTER TO CURRENT EXECUTOR
	MOVE T3,T1		;COPY POINTER TO DESTINATION FOR NODE NAME
	MOVEI T2,T3		;ARGUMENT BLOCK IS IN T3
	MOVX T1,.NDGLN		;GET "GET LOCAL NODE NAME" FUNCTION
	NODE			;GET OUR NODE NAME
	 ERJMP [ NON.FATAL.ERROR (.ERR20)
		JRST .+1 ]	;RETURN
	HRROI T3,OURNAM		;GET LOCAL NAME AGAIN
	NODE			; AND SAVE IT AS NAME OF LOCAL NODE
	 ERJMP [ NON.FATAL.ERROR (.ERR20)
		 JRST .+1 ]	;CONTINUE
	MOVX T1,.NDGNM		;GET LOCAL NODE NUMBER
	MOVX T2,T3		;ARG BLOCK IS IN T3
	NODE			;GET OUR NODE NUMBER
	 ERJMP [ NON.FATAL.ERROR (.ERR20)
		 JRST .+1 ]	;RETURN
	MOVEM T3,OURNUM		;RET

; GET SYSTEM NAME STRING

	MOVE T1,['SYSVER']	;GET TABLE NAME
	SYSGT			;GET TABLE NUMBER
	HLLZ T4,T2		;GET -# OF ENTRIES,,0
	HRRZ T3,T2		;GET TABLE NUMBER

NAM010:	HRL T1,T4		;GET OFFSET INTO TABLE
	HRR T1,T3		;GET TABLE NUMBER
	GETAB			;GET PART OF NAME
	 ERJMP R		;FAILED
	MOVEM T1,SYSNAM(T4)	;STORE TEXT
	AOBJN T4,NAM010		;LOOP OVER ALL ENTRIES IN NAME
	RET			;DONE, RETURN
;ROUTINE TO SEND A "HELLO" MESSAGE TO ORION

;RETURNS +1:	FAILED
;	 +2:	DONE

HELLO:	SAVEQ			;SAVE PERMANENT ACS
	STKVAR <HELLOT>
	SETZM HELLOT		;INITIALIZE RETRY COUNTER
HELLO1:	MOVEI T1,3		;GET THE PID OF ORION
	MOVEI T2,Q1
	MOVEI Q1,.MURSP		;GET PID FROM SYSTEM PID TABLE
	MOVEI Q2,.SPOPR		;GET PID OF ORION
	MUTIL
	 JRST HELLOW		;FAILED, GO WAIT FOR ORION TO START
	MOVEM Q3,OPRPID		;SAVE THE PID OF ORION
	MOVEI T1,4
	MOVEI T2,HMESHD		;NOW SEND THE MESSAGE
	MSEND
	 RETER2 (.ERR3)		;FAILED
	RETSKP			;DONE

	HSMIN==2		;MINUTES BETWEEN WARNING MESSAGES
	HSSLP==5		;SECONDS TO SLEEP BETWEEN TRIES

HELLOW:	AOS T1,HELLOT		;GET COUNTER OF RETRIES
	IDIVI T1,HSMIN*^D60/HSSLP
	SKIPN T2		;TIME FOR A WARNING MESSAGE?
	WRNMES <Waiting for ORION to be started>
	MOVEI T1,HSSLP*^D1000	;NOW WAIT A WHILE BEFORE TRYING AGAIN
	DISMS
	JRST HELLO1		;GO TRY AGAIN


HMESHD:	IP%CFS!IP%CFR!IP%CFP	;HELLO MESSAGE HEADER
	PID			;POINTER TO SENDERS PID
	OPRPID			;POINTER TO RECEIVERS PID
	HMESL,,HMES		;POINTER TO MESSAGE

HMES:
	HMESL,,.OMAHL		;MESSAGE LENGTH,,TYPE
	0			;NO FLAGS
	'NETCON'		;ACKNOWLEDGEMENT CODE
	0			;NO FLAGS AGAIN
	1			;ONE ARG
	3,,.AHNAM		;3 WORDS,,ARGUMENT NAME STRING
	ASCIZ/NCP/		;NAME OF APPLICATION
HMESL==.-HMES+1
;PANIC LEVEL ROUTINES

;THESE ROUTINES ARE CALLED ON LEVEL 1

DEFINE FATMES (A) <
	MOVEM T2,L1SAV2		;SAVE ALL ACS THAT ARE USED
	HRROI T2,[ASCIZ\A\]	;SET UP MESSAGE
	JRST FATAL>

PDLOV:	FATMES <Push down list overflow>

DATERR:	FATMES <I/O data error or parity error>

ILLMRD:	FATMES <Illegal memory read>

ILLMWR:	FATMES <Illegal memory write>

ILLINS:	FATMES <Illegal instruction>

CRUMP:	PIOFF
	FATMES <Fatal error>

MACHSZ:	MOVEM T2,L1SAV2		;SAVE ALL ACS
	MOVE T2,LEV1PC		;GET INTERRUPTED PC
	TLNN T2,(1B5)		;CAME FROM USER MODE?
	JRST [	HRROI T2,[ASCIZ/Machine size exceeded/]
		JRST FATAL]
	MOVEM T1,L1SAV1		;SAVE ACS
	MOVEM T3,L1SAV3
	MOVEM T4,L1SAV4
	WRNMES <Machine size exceeded, attempting recovery...>
	MOVEI T1,^D30*^D1000	;SLEEP FOR 30 SECONDS
	DISMS
	MOVE T1,L1SAV1		;MAYBE THE CONDITION HAS GONE AWAY
	MOVE T2,L1SAV2
	MOVE T3,L1SAV3
	MOVE T4,L1SAV4
	DEBRK			;TRY AGAIN
FATAL:	MOVEM T1,L1SAV1		;SAVE THE ACS
	MOVEM T3,L1SAV3
	HRROI T1,[ASCIZ/
? NETCON: /]
	PSOUT
	MOVE T1,T2		;GET MESSAGE TO BE TYPED
	PSOUT			;TYPE IT OUT
	HRROI T1,[ASCIZ/ at location: /]
	PSOUT
	MOVEI T1,.PRIOU		;NOW OUTPUT THE PC
	HRRZ T2,LEV1PC		;GET THE PC
	MOVEI T3,10		;OCTAL
	NOUT
	 JFCL
	HRROI T1,[ASCIZ/
	(/]
	PSOUT
	MOVEI T1,.PRIOU		;NOW PUT OUT THE MONITOR ERROR MESSAGE
	HRLOI T2,.FHSLF
	SETZ T3,
	ERSTR
	 JFCL
	 SKIPA T1,[-1,,[ASCIZ/Unknown monitor error code)
/]]
	HRROI T1,[ASCIZ/)
/]
	PSOUT
	MOVE T1,L1SAV1		;RESTORE ACS
	MOVE T2,L1SAV2
	MOVE T3,L1SAV3
	HALTF			;BOMB!
	JRST NETCON
;NETCON ERROR CODES

	ERRCD0==500000		;STARTING ERROR CODE VALUE

DEFINE ERCOD <
XLIST
ERR .ERR1,<Could not open any JFNs for the NCU task>
ERR .ERR2,<Could not create a PID for receiving ORION messages>
ERR .ERR3,<Could not send "HELLO" message to ORION>
ERR .ERR4,<Could not set up PID interrupt channel>
ERR .ERR5,<No more free pages available>
ERR .ERR6,<Attempt to return an illegal page address>
ERR .ERR7,<Attempt to return a page that is already on the free list>
ERR .ERR8,<No more free space available>
ERR .ERR9,<Attempt to return a free block outside the free pool area>
ERR .ERR10,<Attempt to return space already marked as in the free pool>
ERR .ERR11,<ORION is not running>
ERR .ERR12,<Failed to successfully send a message to OPR>
ERR .ERR13,<Unimplemented NETCON command>
ERR .ERR14,<Unknown internal NETCON message type>
ERR .ERR15,<Exhausted table space for the known nodes>
ERR .ERR16,<All server JFNs in use>
ERR .ERR17,<NCU process halted prematurely>
ERR .ERR18,<Unknown message type received from ORION>
ERR .ERR19,<JSYS error>
ERR .ERR20,<Could not get name of local node>
ERR .ERR21,<Could not log line counters for communications line>
ERR .ERR22,<Could not initiate Logging Process>
ERR .ERR23,<Invalid line-id>
ERR .ERR24,<Could not open file>
ERR .ERR25,<Bad data in load file>
ERR .ERR26,<Could not initiate automatic dump/load>
ERR .ERR27,<Could not obtain network topology>
ERR .ERR28,<Could not set up topology change server links>
ERR .ERR29,<SYERR JSYS failed creating SYSERR entry>
ERR .ERR30,<Free pool chain sequencing error, blocks not sorted correctly>
LIST
>				;END OF ERCOD DEFINITION

DEFINE ERR (A,B) <
IF1 <IFDEF A,<PRINTX Error code "A" is multiply defined>>
	A==:ZZ
	[ASCIZ\B\]
	ZZ==ZZ+1>

	ZZ==ERRCD0

ERRTAB:	ERCOD
	ERRTBL==.-ERRTAB
;CHANNEL AND PSI DATA BASE

LVTTAB:	LEV1PC			;LEVEL 1 PC
	LEV2PC			;LEVEL 2 PC
	LEV3PC			;LEVEL 3 PC

CHTTAB:	
	PIDCHN==0		;INTERRUPT CHANNEL FOR IPCF MESSAGES
	PIDLVL,,PIDINT		;0
	JFDCHN==1		;1 - NJFN ARE FOR NCU DATA INTERRUPTS

	ZZ==0
REPEAT NJFN,<
DEFINE CHNBLD (A)<
	LALL
	JFDLVL,,JFD'A
	SALL
>
	CHNBLD (\ZZ)
	ZZ==ZZ+1>

	BLOCK 8-NJFN		;UNUSED CHANNELS
	1,,PDLOV		;9 - PDL OVERFLOWS
	0			;10 - UNUSED
	1,,DATERR		;11 - IO DATA ERRORS AND PARITY ERRORS
	BLOCK 3			;12-14 UNUSED
	1,,ILLINS		;15 - ILLEGAL INSTRUCTION
	1,,ILLMRD		;16 - ILLEGAL MEMORY READ
	1,,ILLMWR		;17 - ILLEGAL MEMORY WRITE
	0			;18 - UNUSED
	FKTLVL,,FRKTER		;19 - FORK TERMINATION
	1,,MACHSZ		;20 - MACHINE SIZE EXCEEDED
	BLOCK 2			;21-22 - UNUSED

	JFNCHN==^D23		;START OF JFN INTERRUPT CHANNELS
IFL <^D8-NJFN>,<PRINTX NUMBER OF NCU JFNS EXCEEDED CHANNEL SPACE>
	ZZ==0
REPEAT NJFN,<
DEFINE CHNBLD (A)<
	LALL
	JFNLVL,,JFN'A
	SALL
>
	CHNBLD (\ZZ)
	ZZ==ZZ+1>

	TOPCHN==JFNCHN+NJFN
	ZZ=0
REPEAT TOPMAX,<
DEFINE CHNBLD (A)<
	LALL
	TOPLVL,,TOP'A
	SALL
>
	CHNBLD (\ZZ)
	ZZ=ZZ+1>


	ATOCHN==TOPCHN+TOPMAX		;CHANNEL FOR TOPOLOGY CHANGE INTERRUPT
	TOPLVL,,ATO0			; FROM THE MONITOR

	HCKCHN==ATOCHN+1
	HCKLVL,,HCKINT			;Channel for topology polling TIMER
					;  interrupts

	BLOCK ^D35-HCKCHN-1		;Rest of interrupt table

	JFNCHB==JFNCHN-1+NJFN		;BIT POSITION
	JFNCHM==<-1_-<^D36-NJFN>>	;MASK
	JFDCHB==JFDCHN-1+NJFN		;BIT POSITION
	JFDCHM==<-1_-<^D36-NJFN>>	;BIT MASK
	TOPCHB==TOPCHN-1+TOPMAX		;BIT POSITION
	TOPCHM==<-1_-<^D36-TOPMAX>>	;MASK
	ATOCHB==ATOCHN			;BIT POSITION
	ATOCHM==1			;MASK


	FIXCHN==1B<PIDCHN>!1B9!1B11!1B15!1B16!1B17!1B19!1B20
	VARCHN==<JFNCHM>B<JFNCHB>!<JFDCHM>B<JFDCHB>!<ATOCHM>B<ATOCHB>!1b<HCKCHN>

ONCHNS:	FIXCHN!VARCHN
SUBTTL	Routines to Manipulate the Database


;ADDNOD - ROUTINE TO ADD A NODE TO THE LIST OF KNOWN NODES
;
;ACCEPTS IN T1/	POINTER TO ASCIZ NAME OF NEW NODE
;		CALL ADDNOD
;RETURNS: +1	 FAILURE, INSUFFICIENT RESOURCES FOR ANOTHER NODE
;	  +2	SUCCESS, WITH T1/ ADDRESS OF NODE INFORMATION BLOCK

ADDNOD:	STKVAR <STNNOD,STNNIB>
	MOVE T2,T1		;COPY STRING TO A FREE BLOCK
	MOVEI T1,0		;NO PREVIOUS STRING BLOCK
	MOVEI T3,NODLEN		;STRING IS A NODE NAME
	CALL CPYASC		;COPY THE STRING
	 RETBAD ()		;FAILED

; STORE THE ASCIZ NODE NAME IN THE STRING AREA

	ADDI T1,1		;POINT TO THE ACTUAL TEXT
	MOVEM T1,STNNOD		;SAVE ADDRESS OF NODE NAME IN STRING AREA

; ALLOCATE A NEW NODE INFORMATION BLOCK AND ADD NODE TO NODE TABLE

	CALL SETNIB		;GO GET ADDRESS OF NEXT FREE NIB
	 JRST ADDNO1		;RETURN FAILURE, NO NIB'S AVAILABLE
	MOVEM T1,STNNIB		;SAVE ADDRESS OF NEW NIB
	HRR T2,T1		;GET NIB ADDRESS (DATA PART OF TABLE ENTRY)
	HRL T2,STNNOD		;GET ADDRESS OF ASCIZ NODE NAME
	MOVEI T1,NODTAB		;GET ADDRESS OF NODE TABLE
	TBADD			;ADD THE NODE TO THE TABLE
	 ERJMP ADDNO1		;FAILED, RETURN ERROR

; INITIALIZE THE NEW NODE INFORMATION BLOCK AND RETURN

	MOVE T1,STNNIB		;GET ADDRESS OF NEW NIB TO INITIALIZE
	MOVE T2,STNNOD		;GET ADDRESS OF ASCIZ NODE NAME
	CALL NIBINI		;GO INITIALIZE THE NEW NIB
	MOVE T1,STNNIB		;GET ADDRESS OF NODE INFORMATION BLOCK
	RETSKP			;RETURN SUCCESS


ADDNO1:	MOVE T1,STNNOD		;GET POINTER TO NODE NAME STRING
	CALL RELFRE		;RELEASE IT
	 FATAL.ERROR		;COULDNT RELEASE IT
	RETBAD (.ERR15)		;NO MORE ROOM FOR NODE NAME
;FOCLIN - ROUTINE TO FIND OR CREATE AN ENTRY IN A LINE ADJACENCY TABLE
;
;ACCEPTS IN T1/	ADDRESS OF NIB
;	    T2/	LINE ID
;		CALL FOCLIN
;RETURNS: +1	 FAILED, COULD NOT FIND OR CREATE ENTRY
;	  +2	SUCCESS, WITH T1/ ADDRESS OF ENTRY IN LINE ADJACENCY TABLE

FOCLIN:	STKVAR <FCLNIB,<FCLLIN,2>,FCLFRE>

; SEE IF THERE IS ALREADY AN ENTRY FOR THIS LINE

	SETZM FCLFRE		;INITIALIZE FIRST FREE ENTRY
	LOAD T1,NDLIN,(T1)	;GET ADDRESS OF LINE ADJACENCY TABLE
	MOVSI T4,-MXLNOD	;SET UP TO LOOP OVER EACH ENTRY IN THE TABLE
FCL010:	JN LTUSE,(T1),FCL015	;IF THIS ENTRY IN USE, GO SEE WHICH LINE IT IS
	SKIPN FCLFRE		;FREE ENTRY, ANY PREVIOUS FREE ENTRIES FOUND ?
	MOVEM T1,FCLFRE		;NO, SAVE ENTRY ADDRESS
	JRST FCL020		;GO CHECK NEXT ENTRY IN TABLE
FCL015:	CAMN T2,0(T1)		;TYPE AND CONTROLLER NUMBER COMPARE ?
	CAME T3,1(T1)		;  AND ALSO UNIT NUMBER AND STATION ADDRESS ?
	SKIPA			;NO, GO CHECK NEXT ENTRY
	RETSKP			;FOUND DESIRED ENTRY, RETURN WITH T1/ ENTRY ADR
FCL020:	ADDI T1,LATSIZ		;FORM ADDRESS OF NEXT ENTRY IN TABLE
	AOBJN T4,FCL010		;LOOP OVER ALL ENTRIES IN TABLE
	MOVE T1,FCLFRE		;NOT FOUND, GET ADDRESS OF A FREE ENTRY
	DMOVEM T2,(T1)		;STORE LINE ID IN NEW ENTRY
	SETONE LTUSE,(T1)	;MARK THAT THIS ENTRY IS NOW IN USE
	RETSKP			;AND RETURN WITH T1/ ENTRY ADDRESS
;ROUTINE TO FIND OR CREATE AN ENTRY IN THE PGM TABLE

;ACCEPTS IN T1/	DEVICE TYPE CODE
;	    T2/	CPU TYPE CODE
;	    T3/	PROGRAM TYPE
;	CALL FOCPGM
;RETURNS +1:	COULD NOT CREATE AN ENTRY
;	 +2:	T1/	ADR OF ENTRY IN PGM TABLE

FOCPGM:	SAVEQ			;SAVE SOME ACS
	SETZ Q2,		;INITIALIZE POINTER TO FIRST FREE ENTRY
	MOVE Q1,[-MAXPGM,,PGMTAB]
FOCPG1:	LOAD T4,PGLDV,(Q1)	;CHECK DEVIVE TYPE
	CAME T1,T4		;FOUND A MATCH?
	JRST FOCPG2		;NO, STEP TO NEXT ENTRY
	LOAD T4,PGCPU,(Q1)	;CHECK CPU TYPE
	CAME T2,T4		;FOUND A MATCH?
	JRST FOCPG3		;NO
	LOAD T4,PGPGM,(Q1)	;CHECK PROGRAM TYPE
	CAME T3,T4		;FOUND A MATCH?
	JRST FOCPG3		;NO
	HRRZ T1,Q1		;YES, RETURN THIS ADDRESS IN T1
	RETSKP

FOCPG2:	JUMPN Q2,FOCPG3		;SEEN A FREE ENTRY YET?
	CAIN T4,.PGFRE		;NO, IS THIS ONE FREE?
	HRRZ Q2,Q1		;YES, REMEMBER THIS ENTRY
FOCPG3:	ADDI Q1,PGLEN-1		;STEP TO NEXT ENTRY
	AOBJN Q1,FOCPG1		;...
	JUMPE Q2,R		;SEARCHED WHOLE TABLE, ANY FREE SLOTS?
	STOR T1,PGLDV,(Q2)	;YES, CREATE THIS ENTRY
	STOR T2,PGCPU,(Q2)	;STORE THE DEVICE AND CPU TYPES
	STOR T3,PGPGM,(Q2)	;STORE THE PROGRAM TYPE
	HRRZ T1,Q2		;RETURN THE ADDRESS IN T1
	RETSKP
;SETNIB - ROUTINE TO ALLOCATE THE NEXT FREE NODE INFORMATION BLOCK
;
;CALL:		CALL SETNIB
;RETURNS: +1	 FAILURE, NO MORE NIB'S AVAILABLE
;	  +2	SUCCESS, WITH T1/ ADDRESS OF NODE INFORMATION BLOCK

SETNIB:	AOS T1,NXTNIB		;GET NUMBER OF NEXT AVAILABLE NIB
	CAIL T1,MAXNOD		;ANY MORE AVAILABLE ?
	RET			;NO, RETURN FAILURE
	MOVEM T1,NXTNIB		;YES, STORE NUMBER OF LAST NIB USED
	IMULI T1,NIBSIZ		;COMPUTE STARTING ADDRESS OF THIS NIB
	ADDI T1,NIBTAB		;FORM STARTING ADDRESS OF THE NEW NIB
	RETSKP			;RETURN SUCCESS


;SETLTB - ROUTINE TO ALLOCATE A LINE TABLE
;
;CALL:		CALL SETLTB
;RETURNS: +1	 FAILURE, NO MORE LINE TABLES AVAILABLE
;	  +2	SUCCESS, WITH T1/ ADDRESS OF LINE TABLE

SETLTB:	AOS T1,NXTLIN		;GET NUMBER OF NEXT AVAILABLE LINE TABLE
	CAIL T1,MAXLIN		;ANY MORE AVAILABLE ?
	RET			;NO, RETURN FAILURE
	MOVEM T1,NXTLIN		;YES, STORE NUMBER OF LAST LINE TABLE USED
	IMULI T1,LINSIZ		;COMPUTE STARTING ADDRESS OF THIS LINE TABLE
	ADDI T1,ADJTAB		;FORM STARTING ADDRESS OF THE NEW LINE TABLE
	RETSKP			;RETURN SUCCESS
;NIBINI - ROUTINE TO INITIALIZE A NODE INFORMATION BLOCK
;
;ACCEPTS IN T1/	ADDRESS OF NODE INFORMATION BLOCK
;	    T2/	ADDRESS OF ASCIZ NODE NAME
;		CALL NIBINI
;RETURNS: +1 ALWAYS, WITH NIB INITIALIZED

NIBINI:	STKVAR <NBINIB>
	MOVEM T1,NBINIB		;SAVE ADDRESS OF NIB
	HRLZ T4,T1		;GET STARTING ADDRESS OF NIB
	HRRI T4,1(T1)		;GET DESTINATION ADDRESS FOR BLT
	SETZM (T1)		;ZERO THE FIRST WORD OF THE NIB
	BLT T4,NIBSIZ-1(T1)	;INITIALIZE THE NIB
	HRLI T2,(POINT 7,)	;SET UP A POINTER TO THE NODE NAME
	STOR T2,NDNAM,(T1)	;STORE POINTER TO NODE NAME IN THE NIB
	STOR T2,NDPNA,(T1)	;STORE NAME NODE SHOULD USE ON BEING LOADED
	move t2,[point 7,ournam] ;get pointer to our node name
	STOR T2,NDPHT,(T1)	;STORE POINTER TO DEFAULT HOST FOR LOADS
	SETZRO NDFLG,(T1)	;INITIALIZE THE FLAGS FOR THIS NODE
	SETONE NDPRO,(T1)	;NOTE THAT NO PROTOCOL HAS BEEN DECLARED YET
	setone ndpnu,(t1)	;no default node number
	SETONE NDFRD,(T1)	;FORCE AUTO DUMP
	SETONE NDFRL,(T1)	;FORCE AUTO LOAD
	CALL SETLTB		;GET ADDRESS OF A LINE TABLE
	 RET			;FAILED, RETURN ERROR
	MOVE T4,NBINIB		;GET ADDRESS OF NIB BEING INITIALIZED
	STOR T1,NDLIN,(T4)	;STORE ADDRESS OF LINE TABLE FOR THIS NIB
	RET			;RETURN
SUBTTL	AUTO DUMP/LOAD ROUTINES

;DMPLOD - AUTO DUMP AND LOAD OF NODES

;ACCEPTS:

;RETURNS:	+1,ERROR
;		+2,OTHERWISE

DMPLOD:	STKVAR<DMPTOP,DMPHLD>

; GET CURRENT TOPOLOGY FROM MONITOR

	CALL ASGPAG		;GET A PAGE FOR TOPOLOGY INFORMATION
	 RETBAD			;NO SPACE - ERROR
	MOVEM T2,DMPTOP		;SAVE ADDRESS OF PAGE BUFFER
	CALL TOPLGY		;GET CURRENT NETWORK TOPOLOGY
	 JRST DMPERR		;FAILED, GO RELEASE ASSIGNED PAGE
	SETZM DMPHLD		;GET READY TO GET FIRST NIB
	;...
	;...

; LOOP THROUGH ALL NIB'S. FOR EACH NIB NOT IN TOPOLGY DUMP/LOAD AS INDICATED

DMPLOP:	MOVE T1,DMPHLD		;GET NIB ADDRESS
	CALL GTNXNB		;GET NEXT NIB
	 JRST DMPERR		;ERROR - FAIL
	JUMPE T1,DMPEND		;JUMP IF LOOKED AT ALL NIBS
	MOVEM T1,DMPHLD		;SAVE NIB ADDRESS
	MOVE T2,DMPTOP		;ADDRESS OF TOPOLOGY DATA
	CALL CHKNIB		;SEE IF NIB IS IN TOPOLOGY
	 JRST DMPLOP		;YES - TRY NEXT NIB

; FOUND A NIB NOW PROCESS DUMP COMMAND

	MOVE T1,DMPHLD		;GET NIB ADDRESS
	JN NDDIP,(T1),ATOLOD	;JUMP IF DUMP IN PROGRESS FOR THIS NIB
	JN NDLIP,(T1),ATOLOD	;JUMP IF LOAD IN PROGRESS FOR THIS NIB
	JE NDDOK,(T1),ATOLOD	;JUMP IF NOT RESPONSIBLE FOR THIS NODE
	JE NDFRD,(T1),ATOLOD	;IF BIT NDFRD IS ZERO => NO DUMPING
	SETONE NDDIP,(T1)	;SET DUMP IN PROGRESS
	LOAD T1,NDNAM,(T1)	;GET POINTER TO NODE NAME
	MOVEI T2,.DNDMP		;TELL SNDCMD TO DO A DUMP COMMAND
	CALL SNDCMD		;GO SEND THE DUMP COMMAND
	 JFCL			;ERROR - TRY LOAD WITHOUT DUMPING

; PROCESS LOAD COMMAND

ATOLOD:	MOVE T1,DMPHLD		;GET NIB ADDRESS
	JN NDLIP,(T1),DMPLOP	;JUMP IF  LOAD IN PROGRESS FOR THIS NIB
	JE NDDOK,(T1),DMPLOP	;JUMP IF NOT RESPONSIBLE FOR THIS NODE
	JE NDFRL,(T1),DMPLOP	;IF BIT NDFRL IS ZERO => NO LOADING
	SETONE NDLIP,(T1)	;SET  LOAD IN PROGRESS
	LOAD T1,NDNAM,(T1)	;GET POINTER TO NODE NAME
	MOVEI T2,.DNLOA		;TELL SNDCMD TO DO A LOAD COMMAND
	CALL SNDCMD		;GO SEND THE LOAD COMMAND
	 JRST DMPERR		;ERROR - FAIL
	JRST DMPLOP		;AND LOOP ON ALL NIB'S

DMPEND:	MOVE T1,DMPTOP		;GET TOPOLOGY PAGE ADDRESS
	CALL RELPGA		;AND RELEASE
	 RETBAD			;ERROR - FAIL
	RETSKP

DMPERR:	MOVE T1,DMPTOP		;GET TOPOLOGY PAGE ADDRESS
	CALL RELPGA		;AND RELEASE
	 RETBAD			;ERROR - FAIL
	RETBAD
;TOPLGY - ROUTINE TO GET THE CURRENT NETWORK TOPOLOGY
;
;ACCEPTS IN T2/	ADDRESS OF BUFFER IN WHICH TO PUT TOPOLOGY
;		CALL TOPLGY
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, TOPOLOGY FILLED IN

TOPLGY:	MOVEI T1,.NDGNT		;GET NETWORK TOPOLGY FUNCTION
	MOVEI T3,1000		;LET IT USE THE WHOLE PAGE
	MOVEM T3,.NDNND(T2)	;INTO BLOCK
	NODE
	 ERJMP R		;FAILED, RETURN ERROR
	RETSKP			;DONE, RETURN TOPOLOGY
;GTNXNB - GET NEXT NIB

;ACCEPTS:	T1/ 0 - START AT THE TOP
;		    ADDRESS - OF NIB

;RETURNS:	+1, ERROR
;		+2, OTHERWISE
;			T1/ 0 - NO MORE NIBS
;			    ADDRESS OF NEXT NIB

GTNXNB:	JUMPN T1,GTNXT1		;IF NON-ZERO THEN GET THE NEXT NIB

; HERE TO GET THE FIRST NIB

	HLRZ T1,NODTAB		;GET THE CURRENT LENGTH
	SKIPE T1		;SKIP IF NO NIB'S
	HRRZ T1,NODTAB+1	;GET ADDRESS OF FIRST NIB
	RETSKP			;RETURN

; HERE TO GET OTHER THAN FIRST NIB

GTNXT1:	LOAD T2,NDNAM,(T1)	;GET ASCIZ NODE NAME
	MOVEI T1,NODTAB		;POINT TO TABLE OF NODE NAMES
	TBLUK			;FIND THE ENTRY
	 ERJMP [RETBAD]		;ERROR - RETURN
	TXNN T2,TL%EXM		;EXACT MATCH
	RETBAD			;NO - DISASTER
	MOVEI T3,1(T1)		;BUMP TO NEXT ITEM
	HLRZ T2,NODTAB		;SEE IF NEXT ONE EXISTS
	ADDI T2,NODTAB		;POINT TO END OF TABLE
	HRRZ T1,(T3)		;GET NIB ADDRESS
	CAMG T3,T2		;ARE WE AT THE END
	RETSKP			;NO - RETURN NEXT NIB
	SETZM T1		;YES - SHOW ALL HAVE BEEN RETURNED
	RETSKP
;CHKNIB - CHECK FOR NIB BEING IN TOPOLOGY

;ACCEPTS:	T1/ ADDRESS OF NIB
;		T2/ ADDRESS OF NODE JSYS .NDGNT INFORMATION

;RETURNS:	+1, NIB IN TOPOLOGY
;		+2, NIB NOT IN TOPOLOGY

CHKNIB:	SAVEQ
	MOVEI Q1,.NDBK1(T2)	;POINT TO START OF BLOCK ADDRESSES
	HLRZ T2,.NDNND(T2)	;GET COUNT OF NODES IN PAGE
	JUMPE T2,R		;NO NODES - SHOW BY RETURN
	MOVNS T2		;BUILD THE AOBJN COUNT
	HRL Q1,T2		;...
	LOAD Q2,NDNAM,(T1)	;MOVE NIB NAME POINTER

; HERE TO SEE IF NIB IS IN THE TOPOLOGY

CHKLOP:	MOVE T1,Q2		;MOVE FOR JSYS
	MOVE T2,0(Q1)		;GET ADDRESS OF NODE BLOCK
	MOVE T2,.NDNAM(T2)	;GET POINTER TO NODE NAME
	STCMP			;DO THEY MATCH?
	JUMPE T1,R		;JUMP IF YES
	AOBJN Q1,CHKLOP		;KEEP LOOKING
	RETSKP			;NOT THERE.
;SNDCMD - BUILD AND SEND AN ORION TYPE COMMAND 

;ACCEPTS:	T1/ POINTER TO ASCIZ NODE NAME
;		T2/ .DNDMP/.DNLOA  (FUNCTION CODE FOR DUMP OR LOAD)

;RETURNS:	+1,ERROR
;		+2,OTHERWISE, T1/ADDRESS OF PAGE TO BE SENT TO ORION

SNDCMD:	STKVAR <SNDNAM,SNDHLD,SNDFNC,<SNDBLK,4>>
	MOVEM P2,SNDHLD		;SAVE
	MOVEM T1,SNDNAM		;SAVE THE POINTER TO THE NAME
	MOVEM T2,SNDFNC		;SAVE THE COMMAND FUNCTION
	CALL ASGPAG		;GET A PAGE FOR THE ORION MESSAGE
	 RETBAD			;NO SPACE - ERROR
	MOVEI T4,.OMCMD		;TELL NETCON IT'S  AN OPR COMMAND MESSAGE
	STOR T4,MS.TYP,.MSTYP(T2)	;STORE IN PAGE
	MOVEI T4,200		;[4001]SET COMMAND MESSAGE LENGTH
	STOR T4,MS.CNT,.MSTYP(T2) ;[4001]TOO LARGE VALUE < PAGE
	SETZM .MSCOD(T2)	;ZERO OPR IDENTIFIER
	MOVEI T4,100		;PUT COMMANDS 100 LOCATIONS INTO PAGE
	MOVEM T4,COM.PB(T2)	;PUT IN PROPER FIELD
	MOVEI P2,100(T2)	;POINT TO COMMAND AREA

; BUILT HEADER INFO - NOW START BUILDING COMMANDS. BUILD DUMP/LOAD

	MOVEI T1,.CMKEY		;INDICATE IT'S A KEY WORD
	STOR T1,PBTYP		;INTO TYPE FIELD
	EXCH T2,SNDFNC		;SAVE PAGE ADDRESS - GET FUNCTION TYPE
	STOR T2,PBVAL		;SAVE THE DUMP/LOAD FUNCTION
	MOVEI T1,2		;LENGTH OF BLOCK
	STOR T1,PBLEN		;INTO IT'S FIELD
	ADD P2,T1		;BUMP BASE REG

; DUMP/LOAD REMOTE

	MOVEI T1,.CMKEY		;INDICATE IT'S A KEY WORD
	STOR T1,PBTYP		;INTO TYPE FIELD
	MOVEI T2,.DNNOD		;FUNCTION CODE IS REMOTE
	STOR T2,PBVAL		;SAVE
	MOVEI T1,2		;LENGTH OF BLOCK
	STOR T1,PBLEN		;INTO IT'S FIELD
	ADD P2,T1		;BUMP BASE REG

; DUMP/LOAD REMOTE node name

	MOVEI T1,.CMNOD		;INDICATE IT'S A KEY WORD
	STOR T1,PBTYP		;INTO TYPE FIELD
	MOVE T2,SNDNAM		;GET POINTER TO NODE NAME
	HRROI T1,.PBVAL(P2)	;POINT TO WHERE WE WANT IT TO GO
	SETZ T3,		;COPY WHOLE STRING
	SOUT
	 ERJMP [MOVE T1,SNDFNC	;ERROR - FREE PAGE
		CALL RELPGA
		 NON.FATAL.ERROR
		RETBAD]
	MOVEI T1,<<MAXNOD+12>/5>+2	;INDICATE MAX LENGTH
	STOR T1,PBLEN		;SAVE IN COMMAND BLOCK
	ADD P2,T1		;ADD TO BASE
	;...
	;...

; ADD CONFIRMATION TO LINE

	MOVEI T1,.CMCFM		;GET CRLF CODE
	STOR T1,PBTYP		;INTO TYPE FIELD
	MOVEI T1,2		;LENGTH OF BLOCK
	STOR T1,PBLEN		;INTO IT'S FIELD
	MOVEI T2,SNDBLK		;POINT TO IPCF PDB

; BUILT COMMAND - NOW SEND TO NETCON

	MOVX T1,IP%CFV		;SEND TO NETCON - A WHOLE PAGE
	MOVEM T1,.IPCFL(T2)	;INTO PDB
	MOVE T1,PID		;GET OUR PID
	MOVEM T1,.IPCFS(T2)	;INTO PDB
	MOVEM T1,.IPCFR(T2)	;INTO PDB
	MOVE T1,SNDFNC		;GET PAGE ADDRESS
	LSH T1,-^D9		;MAKE INTO PAGE NUMBER
	HRLI T1,1000		;SHOW IT AS A PAGE MESSAGE
	MOVEM T1,.IPCFP(T2)	;INTO PDB
	MOVEI T1,4		;LENGTH OF PDB
	MSEND			;SEND THE COMMAND
	 RETER2 (.ERR12,<MOVE T1,SNDFNC
			 CALL RELPGA
			  NON.FATAL.ERROR()>)
	MOVE T1,SNDFNC		;GET PAGE TO RELEASE
	CALL RELPGA		;RELEASE IT
	 NON.FATAL.ERROR
	RETSKP			;SUCCESS
SUBTTL	Network Topology Monitoring Routines

;PRUNE - ROUTINE TO PRUNE THE TOPOLOGY OF NODES NO LONGER PRESENT
;
;ACCEPTS IN T1/	POINTER TO ASCIZ NODE NAME FROM WHICH UPDATED INFO CAME
;	    T2/	ADDRESS OF UPDATED NODE LIST FROM THAT NODE
;		CALL PRUNE
;RETURNS: +1 ALWAYS, TOPOLOGY TABLES UPDATED

PRUNE:	SAVEPQ
	ASUBR <PRUNOD,PRUNEW,PRUOLD>

; SET UP TO LOOP OVER EACH NODE IN THE OLD NODE LIST

	MOVE T1,PRUNOD		;GET POINTER TO NAME OF SOURCE NODE
	CALL FNDLST		;GO GET THIS NODE'S OLD NODE LIST
	 RET			;NO LIST-- NO NODES TO PRUNE
	MOVEM T1,PRUOLD		;SAVE ADDRESS OF OLD NODE LIST
	HLRZ P1,(T1)		;GET NUMBER OF ITEMS IN NODE LIST
	MOVN P1,P1		;GET -NUMBER OF ITEMS
	MOVS P1,P1		;GET -NUMBER OF ITEMS,,0
	HRRI P1,1(T1)		;FORM AOBJN POINTER TO OLD NODE LIST

; LOOP OVER EACH NODE IN THE OLD NODE LIST

PRU020:	MOVE T1,PRUNEW		;GET ADDRESS OF NEW NODE LIST
	HLRZ T2,(P1)		;GET ADDRESS OF NODE NAME FROM OLD LIST
	HRLI T2,(POINT 7,)	;FORM POINTER TO NODE NAME FROM OLD LIST
	CALL REMOVE		;REMOVE FROM TOPOLOGY IF NEEDED
	AOBJN P1,PRU020		;NO, CHECK NEXT NODE IN OLD LIST

; REPLACE THE OLD NODE LIST WITH THE NEW NODE LIST

	MOVE T1,PRUOLD		;GET ADDRESS OF OLD NODE LIST
	MOVE T2,PRUNEW		;GET ADDRESS OF NEW NODE LIST
	CALL SWPLST		;GO REPLACE OLD LIST WITH NEW LIST
	RET			;DONE, RETURN
;REMOVE - ROUTINE TO REMOVE A NODE FROM THE TOPOLOGY TABLES
;
;ACCEPTS IN T1/	POINTER TO ASCIZ NODE NAME TO REMOVE
;		CALL REMOVE
;RETURNS: +1 ALWAYS

REMOVE:	ASUBR <RMVNOD>

; REMOVE THE NODE FROM THE MONITOR'S DATABASE

	MOVE T1,RMVNOD		;GET POINTER TO ASCIZ NODE NAME
	CALL MONDEL		;DELETE THE NODE FROM MONITOR

; SEE IF ANY OTHER NODES MUST ALSO BE DELETED

	MOVE T1,RMVNOD		;GET POINTER TO ASCIZ NODE NAME
	CALL TSTTOP		;DOES THIS NODE HAVE A NODE LIST ?
	 RET			;NO, SO NO OTHER NODES TO DELETE
;MONDEL - ROUTINE TO DELETE A NODE FROM THE MONITOR'S DATABSE
;
;ACCEPTS IN T1/	POINTER TO ASCIZ NODE NAME
;		CALL MONDEL
;RETURNS: +1 ALWAYS

MONDEL:	STKVAR <<MNDBLK,20>>
	MOVEI T2,MNDBLK		;GET ADDRESS OF ARGUMENT BLOCK
	MOVEI T4,1		;ONE NODE TO REMOVE
	MOVEM T4,.NDNND(T2)	;STORE NUMBER OF NODE BLOCKS
	MOVEI T4,.NDNBS		;GET SIZE OF A NODE BLOCK
	MOVEM T4,.NDCNT(T2)	;SAVE IN ARG BLOCK
	MOVEI T4,.NDBK1+1(T2)	;GET ADDRESS OF THE NODE BLOCK
	MOVEM T4,.NDBK1(T2)	;STORE IN ARG BLOCK
	MOVEM T1,.NDNAM(T4)	;STORE POINTER TO NODE NAME
	MOVEI T3,.NDSOF		;STATE IS NOW OFF
	MOVEM T3,.NDSTA(T4)	;STORE STATE INDICATING "REMOVE NODE FROM LIST"
	SETZM .NDNXT(T4)	;NO SOURCE NODE NAME
	MOVEI T1,.NDSNT		;GET "SET NETWORK TOPOLOGY" FUNCTION
	NODE			;REMOVE NODE FROM TABLE OF KNOWN NODES
	 ERJMP R		;FAILED
	RET			;DONE, RETURN
;SWPLST - ROUTINE TO REPLACE AN OLD NODE LIST WITH A NEW NODE LIST
;
;ACCEPTS IN T1/	ADDRESS OF OLD NODE LIST
;	    T2/	ADDRESS OF NEW NODE LIST
;	    T3/	POINTER TO ASCIZ NODE NAME
;		CALL SWPLST
;RETURNS: +1 ALWAYS, NEW LIST SAVED AND OLD LIST RELEASED

SWPLST:	ASUBR <SWLOLD,SWLNEW,SWLNOD,SWLENT>

; DELETE OLD LIST AND RELEASE THE SPACE

	LOCK TOPTAB		;LOCK THE MASTER TABLE OF LISTS
	MOVE T1,TOPTAB		;GET ADDRESS OF TABLE OF NODE LISTS
	MOVE T2,SWLNOD		;GET POINTER TO NODE NAME
	TBDEL			;DELETE THE ENTRY
 	 ERJMP SWL010		;FAILED, JUST INSERT NEW LIST
	MOVE T1,SWLOLD		;GET ADDRESS OF OLD LIST
	SUBI T1,1		;POINT TO BLOCK HEADER
	CALL RELFRE		;RELEASE THE LIST
	 FATAL.ERROR		;FAILED

; STORE THE NEW NODE LIST

SWL010:	MOVE T4,SWLNOD		;GET POINTER TO ASCIZ NODE NAME
	IBP T4			;INCREMENT AND DECREMENT THE POINTER IN
	MOVNI T3,1		; CASE IT WAS POINTING TO THE WORD JUST
	ADJBP T3,T4		; BEFORE THE NAME.
	HRLZ T2,T3		;GET ADR OF NAME,,0
	HRR T2,SWLNEW		;GET ADDRESS OF NEW NODE LIST
	MOVE T1,TOPTAB		;GET ADDRESS OF TABLE OF NODE LISTS
	TBADD			;PUT THE NEW NODE LIST IN THE TABLE
	 ERJMP .+1		;FAILED
	UNLOCK TOPTAB		;UNLOCK THE TABLE
	RETSKP			;DONE, RETURN
;FNDLST - ROUTINE TO FIND A NODE'S NODE LIST
;
;ACCEPTS IN T1/	POINTER TO ASCIZ NODE NAME
;		CALL FNDLST
;RETURNS: +1	 FAILED, NODE NOT IN TOPTAB
;	  +2	SUCCESS, WITH T1/ ADDRESS OF NODE LIST

FNDLST:	MOVE T2,T1		;COPY POINTER TO NODE NAME
	MOVEI T1,TOPTAB		;GET ADDRESS OF NODE LIST TABLE
	TBLUK			;FIND THE ENTRY FOR THIS NODE
	 ERJMP R		;FAILED, CANNOT RETURN NODE LIST
	HRRZ T1,(T1)		;GET ADDRESS OF NODE LIST FOR THIS NODE
	RETSKP			;DONE, RETURN SUCCESS
;TSTTOP - ROUTINE TO SEE IF A NODE IS IN TOPTAB
;
;ACCEPTS IN T1/	POINTER TO ASCIZ NODE NAME
;		CALL TSTTOP
;RETURNS: +1	 NODE NOT IN TOPTAB
;	  +2	NODE IS IN TOPTAB AND HAS ITS OWN NODE LIST

; A NODE IS PLACE INTO TOPTAB WHEN NETCON SUCCESSFULLY GETS A NODE
; LIST FROM THE TOPOLOGY TASK IN THE NODE.

TSTTOP:	MOVE T2,T1		;COPY POINTER TO ASCIZ NODE NAME
	MOVEI T1,TOPTAB		;TOPTAB IS ITSELF JUST A NODE LIST
	CALL NODCHK		;IS THE SPECIFIED NODE IN TOPTAB ?
	 RETSKP			;NODE IS IN TOPTAB
	RET			;NODE IS NOT IN TOPTAB
;NODCHK - ROUTINE TO CHECK TO SEE IF A NODE IS IN A NODE LIST
;
;ACCEPTS IN T1/	ADDRESS OF NODE LIST
;	    T2/	POINTER TO ASCIZ NODE NAME TO CHECK
;		CALL NODCHK
;RETURNS: +1	 NODE IS IN THE NODE LIST
;	  +2	NODE IS NOT IN THE NODE LIST

NODCHK:	TBLUK			;SEE IF THE NODE IS IN THE NODE LIST
	 ERJMP RSKP		;FAILED, ASSUME NOT IN LIST
	TXNN T3,TL%EXM		;EXACT MATCH ?
	RETSKP			;NO, NOT IN LIST
	RET			;YES, NODE IS IN THE NODE LIST
;TOPCHK - ROUTINE TO DETERMINE IF TOPOLOGY MONITORING SHOULD BE
;	  INITIATED TO A SPECIFIED NODE.
;
;ACCEPTS IN T1/	POINTER TO ASCIZ NODE NAME
;		CALL TOPCHK
;RETURNS: +1	 DO NOT INITIATE TOPOLOGY MONITORING
;	  +2	NODE IS ADJACENT DN20, INITIATE TOPOLOGY MONITORING

TOPCHK::ASUBR <CKTNOD>

; GET THE SPECIFIED NODE'S NIB

	MOVE T1,CKTNOD		;GET POINTER TO ASCIZ NODE NAME
	CALL GETNIB		;GET THE NODE INFORMATION BLOCK
	 RETBAD ()		;FAILED, RETURN "DO NOT INITIATE"

; SEE IF MONITORING SHOULD BE STARTED BASED ON WHETHER OR NOT THE
; SPECIFIED NODE IS A DN20.

	LOAD T1,NDSRV,(T1)	;GET POINTER TO ASCIZ SERVER NODE NAME
	HRROI T2,OURNAM		;GET POINTER TO OUR NODE NAME
	STCMP			;ARE WE THE SERVER FOR THIS NODE ?
	 ERJMP R		;FAILED, RETURN "DO NOT INTITIATE"
	JUMPE T1,RSKP		;WE ARE THE SERVER, INITIATE MONITORING
	RET			;WE ARE NOT SERVER, MUST NOT BE A DN20
;MONINI - ROUTINE TO INITIALIZE NETWORK TOPOLOGY MONITORING FROM A NODE
;
;ACCEPTS IN T1/	POINTER TO NODE NAME
;		CALL MONINI
;RETURNS: +1	 FAILED
;	  +2	SUCCESS

MONINI::ASUBR <MNINOD,MNIIDX,MNIPAG,MNIERR>
	STKVAR <<MNIHLD,2>,MNIHST,MNILST,MNILNK>

; CONNECT A LOGICAL LINK TO THE TOPOLOGY CHANGE NOTIFIER TASK

	MOVE T1,MNINOD		;GET POINTER TO NODE NAME
	CALL TOPLNK		;GET LINK TO TASK
	 RET			;FAILED
	MOVEM T1,MNILNK		;SAVE DCN: LINK TO TOPOLOGY TASK IN DN20

; SEND THE REQUEST FOR TOPOLOGY CHANGE NOTIFICATIONS

	MOVE T1,MNILNK		;GET DCN: LINK TO TOPOLOGY TASK
	MOVE T2,[ POINT 8,[ BYTE(8) .TPREQ, .TPVER, 1, 0, 0 ]]
	MOVNI T3,5		;FIVE BYTES
	SOUTR			;SEND REQUEST
	 ERJMP [MOVE T1,MNILNK	;FAILED, GET DCN: LINK TO TOPOLOGY TASK
		TXO T1,CZ%ABT	;DO ABORT CLOSE
		CLOSF		;RELEASE THE LINK
		 NON.FATAL.ERROR
		RETBAD (.NRNCE)] ;RETURN FAILURE

; RECEIVE THE RESPONSE FROM THE TOPOLOGY CHANGE TASK

	MOVE T1,MNILNK		;GET DCN: LINK TO TOPOLOGY TASK
	MOVE T2,MNINOD		;GET POINTER TO ASCIZ NODE NAME
	CALL RCVTOP		;GET & PROCESS REPLY FROM TOPOLOGY TASK
	 JRST [	MOVE T1,MNILNK	;FAILED, GET DCN: LINK TO TOPOLOGY TASK
		TXO T1,CZ%ABT	;DO ABORT CLOSE
		CLOSF		;RELEASE THE LINK
		 NON.FATAL.ERROR
		RETBAD (.NRNCE)] ;RETURN FAILURE

; RELEASE THE DCN: LINK TO THE TOPOLOGY TASK

	MOVE T1,MNILNK		;GET DCN: LOGICAL LINK
	CLOSF			;RELEASE THE LINK
	 NON.FATAL.ERROR	;FAILED

; RETURN TO CALLER

	RETSKP			;DONE, RETURN SUCCESS
;RCVTOP - ROUTINE TO RECEIVE AND PROCESS REPLY FROM TOPOLOGY TASK
;
;ACCEPTS IN T1/	JFN OF DCN: LINK TO TOPOLOGY TASK
;	    T2/	POINTER TO ASCIZ NODE NAME
;		CALL RCVTOP
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, MONITOR ADVISED OF TOPOLOGY INFO

RCVTOP:	ASUBR <RTPLNK,RTPHST,RTPPAG,RTPERR>

; ASSIGN A PAGE FOR RECEIPT OF REPLY MSG FROM TOPOLOGY TASK

	CALL ASGPAG		;GET SPACE FOR THE RESPONSE
	 RETBAD ()		;FAILED
	MOVEM T2,RTPPAG		;SAVE PAGE NUMBER

; RECEIVE THE REPLY MESSAGE CONTAINING THE TOPOLOGY INFO

	MOVE T1,RTPLNK		;GET DCN: LINK TO TOPOLOGY TASK
	MOVE T2,RTPPAG		;GET ADDRESS OF MESSAGE PAGE
	HRLI T2,(POINT 8,)	;FORM POINTER TO WHERE DATA IS TO GO
	MOVNI T3,4000		;MAX ONE PAGE OF DATA
	SINR			;GET TOPOLOGY TASK'S REPLY
	 ERJMP RTPINX		;FAILED, GO RELEASE ASSIGNED PAGE

; PARSE INITIAL PART OF REPLY FROM TOPOLOGY TASK

	MOVEI T2,4000(T3)	;COMPUTE NUMBER OF BYTES IN RESPONSE
	MOVE T1,RTPPAG		;GET PAGE ADDRESS WHERE DATA IS
	HRLI T1,(POINT 8,)	;FORM POINTER TO RESPONSE
	CALL CHKTOP		;GO CHECK INITIAL PART OF TOPOLOGY MESSAGE
	 JRST RTPINX		;FAILED, GO CLEAN UP

; ADVISE MONITOR OF TOPOLOGY AS PER REMAINDER OF MESSAGE

	MOVE T3,RTPHST		;GET POINTER TO ASCIZ NODE NAME
	CALL ADVTOP		;ADVISE MONITOR OF NEW NODES IN NETWORK
	 JRST RTPINX		;FAILED
	PUSH P,T1		;Save address of node topology table
	CALL UPDNOD		;Update monitor's list for deleted nodes
	 JRST [POP P,T1		; Get node table address
	       EXCH T1,TOPTAB	; Save address of node list
	       CALL TOPFRE	; Release old topology table
	       JRST RTPINX]	; Failed to update monitor's list
	POP P,T1		;Get node table address back
	EXCH T1,TOPTAB		;Save address of node list
	CALL TOPFRE		;Release the old topology table

; RELEASE PAGE USED FOR MESSAGE

	MOVE T1,RTPPAG		;GET PAGE ADDRESS
	CALL RELPGA		;RELEASE THE PAGE
	 NON.FATAL.ERROR	;FAILED

; RETURN SUCCESS

	RETSKP			;DONE, RETURN

; HERE ON AN ERROR - RELEASE PAGE FOR MESSAGE AND RETURN FAILURE

RTPINX:	MOVEM T1,RTPERR		;SAVE ERROR CODE
	MOVE T1,RTPPAG		;GET PAGE NUMBER
	CALL RELPGA		;RELEASE THE PAGE
	 NON.FATAL.ERROR	;FAILED
	MOVE T1,RTPERR		;RESTORE ERROR CODE
	RET			;FAIL
;TOPLNK - ROUTINE TO GET A LOGICAL LINK TO THE TOPOLOGY CHANGE NOTIFIER TASK
;
;ACCEPTS IN T1/	POINTER TO NODE NAME
;		CALL TOPLNK
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, WITH T1/ JFN FOR DCN: LOGICAL LINK

TOPLNK:	SAVEPQ
	STKVAR <TPLNOD,<TPLSTR,20>,TPLLNK>

; GET A LOGICAL LINK TO THE TOPOLOGY TASK ON THE INDICATED NODE

	MOVEM T1,TPLNOD		;SAVE POINTER TO NODE NAME
	HRROI T1,TPLSTR		;GET POINTER TO WHERE STRING BEING ASSEMBLED
	HRROI T2,[ASCIZ/DCN:/]	;GET POINTER TO FIRST PART OF STRING
	SETZM T3		;TERMINATE ON NULL
	SOUT			;ASSEMBLE INITIAL PART OF TEXT
	 ERJMP R		;FAILED, RETURN ERROR
	MOVE T2,TPLNOD		;GET POINTER TO NODE NAME
	SOUT			;ADD NODE NAME TO STRING
	 ERJMP R		;FAILED, RETURN ERROR
	HRROI T2,[ASCIZ/-TASK-TOPOL.TOPOL/] ;GET REMAINDER OF TASK NAME
	SOUT			;ADD TASK NAME TO STRING
	 ERJMP R		;FAILED, RETURN ERROR
	MOVX T1,GJ%SHT		;SHORT CALL
	HRROI T2,TPLSTR		;GET POINTER TO STRING
	GTJFN			;GET A LOGICAL LINK TO TOPOLOGY TASK
	 ERJMP R		;FAILED, RETURN ERROR
	MOVEM T1,TPLLNK		;SAVE LOGICAL LINK
	MOVE T2,[100000,,300000] ;8 BIT BYTES, READ AND WRITE ACCESS
	OPENF			;OPEN THE FILE
	 ERJMP [MOVE T1,TPLLNK	;FAILED, GET JFN AGAIN
		RLJFN		;RELEASE JFN
		 JFCL		;IGNORE ERROR HERE
		RET ]		;RETURN FAILURE
	MOVSI P1,-^D12		;CHECK FOR ONE MINUTE
TPL010:	MOVE T1,TPLLNK		;GET LOGICAL LINK
	MOVX T2,.MORLS		;READ LINK STATUS
	MTOPR			; TO SEE IF CONNECTED YET
	TXNE T3,MO%CON		;CONNECTED ?
	JRST TPL050		;YES, GO RETURN TABLE INDEX
	MOVX T1,^D5*^D1000	;WAIT TIME IS FIVE SECONDS
	DISMS			; AND THEN CHECK AGAIN
	AOBJN P1,TPL010		;GO CHECK TO SEE IF LINK IS CONNECTED YET

	MOVE T1,TPLLNK		;No .. we have failed
	TXO T1,CZ%ABT		;Set abort flag
	CLOSF			;Close the link
	 NON.FATAL.ERROR	; Tell anyone interested about CLOSE failure
	RETBAD (.NRNCE)		;FAILED

TPL050:	MOVE T1,TPLLNK		;GET DCN: LINK TO TOPOLOGY TASK
	RETSKP			;DONE, RETURN SUCCESS
; UPDNOD - ROUTINE TO REMOVE NODES NO LONGER PRESENT FROM MONITOR DATABASE
;
;ACCEPTS IN T1/	ADDRESS OF NEW NODE LIST
;		CALL UPDNOD
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, NEW NODE LIST SAVED AS CURRENT LIST

UPDNOD:	ASUBR <UPNLST,UPNPAG>
	SAVEPQ

; OBTAIN OLD NODE LIST FROM MONITOR

	CALL ASGPAG		;ASSIGN A PAGE FOR THE OLD LIST
	 RETBAD ()		;FAILED
	MOVEM T2,UPNPAG		;SAVE PAGE ADDRESS
	MOVEM T2,T1		;COPY DESTINATION ADR FOR NODE LIST
	CALL TOPLGY		;OBTAIN MONITOR'S CURRENT LIST
	 JRST [	EXCH T1,UPNPAG	;SAVE ERROR CODE, GET PAGE ADDESS
		CALL RELPGA	;RELEASE THE PAGE
		 NON.FATAL.ERROR
		MOVE T1,UPNPAG	;RESTORE ERROR CODE
		RETBAD () ]	;FAILED

; FORM AOBJN POINTER TO ITEMS IN THE OLD NODE LIST

	MOVE T4,UPNPAG		;GET ADR OF OLD NODE INFO
	HLRZ Q3,.NDNND(T4)	;GET NUMBER OF NODES IN LIST
	JUMPE Q3,UPND30		;IF NONE, GO RELEASE PAGE AND DONE
	MOVNS Q3		;GET -SIZE OF LIST
	HRLZ Q3,Q3		;GET -SIZE,,0
	HRRI Q3,.NDBK1(T4)	;FORM AOBJN POINTER TO ITEMS IN OLD LIST

; LOOP OVER EACH ITEM IN OLD LIST - REMOVE FROM MONITOR DATABASE IF NOT HERE NOW

UPND10:	MOVE T1,UPNLST		;GET ADDRESS OF NEW NODE LIST
	HRRZ T2,(Q3)		;GET ADDRESS OF A NODE BLOCK
	MOVE T2,.NDNAM(T2)	;GET POINTER TO NODE NAME
	TBLUK			;IS THIS NODE STILL PRESENT ?
	 ERJMP UPND20		;FAILED, GO ON TO NEXT ITEM IN LIST
	TXNE T2,TL%EXM		;EXACT MATCH ?
	JRST UPND20		;YES, NODE STILL THERE, DO NOT REMOVE IT

; NODE NO LONGER ACCESSIBLE - REMOVE IT FROM MONITOR'S DATABASE

	HRRZ T1,(Q3)		;GET ADDRESS OF NODE BLOCK
	MOVE T1,.NDNAM(T1)	;GET POINTER TO NODE NAME
	CALL MONDEL		;REMOVE NODE FROM MONITOR'S LIST

UPND20:	AOBJN Q3,UPND10		;LOOP OVER ALL NODES IN OLD LIST
	;..
	;..

; HERE TO RELEASE PAGE WITH OLD NODE LIST

UPND30:	MOVE T1,UPNPAG		;GET PAGE ADDRESS
	CALL RELPGA		;RELEASE THE PAGE
	 NON.FATAL.ERROR	;FAILED
	RETSKP			;DONE, RETURN SUCCESS
; FRELST - ROUTINE TO FREE A NODE LIST
;
;ACCEPTS IN T1/ ADDRESS OF NODE LIST
;		CALL FRELST
;RETURNS: +1	 FAILED
;	  +2	SUCCESS

FRELST::ASUBR <FRLLST>
	SAVEPQ

; FORM AOBJN POINTER TO NODE LIST ENTRIES

	SKIPN T1,FRLLST		;GET ADDRESS OF NODE LIST
	RETSKP			;DONE IF NO NODE LIST
	HLRZ P1,(T1)		;GET # OF NODES IN LIST
	JUMPE P1,FRL020		;IF NO ENTRIES, JUST GO RELEASE LIST
	MOVN P1,P1		;GET -NUMBER OF NODES
	HRLS P1			;GET -NUMBER OF NODES,,0
	HRRI P1,1(T1)		;FORM AOBJN POINTER TO NODE LIST

; LOOP OVER EACH NODE IN LIST, RETURNING FREE BLOCK

FRL010:	HLRZ T1,(P1)		;GET ADDRESS OF A NODE NAME
	SUBI T1,1		;POINT TO START OF BLOCK
	CALL RELFRE		;RELEASE THE BLOCK
	 FATAL.ERROR		;FAILED, ISSUE MESSAGE AND CONTINUE
	AOBJN P1,FRL010		;LOOP OVER EACH ITEM IN NODE LIST

; RELEASE THE NODE LIST ITSELF

FRL020:	MOVE T1,FRLLST		;GET ADDRESS OF NODE LIST
	SUBI T1,1		;POINT TO START OF BLOCK
	CALL RELFRE		;RELEASE THE LIST
	 FATAL.ERROR		;FAILED, ISSUE MESSAGE AND CONTINUE
	RETSKP			;DONE, RETURN SUCCESS
;CHKTOP - ROUTINE TO CHECK INITIAL PART OF FIRST MESSAGE FROM TOPOLOGY TASK
;
;ACCEPTS IN T1/	POINTER TO FIRST FIELD IN TOPOLOGY MESSAGE
;	    T2/ NUMBER OF BYTES IN TOPOLOGY MESSAGE
;		CALL CHKTOP
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, WITH T1/ UPDATED POINTER TO NEXT FIELD IN MESSAGE
;			      T2/ UPDATED COUNT OF BYTES REMAINING IN MESSAGE

CHKTOP:	SUBI T2,5		;AT LEAST MESSAGE TYPE AND VERSION PRESENT ?
	JUMPL T2,R		;NO, RETURN ERROR
	ILDB T3,T1		;YES, GET MESSAGE TYPE
	CAIE T3,.TPACC		;REQUEST ACCEPTED ?
	RET			;NO, FAIL
	ILDB T3,T1		;GET FIELD TYPE
	CAIE T3,.TPVER		;VERSION FIELD ?
	RET			;NO, FAIL
	ILDB T3,T1		;VERSION INFO
	ILDB T4,T1		; OK ?
	CAIN T3,1		;SHOULD BE VERSION
	CAIE T4,0		; 1.0.0
	RET			;NOT CORRECT VERSION
	ILDB T3,T1		;GET LAST VERSION BYTE
	CAIE T3,0		;LAST BYTE OK ?
	RET			;NO, FAIL
	RETSKP			;DONE, RETURN SUCCESS
; ENTRY VECTOR DEFINITION

ENTVEC:	JRST NETCON		;MAIN ENTRY POINT
	JRST NETCON		;REENTER ENTRY POINT
	EXP VNETCON		;VERSION OF NETCON PROGRAM


	END <3,,ENTVEC>