Google
 

Trailing-Edge - PDP-10 Archives - BB-M080E-SM - monitor-sources/nspsrv.mac
There are 31 other files named nspsrv.mac in the archive. Click here to see a list.
;Edit 3029 to NSPSRV.MAC by GRANT on Thu 13-Oct-83
;		In STRMSG, make sure it's really node init
;Edit 2985 to NSPSRV.MAC by WEETON on Tue 5-Jul-83
;		Keep large networks from causing ILMNRFs
;Edit 2963 to NSPSRV.MAC by LOMARTIRE on Thu 19-May-83
;		In NSPTM5, retrieve message address earlier
;Edit 2962 to NSPSRV.MAC by LOMARTIRE on Tue 10-May-83, for SPR #19025
;		Use SIZ39 in GTSBLK - prevents ILMNRF from clobbered free space
;Edit 2940 by COBB on Tue 29-Mar-83 - FIX TYPO IN 2935
;EDIT 2940 - Fix TYPO in 2935
;EDIT 2935 - In DCDCS, fix management of LL block lock
;<COBB.5-1-MAINTENANCE>AM51-NSPSRV.MAC.26, 22-Mar-83 13:52:04, Edit by COBB
;EDIT 2934 - Make ONSRVQ and UNQSRV run NOSKED
;<COBB.5-1-MAINTENANCE>AM51-NSPSRV.MAC.23, 22-Mar-83 13:44:06, Edit by COBB
;EDIT 2933 - In INTLS, remove setting of inactivity timer.  In INACOR, reorder
; the tests to make elimination faster.
;<COBB.5-1-MAINTENANCE>AM51-NSPSRV.MAC.20, 22-Mar-83 10:56:09, Edit by COBB
;EDIT 2932 - rewrite part of incoming CI message processing and modify BADNOD
;<COBB.5-1-MAINTENANCE>AM51-NSPSRV.MAC.15, 22-Mar-83 10:38:02, Edit by COBB
;EDIT 2931 - redo the logic in ACKRUN and DATRUN
;<COBB.5-1-MAINTENANCE>AM51-NSPSRV.MAC.12, 22-Mar-83 10:26:37, Edit by COBB
;EDIT 2930 - add missing OKINT in DCDCS
;<COBB.5-1-MAINTENANCE>AM51-NSPSRV.MAC.9, 22-Mar-83 10:16:32, Edit by COBB
;EDIT 2929 - remove extraneous instruction at MTSNIN
;<COBB.5-1-MAINTENANCE>AM51-NSPSRV.MAC.8, 22-Mar-83 10:11:01, Edit by COBB
;EDIT 2927 - rewrite CHKSCT
; UPD ID= 92, SNARK:<5.1.MONITOR>NSPSRV.MAC.18,  12-Nov-82 14:06:06 by GRANT
;TCO 5.1.1105 - Eliminate some unused internal links code
; UPD ID= 84, SNARK:<5.1.MONITOR>NSPSRV.MAC.17,   2-Nov-82 11:54:42 by GRANT
;TCO 5.1.1100 - release swappable block in CLRBLK
; UPD ID= 83, SNARK:<5.1.MONITOR>NSPSRV.MAC.16,   2-Nov-82 11:15:02 by GRANT
;Minor fix to TCO 5.1.1089
; UPD ID= 79, SNARK:<5.1.MONITOR>NSPSRV.MAC.15,  11-Oct-82 10:01:06 by GRANT
;TCO 5.1.1092 - Change a few IFNSK. to IFSKP.
; UPD ID= 74, SNARK:<5.1.MONITOR>NSPSRV.MAC.14,   9-Oct-82 10:17:51 by GRANT
;TCO 5.1.1089 - Rewrite MCBCQ, process link IDs rather than LL blocks
; UPD ID= 72, SNARK:<5.1.MONITOR>NSPSRV.MAC.13,   8-Oct-82 09:24:27 by GRANT
;TCO 5.1.1087 - Add call to DELNOD in NSPTMO
; UPD ID= 71, SNARK:<5.1.MONITOR>NSPSRV.MAC.12,   8-Oct-82 08:54:04 by GRANT
;TCO 5.1.1086 - In RELLNK and DEDMCB, lock LL tree before calling DELNOD
; UPD ID= 70, SNARK:<5.1.MONITOR>NSPSRV.MAC.11,   7-Oct-82 13:34:02 by GRANT
;TCO 5.1.1085 - In UNQSEG, stop incorrect removal from the resend queue
; UPD ID= 67, SNARK:<5.1.MONITOR>NSPSRV.MAC.10,   6-Oct-82 08:52:33 by GRANT
;TCO 5.1.1074 - Add debugging code for verifying logical link blocks
; UPD ID= 60, SNARK:<5.1.MONITOR>NSPSRV.MAC.9,   1-Oct-82 17:43:28 by GRANT
;TCO 5.1.1080 - In NSPMSG, toss messages which have LLDED set
; UPD ID= 59, SNARK:<5.1.MONITOR>NSPSRV.MAC.8,   1-Oct-82 14:29:34 by GRANT
;TCO 5.1.1079 - Use MOVE instead of LOAD in NSPNXT
; UPD ID= 53, SNARK:<5.1.MONITOR>NSPSRV.MAC.7,  28-Sep-82 19:07:10 by GRANT
;TCO 5.1.1072 - don't retransmit data segments when flow is turned off
; UPD ID= 47, SNARK:<5.1.MONITOR>NSPSRV.MAC.6,  23-Sep-82 12:04:32 by GRANT
;TCO 5.1.1067 - Don't send a disconnect when a link times out
; UPD ID= 46, SNARK:<5.1.MONITOR>NSPSRV.MAC.5,  23-Sep-82 09:23:34 by GRANT
;TCO 5.1.1066 - If link has been aborted, have synchronous CLOSF return success
; UPD ID= 44, SNARK:<5.1.MONITOR>NSPSRV.MAC.4,  21-Sep-82 13:16:30 by GRANT
;TCO 5.1.1063 - In NSNSCH, return characteristics by parameter number
; UPD ID= 43, SNARK:<5.1.MONITOR>NSPSRV.MAC.3,  21-Sep-82 10:50:00 by GRANT
;Fix bug in SNDCTL introduced by an incorrect test in TCO 5.1.1057
; UPD ID= 42, SNARK:<5.1.MONITOR>NSPSRV.MAC.2,  14-Sep-82 12:28:31 by MCINTEE
;TCO 5.1.1061 - Change routine NDGNT to not use so much stack.
; UPD ID= 38, SNARK:<5.1.MONITOR>NSPSRV.MAC.5,  30-Aug-82 14:03:08 by MCINTEE
;TCO 5.1.1058 - Change error message in MTOBJ1
; UPD ID= 36, SNARK:<5.1.MONITOR>NSPSRV.MAC.4,  27-Aug-82 07:02:36 by GRANT
;TCO 5.1.1057 - make proper check for remote node's NSP version
; UPD ID= 34, SNARK:<5.1.MONITOR>NSPSRV.MAC.3,  25-Aug-82 11:49:52 by GRANT
;TCO 5.1.1055 - check for CC sent state in MTRDCK
; UPD ID= 33, SNARK:<5.1.MONITOR>NSPSRV.MAC.2,  25-Aug-82 10:08:46 by GRANT
;TCO 5.1.1054 - prevent CLZRUN from wrongly sending 0-length data messages
; UPD ID= 32, SNARK:<5.1.MONITOR>NSPSRV.MAC.19,  18-Aug-82 09:21:15 by GRANT
;TCO 5.1692 - incorrect test at SQI4
; UPD ID= 31, SNARK:<5.1.MONITOR>NSPSRV.MAC.18,  17-Aug-82 09:50:49 by GRANT
;TCO 5.1.1053 - make NTRNAM return updated user BP to its caller
; UPD ID= 29, SNARK:<5.1.MONITOR>NSPSRV.MAC.17,  10-Aug-82 11:57:17 by GRANT
;TCO 5.1.1051 - Change RETBAD to JRST SRCFAL in SRCOPN
; UPD ID= 28, SNARK:<5.1.MONITOR>NSPSRV.MAC.16,  10-Aug-82 11:26:42 by GRANT
;TCO 5.1.1050 - Change RETERR to RET in DCNOPN's GTOKM
; UPD ID= 25, SNARK:<5.1.MONITOR>NSPSRV.MAC.15,  18-Jul-82 13:48:48 by MURPHY
;TCO 5.1.1048 - Check LLTTA when closing; keep LL block locked until return
;  from TTSETH.
; UPD ID= 21, SNARK:<5.1.MONITOR>NSPSRV.MAC.14,  13-Jul-82 10:51:11 by GRANT
;TCO 5.1.1045 - In NTSNH, unlock LL block when call to TTYSRV fails
; UPD ID= 19, SNARK:<5.1.MONITOR>NSPSRV.MAC.13,   6-Jul-82 09:24:35 by GRANT
;TCO 5.1.1042 - Make NSLDWS resident
; UPD ID= 16, SNARK:<5.1.MONITOR>NSPSRV.MAC.12,  30-Jun-82 09:19:55 by GRANT
;Fix edit history - change TCO 6.1153 to TCO 5.1.1040
; UPD ID= 14, SNARK:<5.1.MONITOR>NSPSRV.MAC.11,  30-Jun-82 08:37:03 by GRANT
;TCO 5.1.1037 - setting local node number requires privileges
; UPD ID= 12, SNARK:<5.1.MONITOR>NSPSRV.MAC.10,  17-Jun-82 09:44:20 by GRANT
;TCO 5.1.1035 - make interrupt messages work again
; UPD ID= 8, SNARK:<5.1.MONITOR>NSPSRV.MAC.9,   8-Jun-82 08:21:51 by GRANT
;Rewrite UNQSEG
; UPD ID= 7, SNARK:<5.1.MONITOR>NSPSRV.MAC.8,   7-Jun-82 16:53:06 by GRANT
;More fixing of TCO 5.1.1022
; UPD ID= 6, SNARK:<5.1.MONITOR>NSPSRV.MAC.7,   7-Jun-82 08:04:44 by GRANT
;TCO 5.1.1033 - Return proper error message in NANUE2
; UPD ID= 5, SNARK:<5.1.MONITOR>NSPSRV.MAC.6,   7-Jun-82 06:58:15 by GRANT
;TCO 5.1.1040 - Fix protocol error of sending data before LS ACK
; UPD ID= 590, SNARK:<5.MONITOR>P3-NSPSRV.MAC.55,   4-Jun-82 21:43:18 by GRANT
;Fix bug in TCO 5.1.1022 change - RESBAZ and RESCHK problems fixed
; UPD ID= 589, SNARK:<5.MONITOR>P3-NSPSRV.MAC.54,   4-May-82 11:55:06 by GRANT
;TCO 5.1.1032 - turn off LLNLS and LLALS in ACKLI not in SNDACK
; UPD ID= 587, SNARK:<5.MONITOR>P3-NSPSRV.MAC.53,  30-Apr-82 13:24:01 by GRANT
;TCO 5.1.1031 - make NTMAN% set and read retransmit factor
; UPD ID= 585, SNARK:<5.MONITOR>P3-NSPSRV.MAC.52,  28-Apr-82 10:36:35 by GRANT
;TCO 5.1.1029 - Process all incoming, non-control messages at scheduler level
; UPD ID= 584, SNARK:<5.MONITOR>P3-NSPSRV.MAC.51,  22-Apr-82 13:40:44 by GRANT
;TCO 5.1.1028 - apply Local Delay Factor in proper place
; UPD ID= 580, SNARK:<5.MONITOR>P3-NSPSRV.MAC.50,  16-Apr-82 12:24:33 by GRANT
;TCO 5.1.1027 - Unlock LL block when CALL ASMCB fails
; UPD ID= 579, SNARK:<5.MONITOR>P3-NSPSRV.MAC.49,  16-Apr-82 07:44:16 by GRANT
;TCO 5.1.1026 - Let background task wake up whenever it has a message to process
; UPD ID= 576, SNARK:<5.MONITOR>P3-NSPSRV.MAC.48,  14-Apr-82 11:12:40 by GRANT
;Performance improvement to TCO 5.1.1022
; UPD ID= 573, SNARK:<5.MONITOR>P3-NSPSRV.MAC.47,  13-Apr-82 15:13:31 by GRANT
;TCO 5.1.1025 - Make Local Delay Factor and Local Delay Weight settable and
;readable by NTMAN%
; UPD ID= 572, SNARK:<5.MONITOR>P3-NSPSRV.MAC.46,  13-Apr-82 14:26:11 by GRANT
;Slight modification to TCO 5.1.1023 - send LS messgae earlier
; UPD ID= 567, SNARK:<5.MONITOR>P3-NSPSRV.MAC.45,   6-Apr-82 10:46:15 by GRANT
;Undo more debugging code
; UPD ID= 566, SNARK:<5.MONITOR>P3-NSPSRV.MAC.44,  31-Mar-82 14:12:28 by GRANT
;TCO 5.1.1024 - Impose a minimum on the round trip calculation
; UPD ID= 564, SNARK:<5.MONITOR>P3-NSPSRV.MAC.43,  31-Mar-82 13:40:41 by GRANT
;TCO 5.1.1023 - Fix free space bug in NETSET
;TCO 5.1.1022 - don't time messages on Phase II links
;More of TCO 5.1.1020
;Remove debugging BUGHLTs
; UPD ID= 560, SNARK:<5.MONITOR>P3-NSPSRV.MAC.42,  23-Mar-82 06:48:09 by GRANT
;Undo previous edit
; UPD ID= 559, SNARK:<5.MONITOR>P3-NSPSRV.MAC.41,  22-Mar-82 11:19:48 by GRANT
;TCO 5.1.1021 - Release message block in DCDCS
; UPD ID= 557, SNARK:<5.MONITOR>P3-NSPSRV.MAC.40,  21-Mar-82 18:22:12 by GRANT
;TCO 5.1.1020 - NAK "too new" segments from Phase II nodes
; UPD ID= 554, SNARK:<5.MONITOR>P3-NSPSRV.MAC.39,  19-Mar-82 17:43:23 by MURPHY
;TCO 5.1.1019 - Make NSPTST wake up less often.
; UPD ID= 548, SNARK:<5.MONITOR>P3-NSPSRV.MAC.38,  17-Mar-82 12:27:28 by GRANT
;TCO 5.1.1018 - Check for CCS state in NTMTCZ
; UPD ID= 541, SNARK:<5.MONITOR>P3-NSPSRV.MAC.37,  16-Mar-82 09:26:52 by GRANT
;TCO 5.1.1017 - Change state transition table for CLOSF in CCS state
; UPD ID= 540, SNARK:<5.MONITOR>P3-NSPSRV.MAC.36,  16-Mar-82 09:11:26 by GRANT
;TCO 5.1.1016 - Remove check for 0 bytes in CLZRUN
; UPD ID= 538, SNARK:<5.MONITOR>P3-NSPSRV.MAC.35,  15-Mar-82 08:58:06 by GRANT
;TCO 5.1.1015 - CALL FLUSH in DCDCS
; UPD ID= 534, SNARK:<5.MONITOR>P3-NSPSRV.MAC.34,  12-Mar-82 08:08:23 by GRANT
;Minor change to UPD 526
; UPD ID= 531, SNARK:<5.MONITOR>P3-NSPSRV.MAC.33,  11-Mar-82 21:32:59 by GRANT
;Fix typo in UPD 522
; UPD ID= 530, SNARK:<5.MONITOR>P3-NSPSRV.MAC.32,  11-Mar-82 16:30:35 by GRANT
;TCO 5.1.1014 - CALL BLKLLK in DATCSS
; UPD ID= 527, SNARK:<5.MONITOR>P3-NSPSRV.MAC.31,  11-Mar-82 16:13:03 by GRANT
;TCO 5.1.1012 - Reset inactivity wake up even if nothing to do
; UPD ID= 526, SNARK:<5.MONITOR>P3-NSPSRV.MAC.30,  11-Mar-82 16:01:25 by GRANT
;TCO 5.1.1013 - Don't turn off inactivity timer unless LS message gets sent
; UPD ID= 525, SNARK:<5.MONITOR>P3-NSPSRV.MAC.29,  11-Mar-82 15:53:39 by GRANT
;TCO 5.1.1011 - Make scheduler send ACKs every 200 milliseconds.
;Previous edit should be TCO 5.1.1010
; UPD ID= 524, SNARK:<5.MONITOR>P3-NSPSRV.MAC.28,  11-Mar-82 15:41:55 by GRANT
;TCO 5.1.1011 - Always go to LLSRVR upon leaving NSPCH7
; UPD ID= 522, SNARK:<5.MONITOR>P3-NSPSRV.MAC.27,   9-Mar-82 14:36:42 by GRANT
;TCO 5.1.1009 - Make .NDGNT function of NODE% return info even on failure
; UPD ID= 521, SNARK:<5.MONITOR>P3-NSPSRV.MAC.26,   9-Mar-82 09:53:18 by GRANT
;Add missing ENDIF. in UPD 512
; UPD ID= 516, SNARK:<5.MONITOR>P3-NSPSRV.MAC.25,   6-Mar-82 21:31:29 by GRANT
;TCO 5.1.1008 - Use BLKSIZ in node init
; UPD ID= 515, SNARK:<5.MONITOR>P3-NSPSRV.MAC.24,   6-Mar-82 21:26:41 by GRANT
;TCO 5.1.1007 - Comment out development paranoid checks
; UPD ID= 512, SNARK:<5.MONITOR>P3-NSPSRV.MAC.23,   6-Mar-82 21:15:00 by GRANT
;TCO 5.1.1006 - Rewrite ONTIMQ and UNQTIM
; UPD ID= 479, SNARK:<5.MONITOR>P3-NSPSRV.MAC.22,  17-Feb-82 14:23:42 by GRANT
;TCO 5.1.1005 - ACKCCS needs to use CALL BLKLLK instead of CALL BLKLOK
; UPD ID= 476, SNARK:<5.MONITOR>P3-NSPSRV.MAC.21,  12-Feb-82 15:26:41 by GRANT
;TCO 5.1729 - NSPINT no longer loaded, remove calls to OUTSEG
; UPD ID= 465, SNARK:<5.MONITOR>P3-NSPSRV.MAC.20,   7-Feb-82 20:35:59 by GRANT
;TCO 5.1721 Make NODE JSYS function .NDGLN use 30-bit addressing
; UPD ID= 461, SNARK:<5.MONITOR>P3-NSPSRV.MAC.19,   5-Feb-82 09:23:31 by GRANT
;TCO 5.1.1004 - put in call to the new code
; UPD ID= 460, SNARK:<5.MONITOR>P3-NSPSRV.MAC.18,   5-Feb-82 07:56:18 by GRANT
;TCO 5.1.1004 - figure out "number of active links" in the NTMAN% JSYS
; UPD ID= 373, SNARK:<5.MONITOR>P3-NSPSRV.MAC.17,   5-Jan-82 08:53:02 by GRANT
;TCO 5.1649 - Add null message handling
; UPD ID= 362, SNARK:<5.MONITOR>P3-NSPSRV.MAC.16,  13-Dec-81 10:48:40 by GRANT
;TCO 5.1636 - use SEGSZ
; UPD ID= 343, SNARK:<5.MONITOR>P3-NSPSRV.MAC.15,   4-Dec-81 14:01:33 by GRANT
;More TCO 5.1503 - make consistent use of symbols
; UPD ID= 340, SNARK:<5.MONITOR>P3-NSPSRV.MAC.14,   4-Dec-81 08:52:03 by GRANT
;TCO 5.1626 - In NODINI, make an extensible field for the node number.
;Another attempt at TCO 5.1510
; UPD ID= 316, SNARK:<5.MONITOR>P3-NSPSRV.MAC.13,   9-Nov-81 11:20:29 by GRANT
;TCO 5.1.1001 - add explicit check for 8-bit bytes in NTMAN%
; UPD ID= 315, SNARK:<5.MONITOR>P3-NSPSRV.MAC.12,   9-Nov-81 10:12:06 by GRANT
;Under DN20SW, enhance checking for multiple MCBs
; UPD ID= 309, SNARK:<5.MONITOR>P3-NSPSRV.MAC.11,   4-Nov-81 08:55:26 by GRANT
;TCO 5.1604 - Only do inactivity checking when link is in the run state
; UPD ID= 286, SNARK:<5.MONITOR>P3-NSPSRV.MAC.10,  22-Oct-81 09:00:19 by GRANT
;TCO 5.1593 - Defensive code in RESEND to prevent looping caused by bad counter
; UPD ID= 276, SNARK:<5.MONITOR>P3-NSPSRV.MAC.9,  21-Oct-81 11:37:09 by GRANT
;TCO 5.1594 - Create TTGETS and TTREMS for TTYSRV to use
; UPD ID= 274, SNARK:<5.MONITOR>P3-NSPSRV.MAC.8,  21-Oct-81 10:01:59 by GRANT
;TCO 5.1592 - Fix failure return in LLSRVR
; UPD ID= 273, SNARK:<5.MONITOR>P3-NSPSRV.MAC.7,  19-Oct-81 16:11:05 by GRANT
;Minor change to UPD ID= 194 - Error return from ACKRMT needs to be different
; UPD ID= 271, SNARK:<5.MONITOR>P3-NSPSRV.MAC.6,  19-Oct-81 10:07:57 by GRANT
;TCO 5.1587 - fix segment number wrap around in VERSEG
; UPD ID= 263, SNARK:<5.MONITOR>P3-NSPSRV.MAC.5,  15-Oct-81 14:07:14 by GRANT
;Fix bug in TCO 5.1534
; UPD ID= 230, SNARK:<5.MONITOR>NSPSRV.MAC.111,  29-Sep-81 10:30:51 by GRANT
;Typo in previous edit - LLCIR should be LLSCIR
; UPD ID= 221, SNARK:<5.MONITOR>NSPSRV.MAC.110,  28-Sep-81 12:51:18 by GRANT
;TCO 5.1534 - make RDSTS reflect MO%WFC correctly
; UPD ID= 220, SNARK:<5.MONITOR>NSPSRV.MAC.109,  28-Sep-81 12:40:10 by GRANT
;TCO 5.1537 - smarter calculation of time out value on retransmission
; UPD ID= 215, SNARK:<5.MONITOR>NSPSRV.MAC.108,  24-Sep-81 22:05:34 by GRANT
;PREVIOUS EDIT NEEDS EXPANDED ACVAR IN NSPTMR
; UPD ID= 214, SNARK:<5.MONITOR>NSPSRV.MAC.107,  24-Sep-81 16:52:00 by GRANT
;TCO 5.1533 - New resend algorithm in NSPTMR.
;Comments added in VERSEG and ONRAWQ.
;Reorganize so scheduler related routines are in one place.
; UPD ID= 207, SNARK:<5.MONITOR>NSPSRV.MAC.106,  22-Sep-81 22:59:02 by GRANT
;TCO 5.1528 - FIX THE CHECK FOR "NEEDS AN ACK" IN LLSRVR
;TCO 5.1529 - FIX THE OUT-OF-ORDER MESSAGE PROCESSING IN GOTSEG
; UPD ID= 203, SNARK:<5.MONITOR>NSPSRV.MAC.105,  21-Sep-81 16:34:29 by GRANT
;More TCO 5.1490 - In DELNOD, CALL UNQSRV so old addresses don't remain on LLSRVQ
; UPD ID= 201, SNARK:<5.MONITOR>NSPSRV.MAC.104,  21-Sep-81 10:09:06 by GRANT
;Fix DSCMOV to accommodate TCO 5.1503 (bigger userid, password, account)
; UPD ID= 194, SNARK:<5.MONITOR>NSPSRV.MAC.103,  17-Sep-81 13:23:21 by GRANT
;TCO 5.1490 - Create a pool of free space blocks reserved for sending ACKs
;Piggyback ACKs in data segments
;Eliminate raw queue, do ACKs in scheduler
; UPD ID= 178, SNARK:<5.MONITOR>NSPSRV.MAC.102,  15-Sep-81 13:54:42 by GRANT
;More of TCO 5.1508
; UPD ID= 177, SNARK:<5.MONITOR>NSPSRV.MAC.101,  15-Sep-81 11:55:12 by GRANT
;TCO 5.1510 - Fix Network Management counter "number of active links"
; UPD ID= 174, SNARK:<5.MONITOR>NSPSRV.MAC.100,  14-Sep-81 16:38:16 by GRANT
;TCO 5.1508 - LL not cleaned up on abort close if other side doesn't answer
; UPD ID= 170, SNARK:<5.MONITOR>NSPSRV.MAC.99,  14-Sep-81 10:53:00 by GRANT
;TCO 5.1503 - Allow user ids, passwords, and accounts to be up to 39 chars
; UPD ID= 169, SNARK:<5.MONITOR>NSPSRV.MAC.98,  14-Sep-81 09:23:33 by GRANT
;TCO 5.1502 - Fix cause of ILLUUO BUGHLT caused by NODE JSYS
; UPD ID= 83, SNARK:<5.MONITOR>NSPSRV.MAC.93,  28-Jul-81 11:48:23 by GRANT
;Move test for NSSNTQ empty from NSPTSK to NSPTMR - prevents unnecessary wakeups
; UPD ID= 39, SNARK:<5.MONITOR>NSPSRV.MAC.92,  16-Jul-81 17:09:25 by GRANT
;Use symbols in NDRNM function of NODE JSYS
; UPD ID= 28, SNARK:<5.MONITOR>NSPSRV.MAC.91,  13-Jul-81 14:50:17 by GRANT
;Add resend queue checking interval to NSPTST
; UPD ID= 21, SNARK:<5.MONITOR>NSPSRV.MAC.90,  12-Jul-81 21:23:54 by GRANT
;IN DATCCS AND IN ACKCCS, RELEASE FREE SPACE AFTER DEQUEUING MESSAGE
; UPD ID= 2297, SNARK:<5.MONITOR>NSPSRV.MAC.89,   6-Jul-81 14:15:47 by GRANT
;TCO 5.1394 - Return correct error when OBJSRC fails in DSCNO2
; UPD ID= 2273, SNARK:<5.MONITOR>NSPSRV.MAC.88,  30-Jun-81 11:47:55 by GRANT
;Add inactivity checking interval to NSPTST
; UPD ID= 2266, SNARK:<5.MONITOR>NSPSRV.MAC.87,  27-Jun-81 22:10:21 by GRANT
;CHANGE BADMSG TO TOSMSG IN ACKMSG ROUTINE - JUST THROW AWAY A CA
;CHANGE BADMSG TO TOSMSG IN DOMSGQ ROUTINE - JUST THROW AWAY TRANSPORT INITS
; UPD ID= 2254, SNARK:<5.MONITOR>NSPSRV.MAC.86,  25-Jun-81 07:20:52 by GRANT
;TCO 5.1385 - Remove CIDON, revise BADMSG, add TOSMSG
;Don't zero LLLSC in INACOR
; UPD ID= 2215, SNARK:<5.MONITOR>NSPSRV.MAC.85,  18-Jun-81 16:53:15 by GRANT
;Fix bugs in NODE JSYS function NDGNT failure returns
; UPD ID= 2204, SNARK:<5.MONITOR>NSPSRV.MAC.84,  17-Jun-81 09:50:15 by GRANT
;Send ACKs to background task
;TCO 5.1371 - Check for resident free space threshold in OPNWRK, NSPSPC, and SNDCHK
; UPD ID= 2186, SNARK:<5.MONITOR>NSPSRV.MAC.83,  11-Jun-81 15:54:37 by MURPHY
;CHANGE TQNx TO TMNx REFLECTING CHANGE IN MACSYM
; UPD ID= 2172, SNARK:<5.MONITOR>NSPSRV.MAC.82,  10-Jun-81 15:48:23 by MURPHY
;MAKE TEMP BUGCHK'S INTO BUGHLT'S
; UPD ID= 2136, SNARK:<5.MONITOR>NSPSRV.MAC.81,   7-Jun-81 21:41:13 by GRANT
;ADD CHECKING INTERVAL TO NSPTMR
;MORE INTELLIGENCE NEEDED IN COMPAR
; UPD ID= 2105, SNARK:<5.MONITOR>NSPSRV.MAC.80,  28-May-81 14:59:02 by GRANT
;Remove calls to RETIDN - Network Management will handle this parameter
;Minor fixes in NTNRAC
; UPD ID= 2096, SNARK:<5.MONITOR>NSPSRV.MAC.79,  28-May-81 09:48:17 by GRANT
;Add range checking on timer value in NSNIAT
; UPD ID= 2092, SNARK:<5.MONITOR>NSPSRV.MAC.78,  27-May-81 16:49:37 by GRANT
;Implement NSP 3.2 logical link inactivity timers
;NTMAN% - add return list of active nodes
; UPD ID= 2043, SNARK:<5.MONITOR>NSPSRV.MAC.77,  20-May-81 09:20:14 by GRANT
;Eliminate DELNDF BUGxxx
; UPD ID= 1980, SNARK:<5.MONITOR>NSPSRV.MAC.76,  12-May-81 16:15:47 by GRANT
;Fix BP bug in NDXLT2 debug conditional
; UPD ID= 1968, SNARK:<5.MONITOR>NSPSRV.MAC.75,   8-May-81 16:41:07 by GRANT
;Give PSI when a message is retransmitted due to timeout
; UPD ID= 1960, SNARK:<5.MONITOR>NSPSRV.MAC.74,   7-May-81 11:52:29 by GRANT
;Obtain a new block of space for the remote descriptor in CLRBLK
; UPD ID= 1936, SNARK:<5.MONITOR>NSPSRV.MAC.73,   5-May-81 13:05:45 by GRANT
;Put CHKLLT in RJECT1 and NSPTMO
; UPD ID= 1933, SNARK:<5.MONITOR>NSPSRV.MAC.72,   4-May-81 15:25:16 by GRANT
;Fix failure returns from CALL SNDLS in RDINT and from CALL SNDDI in NSPTMO
;Add caller's PC as optional data to DELNDF
; UPD ID= 1907, SNARK:<5.MONITOR>NSPSRV.MAC.71,  30-Apr-81 08:37:38 by GRANT
;Generate PSI when LL is squashed due to timeout
; UPD ID= 1906, SNARK:<5.MONITOR>NSPSRV.MAC.70,  29-Apr-81 11:59:26 by GRANT
;Just return after a DELNDF BUGINF
; UPD ID= 1895, SNARK:<5.MONITOR>NSPSRV.MAC.69,  28-Apr-81 16:23:53 by GRANT
;Fix resident free space bugs - DIs and CCs not getting cleaned up
;<5.MONITOR>NSPSRV.MAC.68, 26-Apr-81 22:09:27, EDIT BY GRANT
; UPD ID= 1889, SNARK:<5.MONITOR>NSPSRV.MAC.67,  26-Apr-81 21:01:20 by GRANT
;TCO 5.1279 - DECNET PHASE II+ STUFF (TOPOLOGY, NETWORK MANAGEMENT, AND
;NSP MESSAGE TIMER)
;UPD ID= 1430, SNARK:<5.MONITOR>NSPSRV.MAC.62,   9-Jan-81 17:47:22 by MURPHY
;MOVE STMXDF HERE FROM NSPINT
; UPD ID= 1408, SNARK:<5.MONITOR>NSPSRV.MAC.61,   6-Jan-81 15:02:35 by MURPHY
;MAKE CERTAIN CODE RESIDENT THAT MAY NOW BE CALLED FROM SKED
; UPD ID= 1372, SNARK:<5.MONITOR>NSPSRV.MAC.60,  22-Dec-80 09:48:02 by GRANT
;TCO 5.1218 - Change error message in OPNDFT
; UPD ID= 1360, SNARK:<5.MONITOR>NSPSRV.MAC.59,  17-Dec-80 15:46:00 by MURPHY
;CHKLLT INSTEAD OF CHKMCB
; UPD ID= 1348, SNARK:<5.MONITOR>NSPSRV.MAC.58,  12-Dec-80 11:19:45 by MURPHY
;CHKMCB AT LSIDON
; UPD ID= 1318, SNARK:<5.MONITOR>NSPSRV.MAC.57,  26-Nov-80 07:17:11 by GRANT
;TYPO IN PREVIOUS EDIT
; UPD ID= 1316, SNARK:<5.MONITOR>NSPSRV.MAC.56,  25-Nov-80 16:58:23 by GRANT
;New version of NTMAN% JSYS - NSP node counters and formatted data return
; UPD ID= 1312, SNARK:<5.MONITOR>NSPSRV.MAC.55,  25-Nov-80 09:43:28 by GRANT
;TCO 5.1202 - Verification of message flags subtype field
; UPD ID= 1309, SNARK:<5.MONITOR>NSPSRV.MAC.54,  24-Nov-80 16:49:42 by MURPHY
;Make abort close release LL block immediately
;Certain subroutines need to be resident
; UPD ID= 1299, SNARK:<5.MONITOR>NSPSRV.MAC.53,  19-Nov-80 16:59:45 by MURPHY
;XON, XOFF OPTION FOR NVT
; UPD ID= 1291, SNARK:<5.MONITOR>NSPSRV.MAC.52,  18-Nov-80 16:45:58 by MURPHY
;NRT BUGS
; UPD ID= 1283, SNARK:<5.MONITOR>NSPSRV.MAC.51,  18-Nov-80 14:04:39 by GRANT
;TCO 5.1159 - more, don't shut off line if a Phase III transport msg appears,
; just throw the message away
; UPD ID= 1281, SNARK:<5.MONITOR>NSPSRV.MAC.50,  18-Nov-80 11:14:34 by GRANT
;TCO 5.1159 - again, put test in a better place
; UPD ID= 1274, SNARK:<5.MONITOR>NSPSRV.MAC.49,  14-Nov-80 17:52:09 by MURPHY
;NRT BUGS
; UPD ID= 1266, SNARK:<5.MONITOR>NSPSRV.MAC.48,  11-Nov-80 17:53:58 by MURPHY
;NRT bug - MCBQC
; UPD ID= 1225, SNARK:<5.MONITOR>NSPSRV.MAC.47,   3-Nov-80 16:29:36 by GRANT
;TCO 5.1187 - Make segment size calculation in STRMSG
; UPD ID= 1191, SNARK:<5.MONITOR>NSPSRV.MAC.46,  23-Oct-80 16:08:38 by GRANT
;Fix GETBYM arguments in GTASC0
; UPD ID= 1186, SNARK:<5.MONITOR>NSPSRV.MAC.45,  21-Oct-80 15:46:05 by GRANT
;Add segment size check to DOSRVS and FILLIN
; UPD ID= 1183, SNARK:<5.MONITOR>NSPSRV.MAC.44,  21-Oct-80 09:12:26 by GRANT
;TCO 5.1177 - Rewrite DEDCOR to fix bug and become more efficient
; UPD ID= 1178, SNARK:<5.MONITOR>NSPSRV.MAC.43,  20-Oct-80 17:12:20 by MURPHY
;MAKE GETBYT OPEN CODE (GETBYM MACRO)
; UPD ID= 1168, SNARK:<5.MONITOR>NSPSRV.MAC.42,  15-Oct-80 16:14:55 by GRANT
;Add flow control threshold logic in SQI
; UPD ID= 1150, SNARK:<5.MONITOR>NSPSRV.MAC.41,  10-Oct-80 16:19:28 by GRANT
;More of previous edit
; UPD ID= 1140, SNARK:<5.MONITOR>NSPSRV.MAC.40,   8-Oct-80 10:51:01 by GRANT
;TCO 5.1169 - Make PRSNAM call PARNO1
;<5.MONITOR>NSPSRV.MAC.39,  6-Oct-80 13:31:25, EDIT BY MURPHY
;<5.MONITOR>NSPSRV.MAC.38,  6-Oct-80 11:43:48, EDIT BY MURPHY
; UPD ID= 1124, SNARK:<5.MONITOR>NSPSRV.MAC.37,   5-Oct-80 15:02:30 by MURPHY
;DITTO
; UPD ID= 1119, SNARK:<5.MONITOR>NSPSRV.MAC.36,   3-Oct-80 12:21:08 by MURPHY
;DITTO
; UPD ID= 1111, SNARK:<5.MONITOR>NSPSRV.MAC.35,   3-Oct-80 01:00:34 by MURPHY
;MAKE NSP NOTIFY TTYSRV UPON RECEIPT OF DATA AND ACKS
; UPD ID= 1105, SNARK:<5.MONITOR>NSPSRV.MAC.34,   2-Oct-80 09:35:12 by MURPHY
;DITTO
; UPD ID= 1092, SNARK:<5.MONITOR>NSPSRV.MAC.33,   1-Oct-80 13:35:09 by MURPHY
;FIX ACVAR
; UPD ID= 1067, SNARK:<5.MONITOR>NSPSRV.MAC.32,  30-Sep-80 11:02:43 by GRANT
;TCO 5.1160 - make NSPRTH BUGCHK more meaningful
; UPD ID= 1065, SNARK:<5.MONITOR>NSPSRV.MAC.31,  30-Sep-80 10:46:39 by GRANT
;TCO 5.1159 - must reject Phase III Transport init message
; UPD ID= 1064, SNARK:<5.MONITOR>NSPSRV.MAC.30,  30-Sep-80 10:31:05 by GRANT
;Fix sequential input again and init NMAPLK in NSPINI
; UPD ID= 1061, SNARK:<5.MONITOR>NSPSRV.MAC.29,  30-Sep-80 10:16:15 by MURPHY
;NVT bugs
; UPD ID= 1059, SNARK:<5.MONITOR>NSPSRV.MAC.28,  26-Sep-80 13:30:48 by GRANT
;Add NTMAN% JSYS
; UPD ID= 1056, SNARK:<5.MONITOR>NSPSRV.MAC.27,  26-Sep-80 12:12:52 by MURPHY
;Make BLKULK preserve T2; fix various NVT bugs
; UPD ID= 1036, SNARK:<5.MONITOR>NSPSRV.MAC.26,  24-Sep-80 11:48:18 by GRANT
;TCO 5.1153 - NETSQI must save T2 over the call to BLKULK
; UPD ID= 1023, SNARK:<5.MONITOR>NSPSRV.MAC.25,  16-Sep-80 16:07:18 by GRANT
;Change MONX01 to NSPX26 in NDSIC routine
; UPD ID= 1019, SNARK:<5.MONITOR>NSPSRV.MAC.24,  16-Sep-80 15:34:14 by GRANT
;TCO 5.1146 - Fix free space bug in MTRDIN
; UPD ID= 1007, SNARK:<5.MONITOR>NSPSRV.MAC.23,  11-Sep-80 18:17:22 by GRANT
;Change MONX01 to MONX06 in GETBLK routine
; UPD ID= 943, SNARK:<5.MONITOR>NSPSRV.MAC.21,  20-Aug-80 20:09:04 by MURPHY
;Merge FILNSP into NSPSRV
; UPD ID= 920, SNARK:<5.MONITOR>NSPSRV.MAC.20,  19-Aug-80 15:17:32 by MURPHY
;File open mode 1 for small segsiz
; UPD ID= 902, SNARK:<5.MONITOR>NSPSRV.MAC.19,  14-Aug-80 22:54:49 by MURPHY
;Locks again
; UPD ID= 892, SNARK:<5.MONITOR>NSPSRV.MAC.18,  13-Aug-80 18:21:01 by MURPHY
;Handle locks at scheduler level
; UPD ID= 846, SNARK:<5.MONITOR>NSPSRV.MAC.17,   6-Aug-80 17:32:48 by MURPHY
;ULOKLL again
; UPD ID= 845, SNARK:<5.MONITOR>NSPSRV.MAC.16,   6-Aug-80 14:25:32 by MURPHY
;BUGCHK at ULOKLL if lock not already locked; make few more routines resident
; UPD ID= 820, SNARK:<5.MONITOR>NSPSRV.MAC.15,   1-Aug-80 13:21:31 by GRANT
;TCO 5.1119 - Fix cause of "overly OKINT" BUGCHKs when DN20 gets reloaded
; UPD ID= 790, SNARK:<5.MONITOR>NSPSRV.MAC.14,  23-Jul-80 20:13:13 by MURPHY
;MORE OF THE SAME
; UPD ID= 777, SNARK:<5.MONITOR>NSPSRV.MAC.13,  22-Jul-80 17:07:09 by MURPHY
;MAKE A FEW ROUTINES GLOBAL
; UPD ID= 753, SNARK:<5.MONITOR>NSPSRV.MAC.12,  11-Jul-80 17:05:41 by MURPHY
;MAKE VARIOUS THINGS RESIDENT WITH VIEW TOWARD MAKING THEM RUN AT SKED LEVEL
; UPD ID= 623, SNARK:<5.MONITOR>NSPSRV.MAC.11,  11-Jun-80 11:06:36 by GRANT
;Wrong AC being loaded in PRUNE
; UPD ID= 621, SNARK:<5.MONITOR>NSPSRV.MAC.10,  10-Jun-80 13:23:07 by MURPHY
; UPD ID= 606, SNARK:<5.MONITOR>NSPSRV.MAC.9,   5-Jun-80 10:23:04 by GRANT
;More of UPD ID= 330
; UPD ID= 605, SNARK:<5.MONITOR>NSPSRV.MAC.8,   5-Jun-80 08:40:19 by ENGEL
;MAKE ASCIIZ RESIDENT
; UPD ID= 593, SNARK:<5.MONITOR>NSPSRV.MAC.7,   3-Jun-80 09:44:15 by ENGEL
;MAKE NODINI RESIDENT
; UPD ID= 590, SNARK:<5.MONITOR>NSPSRV.MAC.6,   3-Jun-80 09:03:33 by ENGEL
;FIX ONEBYT
; UPD ID= 588, SNARK:<5.MONITOR>NSPSRV.MAC.5,   2-Jun-80 17:24:28 by ENGEL
;MAKE PORTIONS OF NODINI CODE RESIDENT
; UPD ID= 502, SNARK:<5.MONITOR>NSPSRV.MAC.4,   1-May-80 15:02:52 by GRANT
;TCO 5.1031 - Make CI processing distinguish between busy and non-existent
; UPD ID= 477, SNARK:<5.MONITOR>NSPSRV.MAC.3,  24-Apr-80 16:52:51 by GRANT
;In DEDMCB, use DCN instead of DTEN for valid port number test -
;DTEN won't work on the 2020
; UPD ID= 455, SNARK:<5.MONITOR>NSPSRV.MAC.2,  22-Apr-80 14:02:03 by MURPHY
;FIX UP ENTRY SEQUENCE IN INFERIOR FORK
; UPD ID= 351, SNARK:<4.1.MONITOR>NSPSRV.MAC.421,  25-Mar-80 08:58:26 by GRANT
;Undo the previous edit
; UPD ID= 339, SNARK:<4.1.MONITOR>NSPSRV.MAC.420,  17-Mar-80 18:11:26 by GRANT
;At OUTRR7, don't include SEGNUM bytes in MSDTC count
; UPD ID= 330, SNARK:<4.1.MONITOR>NSPSRV.MAC.419,  14-Mar-80 09:58:02 by GRANT
;In STRSAV, reverse the search order of the DTEs when looking for the MCB
; UPD ID= 226, SNARK:<4.1.MONITOR>NSPSRV.MAC.418,  25-Jan-80 13:30:56 by GRANT
;TCO 4.2599 - DEDMCB should not clear the loopback word
; UPD ID= 190, SNARK:<4.1.MONITOR>NSPSRV.MAC.417,   8-Jan-80 13:34:55 by GRANT
;Fix DTE range check in DEDMCB
; UPD ID= 124, SNARK:<4.1.MONITOR>NSPSRV.MAC.416,  10-Dec-79 15:40:10 by GRANT
;Fix typeo in UPD ID=100 in MOVSEG
; UPD ID= 114, SNARK:<4.1.MONITOR>NSPSRV.MAC.415,   8-Dec-79 13:09:40 by MILLER
;FIX BUGS IN NETINP AND NETSQI.
; UPD ID= 100, SNARK:<4.1.MONITOR>NSPSRV.MAC.413,   5-Dec-79 17:20:06 by MILLER
;REPLACE MISSING CODE IN MOVSEG. FIX ANCIENT RACE BETWEEN MOVSEG AND
; THE SCHEDULER
; UPD ID= 85, SNARK:<4.1.MONITOR>NSPSRV.MAC.412,   3-Dec-79 15:06:50 by GRANT
;TCO 4.2588 - Change CCMSG: and DCMSG: to be compatible with Phase III
;<4.MONITOR>NSPSRV.MAC.411, 20-Nov-79 11:40:56, EDIT BY GRANT
;Previous edit lines removed

;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 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.

	SEARCH NSPPAR,PROLOG,PROKL
	TTITLE (NSPSRV,,< - Network Services Protocol Interface to TOPS20	>)

;THIS MODULE CONTAINS THE CONTROL ROUTINES AND JSYS INTERFACES
;FOR THE HOST-TO-HOST PROTOCOL OF DECNET KNOWN AS NSP.
;NSP ALLOWS COMMUNICATION BETWEEN PROCESSES ON HOSTS BY MEANS
;OF LOGICAL LINKS. A LOGICAL LINK IMPLIES AN "OBJECT" ON ONE
;OF THE HOSTS AND A PROCESS ON ANOTHER HOST WISHING TO AVAIL ITSELF
;OF THE OBJECT'S SERVICES, A PHYSICAL COMMUNICATIONS PATH BETWEEN
;THE HOSTS WHICH IS ERROR-FREE( SEE DDCMP SPECIFICATION FOR THE
;MAGIC BEHIND THIS ASSUMPTION), AND A TON OF LOGIC IN EACH OF
;THE HOSTS AND IN THE INTERVENING MCB NODES (IF ANY) WHICH ROUTE
;AND CONTROL THE FLOW OF THE DATA. THIS MODULE IS RESPONSIBLE
;FOR COMMUNICATING WITH ADJACENT MCB NODES AND FOR MAINTAINING AND
;ESTABLISHING LOGICAL LINKS ON DEMAND OF PROCESSES IN THIS TOPS20
;HOST OR OF PROCESSES IN THE NETWORK.


;THIS MODULE CONTROLS, ALLOCATES, AND DEALLOCATES ENTRIES
;IN THE LOGICAL LINK TABLE. AN ENTRY  IN THE LOGICAL LINK TABLE
;CONTAINS INFORMATION NEEDED BY NSPSRV TO PROPERLY MANAGE
;THE LINK. THE INFORMTION IS FALLS INTO ONE OF TWO CLASSES:
;LOGICAL PARAMETERS AND PROCESS PARAMETERS. AMONG THE LOGICAL
;LINK PARAMETERS ARE: CURRENT LINK STATE, BUFFER COUNTS, FLOW
;CONTROL OPTIONS, AND SEGEMENT NUMBERS. AMONG THE PROCESS
;PARAMETERS ARE: PI CHANNELS FOR VARIOUS EVENTS, OWNING FORK,
;WINDOW PAGE BYTE COUNTS

;THE LINK TABLE IS STORED AS A BINARY TREE. ENTRIES ARE LINKED IN
;THE TREE IN ORDER BY LINK NUMBER, AND THE SEARCH ALGORTIHM INSURES
;THAT A LINK CAN BE LOCATED IN LOG(2) OF THE NUMBER OF ENTRIES.

;WITHIN THE LOGICAL LINK TABLE ARE ENTRIES WHICH REPRESENT
;"LISTENING" OBJECTS. THESE ARE PROCESSES WHICH HAVE DECLARED THEIR
;INTEREST IN PARTICIPATING IN A DIALOGUE, BUT NO NETWORK ENTITY HAS
;ATTEMPTED AS YET TO CONNECT TO THE OBJECT. UPON RECEIPT OF A
;CONNECT-INITIATE, THE LOGICAL LINK TABLE IS SEARCHED FOR A LISTENING
;OBJECT WHICH COORESPONDS TO THE REQUIREMENTS OF THE CONNECTOR. THIS
;SEARCH IS,UNFORTUNATELY, EXHAUSTIVE AND MAY REQUIRE A CONSIDERABLE
;AMOUNT OF TIME.

;MESSAGES ARE STORED IN MONITOR RESIDENT FREE SPACE. EACH MESSAGE
;HAS A HEADER ON IT OF THE FORM:

;	POINTER TO NEXT MESSAGE IN THE CHAIN
;	DTE#, FLAGS, SEG #, LOGICAL LINK ADDRESS OF OWNING LINK
;	MESSAGE FLAGS, # OF DATA BYTES, TOTAL # OF BYTES
;	BYTE POINTER TO DATA BYTES (EXCLUDES NSP HEADER)

;THIS MODULE ALSO CONTAINS ROUTINES FOR PARSING AND VERIFYING NETWORK
;FILE SPECS. A FILE SPEC IS OF THE FORM:
;DCN:HOST-OBJECT-DESCRIPTOR.TASKNAME;ATTRIBUTES
; TO MAKE A CONNECTION, OR:
;SRV:OBJECT-DESCRIPTOR.TASKNAME
; TO DECLARE A SERVER
NSPSW==0			;SWITCH FOR LOGICAL LINK BLOCK VERIFYING
LLSIGN==101010			;THE VERIFICATION SYMBOL

;DEFINE LOCAL MACROS

DEFINE LLLOCK<
   	CALL LOKLL>		;;GO LOCK UP THE TREE

DEFINE LLLULK<
   	CALL ULOKLL>		;;GO UNLOCK THE TREE

DEFINE ATTENT (VALUE,BIN,COUNT,EXCLU)<
	<BIN>B0+<COUNT>B17+EXCLU*1000+VALUE>

DEFSTR (NTATR,,35,9)
DEFSTR (NTATC,,17,6)
DEFSTR (NTATE,,26,9)
DEFSTR (NTATB,,0,1)

DEFAC (STS,P1)
DEFAC (JFN,P2)
DEFAC (DEV,P4)
DEFAC (F1,P5)

RS NSLDWS,1			;LOCAL DELAY WEIGHT SETTING
NR NSLDFS,1			;LOCAL DELAY FACTOR SETTING
NR NSTRYS,1			;RETRANSMIT COUNT SETTING
SUBTTL	Device Dispatch Vectors for SRV: and DCN: Devices

;FOR DEVICE SRV

	SWAPCD

SRVDTB::DTBDSP (NETDIR)		;DIRECTORY SET
	DTBDSP (SRNSET)		;NAME LOOKUP
	DTBDSP (EXTSET)		;EXTENSION LOOKUP
	DTBDSP (VERSET)		;VERSION LOOKUP
	DTBBAD (DESX9)		;NO PROTECTION
	DTBBAD (DESX9)		;NO ACCOUNT
	DTBBAD (DESX9)		;NO STATUS
	DTBDSP (SRCOPN)		;OPEN
	DTBDSP (NETSQI)		;INPUT
	DTBDSP (NETSQO)		;OUTPUT
	DTBDSP (NETCLZ)		;CLOSE
   REPEAT 7,<
	DTBBAD (DESX9)>	;ILLEGAL FUNCTIONS
	DTBDSP (NTMTOP)		;MTOPR
   REPEAT 2,<DTBBAD (DESX9)>	;ILLEGAL FUNCTIONS
	DTBDSP (NETSQR)		;SOUTR
	DTBDSP (RFTADN)		;NO TIME AND DATE
	DTBDSP (RFTADN)		;NO TIME AND DATE
	DTBDSP (NETINP)		;SET FOR INPUT
	DTBDSP (NETOUP)		;SET FOR OUTPUT
	DTBBAD (GJFX49)		;NO ATTRIBUTES

;FOR THE DCN DEVICE

DCNDTB::DTBDSP (NETDIR)		;DIR SET
	DTBDSP (DCNSET)		;NAME LOOKUP
	DTBDSP (EXTSET)		;EXTENSION LOOKUP
	DTBDSP (VERSET)		;VERSION LOOKUP
   REPEAT 3,<
	DTBBAD (DESX9)>	;ILLEGAL FUNCTIONS
	DTBDSP (DCNOPN)		;OPEN
	DTBDSP (NETSQI)		;INPUT
	DTBDSP (NETSQO)		;OUTPUT
	DTBDSP (NETCLZ)		;CLOSE
   REPEAT 7,<
	DTBBAD (DESX9)>	;ILLEGAL FUNCTIONS
	DTBDSP (NTMTOP)		;MTOPR
   REPEAT 2,<DTBBAD (DESX9)>	;ILLEGAL FUNCITONS
	DTBDSP (NETSQR)		;SOUTR
	DTBDSP (RFTADN)		;NO TIME AND DATE
	DTBDSP (SFTADN)		;NO TIME AND DATE
	DTBDSP (NETINP)		;SET FOR INPUT
	DTBDSP (NETOUP)		;SET FOR OUTPUT
	DTBDSP (NETATR)		;PARSE ATTRIBUTES
SUBTTL	GTJFN Routines

;ROUTINES CALLED FROM GTJFN PROCESSING TO LOOK UP FILE NAMES

;NAME LOOKUP FOR SRC DEVICE

SRNSET::JUMPE T1,[RETBAD (GJFX18,<OKINT>)] ;CANT'T STEP IT
	CALL [	TRVAR <NTCNT,NTPNT,NTOBJ,NTDDSC,NTDSS>
		CALL SRCNAM	;GO PARSE THE NAME
		 RETBAD()	;HAD AS ERROR
		RETSKP]		;GOOD
	 RETBAD ()		;FAILED
OKRET:	TQNE <UNLKF>		;WANT TO UNLOCK?
	JRST SK2RET		;NO. RETURN
	OKINT			;YES. GO OKINT THEN
	JRST SK2RET		;AND RETURN

;ROUTINE TO DO NAME LOOKUP FOR DCN DEVICE

DCNSET::JUMPE T1,[RETBAD (GJFX18,<OKINT>)] ;CANT'T STEP IT
	CALL [	TRVAR <NTCNT,NTPNT,NTOBJ,NTDSC,NTDSS,NTHST,NTHSC>
		CALL DCNNAM	;GO PARSE NAME
		  RETBAD()	;SOME SORT OF ERROR
		RETSKP]		;GOOD
	 RETBAD ()		;SOME SORT OF FAILURE
	JRST OKRET		;AND DONE

;EXTENSION CHECKER

EXTSET::JUMPE T1,[RETBAD (GJFX18,<OKINT>)] ;CANT'T STEP IT
	CALL [	TRVAR <NTCNT,NTPNT>
		CALL NETEXT	;CHECK EXTENSION
		 RETBAD()	;SOME SORT OF ERROR
		RETSKP]		;AND DONE
	 RETBAD ()		;SOME SORT OF FAILURE
	JRST OKRET		;AND DONE

;ROUTINE TO LOOK UP DIRECTORY COMPONENT IN NETWORK FILE SPEC

NETDIR::TQNE <STEPF>		;WANT TO STEP?
	RETBAD (GJFX17)		;YES. CAN'T DO IT
	NOINT			;PREVENT INTS
	JRST SK2RET		;AND SAY IT IS SET

;VERSION LOOKUP

VERSET::TQNN <STEPF>		;TRYING TO STEP?
	JRST OKRET		;NO. ALLOW IT THEN
	JUMPGE T1,OKRET		;IF NOT STEPPING, OKAY
	RETBAD (GJFX18,<OKINT>)	;ALL ELSE IS WRONG
;ROUTINE TO ASSIGN WINDOW PAGES TO A JFN.
;ACCEPTS:	NORMAL FILE SYSTEM REGISTER (JFN,ETC...)
;RETURNS:	+1	FAILED
;		+2	SUCCESS.

ASGWDW::SETZM FILWND(JFN)
	SETZM FILBCT(JFN)	;AND CLEAR COUNTS
	TQNN <READF>		;WANT READ ON THIS FILE?
	JRST ASGWRT		;NO. TRY WRITE
	CALL ASGPAG		;GET A JSB PAGE
	 RETBAD (MONX02)	;COULDN'T
	HRRM T1,FILWND(JFN)	;SAVE WINDOW PAGE
	LDB T3,PBYTSZ		;GET BYTE SIZE
	CALL MAKINP		;GET A POINTER FOR INPUT
	MOVEM T1,FILBFI(JFN)	;INIT INPUT POINTER
ASGWRT:	TQNN <WRTF>		;WANT WRITE
	RETSKP			;NO ALL DONE
	CALL ASGPAG		;GET A PAGE FOR OUTPUT
	 JRST [	SKIPE T1,FILWND(JFN) ;FAILED. HAVE READ WINDOW?
		CALL RELPAG	;RELEASE THE INPUT PAGE
		SETZM FILWND(JFN) ;NOTE NO PAGE WAS ASSIGNED
		SETZM FILBFI(JFN) ;PREVENT RELEASE OF FREE SPACE BY RLJFN
		RETBAD (MONX02)] ;AND FAIL
	HRLM T1,FILWND(JFN)	;STORE WINDOW
	RETSKP			;AND DONE
;ROUTINE TO COMPUTE NUMBER OF USEFUL BYTES IN A JSB STRING.
;CALLED FROM ROUTINES THAT PROCESS NETWORK FILE NAMES.
;ACCEPTS:	T1/FREE BLOCK ADDRESS
;	TRVAR <NTCNT,NTPNT,.....>
;RETURNS:	+1 ALWAYS WITH COUNT IN NTCNT AND POINTER IN NTPNT

COMPUT:	HRRZ T3,0(T1)		;GET COUNT OF WORDS IN BLOCK
	SOS T3			;DISCOUNT THE HEADER
	IMULI T3,5		;GET BYTE COUNT
	AOS T3			;ADD IN FINAL TERMINATOR
	HRLI T1,(<POINT 7,0,35>) ;GET STRING POINTER TO THE BLOCK
	MOVEM T1,NTPNT		;AND SAVE THE STARTING POINTER
	CALL CMPLEN		;GET LENGTH OF STRING
	MOVEM T3,NTCNT		;SAVE COUNT
	RET			;DONE, RETURN


;CMPLEN - ROUTINE TO COMPUTE LENGTH OF STRINGS
;
;ACCEPTS IN T1/ POINTER TO START OF STRING
;	    T3/	MAX NUMBER OF BYTES IN STRING
;		CALL CMPLEN
;RETURNS: +1 ALWAYS, WITH T3/ ACTUAL NUMBER OF BYTES IN STRING

CMPLEN::STKVAR <CPLCNT>
	MOVEM T3,CPLCNT		;STARTING COUNT
	MOVE T2,[POINT 0,0,2]	;GET DUMMY POINTER
	SETZ T4,
	SIN			;FIND NUMBER OF USEFUL BYTES IN THE STRING
	JUMPE T3,R		;IF NO NULLS, ALL SET
	SUB T3,CPLCNT		;FOUND A NULL THEN. GET CHARACTERS SKIPPED
	MOVNS T3		;GET COUNT
	RET			;AND DONE

;ROUTINE TO SCAN NAME STRING FOR NETWORK PUNCTUATION CHARACTER AND
;UPDATE COUNTS.
;ACCEPTS:	IN TRVAR'S
;	NTPNT	CURRENT TEXT POINTER
;	NTCNT	CURRENT BYTE COUNT

;RETURNS:
;	NTPNT	UPDATED POINTER
;	NTCNT	UPDATED COUNT
;	T1/ ORIGINAL POINTER
;	T3/ NUMBER OF CHARCTERS FOUND BEFORE PUNCTUATION

NETDSH:	MOVE T1,NTPNT		;GET BYTE POINTER
	MOVE T2,[POINT 0,0,2]	;DUMMY
	MOVE T3,NTCNT		;THE COUNT
	MOVEI T4,"-"		;STOP ON THE END OF THE HOST FIELD
	SIN			;GET IT
	EXCH T1,NTPNT		;STORE NEW POINTER. GET OLD
	EXCH T3,NTCNT		;STORE NEW COUNT. GET OLD COUNT
	SUB T3,NTCNT		;GET BYTES TRANSPIRED
	RET			;AND DONE
;ROUTINE TO PARSE THE NAME FIELD OF A SOURCE SPECIFICATION.
;A NAME FIELD LOOKS LIKE:
;	OBJECT-DESCRIPTOR
;OR
;	-
;WHERE THE FORMER IS THE SYNTAX FOR A GENERIC OBJECT
;AND THE LATTER IS THE SYNTAX FOR A TASK ONLY
;ACCEPTS:
;	T1/ POINTER TO NAME BLOCK
;	TRVAR <NTCNT,NTPNT,NTOBJ,NTDSC,NTDSS>
;RETURNS:
;	+1 SYNTAX OR SEMANTICS ERROR. CODE IN T1
;	+2 ACCEPTABLE NAME.

;	WITH TRVAR'S FILLED IN

SRCNAM::CALL COMPUT		;COMPUTE STRING COUNT
	SETOM NTOBJ		;ASSUME NO OBJECT
	CALL NETDSH		;GO FIND OBJECT NAME
	CAIG T3,1		;WAS IT NULL?
	JRST SRCNOB		;YES. NO GENERIC OBJECT GIVEN
	LDB T4,NTPNT		;GET TERMINATOR
	MOVEM T4,NTOBJ		;SAVE IT
	SETZ T4,		;GET A NULL
	DPB T4,NTPNT		;TIE OFF OBJECT NAME
	CALL OBJLOK		;GO LOOK UP THE OBJECT
	 RETBAD (DCNX3)		;NO SUCH OBJECT. COMPLAIN
	SKIPG T1		;A LEGAL OBJECT TYPE?
	RETBAD (DCNX3)		;NO. COMPLAIN
	CAIG T1,DECOBJ		;IS IT A DEC RESERVED OBJECT?
	JRST [	MOVX T3,SC%WHL!SC%OPR ;YES. MUST BE PRIVILEGED THEN
		TDNE T3,CAPENB	;IS IT ENABLED?
		JRST .+1	;YES. PROCEED
		RETBAD (DCNX3)]	;NO. ERROR
	EXCH T1,NTOBJ		;SAVE GENERIC OBJECT TYPE
	DPB T1,NTPNT		;AND PUT BACK TERMINATOR
SRCNOB:	SETZM NTDSC		;ASSUME NO DESCRIPTOR
	SKIPE T3,NTCNT		;ANY BYTES LEFT IN STRING?
	CAIG T3,1		;YES. ENOUGH TO MAKE A DESCRIPTOR?
	RETSKP			;NO ALL DONE THEN
	MOVEM T3,NTDSC		;STORE COUNT OF DESCRIPTOR
	SKIPGE NTOBJ		;HAVE AN OBJECT?
	RETBAD (DCNX3)		;NO. ILLEGAL SPECIFICATION
	CAILE T3,MAXDSC		;WITHIN RANGE?
	RETBAD (DCNX12)		;NO.ILLEGAL DESCRIPTOR
	MOVE T1,NTPNT		;GET POINTER
	MOVEM T1,NTDSS		;SAVE BEGINNING OF DESCRIPTOR
	RETSKP			;AND DONE
;ROUTINE TO PARSE NAME FOR A CONNECT ATTEMPT.
;AACEPTS:	T1/ BLOCK ADDRESS OF NAME
;	TRVAR <NTCNT,NTPNT,NTOBJ,NTDSC,NTDSS,NTHST,NTHSC>
;RETURNS:
;		+1 SYNTAX ERROR
;		+2 NAME IS GOOD. TRVAR'S FILLED IN

DCNNAM::CALL COMPUT		;FIND COUNT
	CALLRET PRSNAM		;GO PARSE NAME FIELD



;PRSNAM - ROUTINE TO DO THE PARSING OF THE NAME
;
;ACCEPTS:	IN TRVAR'S
;	NTPNT	CURRENT TEXT POINTER
;	NTCNT	CURRENT BYTE COUNT
;		CALL PRSNAM
;RETURNS: +1	 FAILED, SYNTAX ERROR
;	  +2	SUCCESS, WITH APPROPRIATE TRVARS FILLED IN

PRSNAM::CALL NETDSH		;GO PICK OFF HOST NAME
	SKIPN NTCNT		;MORE IN THE STRING?
	RETBAD (DCNX1)		;NO. SYNTAX ERROR THEN
	SETOM NTHSC		;ASSUME LOCAL CONNECTION
	SOSG T3			;HAVE A REAL STRING?
	JRST DCNOBJ		;NO. GO LOOK FOR OBJECT THEN
	CAILE T3,MAXHST		;WITHIN BOUNDS?
	RETBAD (COMX19)		;NO. STRING TOO LONG
	MOVEM T1,NTHST		;SAVE POINTER TO HOST
	MOVEM T3,NTHSC		;AND SAVE COUNT
	AOS T1			;POINT TO THE ACTUAL TEXT
	HRLI T1,440700		;MAKE A BYTE POINTER FOR PARSING
	MOVE T2,T3		;GET NODE NAME CHARACTER COUNT
	CALL PARNO1		;SEE IF VALID NODE NAME SYNTAX
	 RETBAD ()		;INVALID NODE NAME - RETURN THE ERROR
DCNOBJ:	CALL NETDSH		;GO FIND OBJECT
	CAIG T3,1		;HAVE A REAL STRING?
	RETBAD (DCNX3)		;NO. INVALID OBJECT THEN
	LDB T4,NTPNT		;GET BACK TERMINATOR
	MOVEM T4,NTOBJ		;SAVE IT
	SETZ T4,		;GET A NULL
	DPB T4,NTPNT		;TIE OFF STRING
	CALL OBJLOK		;GO LOOK UP THE OBJECT
	 RETBAD (DCNX3)		;NO SUCH
	EXCH T1,NTOBJ		;SAVE OBJECT
	DPB T1,NTPNT		;AND PUT BACK TERMINATOR
	JRST SRCNOB		;FINISH UP ON DESCRIPTOR

;ROUTINE TO PARSE EXTENSION. THIS FIELD WILL BE THE TASKNAME

NETEXT:	CALL COMPUT		;GET COUNT
	MOVE T1,NTCNT		;GET THE COMPUTED COUNT
	CAILE T1,TSKMAX		;WITHING RANGE
	RETBAD (DCNX12)		;NO. TOO LONG
	RETSKP			;AND DONE
SUBTTL	Routines to open DCN: or SRV: links

;COMMON ROUTINE FOR OPENF JSYS. THIS CODE IS CALLED BY BOTH SRCOPN
;AND DCNOPN TO ASSIGN A LL BLOCK, ASSIGN A LL ADDRESS, AND FILL
;IN COMMON VALUES.
;	RETURNS +1	FAILED. T1/ ERROR CODE
;		+2 SUCCESS	T1/ LL BLOCK ADDRESS
;			 AND LL TREE LOCKED

OPNDNC::TDZA T4,T4		;NOTE OPENING DCN:
OPNSRC::SETOM T4		;NOTE OPENING SRV:
	TQZE <RNDF>		;WANT APPEND?
	TQO <WRTF>		;YES. FORCE ON WRITE THEN
	TQNN <READF,WRTF>	;WANT SOME FORM OF ACCESS?
	RETBAD (OPNX14)		;NO. ILLEGAL OPEN
	LDB T2,PBYTSZ		;LOOK AT REQUESTED BYTE SIZE
	CAIE T2,10		;BYTES?
	CAIN T2,7		;OR ASCII?
	JRST BYTGUD		;YES. ACCEPTS IT
	CAIE T2,44		;-10 WORD MODE?
	RETBAD (SFBSX2)		;NO. ILLEGAL BYTE SIZE
BYTGUD:	HRRZ T1,FILNEN(JFN)	;GET ADDRESS OF STRING BLOCK
	ADDI T1,1		;GET ADDRESS OF STRING
	LDB T2,PBYTSZ		;GET BYTESIZE OF OPENF
	SKIPE T4		;OPENING DCN: ?
	JRST [	CALL OPNSWK	;NO, CALL WORK ROUTINE TO OPEN SRV:
		 RETBAD ()	;FAILED, RETURN ERROR CODE
		JRST SAVLLB ]	;GO SAVE LL BLOCK ADDRESS IN JFN BLOCK
	CALL OPNDWK		;CALL WORK ROUTINE TO OPEN DCN:
	 RETBAD ()		;FAILED, RETURN ERROR CODE


SAVLLB:	MOVEM T1,FILLLB(JFN)	;SAVE BLOCK ADDRESS
   IFN NSPSW,<
	MOVEI T2,LLSIGN		;GET LL BLOCK UNIQUE INDICATOR
	MOVEM T2,LLMSG(T1)	;PUT IT IN BLOCK (LLMSG IS NOT USED BY 5.1)
   >
	TQNE <READF>		;WANT BI-DIRECTIONAL LINK?
	CALL SETOPI		;SET INPUT FLAG FOR LOGICAL LINK
	TQNE <WRTF>		;WANT WRITE?
	CALL SETOPW		;SET OUTPUT FLAG FOR LOGICAL LINK
	CALL STMXDF		;SET INPUT/OUTPUT MAX QUEUE DEFAULTS
	RETSKP			;AND DONE
;STMXDF - SET MAX INPUT/OUTPUT QUEUE DEFAULTS
;
;ACCEPTS:	T1/ ADDRESS OF LOGICAL LINK BLOCK
;
;RETURNS:	+1,ALWAYS
;
;DESTROYS T2

STMXDF::MOVEI T2,MAXSEG		;ASSUME READ ONLY
	OPSTR <SKIPE>,LLOPW,(T1) ;OPEN FOR WRITE AS WELL?
	MOVEI T2,MAXSG1		;YES. USE A SMALLER NUMBER
	STOR T2,LLMQI,(T1)	;SAVE THE INPUT QUEUE LENGTH (ALSO FLOW CONTROL)
	MOVEI T2,MAXSGQ		;SET OUTPUT QUEUE LENGTH
	STOR T2,LLMQO,(T1)	;SAVE IN LINK BLOCK
	RET


;VERIFY A LOGICAL LINK BLOCK
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;RETURNS:	+1 PASSED THE TEST

   IFN NSPSW,<
CHKLLB:	PUSH P,T2		;PRESERVE T2
	MOVE T2,LLMSG(T1)	;GET THE VERIFICATION WORD
	CAIE T2,LLSIGN		;IS IT GOOD?
	JSR BUGHLT		;NO, TOO BAD
	POP P,T2		;OK, RETRIEVE T2
	RET			;YES
   >
;ROUTINE CALLED FROM THE OPENF JSYS TO OPEN A DCN NETWORK CONNECTION

DCNOPN::TRVAR <NTCNT,NTPNT,NTOBJ,NTDSC,NTDSS,NTHST,NTHSC,NTCIB>
	GTOKM (.GODNA,,[RET]) ;ASK ACJ TO GIVE ITS BLESSING
	HLRZ T1,FILNEN(JFN)	;GET NAME FOR THE CONNECTION
	CALL DCNNAM		;GO PARSE THE NAME FIELD
	 RETBAD ()		;FAILED
	CALL OPNDNC		;GO DO COMMON SETUP
	 RETBAD () 		;FAILED
	CALL ASGWDW		;NOW SET UP WINDOWS
	 RETBAD (,<CALL CLENUP>) ;FAILED, RETURN ERROR
	MOVE T1,FILLLB(JFN)	;GET ADDRESS OF LOGICAL LINK BLOCK
	HRL T2,NTHSC		;GET COUNT OF HOST STRING BYTES
	HRR T2,NTDSC		;GET COUNT OF DESCRIPTOR STRING BYTES
	MOVE T3,NTHST		;GET ADDRESS OF BLOCK HOLDING HOST NAME STRING
	MOVE T4,NTDSS		;GET POINTER TO DESCRIPTOR STRING
	CALL STRSAV		;GO MOVE PERMANENT LL STRINGS
	 RETBAD (,<CALL CLENUP>) ;FAILED, RETURN ERROR
	MOVE T1,FILLLB(JFN)	;GET LOGICAL LINK BLOCK ADDRESS
	LOAD T2,FILATL,(JFN)	;GET POINTER TO ATTRIBUTE LIST
	HRL T3,NTOBJ		;GET OBJECT
	HRR T3,NTDSC		;GET DESCRIPTOR COUNT
	MOVE T4,NTDSS		;GET DESCRIPTOR POINTER
	CALL CRTLNK		;GO CREATE THE LOGICAL LINK
	 RETBAD (,<CALL CLENUP>) ;FAILED
	RETSKP			;DONE, RETURN SUCCESS


;CLENUP - ROUTINE TO CLEAN UP JFN BLOCK IF OPEN OF DCN: FAILS
;
;ACCEPTS IN JFN/ OFFSET TO JFN BLOCK
;		CALL CLENUP
;RETURNS: +1 ALWAYS

CLENUP:	STKVAR <CLNERR>
	MOVEM T1,CLNERR		;SAVE ERROR CODE
	DECR DCCUR		;ONE LESS LINK ON FAILURE
	MOVE T1,FILLLB(JFN)	;GET ADDRESS OF LOGICAL LINK BLOCK
	CALL DELNOD		;FREE THE NODE
	HLRZ T1,FILWND(JFN)	;GET WINDOW PAGE ADDRESS
	SKIPE T1		;ANY WINDOW PAGE ASSIGNED YET ?
	CALL RELPAG		;YES, RELEASE IT
	HRRZ T1,FILWND(JFN)	;GET OTHER WINDOW PAGE
	SKIPE T1		;ANY ASSIGNED ?
	CALL RELPAG		;YES, RELEASE IT ALSO
	SETZM FILBFI(JFN)	;PREVENT RELEASE OF SPACE BY RLJFN
	CALL ULOKLL		;UNLOCK THE LL TREE
	MOVE T1,CLNERR		;RESTORE ERROR CODE
	RET
SUBTTL	MTOPR Routines

NTMTOP:	TQNN <OPNF>		;CHECK FOR OPENED
	RETBAD (CLSX1)		;NO IT IS ILLEGAL
	CALL NETINP		;SET UP FOR INPUT
	MOVE T1,FILLLB(JFN)	;MUST LOCK UP BLOCK
	CALL BLKLLK		;DO IT
	 JRST [	TQO BLKF	;CANNOT LOCK IT, INDICATE BLOCK NEEDED
		RET ]		;RETURN AND TRY AGAIN LATER
	XCTU [HRRZ T2,2]	;GET FUNCTION CODE
	MOVSI T3,-NTMTCT	;SCAN TABLE FOR THE FUNCTION
NTMTO1:	HLRZ T4,NTMTTB(T3)	;GET NEXT ENTRY
	CAIN T2,0(T4)		;IS THIS IT?
	JRST [	HRRZ T2,NTMTTB(T3) ;GET DISPATCH ADDRESS
		JRST 0(T2)]	;AND GO DO IT
	AOBJN T3,NTMTO1		;DO ENTIRE TABLE
	MOVE T1,FILLLB(JFN)	;GET LOGICAL LINK BLOCK ADDRESS
	CALL BLKULK		;UNLOCK THE BLOCK
	RETBAD (MTOX1)		;FAIL

NTMTTB:	.MOACN,,MTASGN		;SET CONNECT INTERRUPT
	.MORLS,,NTSTS		;READ LINK STATUS
	.MORHN,,NTRHN		;READ FOREIGN HOST NAME
	.MORTN,,NTRTN		;READ LINK TASK NAME
	.MORUS,,NTRUS		;READ USER STRING
	.MORPW,,NTRPW		;READ PASSWORD
	.MORAC,,NTRAC		;READ ACCOUNT STRING
	.MORDA,,NTRDA		;READ OPTIONAL DATA
	.MORIM,,MTRDIN		;READ INT MESSAGE
	.MOSIM,,MTSNIN		;SEND INT MESSAGE
	.MOROD,,NTRCOB		;READ OBJ-DESC OF CONNECT OBJECT
	.MOCLZ,,NTMTCZ		;CLOSE/REJECT A CONNECTION
	.MOCC,,NTACPT		;ACCEPT A CONNECTION
	.MORCN,,NTRCN		;READ CONNECT OBJECT NUMBER
	.MORSS,,MTGSS		;GET LINK SEGMENT SIZE
	.MOANT,,NTANT		;ATTACH NETWORK TERMINAL
	.MOSNH,,NTSNH		;SET NETWORK HOST FOR TERMINAL
NTMTCT==.-NTMTTB		;LENGTH OF TABLE
;ATTACH NETWORK TERMINAL TO JOB
; JFN, etc. setup by .MTOPR entry code
;returns with LL connected to terminal and JFN released
; T2/ terminal line number assigned

NTANT:	MOVE T1,FILLLB(JFN)	;GET LL BLOCK
	CALL ASMCB		;ASSIGN "MCB" TERMINAL AND CONNECT TO LL
	IFNSK.			;COULDN'T
	   MOVE T1,FILLLB(JFN)	;RETRIEVE LL BLOCK
	   CALL BLKULK		;RELEASE THE LOCK
	   RETBAD (ANTX01)	;RETURN ERROR
	ENDIF.
	UMOVEM T1,T2
	SETZ T1,
	EXCH T1,FILLLB(JFN)	;DISASSOCIATE JFN FROM LL
	SETONE LLFRK,(T1)	;NO FORK
	SETZRO <LLDRC,LLPII,LLPIC>,(T1) ;NO INTERRUPTS
	CALL BLKULK		;UNLOCK LL
	HLRZ T1,FILWND(JFN)	;GET OUTPUT WINDOW
	SKIPE T1
	CALL RELPAG		;RELEASE IT
	HRRZ T1,FILWND(JFN)	;GET INPUT WINDOW
	SKIPE T1
	CALL RELPAG		;RELEASE IT
	SETZM FILBFO(JFN)
	SETZM FILBFI(JFN)
	CALL RELJFN
	RETSKP

;SET NETWORK HOST
; T1/ JFN of LL (JFN, STS, etc setup at .MTOPR entry)
; T2/ ptr to arg block:
;	0 - size in words (including this one)
;	1 .SHTTY - terminal ident
;	2 .SHESC - flags,,escape char
; returns with line connected to LL, JFN unchanged

NTSNH:	SAVEAC <Q1>
	UMOVE Q1,T3		;GET ARG PTR
	UMOVE T1,.SHTTY(Q1)
	CALL [	SAVEAC <JFN,STS,DEV> ;KEEP THESE FOR ORIGINAL JFN
		CALLRET CHKTTM]	;GET LINE NUMBER IN T2
	IFNSK.			;COULDN'T
	   MOVE T1,FILLLB(JFN)	;RETRIEVE LL BLOCK
	   CALL BLKULK		;RELEASE THE LOCK
	   RETBAD (ANTX01)	;RETURN ERROR
	ENDIF.
	MOVE T1,FILLLB(JFN)
	UMOVE T3,.SHESC(Q1)	;GET ESC CHAR AND FLAGS
	CALL TTSETH
	IFNSK.
	  CALL BLKULK		;FAILED, UNLOCK LL
	  RETBAD()
	ENDIF.
	CALL BLKULK		;UNLOCK LL
	RETSKP
;SET INTERRUPT CHANNEL NUMBERS

MTASGN:	ACVAR <W1>		;GET A WORK REG
	UMOVE W1,3		;GET ARGUMENT
	LOAD T2,MO%CDN,W1	;GET CONNECT INTERRUPT
	CALL MTSETC		;GO SET IT
	 JRST NTMERR		;BAD
	LOAD T2,MO%INA,W1	;GET INT CHANNEL
	CALL MTSETI		;GO DO INT CHANNEL
	 JRST NTMERR		;BAD
	LOAD T2,MO%DAV,W1	;GET DATA CHANNEL
	CALL MTSETD		;SET IT
	 JRST NTMERR		;BAD
	CALL BLKULK		;FREE BLOCK
	RETSKP			;AND DONE

; HERE ON AN ERROR SETTING THE INTERRUPT CHANNELS

NTMERR:	EXCH T1,FILLLB(JFN)	;SAVE ERROR CODE, GET LL BLOCK ADDRESS
	CALL BLKULK		;UNLOCK THE BLOCK
   IFN NSPSW,<
	CALL CHKLLB
   >
	EXCH T1,FILLLB(JFN)	;RESTORE LL BLOCK ADDRESS, GET ERROR CODE
	RETBAD ()		;FAIL

	ENDAV.			;END ACVAR
;READ LINK STATUS

NTSTS:	CALL RDSTS		;GO GET THE STATUS
	UMOVEM T3,3		;RETURN RESULT
	CALL BLKULK		;FREE BLOCK
	RETSKP			;AND DONE
;UNDO OUTPUT

NETUOU::TQZN <FILOUP>		;NOW DOING OUTPUT?
	RET			;NO. ALL DONE
	MOVE T1,FILLLB(JFN)	;GET LL BLOCK
	CALL SKPFLO		;IS FLOW FROM THE FILE-SYSTEM ?
	 RET			;NO. DONE
	MOVE T1,FILCNT(JFN)	;GET COUNT
	SKIPGE T1
	SETZM T1		;ONLY ALLOW DOWN TO ZERO
	HRLM T1,FILBCT(JFN)	;STORE NEW COUNT
	MOVE T1,FILBYT(JFN)	;GET BYTE POINTER
	MOVEM T1,FILBFO(JFN)	;SAVE IT
	RET			;DONE

;UNDO INPUT

NETUIN::TQZN <FILINP>		;NOW DOING INPUT?
	RET			;NO. ALL DONE
	MOVE T1,FILLLB(JFN)	;GET LL BLOCK
	CALL SKPFLI		;IS FLOW TO THE FILE-SYSTEM ?
	 RET			;NO. ALL DONE
	MOVE T1,FILCNT(JFN)	;GET COUNT
	SKIPGE T1		;VALID COUNT?
	SETZM T1		;ONLLY ALLOW DOWN TO ZERO
	HRRM T1,FILBCT(JFN)	;SAVE IT
	MOVE T1,FILBYT(JFN)	;GET BYTE POINTER
	MOVEM T1,FILBFI(JFN)	;SAVE IT
	RET			;AND DONE
SUBTTL	Sequential I/O JSYS's.

;SEQUENTIAL OUTPUT.

NETSQO:	ASUBR <NETCHR>		;SAVE THE CHARACTER
	MOVE T1,FILLLB(JFN)	;GET LL BLOCK ADDRESS
	CALL BLKLLK		;LOCK IT UP
	 JRST [	TQO <BLKF>	;CANNOT LOCK IT,
		RETBAD() ]	; WAIT UNTIL LOCK IS FREE
	CALL GETSTA		;GO GET CURRENT LOGICAL LINK STATE
	JRST @SQOSTA-1(T2)	;AND DO PROPER THING

NETSQ1::SOSGE FILCNT(JFN)	;HAVE ANY CHARACTERS?
	JRST [	CALL OUTRR	;AND SEND SOME MESSAGES
		 RETBAD()	;FAILED
		CALL NETOUP	;SET UP FOR OUTPUT
		MOVE T1,FILLLB(JFN) ;GET BACK LL BLOCK
		JRST NETSQ1]	;AND TRY AGAIN
	MOVE T2,NETCHR		;GET BYTE
	IDPB T2,FILBYT(JFN)	;STASH BYTE
	CALLRET BLKULK		;RELEASE BLOCK AND RETURN

;FORCE OUT ALL BUFFERED CHARACTERS. CALLED FROM SOUTR

NETSQR:	MOVE T1,FILLLB(JFN)	;GET LL BLOCK ADDRESS
	CALL BLKLLK		;LOCK IT
	 JRST [	TQO <BLKF>	;CANNOT LOCK IT,
		RETBAD() ]	; WAIT UNTIL LOCK IS FREE
	CALL GETSTA		;GO GET CURRENT LOGICAL LINK STATE
	JRST @SQOOTR-1(T2)	;DO WORK

NETSR1::CALL SETEOM		;NOTE THAT NEXT OUTPUT IS AN ENTIRE MESSAGE
	CALL OUTRR		;DO THE WORK
	 RETBAD()		;FAILED
	MOVE T1,FILLLB(JFN)	;GET BACK LL BLOCK
	CALL BLKULK		;UNLOCK BLOCK
	RETSKP			;AND RETURN GOOD
SUBTTL	NSP Initialization


;NAMINI INITIALIZES NODE NAME TO "TOPS20"

	RESCD

NAMINI::UNLOCK NODLOK		;INIT THE "REACHABLE NODES TABLE" LOCK
	UNLOCK NMAPLK		;INIT THE "NODE NAME MAPPING TABLE" LOCK
	DMOVE T1,[ASCIZ /TOPS20/] ;GET OUR DEFAULT NODE NAME
	DMOVEM T1,OURNAM	;SET IT (ASSUME SETSPD HASN'T RUN YET!)
	MOVEI T1,6		;COUNT OF CHARS IN "OURNAM"
	MOVEM T1,OURCNT		;STORE IT (OURNAM COPIED TO LLSR EVEN ON
				;NON-DECNET SYSTEMS, AND .SJLL,
				;.JILLO REFERENCE IT!)
	MOVEI T1,NODNUM		;GET OUR DEFAULT NODE NUMBER
	MOVEM T1,OURNUM		;SET IT
	CALL ININOD		;INIT REACHABLE NODES TABLE
	 BUG(NDINIT)
	RET

;ROUTINE TO INIT NETWORK DATA BASES,ETC.

	SWAPCD			;SWAPPABLE

NSPINI::ACVAR <INDEX>		;INDEX INTO ACKLST
	MOVEI INDEX,AKLSTL-1	;GET LENGTH OF ACK LIST
NSPIN1:	MOVEI T1,ACKLEN+MSHDR	;GET NUMBER OF WORDS NEEDED FOR AN ACK MSG
	CALL GETRES		;GET THE SPACE
	IFSKP.			;OK
	   MOVEM T1,ACKLST(INDEX)  ;SAVE THE ADDRESS
	ELSE.			;COULDN'T GET SPACE
	   SETZM ACKLST(INDEX)	;NO ENTRY IN LIST
	ENDIF.
NSPIN2:	SOJGE INDEX,NSPIN1	;IF NOT DONE, GO GET ANOTHER
	UNLOCK LLLLCK		;UNLOCK LOCK
	UNLOCK OUTLOK		;INITIALIZE LOCK ON BACKGROUND TASK'S QUEUE
	MOVX T1,INIWAT		;GET TIME BEFORE BLOCKED OUTPUT RETRY
	MOVEM T1,OUTIVL		;SAVE DEFAULT TIME INTERVAL
	CALL OBJINI		;INIT OBJECT TABLE
	CALL LLINIT		;AND INIT LL ADDRESS BIT TABLE
	MOVEI T1,SEGSIZ		;GET DEFAULT SEGMENT SIZE
	MOVEM T1,SEGSZ		;SET IT UP
	MOVEI T1,NSINTM		;GET DEFAULT INACTIVITY TIMEOUT VALUE
	MOVEM T1,NSINAC		;SET IT UP
	MOVEI T1,NSLDWD		;GET DEFAULT LOCAL DELAY WEIGHT
	MOVEM T1,NSLDWS		;SET IT
	MOVEI T1,NSLDFD		;GET DEFAULT LOCAL DELAY FACTOR
	MOVEM T1,NSLDFS		;SET IT
	MOVEI T1,NSTRYD		;GET DEFAULT RETRANSMIT COUNT
	MOVEM T1,NSTRYS		;SET IT
	SETZM LSTINT		;INIT THE INACTIVITY TIME CHECKER
	MOVX T1,1B1		;MAKE FORK HAVE ALL CAPS
	SETZ T2,
	CFORK			;GET A FORK
	 BUG (NSPFRK,<<T1,REASON>>)
	MOVEI T2,TSKINI		;THE STARTING ADDRESS
	MSFRK			;START IT
	MOVX T2,FRKRUN		;SAY FORK IS RUNNING
	IORM T2,MCBDTE		;SET FLAG
	RET			;DONE

	ENDAV.
; INITIALIZE TABLE OF KNOWN NODES

ININOD:	NOINT			;NO INTERRUPTIONS
	LOCK NODLOK		; WHILE TABLE IS LOCKED
	SETZM NODTBL		;ZERO
	HRLI T1,NODTBL		; THE
	HRRI T1,NODTBL+1	;  ENTIRE
	BLT T1,NODTBL+<BIGNOD/22>  ;   TABLE
	UNLOCK NODLOK		;DONE WITH
	OKINT			; THE LOCK
	MOVE T1,OURNUM		;GET OUR NODE NUMBER
	MOVX T2,.NDSON		;SAY NODE IS TO BE ADDED
	MOVEI T3,2		;WE ARE PHASE II
	CALL ADDNOD		;PUT US IN
	 RETBAD ()		;FAILED
	RETSKP			;SUCCESS
;ADDNOD - ROUTINE TO ADD A NODE TO THE TABLE OF REACHABLE NODES
;
;ACCEPTS: T1/ NODE NUMBER
;	  T2/ STATE OF NODE
;	  T3/ 2 - IF DECNET PHASE II
;	      3 - IF DECNET PHASE III
;
;RETURNS: +1	FAILED
;	  +2	SUCCESS, NODE ADDED IF NOT ALREADY IN TABLE

ADDNOD:	CAIN T2,.NDSOF		;NODE OFF?
	JRST [CALL REMNOD	;YES, REMOVE FROM REACHABLE NODES TABLE
	       RET		;FAILED
	      JRST ADDTEL]	;NOTIFY INTERESTED USERS OF TOPOLOGY CHANGE
	NOINT			;NO INTERRUPTIONS
	LOCK NODLOK		; WHILE TABLE LOCKED
	MOVE T4,[POINT 2,NODTBL]  ;MAKE BYTE POINTER TO TABLE
	ADJBP T1,T4		;POINT TO THE NODE BEING ADDED
	DPB T3,T1		;INSERT DECNET PHASE
	UNLOCK NODLOK		;DONE WITH
	OKINT			; THE LOCK

;HERE TO NOTIFY INTERESTED USERS THAT TOPOLGY HAS CHANGED

ADDTEL:	MOVEI Q1,NTCTAB		;START LOOKING AT TOP OF TABLE
NTCIN1:	SKIPN (Q1)		;IS THERE AN ENTRY?
	JRST NTCIN2		;NO. KEEP LOOKING.
	LOAD T2,NTCFRK,(Q1)	;GET FORK NUMBER
	LOAD T1,NTCCHN,(Q1)	;GET THE CHANNEL NUMBER
	CALL PSIRQ		;INTERRUPT USER
NTCIN2:	CAIE Q1,NTCTAB+<NTCMAX-1>	;DID WE SEARCH WHOLE TABLE?
	AOJA Q1,NTCIN1		;NO - CHECK NEXT ENTRY
	RETSKP
;REMNOD - ROUTINE TO REMOVE A NODE FROM THE TABLE OF REACHABLE NODES
;
;ACCEPTS IN T1/	NODE NUMBER
;
;RETURNS: +1	FAILED
;	  +2	SUCCESS

REMNOD:	NOINT			;NO INTERRUPTIONS
	LOCK NODLOK		; WHILE TABLE LOCKED
	MOVE T2,[POINT 2,NODTBL]  ;MAKE BYTE POINTER TO TABLE
	ADJBP T1,T2		;POINT TO THE NODE WE WANT
	SETZ T3,		;INIT TEST WORD
	DPB T3,T1		; NO LONGER REACHABLE
	UNLOCK NODLOK		;DONE WITH
	OKINT			; THE LOCK
	RETSKP
SUBTTL	Routines to Manipulate Logical Link Blocks and Object Tables

	RESCD			;CALLED ONLY IN PROCESS CONTEXT

;ROUTINES USED TO LOCK AND UNLOCK LL TREE

LOKLL::
	SKIPN INSKED		;SKED LEVEL?
	NOINT			;PREVENT INTS
	LOCK LLLLCK,<CALL LCKTST> ;LOCK UP THE TREE
	RET			;DONE

ULOKLL::SKIPGE LLLLCK		;NOW LOCKED?
	JRST [	BUG(LLLKBD)	;NO, CONFUSION
		RET]
	UNLOCK LLLLCK
	SKIPN INSKED
	OKINT
	RET
;ROUTINES TO LOCK AND UNLOCK INDIVIDUAL LL BLOCKS

;LOCK A BLOCK.
;	T1/ BLOCK ADDRESS
;RETURNS:	+1 FAILED. BLOCK ROUTINE IN T1
;		+2 SUCCESS

;ENTRY POINT IF LLLLCK NOT LOCKED

BLKLLK::NOINT
	LOCK LLLLCK,<JRST [
		MOVEI T1,LLLCKT	;BUSY, RETURN TEST
		RET]>
	CALL BLKLOK
	 CALLRET ULOKLL		;UNLOCK AND GIVE UP
	CALL ULOKLL
	RETSKP

;ENTRY POINT IF LLLLCK ALREADY LOCKED

BLKLOK::SAVEAC <T4>		;PRESERVE TEMP AC
REPEAT 0,<
	SKIPGE LLLLCK		;*** TEMP - ENSURE OUTER LOCK ALREADY SET ***
	JSR BUGHLT
	SKIPE INSKED		;MAKE SURE ONLY PROPER SCHEDULER CONTEXT
	SKIPGE FORKX
	SKIPA
	JSR BUGHLT
>;END REPEAT 0
	JE LLRCT,(T1),BLKLK0	;IF FIRST LOCKER, NO CHECKS NEEDED
	LOAD T4,LLRFK,(T1)	;GET PREVIOUS LOCKER'S ID
	CAME T4,FORKX		;WERE WE PREVIOUS LOCKER
	JRST BLKLK1		;NO, FAIL RETURNING SCHED TEST
BLKLK0:	INCR LLRCT,(T1)		;OK TO LOCK (EITHER FIRST LOCKER OR LAST WAS US)
	MOVE T4,FORKX		;GET OUR FORK ID
	STOR T4,LLRFK,(T1)	;STORE OUR ID AS LAST LOCKER
	SKIPN INSKED
	NOINT			;PREVENT INTERRUPT WHILE BLOCK LOCKED
	RETSKP			;DONE, BLOCK NOW LOCKED

; HERE IF LOCK WILL NOT BE PERMITTED - RETURN A SCHEDULER TEST

BLKLK1:	LOAD T1,LLLNK,(T1)	;GET LL ADDRESS
	HRLS T1			;TO THE LH
	HRRI T1,CHKLOK		;THE TEST ROUTINE
	RET			;AND DONE
;UNLOCK A BLOCK
;	T1/ BLOCK ADDRESS
;RETURNS:	+1 ALWAYS

BLKULK::SAVEAC <T2>		;BE TRANSPARENT
	LOAD T2,LLRCT,(T1)	;GET LOCK COUNT
	CAIE T2,1		;OUTERMOST?
	JRST [	DECR LLRCT,(T1)	;NO, JUST DECREMENT
		JRST BLKUK1]
	SETZRO LLRFK,(T1)	;LOCK BECOMING CLEAR, CLEAR LAST FORK
	SETZRO LLRCT,(T1)
BLKUK1:	SKIPN INSKED
	OKINT
	RET

;SCHED TEST FOR ABOVE

LLLCKT:	SKIPL LLLLCK
	JRST 0(T4)		;STILL BUSY
	JRST 1(T4)		;FREE
;ROUTINE TO INIT LL ADDRESS BIT TABLE. CALLED AT SYSTEM STARTUP

LLINIT:	ACVAR <W1>		;GET A WORK REGISTER
	MOVSI W1,-MAXLNK	; GET MAX LINK VALUE
	AOS W1			;SKIP ENTRY 0
LLINI1:	HRRZ T1,W1		;GET LINK ADDRESS
	CALL FRELNK		;FREE LINK #
	AOBJN W1,LLINI1		;DO 'EM ALL
	RET			;AND DONE

	ENDAV.			;END ACVAR
;LOKPIP - ROUTINE TO LOCK AN ATS DATA DATA OR CONTROL PIPE
;
;ACCEPTS IN T3/	ATS PIPE IDENTIFIER
;		CALL LOKPIP
;RETURNS: +1	 FAILED, SCHEDULER TEST IN T1
;	  +2	SUCCESS, PROCESS NOINT AND PIPE LOCKED

LOKPIP::TRVAR <LKPCOD,LKPLLB>
	MOVEM T3,LKPCOD		;SAVE ATS ID

; GET THE ADDRESS OF THE LOGICAL LINK BLOCK

	LLLOCK			;LOCK THE LOGICAL LINK TREE
	MOVEI T1,CHKPIP		;GET COROUTINE TO FIND ATS PIPE
	SETOM T2		;ANY LINK
	CALL OBJSRC		;GO FIND BLOCK
	 JRST [	LLLULK		;DOES NOT EXIST
		BUG(NSPPWA)
		RET ]		;UNLOCK THE TREE AND RETURN FAILURE
	MOVEM T1,LKPLLB		;SAVE LOGICAL LINK BLOCK ADDRESS

; LOCK THE BLOCK

	MOVE T1,LKPLLB		;GET LOGICAL LINK BLOCK ADDRESS
	CALL BLKLOK		;GO LOCK THE LOGICAL LINK BLOCK
	 JRST [	LLLULK		;CANNOT LOCK IT NOW, UNLOCK THE TREE
		RET ]		;RETURN SCHED TEST
	LLLULK			;BLOCK IS NOW RESERVED. UNLOCK THE TREE
	RETSKP			;DONE, RETURN WITH PIPE LOCKED



;CHKPIP - COROUTINE TO FIND ATS LINK BLOCK WITH GIVEN ATS DATA PIPE
;
;ACCEPTS IN TRVAR LKPCOD/ ATS ID FOR PIPE
;	    T1/	ADDRESS OF LINK BLOCK TO CHECK
;		CALL CHKPIP
;RETURNS: +1	 NOT DESIRED BLOCK
;	  +2	SUCCESS, FOUND BLOCK WITH REQUESTED ID

CHKPIP:	SAVET			;PRESERVE TERMPORARY AC'S
	JE LLINT,(T1),R		;LOOK AT INTERNAL LINKS ONLY
	LOAD T2,LLDRV,(T1)	;GET DRIVER CORRELATION CODE
	CAME T2,LKPCOD		;DESIRED ATS ID ?
	RET			;NO, RETURN FAILURE
	RETSKP			;YES, RETURN SUCCESS
;ULKPIP - ROUTINE TO UNLOCK AN ATS DATA OR CONTROL PIPE
;
;ACCEPTS IN T3/	ATS PIPE IDENTIFIER
;		CALL ULKPIP
;RETURNS: +1 ALWAYS, WITH PIPE UNLOCKED

ULKPIP::TRVAR <LKPCOD>
	MOVEM T3,LKPCOD		;SAVE ATS ID FOR COROUTINE
	LLLOCK			;LOCK THE LOGICAL LINK TREE
	MOVEI T1,CHKPIP		;GET COROUTINE ADDRESS
	SETOM T2		;ANY LINK
	CALL OBJSRC		;GO FIND BLOCK
	 JRST [	LLLULK		;DOES NOT EXIST
		BUG(NSPPHV)
		RET ]		;UNLOCK THE TREE AND RETURN FAILURE
	LLLULK			;UNLOCK THE TREE
	CALLRET BLKULK		;UNLOCK PIPE AND RETURN
;ROUTINE TO FIND INDEX INTO LOGICAL LINK TABLES.
;ACCEPTS:	T1/ LOGICAL LINK
;		T2/ FOREIGN LINK I.D. -1 FOR ANY
;		T3/ HOST NAME STRING IF LLLKUH USED
;RETURNS:	+1 FAILED. LINK NOT FOUND
;			T1/ INSERT POINT FOR NEW ENTRY
;		+2 SUCCESS. T1/ ADDRESS OF LINK ENTRY
;			T2/ PREVIOUS NODE ADDRESS
;PRESERVES T4

	RESCD			;NEEDS TO BE RESIDENT

LLLKUP::SETOM T3		;NO HOST MATCH IF ENTERED HERE
LLLKUH:	SAVEAC <T4>		;PRESERVE AC
	STKVAR <LASTM,LNKID,LLHO> ;REMEMBER INSERT POINT
	MOVEM T3,LLHO		;SAVE HOST STRING POINTER
	SETZM LASTM		;NO INSERT FOUND YET
	MOVEM T1,LNKID		;SAVE DESIRED ADDRESS
	MOVE T1,LLHEAD		;GET HEAD OF TREE
LLLKU1:	JUMPE T1,LLFAIL		;NO THERE. ERGO, NOT FOUND
	LOAD T3,LLLNK,(T1)	;GET THE LINK I.D.
	CAME T3,LNKID		;IS THIS IT?
	JRST [	MOVEM T1,LASTM	;REMEMBER THIS AS INSERT POINT
		CAMG T3,LNKID	;NEED TO GO UP OR DOWN?
		JRST [	LOAD T1,LLUPL,(T1) ;GET UP POINTER
			JRST LLLKU1] ;AND GO SEE ABOUT IT
		LOAD T1,LLDWN,(T1) ;DOWN. GET DOWN POINTER
		JRST LLLKU1]	;AND GO SEE ABOUT IT
	JUMPL T2,LLLKU2		;IF NO HOST CHECK, FOUND IT
	OPSTR <CAME T2,>,LLHLK,(T1) ;DOES THE HOST MATCH?
	RETBAD (NSPX2)		;NO. GIVE ERROR
LLLKU2:	MOVE T2,LASTM		;RETURN PREVIOUS NODE
	SKIPG LLHO		;WANT HOST MATCH?
	RETSKP			;NO. ALL DONE THEN
	LOAD T2,LLHST,(T1)	;GET HOST STRING
	EXCH T1,LLHO		;SAVE LINK. GET SOURCE HOST NAME
	CALL CMPSTR		;DO COMPARE
	 RETBAD (NSPX2)		;NO MATCH
	MOVE T1,LLHO		;A MATCH. GET LINK
	MOVE T2,LASTM		;GET PREVIOUS
	RETSKP			;AND DONE

;COULDN'T FIND REQUIRED LINK. RETURN INSERT POINT

LLFAIL:	MOVE T1,LASTM		;FOUND AN INSERT POINT?
	RET			;AND RETURN
;ALL OF THIS CODE IS UNSUITABLE FOR EXTENDED ADDRESSING. SINCE
;OBJECT NAMES CAN RESIDE IN SWAPPABLE FREE SPACE, OBJTBL
;NEEDS TO HAVE 36 BIT ADDRESSES POINTING TO THE STRINGS. ALSO,
;A REPLACEMENT FOR TBLUK IS NEEDED WHICH WILL DO LOOK UP, DELETE
;AND ADD ENTRIES TO SUCH AN "EXTENDED" TABLE. FOR THE TIME BEING,
;HOWEVER, THE CODE AS WRITTEN WILL SUFFICE.

;ROUTINE TO INITIALIZE THE OBJECT TABLE FOR THE MONITOR.

	SWAPCD

OBJINI:	MOVE T1,[OBJPRO,,OBJTBL]
	BLT T1,OBJTBL+OBJENT	;INIT THE TABLE
	RET			;AND DONE

;THIS TABLE SHOULD BE MOVED TO STG SOMEDAY*****************
;PROTOTYPE OBJECT TABLE

OBJPRO:	OBJENT,,OBJMAX
	[ASCIZ /ATS/],,3
	[ASCIZ /FAL/],,21
	[ASCIZ /NCU/],,23
	[ASCIZ /NRM/],,7
	[ASCIZ /TASK/],,0
OBJENT==.-OBJPRO-1		;# OF ENTRIES

;ROUTINE TO LOOK UP AN OBJECT NAME IN THE SYSTEM OBJECT TABLES
;ACCEPTS:	T1/ POINTER TO TEST OBJECT NAME
;RETURNS:	+1 NOT FOUND. NO SUCH OBJECT
;		+2 OBJECT FOUND
;			T1/ OBJECT NUMBER

OBJLOK::ASUBR <OBJPTR>		;SAVE POINTER
	MOVE T2,T1		;COPY POINTER
	MOVE T1,[OBJTBL]	;GET THE OBJECT TABLE
	TBLUK			;LOOK UP THE OBJECT
	TXNN T2,TL%EXM		;FOUND IT?
	JRST OBJLO1		;NO. GO CHECK FOR NUMBER
	HRRZ T1,0(T1)		;YES. GET OBJECT NUMBER
	RETSKP			;AND RETURN WITH IT

;TBLUK DIDNT'T FIND IT. SEE IF IT IS NUMERIC

OBJLO1:	SETZ T1,		;GET AN ACCUMULATOR
OBJLO2:	ILDB T2,OBJPTR		;GET NEXT BYTE
	JUMPE T2,RSKP		;IF AT THE END, GOOD NUMBER
	CAIL T2,"0"		;A VALID NUMBER
	CAILE T2,"9"		;STILL?
	RET			;NO. NOT A VALID NUMBER
	IMULI T1,^D10		;YES. ADJUST ACCUMULATOR
	ADDI T1,-"0"(T2)	;AND ADD IN NEW QUANTITY
	CAILE T1,OBJMAX		;STILL VALID?
	RET			;NO. GIVE AN ERROR
	JRST OBJLO2		;GO DO ALL OF IT
;ROUTINE TO FIND A "LISTENING" OR ACTIVE OBJECT IN THE LOGICAL
;LINK TABLE. WILL ALSO DO SCAN OF ENTIRE TREE
;ACCEPTS:
;	T1/ COUROUTINE ADDRESS TO CALL WHEN OBJECT IS FOUND
;	T2/ 0 IF OBJECT MAY BE LISTENING OR ACTIVE
;		1 IF OBJECT MUST BE LISTENING ONLY
;		-1 IF ANY LINK IS ACCEPTBLE
;RETURNS:
;	+1 OBJECT NOT FOUND
;	+2 OBJECT FOUND.
;		T1/ POINTER INTO LINK TABLE FOR THIS OBJECT
;		T2/ LINK I.D. OF THE OBJECT

;THE COROUTINE IS CALLED TO CHECK IF THE OBJECT IS THE ONE
;WANTED. THE COROUTINES ARE CALLED WITH THE FOLLOWING ARGS:
;	T1/ ADDRESS OF LOGICAL LINK ENTRY
;	ALL OF THE P AND Q REGISTERS INTACT
;THE COROUTINES RETURN AS FOLLOWS:
;	+1 DON'T WANT THIS OBJECT
;	+2 THIS IS THE ONE
;THE COROUTINE MUST PRESERVE ALL TEMPORARY AC'S

OBJSRC::SETZM GUDOBJ		;INIT "GOOD OBJECT" FLAG
	DMOVE T3,T1		;SAVE ARGS
	SKIPN T1,LLHEAD		;ANY LINKS?
	JRST [MOVEI T2,.DCX4	;NO, SAY "DESTINATION PROCESS
	      RET]		; DOES NOT EXIST"
	PUSH P,[0]		;PUT A "FENCE" ON THE STACK
OBJSND:	PUSH P,T1		;SAVE THIS ONE
	JUMPL T4,OBJSN2		;IF ANY MATCH, GO HANDLE THIS ONE
	JE LLFOB,(T1),OBJSNO	;IF NOT OBJECT, CAN'T BE A MATCH
OBJSN2:	JUMPE T3,OBJSFD		;IF NO COROUTINE, DONE
	CALL 0(T3)		;CALL THE COROUTINE
	SKIPA			;NOT THE ONE
	JRST OBJSFD		;FOUND IT
OBJSNO:	LOAD T1,LLUPL,(T1)	;NOT THE ONE. GET THE UP POINTER
	JUMPN T1,OBJSND		;HAVE ONE. GO LOOK AT IT
OBJSN1:	POP P,T1		;NOT FOUND. GET PREVIOUS ONE
	JUMPE T1,[MOVEI T2,.DCX4	;NO MORE, SAY "DESTINATION PROCESS
	          SKIPE GUDOBJ		; DOES NOT EXIST"
	          MOVEI T2,.DCX33	;OR "TOO MANY CONNECTIONS"
	           RET]
	LOAD T1,LLDWN,(T1)	;GET DOWN SIDE
	JUMPN T1,OBJSND		;IF HAVE ONE, GO LOOK AT IT
	JRST OBJSN1		;IF NOT, KEEP POPING

;FOUND THE OBJECT

OBJSFD:	SETOM GUDOBJ		;FOUND THE RIGHT SERVER
	JUMPG T4,[LOAD T2,LLSTA,(T1)	;GET LL STATE
	          CAIE T2,LLSLIS	;IS IT LISTENING?
	          JRST OBJSNO		;NO, TRY AGAIN
	          JRST .+1]		;YES, EVERYTHING OK
	POP P,T2		;MUST CLEAN UP THE STACK
	JUMPN T2,.-1		;KEEP CLEANING
	LOAD T2,LLLNK,(T1)	;GET LOGICAL LINK I.D.
	RETSKP			;DONE. RETURN GOOD
;ROUTINE TO GET A UNIQUE TASK NAME.
;ACCEPTS:	T1/ LL POINTER
;		LL TREE MUST BE LOCKED
;RETURNS:	+1 ALWAYS
;		LLTSK FILLED IN WITH NAME
;PRESERVES T1

GETTSK:	TRVAR <LLADDR,TSKBLK>
	MOVEM T1,LLADDR		;SAVE LL BLOCK ADDRESS
	MOVEI T1,3		;NEED A BLOCK OF THIS SIZE
	CALL GETBLK		;GO GET A BLOCK
	 RET			;NO MORE SPACE
	MOVEM T1,TSKBLK		;SAVE ADDRESS
GETTS1:	HRLI T1,(<POINT 7,>)	;MAKE A BYTE POINTER
	AOS T2,LASTSK		;GET A NUMBER FOR THE TASK NAME
	MOVEI T3,10		;CONVERT OCTAL
	NOUT			;MOVE NUMBER
	 JFCL			;WILL WORK
	XMOVEI T1,TSKLOK	;MAKE SURE IS UNIQUE
	SETOM T2		;ANY LINK
	CALL OBJSRC		;GO LOOK FOR A MATCH
	 JRST [	MOVE T1,LLADDR
		MOVE T2,TSKBLK	;GET BLOCK ADDRESS
		STOR T2,LLTSK,(T1)
		RETSKP]		;AND DONE
	MOVE T1,TSKBLK		;FOUND IT
	JRST GETTS1		;TRY AGAIN

;COROUTINE TO CHECK FOR TASK MATCH

TSKLOK:	SAVET			;SAVE ALL TEMPS
	LOAD T2,LLTSK,(T1)	;GET THIS ONE'S ADDRESS
	JUMPE T2,R		;IF NONE, CAN'T BE IT
	MOVE T1,TSKBLK		;GET BLOCK ADDRESS
	CALLRET CMPSTR		;GO DO THE COMPARE
;COLLECTION OF UTILITIES

;MOVE ONE STRING TO ANOTHER.
;ACCEPTS:	T1/ DEST STRING BLOCK
;		T2/ SOURCE STRIGN BLOCK
;		T3/ COUNT OR -1
;RETURNS:	+1 ALWAYS.
;ALL REGISTERS PRESERVED

MOVSTR::SAVET			;SAVE ALL TEMPS
	ACVAR <W1,W2>		;GET SOME WORK REGS
	MOVE W1,[POINT 7,0(T1)]
	MOVE W2,[POINT 7,0(T2)]	;SET UP ARGS
MOVST0:	ILDB T4,W2		;GET NEXT BYTE
	IDPB T4,W1		;STASH IT
	JUMPE T4,R		;IF NULL, ALL DONE
	JUMPL T3,MOVST0		;IF NO COUNT, KEEP GOING
	SOJG T3,MOVST0		;MORE IN THE COUNT?
	RET			;NO. ALL DONE

	ENDAV.			;END ACVAR

;ROUTINE TO "FREE" A LL ADDRESS.
;ACCEPTS:	T1/ LL ADDRESS TO FREE
;RETURNS:	+1 ALWAYS

FRELNK:	ANDI T1,MAXLNK		;ISOLATE LOCAL INDEX
	IDIVI T1,44		;COMPUTE WORD AND OFFSET
	ADD T1,[LLBITS]		;GET BIT TABLE OFFSET
	MOVE T2,BITS(T2)	;GET A BIT
	IORM T2,0(T1)		;TURN OF THE BIT
	RET			;AND DONE
;ROUTINES TO GET AND RETURN SWAPPABLE FREE SPACE

;ROUTINE TO GET A BLOCK FROM THE LL STRING SPACE POOL
;ACCEPTS:	T1/ SIZE TO GET
;RETURNS:	+1 FAILED. T1/ERROR CODE
;		+2 SUCCESS T1/ BLOCK ADDRESS

GETBLK::MOVEI T2,1(T1)		;ACCOUNT FOR HEADER
	ADD T2,BLKASG		;COMPUTE AMOUNT THIS WOULD MAKE
	CAILE T2,MAXBLK		;WITHIN BOUNDS?
	RETBAD (MONX06)		;NO. INSUFFICIENT RESOURCES - NO SWAPPABLE FREE SPACE
	AOS T1			;GET SPACE +1
	CALL ASGSWP		;GET SOME SPACE
	 RETBAD			;FAILED. GIVE IT UP
	HRRZ T2,0(T1)		;GET COUNT ASSIGNED
	ADDM T2,BLKASG		;ACCOUNT FOR IT
	AOS T1			;POINT TO FIRST USEFUL BLOCK
	RETSKP			;AND GOOD

;ROUTINE TO RETURN A STRING BLOCK
;ACCEPTS:	T1/ ADDRESS OF FIRST DATA LOCATION (HEADER+1)
;RETURNS:	+1 ALWAYS

RELBLK::SOS T1			;POINT TO HEADER
	HRRZ T2,0(T1)		;GET WORDS IN THIS BLOCK
	EXCH T2,BLKASG
	SUBM T2,BLKASG		;COMPUTE NEW COUNT
	HRRZ T2,0(T1)		;GET SIZE OF THE BLOCK AGAIN
	CALLRET RELSWP		;RELEASE THE BLOCK

;ROUTINE TO GET A RESIDENT FREE SPACE BLOCK
;ACCEPTS:	T1/ SIZE REQUIRED

	RESCD

GETRES::HRLI T1,.RESP3		;IN PROCESS CONTEXT
	SKIPE INSKED		;SKED CONTEXT?
	HRLI T1,.RESP2		;YES, NO PAGE FAULTS PLEASE
	MOVE T2,[RS%SE0!.RESNP]	;FROM THE NETWORK
	CALL ASGRES		;GET SOME SPACE
	 RETBAD()		;COULDN'T
	RETSKP			;GOT IT

	SWAPCD

;ROUTINE TO MOVE A STRING FROM JSB FREE SPACE TO SWAPPABLE FREE SPACE.
;ACCEPTS:	T1/ DESTINATION BLOCK ADDRESS
;		T2/ SP TO JSB FREE SPACE
;		T3/ COUNT
;CLOBBERS ALL TEMPS

MOVST1::STKVAR <MVSPTR>
	MOVE T4,[POINT 7,0(T1)]	;FORM STRING POINTER
	MOVEM T4,MVSPTR		;SAVE POINTER
MOVST2:	ILDB T4,T2		;GET A BYTE
	IDPB T4,MVSPTR		;STORE IT
	SOJG T3,MOVST2		;DO ALL BYTES
	RET			;DONE
SUBTTL	Logical Link Creation

; ROUTINES TO SET INPUT/OUTPUT FLAGS IN LOGICAL LINK BLOCKS
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS
;		CALL SETOPI/SETOPW
;RETURNS: +1 ALWAYS

SETOPI::SETONE LLOPI,(T1) 	;SET INPUT FLAG
	RET			;DONE, RETURN


SETOPW::SETONE LLOPW,(T1)	;SET OUTPUT FLAG
	RET			;DONE, RETURN


; ROUTINES TO TEST THE DIRECTION OF I/O
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS

SKPFLO::JE LLFLO,(T1),R		;NON-SKIP IF FLOW NOT FROM FILE-SYSTEM
	RETSKP			;SKIP IF FLOW IS FROM THE FILE-SYSTEM


SKPFLI::JE LLFLI,(T1),R		;NON-SKIP IF FLOW NOT TO THE FILE-SYSTEM
	RETSKP			;SKIP if FLOW IS TO THE FILE-SYSTEM


; ROUTINES TO SET/CLEAR DIRECTION-OF-FLOW BITS

CLRFLO::SETZRO LLFLO,(T1) 	;SWITCH FLOW TO BE "TO THE NETWORK"
	RET			;DONE, RETURN

SETFLO::SETONE LLFLO,(T1) 	;SWITCH FLOW TO BE "FROM FILE-SYSTEM"
	RET			;DONE, RETURN


;GETBSZ - ROUTINE TO OBTAIN THE BYTE SIZE FOR A LOGICAL LINK
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS
;	    	CALL GETBSZ
;RETURNS: +1 ALWAYS, WITH T3/ BYTE SIZE
;
; PRESERVES LOGICAL LINK BLOCK ADDRESS IN T1

GETBSZ::LOAD T3,LLBSZ,(T1)	;GET BYTE SIZE
	RET			;DONE, RETURN


;GETSTA - ROUTINE TO RETURN CURRENT STATE OF A LOGICAL LINK
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS
;		CALL GETSTA
;RETURNS: +1 ALWAYS, WITH T2/ LINK STATE
;
; PRESERVES LOGICAL LINK BLOCK ADDRESS IN T1

GETSTA::LOAD T2,LLSTA,(T1)	;GET CURRENT STATE
	RET



;SETEOM - ROUTINE TO SET "END-OF-MESSAGE-NEEDED" FLAG FOR A LOGICAL LINK
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL SETEOM
;RETURNS: +1 ALWAYS

SETEOM::SETONE LLFEM,(T1)	;SAY SHOULD GET EOM ON OUTPUT
	RET			;DONE, RETURN


;GETMXS - ROUTINE TO GET MAX SEGMENT SIZE
;
;ACCEPTS IN T1/ LOGICAL LINK BLOCK ADDRESS


GETMXS::LOAD T4,LLSWG,(T1)	;GET MAX SEG SIZE
	RET			;DONE, RETURN
;WORK ROUTINES TO OPEN DCN: OR SRV:
;
;	OPNDWK - OPEN A FILESYSTEM DCN: LINK
;	OPNSWK - OPEN A FILESYSTEM SRV: LINK
;	OPNIWK - OPEN AN INTERNAL LINK
;
;ACCEPTS IN T1/	ADDRESS OF TASK STRING
;	    T2/	BYTE SIZE OF OPEN
;		CALL OPNSWK/OPNDWK
;RETURNS: +1	 FAILED, ERROR CODE IN T1
;	  +2	SUCCESS, WITH T1/ ADDRESS OF LOGICAL LINK BLOCK

OPNDWK::MOVEI T3,LKSIZE		;BASIC LL BLOCK SIZE
	JRST OPNWRK		;CALL WORK ROUTINE
OPNSWK::MOVEI T3,LKSIZE+LKOBJS	;BASIC SIZE PLUS WORDS NEEDED FOR SRV: LINKS
	JRST OPNWRK		;CALL WORK ROUTINE
OPNIWK::MOVEI T3,LKSIZE+LKISIZ	;BASIC SIZE PLUS WORDS NEEDED FOR INTERNAL LINKS
	JRST OPNWRK		;GO DO THE OPEN
;OPNWRK - WORK ROUTINE TO OPEN A LOGICAL LINK
;
;ACCEPTS IN T1/	ADDRESS OF TASK STRING
;	    T2/	BYTE SIZE OF OPEN
;	    T3/	SIZE OF LOGICAL LINK BLOCK NEEDED
;		CALL OPNWRK
;RETURNS: +1	 FAILED, ERROR CODE IN T1
;	  +2	SUCCESS, WITH T1/ ADDRESS OF LOGICAL LINK BLOCK

OPNWRK:	TRVAR <SAVBLK,SAVERR,SAVSTR,SAVBSZ>
				; NOTE: TRVAR IS NEEDED HERE INSTEAD OF STKVAR
				;	BECAUSE COROUTINES ACCESS THE VARIABLES.
	MOVEI T4,.RESNP		;GET DECNET POOL NUMBER
	MOVE T4,RESUTB(T4)	;GET NUMBER OF BLOCKS LEFT
	CAIG T4,RESHLD		;LOW ON SPACE?
	RETBAD (MONX05)		;YES, NO MORE LINKS NOW
	MOVEM T1,SAVSTR		;SAVE STRING BLOCK ADDRESS
	MOVEM T2,SAVBSZ		;SAVE BYTE SIZE
	MOVX T2,FRKRUN		;SEE IF NETWORK IS INTIALIZED
	TDNN T2,MCBDTE		;IS IT?
	RETBAD (DCNX11)		;NO. ILLEGAL TO USE IT THEN
	MOVE T1,T3		;COPY # OF ADDITIONAL WORDS NEEDED FOR LL BLOCK
	HRLI T1,.RESP3		;IN PROCESS CONTEXT
	MOVEI T2,.RESNP		;FROM THE NETWORK POOL
	CALL ASGRES		;GET A LL BLOCK
	 RET			;COULDN'T. MUST FAIL
	MOVEM T1,SAVBLK
	MOVEI T1,OPTSIZ		;SIZE OF OPTDATA BLOCK
	CALL GETBLK		;GET A BLOCK OF PROPER SIZE
	 JRST RLBLK		;COULDN'T. FREE BLOCK
	MOVE T2,SAVBLK		;GET BACK BLOCK ADDRESS
	STOR T1,LLOPT,(T2)	;SAVE BLOCK ADDRESS
	MOVE T1,T2		;GET LL BLOCK ADDRESS
	LLLOCK			;LOCK UP THE TREE
	CALL MAKLNK		;GET LL ADDRESS AND INSERT ENTRY
	 JRST [	MOVEM T1,SAVERR	;SAVE ERROR CODE
		LLLULK
		MOVE T1,SAVBLK	;GET BLOCK
		LOAD T1,LLOPT,(T1)
		CALL RELBLK	;FREE UP OPT BLOCK
		JRST RLBLK1]	;AND GET RID OF LL BLOCK
	LLLULK			;RELEASE LOCK
	; ..
;OPEN CONTINUED. CHECK QUOTA TO SEE IF CAN MAKE THIS LINK

	INCR DCCUR		;INCREMENT COUNT
	LOAD T2,DCCUR		;GET IT
	LOAD T4,DCMAX		;GET MAX COUNT ALLOWED
	CAMLE T2,T4		;NO. ALLOWED TO MAKE ANOTHER LINK?
	JRST [	MOVE T3,CAPENB	;NO, SEE IF CAPS
		TXNE T3,SC%WHL!SC%OPR
		JRST .+1	;OK
		MOVEI T1,DCNX5	;NO. GIVE ERROR
		JRST OPNFAI]	;AND GO FAIL
	MOVE T2,SAVBLK		;GET LL BLOCK ADDRESS
	MOVEI T3,LLHNM1(T2)	;GET PLACE TO PUT REMOTE HOST NAME STRING
	STOR T3,LLHST,(T2)	;SET IT
	MOVEI T1,<MAXDSC+4>/4	;A BLOCK FOR REMOTE DESCRIPTOR
	CALL GETBLK		;GET ONE
	 JRST OPNFAI		;COULDN'T
	MOVE T2,SAVBLK		;GET LL BLOCK
	STOR T1,LLFDS,(T2)	;SAVE BLOCK
	MOVE T1,SAVSTR		;GET POINTER TO EXTENSION BLOCK
	JUMPE T1,OPNDFT		;NONE. GO DEFAULT TASK NAME
	LDB T2,[POINT 7,(T1),6] ;GET FIRST BYTE
	JUMPE T2,OPNDFT		;IF NULL EXTENSION. GO DEFAULT TASK NAME
	; ..
;USER SPECIFIED EXTENSION. CHECK FOR DUPLICATE

	HRLI T1,(POINT 7,)	;FORM POINTER TO THE STRING
	MOVX T3,MAXLC		;GET MAX SIZE OF EXTENSION
	CALL CMPLEN		;COMPUTE ACTUAL NUMBER OF BYTES IN STRING
	IDIVI T3,5		;COMPUTE NUMBER OF WORDS IN STRING
	SKIPE T4		;AND ROUND RESULT UP
	ADDI T3,1		; IF NEEDED
	MOVE T1,T3		;COPY SIZE OF STRING
	CALL GETBLK		;GET A BLOCK TO HOLD IT
OPNFAI:	 JRST [	LLLOCK		;LOCK UP TREE
		EXCH T1,SAVBLK	;GET BLOCK ADDRESS
		CALL DELNOD	;RELEASE LL BLOCK
		LLLULK		;RELEASE LOCK
		MOVE T1,SAVBLK	;GET ERROR CODE
		DECR DCCUR	;DISCOUNT THIS LINK
		RET]		;DONE
	MOVEM T1,SAVERR		;SAVE BLOCK ADDRESS
	MOVE T2,SAVSTR		;GET STRING BLOCK
	SETOM T3		;NO COUNT
	CALL MOVSTR		;MOVE THE STRING
	MOVEI T1,TSKCHK		;COROUTINE ADDRESS
	SETOM T2		;SEARCH ALL LOGICAL LINKS
	LLLOCK			;LOCK UP THE TREE
	CALL OBJSRC		;DO IT
	 SKIPA			;NOT FOUND. CAN USE IT
	JRST [	MOVE T1,SAVERR	;GET TASK NAME BLOCK
		CALL RELBLK	;RELEASE IT
		MOVE T1,SAVBLK	;GET LL BLOCK ADDRESS
		CALL DELNOD	;RELEASE THE BLOCK
		LLLULK		;FREE THE TREE LOCK
		MOVEI T1,DCNX4	;ILLEGAL TASK NAME
		DECR DCCUR	;DISCOUNT THIS LINK
		RET]		;AND DONE
	MOVE T2,SAVERR		;GET TASK BLOCK
	MOVE T1,SAVBLK		;GET LL BLOCK ADDRESS
	STOR T2,LLTSK,(T1)	;STORE BLOCK ADDRESS
OPNEXT:	SETONE LLBOM,(T1)	;NEXT OUTPUT WILL BE BOM
	MOVE T3,SAVBSZ		;GET BYTE SIZE
	STOR T3,LLBSZ,(T1)	;SAVE BYTE SIZE IN LOGICAL LINK BLOCK
	CAIE T3,44		;WORD MODE?
	JRST OPENX1		;NO. GO ON
	SETONE LLFDI,(T1)	;YES. REMEMBER THIS
OPENX1:	MOVEI T2,NSPTIM		;GET INITIAL RESEND TIME OUT VALUE
	MOVEM T2,LLTIMO(T1)	;PUT IT IN LL BLOCK
	RETSKP			;DONE, RETURN SUCCESS WITH T1/ LL BLOCK ADDRESS
;ROUTINE TO GET RID OF LL BLOCK AFTER ERROR

RLBLK:	MOVEM T1,SAVERR		;SAVE ERROR
RLBLK1:	MOVE T1,SAVBLK		;GET BLOCK ADDRESS
	CALL RELRES		;FREE IT
	MOVE T1,SAVERR		;GET ERROR
	RET			;AND DONE

;ROUTINE TO GET DEFAULT TASK NAME FOR A LINK

OPNDFT:	LLLOCK			;LOCK UP THE TREE
	MOVE T1,SAVBLK		;GET BLOCK ADDRESS
	CALL GETTSK		;GO GET A NAME
	 JRST [	MOVE T1,SAVBLK	;FAILED
		CALL DELNOD	;SO RELEASE LL BLOCK
		LLLULK		;FREE TREE LOCK
		MOVEI T1,MONX06	;"NO MORE SWAPPABLE FREE SPACE"
		RET]		;DONE
	MOVE T1,SAVBLK		;GET BACK LL BLOCK ADDRESS
	JRST OPNEXT		;AND DONE

;COROUTINE OF OPEN CODE TO CHECK VALIDITY OF A USER-SUPPLIED
;TASK NAME

TSKCHK:	SAVET			;SAVE TEMPS
	LOAD T2,LLFRK,(T1)	;SEE IF THE SAME FORK
	HLRZ T2,FKJOB(T2)	;GET FORK'S JOB NUMBER
	MOVE T4,FORKX		;GET THIS FORK'S NUMBER
	HLRZ T4,FKJOB(T4)	;GET THIS FORK'S JOB NUMBER
	CAMN T2,T4		;IS IT?
	RET			;YES. NO NEED TO CHECK ANYMORE
	LOAD T2,LLTSK,(T1)	;GET THIS ONE'S ADDRESS
	JUMPE T2,R		;IF NONE, CAN'T BE IT
	MOVE T1,SAVERR		;GET TASK BLOCK ADDRESS
	CALLRET CMPSTR		;GO DO THE COMPARE
SUBTTL	Routines to Manipulate the Logical Link Tree

;DELETE NODE FROM LL TREE
;	T1/ BLOCK ADDRESS

DELNOD::MOVE T2,(P)		;GET CALLER'S ADDRESS
	ASUBR <SAVBLK,SAVCAL>	;SAVE BLOCK ADDRESS AND PC OF CALLER
	LOAD T1,LLLNK,(T1)	;GET ITS ADDRESS
	SETOM T2		;ANY MATCH
	CALL LLLKUP		;GO LOOK IT UP
	 JRST [
;		MOVE T2,SAVCAL	;DIDN'T FIND IT, RETRIEVE CALLER'S PC
;		BUG (DELNDF,<<T2,CALLER>>)
		RET]		;ALL DONE
	JUMPE T2,[SETZM LLHEAD	;IF THE HEAD. CLEAR HEADER
		JRST DELNO1]	;AND PROCEED
	LOAD T3,LLUPL,(T2)	;SEE IF THIS IS UP OR DOWN
	NOSKD1
	CHNOFF DLSCHN		;TURN OFF INTERRUPTS
	CAMN T3,T1
	JRST [	SETZRO LLUPL,(T2) ;UP
		JRST DELINS]	;GO DO INSERTS
	SETZRO LLDWN,(T2)	;DOWN
DELINS:	CHNON DLSCHN
	OKSKD1
DELNO1:	LOAD T1,LLLNK,(T1)	;GET ADDRESS
	CALL FRELNK		;RELEASE THE LINK #
	MOVE T1,SAVBLK		;GET BACK LL BLOCK ADDRESS
	LOAD T2,LLUPL,(T1)	;DOES THIS HAVE AN UP POINTER?
	JUMPE T2,DELDWN		;NO
	MOVE T1,T2		;YES.
	CALL ADDLNK		;GO PUT IT IN
	MOVE T1,SAVBLK		;GET BACK ADDRESS
DELDWN:	LOAD T2,LLDWN,(T1)	;SEE IF IT HAS A DOWN
	JUMPE T2,DELDNE		;AND GO RELEASE BLOCKS
	MOVE T1,T2		;GET ADDRESS
	CALL ADDLNK
	MOVE T1,SAVBLK		;GET BACK BLOCK ADDRESS
DELDNE:	OPSTR <SKIPE T2,>,LLOPT,(T1) ;HAVE AN OPTDATA STRING?
	CALL DELREL		;YES. GET RID OF IT
	OPSTR <SKIPE T2,>,LLTSK,(T1) ;HAVE A TASK NAME?
	CALL DELREL		;YES. GET RID OF IT
	OPSTR <SKIPE T2,>,LLFDS,(T1) ;HAVE A DESCRIPTOR STRING?
	CALL DELREL		;YES. GET RID OF IT
	JE LLFOB,(T1),DELBLK	;AN OBJECT?
	OPSTR <SKIPE T2,>,LLDSC,(T1) ;YES. HAVE A DESCRIPTOR STRING?
	CALL DELREL		;YES. GET RID OF IT
	; ..
	; ..

	OPSTR <SKIPE T2,>,LLUSR,(T1) ;HAVE A USER STRING?
	CALL DELREL		;YES. GET RID OF IT
	OPSTR <SKIPE T2,>,LLACT,(T1) ;HAVE AN ACCOUNT STRING?
	CALL DELREL		;YES. GET RID OF IT
	OPSTR <SKIPE T2,>,LLPSW,(T1) ;HAVE A PASSWORD STRING?
	CALL DELREL		;YES. GET RID OF IT
DELBLK:	CALL REMQUE		;REMOVE BLOCK FROM OUTQUE OF NEEDED
	CALL UNQSRV		;REMOVE LL BLOCK FROM "NEEDS SERVICE" QUEUE
	CALLRET RELRES		;FREE BLOCK AND RETURN

DELREL:	SAVET
	NOINT			;PREVENT INTERRUPTS WHILE DEASSIGNING SPACE
	MOVE T1,T2		;GET BLOCK ADDRESS
	CALL RELBLK		;FREE BLOCK
	OKINT			;PREMIT INTERRUPTS AGAIN
	RET			;RETURN

	ENDAS.
;REMQUE - ROUTINE TO REMOVE A LINK FROM OUTQUE
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL REMQUE
;RETURNS: +1 ALWAYS, WITH LINK REMOVED IF QUEUED

REMQUE:	JE LLQUE,(T1),R		;NOTHING TO DO IF THIS LINK WAS NOT QUEUED

; INITIALIZATION

	LOCK OUTLOK		;LOCK THE QUEUE
	MOVEI T4,0		;INITIALIZE CURRENT QUEUE ITEM
	HRRZ T3,OUTQUE		;GET ITEM AT HEAD OF QUEUE

; SEARCH THE QUEUE FOR THE DESIRED LINK

RMQ010:	CAMN T3,T1		;FOUND DESIRED ITEM ?
	JRST RMQ020		;YES, GO REMOVE IT FROM THE QUEUE
	MOVE T4,T3		;NO, SAVE CURRENT ITEM AS PREVIOUS ITEM
	LOAD T3,LLOUT,(T3)	;MAKE NEXT ITEM CURRENT ITEM
	JUMPN T3,RMQ010		;AND GO CHECK NEW CURRENT ITEM
	BUG(NSPLNQ)
	RET			;SHOULD NEVER HAPPEN

; HERE WITH THE DESIRED LINK ADDRESS IN T3, PREVIOUS ITEM IN T4

RMQ020:	HLRZ T2,OUTQUE		;GET POINTER TO TAIL OF QUEUE
	CAMN T2,T3		;REMOVING TAIL OF QUEUE ?
	HRLM T4,OUTQUE		;YES, SAVE POINTER TO NEW TAIL OF QUEUE
	LOAD T2,LLOUT,(T3)	;GET POINTER TO NEXT BLOCK
	SKIPN T2		;REMOVING HEAD OF QUEUE ?
	JRST [	HRRM T2,OUTQUE	;YES, SAVE NEXT BLOCK AS NEW HEAD
		JRST RMQ030 ]	;AND CLEAN UP
	STOR T2,LLOUT,(T4)	;STORE NEXT BLOCK IN PREVIOUS

; HERE WITH ITEM REMOVED FROM QUEUE

RMQ030:	SETZRO LLQUE,(T1)	;CLEAR "LINK ON OUTQUE" FLAG
	UNLOCK OUTLOK		;UNLOCK THE QUEUE
	RET			;DONE, RETURN
;ROUTINE TO RESET AN LL BLOCK SO THAT IT CAN REVERT TO
;THE LISTENING STATE. USED WHEN A SERVER REJECTS A CONNECTION.
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;RETURNS:	+1 FAILED
;		+2 SUCCESS

CLRBLK:	ASUBR <CLRLLB>		;LL BLOCK ADDRESS
	CALL FLUSH		;FIRST GET RID OF MESSAGES
	SETZRO LLFNM,(T1)	;CLEAR CONNECTOR
	SETZRO LLHLK,(T1)
	SETZRO LLUCT,(T1)	;NO OPTDATA
	LOAD T2,LLHST,(T1)
	SETZM 0(T2)		;NO REMOTE HOST NAME
	OPSTR <SKIPE T2,>,LLFDS,(T1)  ;HAVE A DESCRIPTOR?
	CALL DELREL		;YES, RELEASE THE SPACE
	MOVEI T1,<MAXDSC+4>/4	;MAX CHARS IN DESCRIPTOR
	CALL GETBLK		;GET SWAPPABLE FREE SPACE BLOCK
	 RETBAD ()		;COULDN'T
	MOVE T2,T1		;POSITION THE ADDRESS
	MOVE T1,CLRLLB		;RETRIEVE THE LL BLOCK ADDRESS
	STOR T2,LLFDS,(T1)	;PUT BLOCK ADDRESS IN LL BLOCK
	SETZRO LLRSN,(T1)	;NO DISCONNECT REASON
	JE LLFOB,(T1),RSKP	;IN CASE CALLED FOR NON-OBJECT
	SETZM LLUSGP(T1)	;NO GROUP,USER
	SETZRO LLSOB,(T1)	;NO OBJECT #
	LOAD T2,LLUSR,(T1)	;GET USER BLOCK
	SETZM 0(T2)		;NO USER
	LOAD T2,LLACT,(T1)	;GET ACCOUNT BLOCK
	SETZM 0(T2)		;NONE
	SETZRO LLPCT,(T1)	;NO PASSWORD DATA
	RETSKP			;AND DONE
;ROUTINE TO GET A LL ADDRSS AND INSERT A NODE IN THE TREE
;MUST BE CALLED WITH LL LOCK LOCKED.
;ACCEPTS:	T1/ BLOCK ADDRESS
;RETURNS:	+1 SOME SORT OF FAILURE (SHOULDN'T HAPPEN)
;		+2 INSERTED.

MAKLNK:	ASUBR <SAVADR>		;SAVE BLOCK ADDRESS
	MOVSI T1,-LLBIT		;# OF WORDS IN BIT TABLE
	MOVE T2,[LLBITS]	;THE TABLE ITSELF
MAKLN1:	SKIPN T3,0(T2)		;HAVE SOME BITS?
	JRST [	AOS T2		;NO. NEXT WORD THEN
		AOBJN T1,MAKLN1	;SEE IF ANY MORE
		MOVEI T1,DCNX5	;NO MORE LINKS
		RET]		;AND DONE
	JFFO T3,.+1		;COMNPUTE LEADING ZEROES
	MOVE T3,BITS(T4)	;GET THE BIT
	ANDCAM T3,0(T2)		;TURN IT OFF
	HRRZS T1		;GET # OF FULL WORDS SKIPPED
	IMULI T1,44		;COMPUTE SKIPPED BITS
	ADDI T1,0(T4)		;THE INDEX
	HRRZ T2,TODCLK		;GET THE CURRENT CLOCK
	LSH T2,MAXEXP		;ZERO RIGHT-HAND BITS
	ANDI T2,177777		;GET A 16 BIT QUANTITY
	ADDI T2,0(T1)		;FORM LL ADDRESS
	MOVE T1,SAVADR		;GET BACK BLOCK ADDRESS
	STOR T2,LLLNK,(T1)	;PUT IN THE ADDRESS
	MOVE T2,FORKX		;PUT IN FORK OWNER
	STOR T2,LLFRK,(T1)	;TO THE BLOCK
	CALL ADDLNK		;AND GO ADD IN THE LINK
	RETSKP			;DONE

;ROUTINE TO ADD A BLOCK TO THE LL TREE
;ACCEPTS:	T1/BLOCK TO ADD
;RETURNS:	+1 ALWAYS.
;MUST BE CALLED WITH TREE LOCKED

ADDLNK:	ASUBR <SAVBLK>		;SAVE BLOCK ADDRESS
	LOAD T1,LLLNK,(T1)	;GET LINK I.D.
	SETO T2,		;NO HOST CHECK
	CALL LLLKUP		;GO GET INSERT POINT
	 SKIPA			;GOOD
	BUG (ADDONF)
	MOVE T2,SAVBLK		;GET BACK LL BLOCK
	JUMPE T1,[MOVEM T2,LLHEAD ;FIRST ONE
		RET]		;AND DONE
	LOAD T3,LLLNK,(T2)	;GET THIS LINK I.D.
	LOAD T4,LLLNK,(T1)	;GET INSERT I.D.
	CAML T3,T4
	JRST [	STOR T2,LLUPL,(T1)
		RET]		;DONE
	STOR T2,LLDWN,(T1)	;NEW LINK
	RET			;AND DONE
SUBTTL	More Link Creation Routines

;ROUTINE CALLED FROM GTJFN TO VERIFY AN ATTRIBUTE
;ACCEPTS:	T1/ BLOCK ADDRESS
;		T2/ ATTRIBUTE VALUE
;RETURNS:	+1 INVALID. ERROR CODE IN T1
;		+2 GOOD ATTRIBUTE

NETATR::ACVAR <W1>		;GET A WORK REG
	MOVSI T3,-MAXNTA	;# OF ATTRIBUTES IN TABLE
NETAT2:	OPSTR <CAME T2,>,NTATR,ATTRTB(T3) ;IS THIS IT?
	JRST [	AOBJN T3,NETAT2	;DO ALL OF THEM
		RETBAD (GJFX49)] ;COULDN'T FIND IT
	LOAD W1,NTATB,ATTRTB(T3) ;FOUND IT. GET BINARY BIT
	LOAD T2,NTATC,ATTRTB(T3) ;GET MAX COUNT
	SKIPE W1		;BINARY?
	IMULI T2,3		;YES. ADJUST COUNT
	HRLI T1,(<POINT 7,0,34>) ;FORM A BYTE POINTER
CNTLOP:	ILDB T4,T1		;GET NEXT BYTE
	JUMPE T4,NETAT1		;IF NULL, DONE
	SOJL T2,[RETBAD (GJFX50)] ;ATTRIBUTE TOO LONG
	JUMPE W1,CNTLOP		;IF NOT BINARY, GO GET MORE
	CAIL T4,"0"		;IS BINARY. CHECK RANGE
	CAILE T4,"7"		;""
	SKIPA
	JRST CNTLOP		;GOOD RANGE
	RETBAD (GJFX50)		;INVALID
NETAT1:	LOAD T2,NTATE,ATTRTB(T3) ;GET EXCLUSION PARTNER
	SKIPE T2		;HAVE ONE?
	CALL FNDATR		;YES. GO LOOK FOR IT
	 RETSKP			;NOT THERE. ERGO, GOOD ARG
	RETBAD (GJFX45)		;CONFLICT

	ENDAV.			;END ACVAR

;THE ATTRIBUTE TABLE

ATTRTB:	ATTENT (.PFUDT,0,MAXUAP,0)
	ATTENT (.PFPWD,0,MAXUAP,.PFBPW)
	ATTENT (.PFBPW,1,MAXUAP,.PFPWD)
	ATTENT (.PFACN,0,MAXUAP,0)
	ATTENT (.PFOPT,0,MAXOPT,.PFBOP)
	ATTENT (.PFBOP,1,MAXOPT,.PFOPT)
MAXNTA==.-ATTRTB

;ROUTINES TO OPEN NETWORK CONNECTION. CALLED FROM OPENF JSYS

;OPEN SRC JFN

SRCOPN::ACVAR <W1>		;GET A WORK REG
	TRVAR <NTCNT,NTPNT,NTOBJ,NTDSC,NTDSS>
	HLRZ T1,FILNEN(JFN)	;GET NAME FOR THE CONNECTION
	CALL SRCNAM		;PARSE NETWORK NAME
	 RETBAD()		;ERROR
	CALL OPNSRC		;GO DO COMMON OPEN SETUP
	 RETBAD()		;FAILED
	MOVE W1,T1		;SAVE LL BLOCK
	SKIPG T2,NTOBJ		;GET OBJECT TYPE
	JRST NOOOBJ		;NONE GIVEN
	STOR T2,LLNAM,(W1)	;SAVE OBJECT
NOOOBJ:	SKIPN T1,NTDSC		;HAVE A DESCRIPTOR?
	JRST NODESC		;NO. GO ON
	ADDI T1,4
	IDIVI T1,5		;COMPUTE WORDS NEEDED
	CALL GETBLK		;GET ONE
	 JRST SRCFAL		;COULDN'T
	STOR T1,LLDSC,(W1)	;SAVE POINTER
	MOVE T2,NTDSS		;GET STRING POINTER
	MOVE T3,NTDSC		;GET COUNT
	CALL MOVST1		;MOVE THW STRING
	MOVEI T1,OPNUNQ		;MUST VERIFY UNIQUENESS OF NAME
	SETZM T2		;NEED TO CHECK OBJECTS ONLY
	CALL OBJSRC		;DO IT
	 JRST NODESC		;NOT FOUND. CAN HAVE IT
	LOAD T2,LLFRK,(T1)	;FOUND ONE. WHICH JOB?
	HLRZ T2,FKJOB(T2)	;""
	MOVEI T1,DCNX9		;DUPICATE NAME ERROR
	CAME T2,JOBNO		;THIS JOB?
	JRST SRCFAL		;NO. CAN'T HAVE IT
NODESC:	CALL GTSBLK		;GET A BLOCK FOR USER NAME
	 JRST SRCFAL		;NONE
	STOR T1,LLUSR,(W1)	;SAVE IT
	CALL GTSBLK		;GET A BLOCK FOR THE ACCOUNT
	 JRST SRCFAL		;NONE
	STOR T1,LLACT,(W1)	;SAVE IT
	CALL GTSBLK		;GET A BLOCK FOR THE PASSWORD
	 JRST SRCFAL		;NONE
	STOR T1,LLPSW,(W1)	;SAVE IT
	CALL ASGWDW		;GO GET WINDOW PAGES
	 JRST SRCFAL		;FAILED
	MOVEI T1,LLSLIS		;GET INITIAL STATE
	STOR T1,LLSTA,(W1)	;SET UP THIS LISTENER
	SETONE LLFOB,(W1)	;SAY THIS IS AN OBJECT
	LLLULK			;FREE LOCK
	RETSKP			;AND DONE
;COROUTINE OF SRCOPN TO CHECK FOR UNIQUE NAME

OPNUNQ:	SAVET			;SAVE TEMPS
	LOAD T2,LLNAM,(T1)	;GET OBJECT NUMBER
	OPSTR <CAME T2,>,LLNAM,(W1) ;SAME AS OURS?
	RET			;NO. NO CONFLICT THEN
	LOAD T1,LLDSC,(T1)	;GET ITS DESCRIPTOR
	LOAD T2,LLDSC,(W1)	;GET OURS
	CALL CMPSTR		;SEE IF A MATCH
	 RET			;NO.
	RETSKP			;YES. COULD BE A PROBLEM

;OPEN FAILURE ROUTINE. CLEAN UP FROM ATTEMPT

SRCFAL:	DECR DCCUR		;ONE LESS LINK ON FAILURE
	EXCH T1,W1		;GET BLOCK ADDRESS
	CALL DELNOD		;FREE THE NODE
	LLLULK			;UNLOCK THE TREE
	MOVE T1,W1		;GET ERROR CODE
	RET			;AND FAIL

;LOCAL ROUTINE TO GET A STRING BLOCK FOR SRCOPN.

;**;[2962]  Change 1 line at GTSBLK:+0			DML	10-MAY-83
GTSBLK:	MOVEI T1,SIZ39		;[2962] THE PROPER SIZE
	CALL GETBLK		;GET ONE
	 RET			;FAILED
	RETSKP			;GOT IT

	ENDAV.			;END ACVAR
;CRTLNK - ROUTINE TO CREATE A LOGICAL LINK
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;	    T2/	ADDRESS OF ATRIBUTE LIST
;	    T3/	OBJECT,,COUNT OF BYTES IN DESCRIPTOR
;	    T4/	POINTER TO DESCRIPTOR STRING
;	 TRVARS -- NTCNT,NTPNT,NTOBJ,NTDSC,NTDSS,NTHST,NTHSC
;
;		CALL CRTLNK
;RETURNS: +1	 FAILED, ERROR CODE IN T1
;	  +2	SUCCESS

CRTLNK::ACVAR <W1,W2,W3>	;GET A WORK REGISTER
	STKVAR <CRLATR,CRLCIB,CRLCNT,CRLOBJ,CRLHST,CRLHSC,CRLDSS,CRLDSC>

; SAVE INPUT ARGUMENTS

	MOVE W1,T1		;SAVE LL BLOCK ADDRESS
	MOVEM T2,CRLATR		;SAVE ATTRIBUTE LIST POINTER
	HLRZM T3,CRLOBJ		;SAVE OBJECT
	HRREM T3,CRLDSC		;SAVE COUNT OF BYTES IN DESCRIPTOR
	MOVEM T4,CRLDSS		;SAVE DESCRIPTOR POINTER

	MOVE T1,CRLOBJ		;GET OBJECT
	STOR T1,LLFNM,(W1)	;SAVE IT
	SKIPG T3,CRLDSC		;ANY DESCRIPTOR GIVEN
	JRST DSCNUL		;NO, SKIP MOVING STRING
	LOAD T1,LLFDS,(W1)	;GET DESCRIPTOR BLOCK
	MOVE T2,CRLDSS		;GET JSB STRING POINTER
	CALL MOVST1		;AND MOVE IT

;ALL STRINGS ARE MOVED. MUST GENERATE CONNECT-INITIATE MESSAGE

DSCNUL:	MOVEI T1,CONLEN+MSHDR+RTHLEN ;GET A BLOCK FOR THE CI
	CALL GETRES		;GET A RESIDENT BLOCK
	 RETBAD ()		;FAILED, RETURN ERROR
	MOVEM T1,CRLCIB		;SAVE BLOCK ADDRESS
	HRLI T1,(<POINT 8,>)	;MAKE A BYTE POINTER
	ADDI T1,MSHDR		;RESERVE HEADER
	MOVEM T1,LLBPTR(W1)	;SAVE IN LL BLOCK
	SETZM LLBPCT(W1)	;ZERO COUNT
	MOVE T1,W1		;LL BLOCK ADDRESS
	MOVEI T2,CNMRFL+CNMCI	;MESSAGE FLAGS
	CALL RTHDCI		;PUT ON ROUTING HEADER AND FLAGS
	CALL DOSRVS		;INSERT LL ADDRESSES AND STANDARD SERVICES
	;..
	; ..

;NOW BUILD OBJECT ADDRESSING FIELDS

	SKIPG CRLDSC		;HAVE A COUNT FOR DESCRIPTOR
	JRST [	MOVEI T2,OBJZRO	;GET OBJECT TYPE ZERO INDICATOR
		CALL ONEBYT
		MOVE T2,CRLOBJ	;GET OBJECT TYPE
		CALL ONEBYT
		LOAD T1,LLFDS,(W1) ;GET DESCRIPTOR STRING
		SETZRO LLFDS,(W1) ;CLEAR LOCATION
		CALL RELBLK	;RELEASE UNUSED BLOCK
		MOVE T1,W1	;RESTORE LL BLOCK ADDRESS
		JRST DSCDON]	;DONE WITH THIS
	MOVEI T2,OBJONE		;GET OBJECT TYPE 1
	CALL ONEBYT		;STORE HEADER
	MOVE T2,CRLOBJ		;GET OBJECT NUMBER
	CALL ONEBYT		;PUT IT IN
	LOAD T3,LLFDS,(T1)	;GET DESCRIPTOR STRING
	CALL ASCIIZ		;PUT IT IN

;MESSAGE BUILT. INSERT SENDER'S NAME AND USER DATA

DSCDON:	MOVEI T2,OBJONE		;SENDER IS A TASK
	CALL ONEBYT
	MOVEI T2,OBJTSK		;THE I.D. FOR TASK
	CALL ONEBYT
	LOAD T3,LLTSK,(T1)	;GET POINTER TO TASK NAME
	CALL ASCIIZ		;AND INSERT IT

;NOW CHECK FOR AND INSERT ANY OPTIONAL DATA

	MOVE T1,W1		;GET LOGICAL LINK BLOCK ADDRESS
	MOVE T2,CRLATR		;GET ADDRESS OF ATTRIBUTE LIST
	CALL INSATR		;GO INSERT ATTRIBUTES IN MESSAGE

	MOVEI T2,LLSCIS		;GET NEW STATE
	STOR T2,LLSTA,(T1)	;STORE NEW STATE
	LLLULK			;RELEASE TREE NOW
	MOVE T2,CRLCIB		;GET BLOCK ADDRESS
	LOAD T3,LLHSN,(T1)	;GET NODE NUMBER
	ADD T3,[NSCONS]		;OFFSET INTO "CONNECTS SENT" TABLE
	AOS (T3)		;INCR THE COUNT
	CALL SNDCTL		;SEND MESSAGE TO THE NETWORK
	RETSKP			;AND DONE FOR NOW

	ENDAV.			;END ACVAR
;INSATR - ROUTINE TO INSERT ATTRIBUTE VALUES INTO THE CI MESSAGE
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS
;	    T2/	ADDRESS OF ATTRIBUTE TABLE
;		CALL INSATR
;RETURNS: +1 ALWAYS

INSATR:	STKVAR <INALLB,INAATR,INAPNT,INACNT>
	MOVEM T1,INALLB		;SAVE LOGICAL LINK ADDRESS
	MOVEM T2,INAATR		;SAVE ATTRIBUTE LIST ADDRESS

	MOVE T1,INALLB		;GET LOGICAL LINK BLOCK ADDRESS
	SETZ T2,		;DEFAULT MENU BYTE
	CALL ONEBYT		;PUT IT IN
	MOVE T3,LLBPTR(T1)	;GET POINTER TO MENU
	MOVEM T3,INAPNT		;SAVE IT
	MOVEI T2,1		;ASSUME WILL BE PRESENT
	MOVEM T2,INACNT		;SET IT
	MOVEI T2,.PFUDT		;SEE IF USER I.D. GIVEN
	MOVE T3,INAATR		;GET ATTRIBUTE LIST ADDRESS
	CALL GETATR		;IS IT?
	 JRST [	SETZM T2	;NOT THERE.
		CALL ONEBYT	;SAY IS NULL
		JRST DOSPW1]	;AND GO ON TO PASSWORD
	CALL ASCIIZ		;PUT IN THE DATA
DOSPW1:	MOVEI T2,.PFPWD		;SEE IF A PASSWORD IS GIVEN
	MOVE T3,INAATR		;GET ATTRIBUTE LIST ADDRESS
	CALL GETATR		;IS IT?
	 JRST [	MOVEI T2,.PFBPW	;NO. SEE ABOUT ALTERNATE FORM
		MOVE T3,INAATR	;GET ATTRIBUTE LIST ADDRESS
		CALL GETATR	;IS IT?
		 JRST [	SETZ T2, ;NO.
			CALL ONEBYT ;INSERT A PLACEHOLDER
			JRST DOACT] ;AND GO ON
		MOVEI T4,BININ	;YES. INSERT BINARY VALUE
		JRST DOPSWD]
	MOVEI T4,ASCIIZ		;YES. INSERT ASCII FORM
DOPSWD:	CALL 0(T4)		;PUT IT IN
DOACT:	MOVEI T2,.PFACN		;SEE IF AN ACCOUNT
	MOVE T3,INAATR		;GET ATTRIBUTE LIST ADDRESS
	CALL GETATR		;IS IT?
	 MOVEI T3,[0]		;NO. PUT IN NULL STRING
	CALL ASCIIZ		;YES. PUT IT IN
	; ..
	; ..

	MOVEI T2,.PFOPT		;HAVE OPTIONAL USER DATA?
	MOVE T3,INAATR		;GET ATTRIBUTE LIST ADDRESS
	CALL GETATR		;IS IT?
	 JRST [	MOVEI T2,.PFBOP	;NO. TRY OTHER FORM
		MOVE T3,INAATR	;GET ATTRIBUTE LIST ADDRESS
		CALL GETATR	;IS IT?
		 JRST INMENU	;NO USER DATA
		MOVEI T4,BININ	;FOUND IT
		JRST DOOPT]	;PUT IT IN
	MOVEI T4,ASCIIZ		;FOUND ASCII FORM
DOOPT:	MOVEI T2,2		;SAY FOUND OPTDATA
	IORM T2,INACNT		;TO THE MENU
	CALL 0(T4)		;INSERT IT
INMENU:	MOVE T2,INACNT		;GET FINAL MENU
	DPB T2,INAPNT		;PUT IT IN THE MESSAGE
	RET			;DONE, RETURN
;STRSAV - ROUTINE TO SAVE NAME STRINGS ON LINK CREATION
;
;ACCEPTS IN TRVARS:	NTHST, NTHSC, NTDSS, NTDSC, NTOBJ
;	    T1/	ADDRESS OF LL BLOCK
;	    T2/	COUNT OF HOST STRING BYTES,,COUNT OF DESCRIPTOR STRING BYTES
;	    T3/	ADDRESS OF HOST NAME STRING BLOCK
;	    T4/	ADDRESS OF DESCRIPTOR STRING BLOCK
;		CALL STRSAV
;RETURNS: +1	 FAILED, ERROR CODE IN T1
;	  +2	SUCCESS, STRINGS SAVED

STRSAV::SAVEQ
	STKVAR <SSVHST,SSVHSC>
	HLREM T2,SSVHSC		;SAVE HOST STRING BYTE COUNT
	MOVEM T3,SSVHST		;SAVE HOST NAME STRING POINTER
	MOVE Q1,T1		;SAVE LL BLOCK ADDRESS
	SKIPG T3,SSVHSC		;HAVE A HOST NAME?
	JRST [SETONE LLLOC,(Q1) ;NOTE THIS IS A LOCAL LINK
	      RETSKP]		;DONE
	CAME T3,OURCNT		;SAME COUNT AS OUR NAME?
	JRST DCNOP0		;NO. CAN'T BE LOCAL
	MOVE T1,SSVHST		;YES, COULD BE US - GET BLOCK POINTER
	AOS T1			;POINT TO ACTUAL TEXT STRING
	HRLI T1,440700		;MAKE A BYTE POINTER
	MOVE T2,[POINT 7,OURNAM] ;GET POINTER TO OUR NAME
	SETZ T4,		;NO OFFSET IN COMPARISON
	CALL COMPAR		;SEE IF THE SAME
	 JRST DCNOP0		;NO. SAVE IT THEN
	SETONE LLLOC,(Q1)	;YES, NOTE LOCAL LINK
	MOVE Q3,OURNUM		;GET LOCAL NODE NUMBER
	STOR Q3,LLHSN,(Q1)	;PUT IT IN LL BLOCK
	RETSKP			;DONE

;THE ATTEMPTED CONNECTION IS NOT LOCAL

DCNOP0:	MOVE T1,SSVHST		;GET ADDRESS OF STRING BLOCK
	AOS T1			;POINT TO ACTUAL TEXT
	HRLI T1,440700		;MAKE A BYTE POINTER
	MOVEM T1,SSVHST		;SAVE THE BYTE POINTER
	MOVNI Q2,BIGNOD		;MAKE
	HRLZS Q2		; AOBJN
	HRRI Q2,1		;  WORD
	MOVE T3,SSVHSC		;GET HOST NAME CHARACTER COUNT
	MOVEI T4,40		;COMPARE ASCII
	MOVNS T4		; TO SIXBIT
	NOINT			;NO INTERRUPTIONS
	LOCK NMAPLK		; WHILE TABLE LOCKED
DCNOP4:	MOVE T1,SSVHST		;RETRIEVE THE BYTE POINTER TO THE HOST
	HRLI T2,440600		;MAKE A BYTE POINTER
	HRRI T2,NODMAP(Q2)	; TO THE NAME IN THE TABLE
	TLO T3,400000		;MAY BE DIFFERENT LENGTH STRINGS
	CALL COMPAR		;ARE THEY THE SAME?
	 JRST [AOBJN Q2,DCNOP4	;NO, TRY FOR MORE
	       UNLOCK NMAPLK	;DONE WITH
	       OKINT		; THE LOCK
	       RETBAD (NSPX24)]	;DIDN'T FIND IT
	UNLOCK NMAPLK		;DONE WITH
	OKINT			; THE LOCK

;USER'S NODE NAME IS IN NODE NAME MAPPING TABLE

   IFN DN20SW,<			;LOOK FOR OTHER MCBS
	MOVEI Q3,2		;NEXT DTE TO CHECK
DCNOP7:	MOVE T2,Q3		;PRESERVE DTE NUMBER
	IMULI T2,2		;CALC CORRECT OFFSET FOR NODE NAME
	HRRI T2,ITSNAM(T2)	;MAKE A BP
	HRLI T2,440700		; TO THE NODE NAME
	MOVE T1,SSVHST		;GET BP TO HOST NAME
	MOVE T3,SSVHSC		;GET NO. OF CHARS IN HOST NAME
	SETZ T4,		;NO CONVERSION FACTOR
	CALL COMPAR		;DO THEY MATCH?
	 JRST DCNOP2		;NO, NOT FOR THIS MCB
	SKIPGE T2,MCBDTE(Q3)	;DTE ACTIVE?
	TXNE T2,NTSHUT		;YES, NODE SHUTTING DOWN?
	RETBAD (NSPX18)		;ERROR RETURN - NO PATH
	MOVEI Q3,(Q3)		;GET DTE #
	MOVEI T1,3		;SAY PHASE III NODE
	JRST DCNOP5		;MOVE ON
DCNOP2:	CAIGE Q3,3		;DONE ALL DTES YET?
	IFNSK.			;NO
	   AOS Q3		;MAKE NEXT DTE
	   JRST DCNOP7		;TRY IT
	ENDIF.
   >
	MOVE T1,[POINT 2,NODTBL]  ;POINT TO REACHABLE NODES TABLE
	HRRZ T2,Q2		;GET NODE NUMBER TO PLAY WITH
	ADJBP T2,T1		;POINT TO NODE
	LDB T1,T2		;GET ITS INFO
	SKIPN T1		;IS IT REACHABLE
	RETBAD (NSPX18)		;ERROR - NO PATH TO DESTINATION NODE

;NODE IS REACHABLE

	MOVSI Q3,-DCN		;MAKE AOBJN WORD FOR MCB SEARCH
DCNOP1:	SKIPGE T2,MCBDTE(Q3)	;IS THIS FE ACTIVE?
	TXNE T2,NOTMCB		;YES, IS IT AN MCB?
	JRST DCNOP3		;NO, CAN'T USE IT
	TXNN T2,NTSHUT		;YES, IS IT SHUTTING DOWN?
	JRST DCNOP5		;NO, EVERYTHING OK
	RETBAD (NSPX18)		;YES - NO PATH TO DESTINATION NODE
DCNOP3:	AOBJN Q3,DCNOP1		;TRY NEXT FE
	RETBAD (NSPX18)		;ERROR - NO PATH TO DESTINATION NODE

;STORE INFO IN LL BLOCK

DCNOP5:	CAIE T1,2		;PHASE II ROUTING?
	IFSKP.			;YES
	   MOVX T1,.NSP31	;SAY NSP 3.1
	ELSE.			;NO, PHASE III
	   MOVX T1,.NSP32	;SAY NSP 3.2
	ENDIF.
	STOR T1,LLLKP,(Q1)	;IN LL BLOCK
DCNOP6:	STOR Q3,LLPRT,(Q1)	;SAVE PORT NUMBER
	LOAD T1,LLHST,(Q1)	;GET PLACE TO PUT HOST'S NUMERIC NAME
	HRLI T1,440700		;MAKE A BYTE POINTER
	HRRZ T2,Q2		;GET THE NODE NUMBER
	STOR T2,LLHSN,(Q1)	;SAVE REMOTE HOST NUMBER
	MOVEI T3,^D10		;IN DECIMAL
	NOUT			;MAKE IT 7-BIT ASCII
	 JFCL
	RETSKP

	ENDSV.
;COMPARE TWO STRINGS
;ACCEPTS:	T1/ BYTE POINTER TO STRING 1
;		T2/ BYTE POINTER TO STRING 2
;		T3/ FLAGS ,, COUNT OF CHARS. IN STRING
;		    1B0 = STRINGS MAY BE OF DIFFERENT LENGTH
;		T4/ OFFSET (IF NEEDED)
;RETURNS:	+1 NO MATCH
;		+2 MATCH
;PRESERVES T3,T4

COMPAR:	ACVAR <W1,W2,W3>	;GET SOME REGS
	MOVE W1,T1		;COPY POINTER TO FIRST STRING
	MOVE W2,T2		;COPY POINTER TO SECOND STRING
	HRRZ W3,T3		;SAVE COUNT
	SOS W3			;FIXUP COUNTER FOR THE LOOP
CMPRLP:	ILDB T1,W1		;GET NEXT BYTE
	ILDB T2,W2		;GET THIS ONE'S NEXT
	SKIPE T4		;IS THERE AN OFFSET?
	ADD T1,T4		;YES, MAKE THE ADJUSTMENT
	CAME T1,T2		;MATCH?
	RET			;NO. NO MATCH THEN
	SOJGE W3,CMPRLP		;DO ALL THE BYTES
	TLZN T3,400000		;CHECKING WITH NODMAP?
	RETSKP			;NO, MATCH
	CAIL T3,6		;DONE MAX CHARACTERS IN A NODE NAME?
	RETSKP			;YES, MATCH
	ILDB W3,W2		;NO, GET THE NEXT BYTE
	SKIPE W3		;ONE THERE?
	RET			;YES, NO MATCH
	RETSKP			;A MATCH!!!!

	ENDAV.
;ROUTINE TO INSERT THE LL ADDRESSES IN A MESSAGE.
;ACCEPTS:	T1/ LL BLOCK ADDRESS

	RESCD

PUTLLR:	TDZA T2,T2		;SAY SEND 0 SOURCE IF IN CIR
PUTLLA:	SETOM T2		;SAY ALWAYS SEND CURRENT SOURCE
	ACVAR <W1>		;GET A WORK REG
	MOVE W1,T2		;SAVE ENTRY FLAG
	LOAD T2,LLHLK,(T1)	;GET DEST ADDRESS
	CALL TWOBYT		;PUT IT IN
	LOAD T2,LLLNK,(T1)	;GET SOURCE ADDRESS
	JUMPN W1,PUTLL1		;IF NO REJECT CHECK, GO ON
	LOAD W1,LLSTA,(T1)	;GET LINK STATE
	CAIN W1,LLSCIR		;IS THIS A LINK REJECT THEN?
	SETZM T2		;YES. SEND 0 SOURCE ADDRESS
PUTLL1:	CALLRET TWOBYT		;AND PUT IT IN


	ENDAV.			;END ACVAR
	SWAPCD
;ROUTINE TO INSERT CI/CC COMMON FIELDS

;	T1/ LL BLOCK

DOSRVS:	STKVAR <MSGFLG>
	MOVEM T2,MSGFLG		;SAVE FLAGS
	CALL PUTLLA		;PUT IN LL ADDRESSES
	MOVEI T2,CISRVS+CIMSCT	;ASSUME SEG COUNTS
	TMNE LLIMS,(T1)		;WANT MESSAGE COUNTS?
	MOVEI T2,CISRVS+CIMCNT	;YES
	CALL ONEBYT		;PUT IN SERVICES BYTE
	MOVEI T2,LNKPRI		;GET DEFAULT PRIORITY
	CALL ONEBYT
	LOAD T3,IOMODE		;GET FILE OPEN MODE
	CAIN T3,.GSSMB		;SMALL BUFFER MODE?
	SKIPA T3,[SMLSEG]	;YES, USE SMALL SEGSIZ
	MOVE T3,SEGSZ		;NO, USE NORMAL SEGMENT SIZE
	MOVE T2,MSGFLG		;GET MESSAGE TYPE
	CAIE T2,CIMMFL		;IS IT A CI?
	JRST [	LOAD T2,LLSWG,(T1)	;NO, A CC - GET CI'S SEG SIZE
		CAMLE T2,T3		;LESS THAN OURS?
		MOVE T2,T3		;NO, USE OURS
		TMNE LLLOC,(T1)		;LOCAL CONNECTION?
		JRST DOSRV1		;YES, NO NEED TO CHECK FURTHER
		LOAD T4,LLPRT,(T1)	;GET PORT NUMBER
		CAMLE T2,NSPMAX(T4)	;LESS THAN PORT'S SEGSIZ?
		MOVE T2,NSPMAX(T4)	;NO, USE PORT'S
		JRST DOSRV1]
	MOVE T2,T3		;USE SEGSIZE SELECTED ABOVE
DOSRV1:	STOR T2,LLSWG,(T1)	;PUT SEG SIZE IN LL BLOCK
	TMNE LLFDI,(T1)		;OPEN IN WORD MODE?
	MOVEI T2,WSEGSZ		;YES. GET PROPER SEG SIZE
	JN LLINT,(T1),[	MOVEI T2,ISEGSZ ;IF INTERNAL LINK USE DIFFERENT
			JRST .+1 ]	; SEGMENT SIZE
	SETZRO LLFDI,(T1)	;INIT THIS FLAG
	CALLRET TWOBYT

	ENDSV.
;ROUTINE TO BUILD A ROUTING HEADER.
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T2/ PROPER MESSAGE FLAGS

	RESCD

RTHDCI:	SAVEAC <T2>		;PRESERVE THE FLAGS
	STKVAR <MSGFLG>		;TO SAVE THE FLAGS
	MOVEM T2,MSGFLG		;SAVE FLAGS
	JN LLLOC,(T1),RTHDC1	;JUMP IF LOCAL
	MOVEI T2,RTFLG		;ROUTING FLAGS ARE FIRST
	CALL ONEBYT		;PUT IN FLAGS
	LOAD T3,LLHST,(T1)	;GET HOST STRING POINTER
	CALL ASCIIZ		;GO PUT IN IMAGE ASCII FIELD
	MOVEI T3,OURNAM		;GET OUR NAME
	CALL ASCIIZ		;PUT IT IN
RTHDC1:	MOVE T2,MSGFLG		;GET MESSAGE FLAGS
	CALLRET ONEBYT		;AND PUT IT IN THE MESSAGE

;ROUTINE TO INSERT IMAGE-ASCII FIELD INTO MESSAGE
;		T2/ COUNT OF BYTES
;ACCEPTS:	T3/ BLOCK ADDRESS

ASCIIZ:	MOVX T2,1B1		;ENTRY FOR ZERO TERMINATED STRING
ASCIIC:	ACVAR <W1,W2,W3>	;GET A REGISTER
	MOVE W1,[POINT 7,0(T3)]	;GET A BYTE POINTER
	STKVAR <ASCCNT>		;THE COUNT
	MOVEM T2,ASCCNT		;SAVE COUNT
	SETZB T2,W3		;SET COUNT REGS
	CALL ONEBYT		;PUT IN ZERO COUNT
	MOVE W2,LLBPTR(T1)	;SAVE BYTE POINTER
ASCIIL:	SOSGE ASCCNT		;HAVE ANY MORE BYTES?
	JRST ASCIID		;NO. GO WRAP UP
	ILDB T2,W1		;GET NEXT BYTE
	JUMPG T2,ASCII1		;NO. IS THIS A NULL?
ASCIID:	DPB W3,W2		;YES.
	RET			;ALL DONE

ASCII1:	CALL ONEBYT		;STASH IT
	AOJA W3,ASCIIL		;AND DO ENTIRE STRING


	ENDAV.			;END ACVAR
	SWAPCD
;MOVE A BINARY FIELD

MVBNRY:	ACVAR <W1,W2>		;GET WORK REGS
	MOVE W1,[POINT 8,0(T3)]	;GET A POINTER
	MOVE W2,T2		;SAVE COUNT
MVBNR1:	CALL ONEBYT		;PUT IN THE BYTE
	SOJL W2,R		;ANY MORE?
	ILDB T2,W1		;GET NEXT BYTE
	JRST MVBNR1		;GO STASH IT

	ENDAV.			;END ACVAR
;MORE ROUTINES

;INSERT BINARY QUANTITY IN A MESSAGE
;ACCEPTS:	3/ BLOCK ADDRESS

BININ:	ACVAR <W1,W2,W3>	;GET A WORK REG
	SETZB T2,W2
	HRLI T3,(<POINT 7,>)	;FORM A BYTE POINTER
	CALL ONEBYT		;PUT IN COUNT BYTE
	MOVE W3,LLBPTR(T1)	;SAVE POINTER
BININ1:	MOVSI W1,-3		;DO 3 BYTES
	SETZ T2,		;AN ACCUMULATOR
BININ2:	CALL BINXT		;GET NEXT BYTE
	 JRST BININ3		;DONE
	LSH T2,3		;ADJUST ACCUMULATOR
	ADDI T2,-"0"(T4)	;PUT IN NEXT BYTE
	AOBJN W1,BININ2		;DO AN OCTET
BININ3:	TRNN W1,-1		;FOUND ANY?
	JRST BININ4		;NO. ALL DONE
	CALL ONEBYT		;YES. PUT IT IN
	AOS W2			;ONE MORE IN
	JUMPGE W1,BININ1	;IF MORE TO DO, DO THEM
BININ4:	DPB W2,W3		;PUT IN FINAL COUNT
	RET			;AND DONE

BINXT:	ILDB T4,T3		;GET NEXT BYTE
	JUMPE T4,R		;IF THE NULL, ALL DONE
	RETSKP			;A VALID BYTE

	ENDAV.			;END ACVAR

;ROUTINES TO INSERT BYTES IN MESSAGE AND ACCOUNT FOR THEM

;INSERT ONE BYTE. ACCEPTS:	T2/ THE BYTE
;				T1/ LL BLOCK ADDRESS
;PRESERVES ALL REGISTERS

	RESCD
ONEBYT:	IDPB T2,LLBPTR(T1)	;STASH BYTE
	AOS LLBPCT(T1)		;ACCOUNT FOR IT
	RET			;DONE

;ROUTINE TO INSERT TWO BYTES, EXTENDED OR NOT
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T2/ THE BYTE
;MAY CLOBBER T2.

TWOBYT:	CALL ONEBYT		;STORE LOW ORDER BYTE
	ROT T2,-^D8		;GET HIGH ORDER BYTE
	CALLRET ONEBYT		;STORE IT
	SWAPCD
;ROUTINES TO FIND AND PARSE ARBITRARY ATTRIBUTES

;FIND ATTRIBUTE:
;ACCEPTS:	T2/ PREFIX VALUE
;RETURNS:	+1/ NO SUCH PREFIX
;		+2/ FOUND. T3=POINTER TO VALUE STRING

FNDATR:	LOAD T3,FILATL,(JFN)	;GET LIST OF ATTRIBUTES
	CALLRET GETATR		;GO FIND ATTRIBUTE


;GETATR - ROUTINE TO FIND AN ATTRIBUTE
;
;ACCEPTS IN T2/	PREFIX VALUE
;	    T3/	ADDRESS OF ATTRIBUTE LIST
;		CALL GETATR
;RETURNS: +1	 FAILED, NO SUCH PREFIX
;	  +2	SUCCESS, WITH T3/ POINTER TO VALUE STRING

GETATR:	JUMPE T3,R		;IF NO MORE, ALL DONE
	OPSTR <CAME T2,>,PRFXV,(T3) ;IS THIS THE ONE WE WANT
	JRST [	LOAD T3,PRFXL,(T3) ;NO. GET NEXT
		JRST GETATR]	;AND LOOK AT IT
	MOVEI T3,1(T3)		;GET POINTER TO BLCOK
	RETSKP			;AND SAY WE FOUND IT


;ROUTINE TO MAKE PROPER BYTE POINTER AND RETURN MAX COUNT FOR A
;BUFFER.
;ACCEPTS:	T1/ WINDOW ADDRESS
;		T3/ BYTE SIZE
;RETURNS:	+1
;		T1/ BYTE POINTER
;		T2/ COUNT

MAKPTR:	MOVE T4,T3		;SAVE IT
	IORI T3,4400		;MAKE A BYTE POINTER
	DPB T3,[POINT 12,T1,11]
	MOVEI T2,44		;BITS IN A WORD
	IDIVI T2,0(T4)		;COMPUTE BYTES IN A WORD
	LSH T2,PGSFT		;COMPUTE BYTES IN A PAGE
	RET			;AND DONE

;SPECIAL ROUTINE TO MAKE AN INPUT POINTER FOR FLOW FROM NETWORK

MAKINP::PUSH P,T3		;SAVE BYTE SIZE
	CALL MAKPTR		;GET A POINTER
	POP P,T3		;GET BACK BYTE SIZE
	CAIN T3,44		;WORD MODE?
	HRRZS T1		;YES. GET ADDRESS ONLY
	RET			;DONE
SUBTTL	MTOPR Utility Functions


;READ LINK TASK NAME

NTRTN::	LOAD T2,LLTSK,(T1)	;GET THE NAME
NTCPY:	CALL NTACPY		;DO THE WORK
	CALL BLKULK		;RELEASE LL BLOCK
	RETSKP			;AND DONE

;READ FOREIGN HOST NAME

NTRHN::	CALL MTRDCK		;VERIFY LINK STATE
	JRST [	MOVEI T1,DCNX11	;SAY NOT CONNECTED ANYMORE
		JRST SQOBAD]	;AND DONE
	TMNE LLLOC,(T1)		;LOCAL LINK?
	 JRST [MOVEI T2,OURNAM  ;YES
	       CALLRET NTCPY]	;GO COPY OUR NAME TO USER
	LOAD T2,LLHSN,(T1)	;GET THE NODE NUMBER
	NOINT			;NO INTERRUPTIONS
	LOCK NMAPLK		; WHILE TABLE LOCKED
	HRLI T2,440600		;POINT TO NODE'S
	HRRI T2,NODMAP(T2)	; ALPHABETIC NAME
	UMOVE T3,3		;GET USER'S STRING POINTER
	CALL NTRNAM		;GO RETURN NAME TO USER
	UMOVEM T3,3		;RETURN UPDATED BP TO USER
	SETZ T4,		;GIVE HIM
	XCTBU [IDPB T4,T3]	; THE NULL
	UNLOCK NMAPLK		;DONE WITH
	OKINT			; THE LOCK
	CALL BLKULK		;UNLOCK THE LL BLOCK
	RETSKP


;RETURN A NODE NAME TO THE USER
;ACCEPTS:	2/ BP TO NODE NAME
;		3/ USER'S BP
;RETURNS:	+1  T3/  UPDATED USER'S BP

NTRNAM:	TLC T3,-1
	TLCN T3,-1		;WANT DEFAULT?
	HRLI T3,(<POINT 7,>)	;USE. DO IT
	ACVAR <W1>		;GET A WORK REG
	MOVEI W1,6		;MAX. OF 6 CHARS IN NAME
NTRHN1:	ILDB T4,T2		;GET A BYTE
	JUMPE T4,R		;IF NULL, DONE
	ADDI T4,40		;CONVERT FROM 6-BIT TO 7-BIT
	XCTBU [IDPB T4,T3]	;GIVE IT TO USER
	SOJG W1,NTRHN1		;IF MORE, GO GET NEXT
	RET			;DONE

	ENDAV.
;WORKER ROUTINE TO COPY AN ASCII STRING TO THE USER.
;ACCEPTS:	2/ ADDRESS OF STRING
;RETURNS:	+1
;
;PRESERVES T1

NTACPY:	UMOVE T3,3		;GET USER'S STRING POINTER
	TLC T3,-1
	TLCN T3,-1		;WANT DEFAULT?
	HRLI T3,(<POINT 7,>)	;USE. DO IT
	ACVAR <W1>		;GET A WORK REG
	MOVE W1,[POINT 7,0(T2)]	;POINT TO SOURCE
NTCPY1:	ILDB T4,W1		;GET A BYTE
	JUMPE T4,NTCPY2		;IF NULL, ALL DONE
	XCTBU [IDPB T4,T3]	;STORE BYTE
	JRST NTCPY1		;DO THEM ALL
NTCPY2:	UMOVEM T3,3		;RETURN BYTE POINTER
	XCTBU [IDPB T4,T3]	;APPEND A NULL
	RET			;AND DONE

	ENDAV.			;END ACVAR
;MTOPR FUNCTIONS CONTINUED...

;RDSTS - GET LINK STATUS
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK (ASSUMED LOCKED)
;		CALL RDSTS
;RETURNS: +1 ALWAYS, WITH T3/ LINK STATUS

RDSTS::	LOAD T3,LLRSN,(T1)	;GET REASON IN CASE NOW DISCONNECTED
	TMNE LLFOB,(T1)		;IS THIS AN OBJECT?
	TXO T3,MO%SRV		;YES
	LOAD T2,LLSTA,(T1)	;GET CURRENT STATE
	CAIN T2,LLSRUN		;RUNNING?
	TXO T3,MO%CON		;YES. ALL CONNECTED
	CAIN T2,LLSLIS		;LISTENING?
	TXO T3,MO%WFC		;YES. WAITING FOR INCOMING CONNECT
	CAIN T2,LLSCIS		;CI SENT?
	TXO T3,MO%WCC		;YES, WAITING FOR CONNECTION TO COMPLETE
	CAIN T2,LLSCCS		;CC SENT?
	TXO T3,MO%WCC		;YES, WAITING FOR CONNECTION TO COMPLETE
	CAIN T2,LLSCIR		;CI RECEIVED?
	TXO T3,MO%WCC		;YES, WAITING FOR CONNECT TO COMPLETE
	CAIE T2,LLSDIR		;DI RECEIVED?
	CAIN T2,LLSABT		;OR ABORTED?
	JRST [	TXO T3,MO%ABT	;YES. ASSUME ABORTED
		JE LLFDI,(T1),.+1
		TXC T3,MO%ABT!MO%SYN ;NO. SWITCH TO SYNCH DI
		JRST .+1]	;AND PROCEED
	TMNE LLFIM,(T1)		;HAVE WHOLE MESSAGE IN BUFFER?
	TXO T3,MO%EOM		;YES
	SKIPE LLMSI(T1)		;HAVE ANY INTERRUPT MESSAGES?
	TXO T3,MO%INT		;YES. SAY SO
	JN LLLWC,(T1),[TXO T3,MO%LWC ;IF LINK WAS CONNECTED, SO NOTE
		       JRST .+1] ;CONTINUE
	RET			;DONE, RETURN

;MTOPR FUNCTION TO RETURN OBJECT USED TO CONNECT TO THE SERVER

NTRCN::	JE LLFOB,(T1),[CALL BLKULK ;FREE BLOCK
			RETBAD (DESX9)] ;AND RETURN ERROR
	LOAD T2,LLSTA,(T1)	;GET CURRENT STATE
	CAIN T2,LLSLIS		;LISTENING?
	JRST [	MOVEI T1,DCNX11	;YES. NOT CONNECTED
		JRST SQOBAD]	;GO CLEAN UP AND GIVE ERROR
	LOAD T2,LLSOB,(T1)	;GET OBJECT USED TO CONNECT
	UMOVEM T2,3		;RETURN TO USER
MTDON:	CALL BLKULK		;FREE BLOCK
	RETSKP			;AND DONE
;MORE MTOPR ROUTINES...

;READ USER NAME

NTRUS::	CALL MTOBJ		;MAKE SURE IS RUNNING OBJECT
	 JRST SQOBAD		;NOT
	LOAD T2,LLUSR,(T1)	;GET BLOCK ADDRESS
	CALLRET NTCPY		;GO DO IT

;READ ACCOUNT STRING

NTRAC::	CALL MTOBJ		;MAKE SURE IS RUNNING OBJECT
	 JRST SQOBAD		;NOT
	LOAD T2,LLACT,(T1)	;GET BLOCK
	CALLRET NTCPY		;AND GO DO IT

;COMMON ROUTINE TO VERIFY OBJECT


MTOBJ:	JE LLFOB,(T1),MTOBJ1	;MAKE SURE IS OBJECT
MTRDCK:	LOAD T2,LLSTA,(T1)	;IT IS. GET CURRENT STATE
	CAIE T2,LLSCIR		;IN CIR STATE?
	CAIN T2,LLSCCS		; OR CC SENT?
	RETSKP			;YES. IS GOOD THEN
MTRNCK::LOAD T2,LLSTA,(T1)	;GET STATE
	CAIN T2,LLSRUN		;RUNNING?
	RETSKP			;YES.
MTOBJ1:	RETBAD (DCNX8)		;NOT A RUNNING OBJECT

;READ PASSWORD

NTRPW::	CALL MTOBJ		;MAKE SURE IS RUNNING OBJECT
	 JRST SQOBAD		;NOT
	LOAD T2,LLPSW,(T1)	;GET BLOCK ADDRESS
	LOAD T3,LLPCT,(T1)	;AND THE COUNT
NTCPYB:	UMOVEM T3,4		;RETURN COUNT
	ACVAR <W1,W2>		;GET WORK REGS
	MOVE W2,T3		;SAVE COUNT
	MOVE W1,[POINT 8,0(T2)]	;GET POINTER TO DATA
	UMOVE T3,3		;GET USER SP
	TLC T3,-1
	TLCN T3,-1
	HRLI T3,(<POINT 7,>)	;FORM DEFAULT
	JRST NTCP11		;GO MAKE SURE IS AT LEAST ONE
NTCP1:	ILDB T4,W1		;GET NEXT BYTE
	XCTBU [IDPB T4,T3]	;STORE IT
NTCP11:	SOJGE W2,NTCP1		;AND DO THEM ALL
	UMOVEM T3,3		;RETURN BYTE POINTER
NTMTGD:	CALL BLKULK		;FREE THE BLOCK
	RETSKP			;AND DONE

	ENDAV.			;END ACVAR
;READ OPT DATA

NTRDA::	LOAD T2,LLOPT,(T1)	;GET OPTIONAL DATA BLOCK
	LOAD T3,LLUCT,(T1)	;GET COUNT
	CALLRET NTCPYB		;AND GO DO IT

;SET CONNECT DONE INTERRUPT CHANNEL

MTSETC::CALL CHKCHL		;VERIFY CHANNEL
	 RET			;BAD
	JUMPL T2,RSKP		;IF NO CHANGE, DONE
	STOR T2,LLPIC,(T1)	;SAVE CHANNEL
	LOAD T3,LLSTA,(T1)	;GET STATE OF LINK
	CAIL T3,LLSCIR		;NEED INTERRUPT NOW?
	CALL CONINT		;YES. GIVE IT
	RETSKP			;AND DONE

;SET INTERRUPT MESSAGE CHANNEL

MTSETI::CALL CHKCHL		;CHECK CHANNEL
	 RET			;BAD
	JUMPL T2,RSKP		;IF NO CHANGE, ALL DONE
	STOR T2,LLPII,(T1)	;SAVE CHANNEL
	SKIPE LLMSI(T1)		;HAVE ANY INT MESSAGES
	CALL INTINT		;YES. DO INTERRUPT NOW THEN
	RETSKP			;AND DONE

;SET DATA ARRIVED INT CHANNEL

MTSETD::CALL CHKCHL		;VERIFY CHANNEL
	 RET
	JUMPL T2,RSKP		;IF NO CHANGE, RETURN
	STOR T2,LLDRC,(T1)	;SAVE CHANNEL
	SKIPE LLOMSG(T1)	;ANY MESSAGES?
	CALL DATINR		;YES. GIVE INT THEN
	RETSKP			;DONE
;ROUTINE TO VERIFY CHANNEL #
;		T2/ CHANNEL
;RETURNS:	+1 BAD CHANNEL
;		+2 VALID CHANNEL

CHKCHL:	CAIN T2,.MOCIA		;CLEAR?
	JRST [	SETZM T2	;IF SO. UNSETTING
		RETSKP]		;SO, RETURN A ZERO
	CAIN T2,.MONCI		;NO CHANGE?
	JRST [	SETOM T2	;YES
		RETSKP]		;SO SAY SO
	CAIL T2,44		;WITHIN RANGE?
	JRST CHKILL		;NO
	CAILE T2,5		;WITHIN RANGE 0-5?
	CAIL T2,^D23		;OR WITHIN RANGE 23-35
	AOSA T2			;YES. A GOOD CHANNEL
	JRST CHKILL		;NO. ILLEGAL
	RETSKP			;RETURN GOOD VALUE
CHKILL:	RETBAD (ARGX13)		;INVALID CHANNEL

;COMMON ROUTINE TO GENERATE INTERRUPT RECEIVED INTERRUPT

INTINT:	SAVET			;SAVE REGS
	CALL TELINT		;GO NOTIFY DRIVER IF THIS IS AN INTERNAL LINK
	LOAD T2,LLFRK,(T1)	;GET FORK TO INT
	OPSTR <SKIPN T1,>,LLPII,(T1) ;HAVE AN INT CHANNEL?
	RET			;NO
	SOS T1			;YES
	CALLRET PSIRQ		;GO DO THE INTERRUPT



;TELINT - ROUTINE TO NOTIFY THE DRIVER WHEN AN INTERRUPT MSG IS RECEIVED
;	  FOR AN INTERNAL LOGICAL LINK
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL TELINT
;RETURNS: +1 ALWAYS, WITH DRIVER NOTIFIED

TELINT:	JE LLINT,(T1),R		;IF NOT AN INTERNAL LINK, THEN DONE
	SAVET			;PRESERVE TEMPORARY AC'S
	LOAD T4,LLVEC,(T1)	;GET DRIVER VECTOR ADDRESS
	LOAD T1,LLDRV,(T1)	;GET DRIVER CORRELATION CODE
	CALLRET @.NSINT(T4)	;NOTIFY DRIVER AND RETURN
;MORE MTORP FUNCTIONS...

;RECEIVE INTERRUPT MESSAGE

MTRDIN::MOVE T2,[IFIW![	XCTBUU [IDPB T2,3] ;ROUTINE TO RETURN BYTE
			RET ]]	; AND DONE
	UMOVE T3,3		;GET USER'S DESTINATION POINTER
	CALL RDINT		;GO READ AN INTERRUPT MESSAGE
	 JRST [	JUMPE T2,SQOBAD	;FAILED, RETURN ERROR
		JRST ULKRET ]	; OR BLOCK IF NEEDED
	UMOVEM T3,4		;RETURN BYTE POINTER
	UMOVEM T4,3		;RETURN COUNT TO USER
	PUSH P,T2		;STASH MESSAGE ADDRESS
	CALL BLKULK		;DONE WITH BLOCK
	POP P,T1		;RETRIEVE MESSAGE ADDRESS
	CALL RELRES		;RELEASE MESSAGE
	RETSKP			;AND DONE




;ULKRET - ROUTINE TO UNLOCK LOGICAL LINK BLOCK AND GIVE BLOCK-NEEDED RETURN
;
;ACCEPTS IN JFN/ ADDRESS OF JFN BLOCK
;		JRST ULKRET
;RETURNS TO CALLER WITH BLKF SET

ULKRET:	TQO <BLKF>		;NOTE BLOCK IS NEEDED
	EXCH T1,FILLLB(JFN)	;SAVE ERROR. GET BLOCK ADDRESS
	CALL BLKULK		;FREE BLOCK
   IFN NSPSW,<
	CALL CHKLLB
   >
	EXCH T1,FILLLB(JFN)	;GET BACK ERROR
	RETBAD ()		;AND DONE
;RDINT - ROUTINE TO READ AN INTERRUPT MESSAGE
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;	    T2/	ADDRESS OF ROUTINE TO STORE BYTES
;			(SHOULD ASSUME BYTE POINTER IS IN T3)
;	    T3/	DESTINATION BYTE POINTER
;		CALL RDINT
;RETURNS: +1	 FAILED, T2/ 0 => DO NOT BLOCK, T2/ -1 => BLOCK
;	  +2	SUCCESS, INTERRUPT MESSAGE DELIVERED, WITH
;		T2/ ADDRESS OF MESSAGE
;		T3/ UPDATED COUNT
;		T4/ UPDATED POINTER

RDINT::	ACVAR <W1>
	STKVAR <RDICNT,RDIPTR,RDIRTN>
	MOVEM T1,W1		;SAVE LL BLOCK ADDRESS
	MOVEM T2,RDIRTN		;SAVE ROUTINE TO STORE BYTES
	MOVEM T3,RDIPTR		;SAVE DESTINATION BYTE POINTER
RDINT1:	CALL MTRNCK		;CHECK STATE
	 JRST RDINX		;FAIL, NOT IN RUN STATE
	SKIPN T2,LLMSI(T1)	;HAVE AN INT MESSAGE?
	JRST [	MOVX T1,DCNX15	;NO INTERRUPT MESSAGE AVAILABLE
		JRST RDINX ]	;RETURN ERROR
	MOVEI T2,1		;ASK FOR ONE MORE
	MOVEI T3,MSLSI		; INTERRUPT MESSAGE
	CALL SNDLS		;SEND MESSAGE
	 JRST [	MDISMS		;CAN'T, WAIT A BIT
		MOVE T1,W1	;RETRIEVE THE LL BLOCK ADDRESS
		JRST RDINT1]	;TRY IT AGAIN
	MOVE T2,LLMSI(T1)	;GET BACK MESSAGE
	LOAD T4,MSDTC,(T2)	;GET COUNT
	MOVEM T4,RDICNT		;SAVE COUNT
	MOVEM T4,W1		;AND SAVE AS LOOP VARIABLE
	MOVE T3,RDIPTR		;GET DESTINATION POINTER SUPPLIED
	TLC T3,-1
	TLCN T3,-1
	HRLI T3,(<POINT 7,>)	;GET DEFAULT
	MOVEM T3,RDIPTR		;SAVE POINTER
	MOVE T4,MSBPTR(T2)	;GET POINTER TO MESSAGE DATA
	JRST MTRDI2		;GO MOVE DATA

MTRDI1:	ILDB T2,T4		;GET NEXT BYTE
	CALL @RDIRTN		;STORE A BYTE
MTRDI2:	SOJGE W1,MTRDI1		;DO THEM ALL
	MOVE T2,LLMSI(T1)	;GET BACK MESSAGE
	SETZM LLMSI(T1)		;NONE NOW
	MOVE T3,RDICNT		;RESTORE COUNT
	MOVE T4,RDIPTR		;RESTORE POINTER
	RETSKP			;DONE, RETURN SUCCESS

; HERE ON AN ERROR

RDINX:	TDZA T2,T2		;NOTE BLOCK NOT WANTED
RDINB:	SETOM T2		;BLOCK NEEDED
	RET			;FAIL

	ENDAV.			;END ACVAR
;MORE MTOPR'S....  SEND INTERRUPT MESSAGE

MTSNIN::UMOVE T4,4		;GET COUNT
	UMOVE T3,3		;GET BP

;**;[2929]REMOVE 1 LINE AT MTSNIN: + 2L	DSC	22-MAR-83

	MOVE T2,[IFIW![	XCTBUU [ILDB T2,3]
			RET]]	;ROUTINE TO GET BYTES
	CALL SNINT		;SEND THE INTERRUPT MESSAGE
	 JRST SQOBAD		;FAILED, RETURN ERROR
	UMOVEM T3,3		;STORE UPDATED BYTE POINTER
	MOVE T1,FILLLB(JFN)	;GET BACK BLOCK ADDRESS
	CALL BLKULK		;UNLOCK THE LOGICAL LINK BLOCK
	RETSKP			;DONE, RETURN SUCCESS


;SNINT - ROUTINE TO SEND AN INTERRUPT MESSAGE
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;	    T2/	ADDRESS OF ROUTINE TO GET BYTES
;			(PLACES BYTE IN T2, ASSUMES PTR IN T3)
;	    T3/	BYTE POINTER FOR GETTING BYTES
;	    T4/	COUNT OF BYTES TO SEND
;		CALL SNINT
;RETURNS: +1	 FAILED, ERROR CODE IN T1
;	  +2	SUCCESS, WITH T3/ UPDATED BYTE POINTER

SNINT::	ACVAR <W1>		;CAN SEND IT
	STKVAR <SIMLLB,SIMRTN,SIMPTR,SIMCNT>
	MOVEM T2,SIMRTN		;SAVE ROUTINE ADDRESS
	MOVEM T3,SIMPTR		;SAVE POINTER FOR GETTING BYTES
	MOVEM T4,SIMCNT		;SAVE COUNT OF BYTES TO SEND
	CALL MTRNCK		;MAKE SURE IS RUNNING
	 RET			;NOT IN RUN STATE, FAIL
	MOVE T4,SIMCNT		;GET COUNT
	CAILE T4,MAXINT		;WITHIN RANGE?
	JRST [	MOVEI T1,DCNX12	;ARG TOO LARGE
		RET ]		;RETURN ERROR
	JE LLMIC,(T1),[	MOVEI T1,DCNX14 ;ANY QUOTA?
			RET ]	;NO, FAIL
	MOVEI T1,INTLEN+MSHDR	;LENGTH
	CALL GETRES		;GET SOME SPACE
	 RET			;NO SPACE, FAIL
	MOVE W1,T1		;SAVE BLOCK ADDRESS
	MOVEI T2,MSHDR(T1)	;GET TO DATA PART
	HRLI T2,(<POINT 8,>)
	MOVE T1,FILLLB(JFN)	;GET LL BLOCK
	MOVEM T2,LLBPTR(T1)	;THE POINTER
	SETZM LLBPCT(T1)	;INIT COUNT
	MOVEI T2,DATMFL+DATFLI+DATINT ;FLAGS
	STOR T2,MSMFL,(W1)	;SAVE IN MESSAGE
	CALL RTHDCI		;PUT ON ROUTE HEADER AND FLAGS
	CALL PUTLLA		;PUT IN LL ADDRESSES
	LOAD T2,LLISN,(T1)	;GET SEG #
	AOS T2			;NEXT ONE
	ANDI T2,7777		;MOD 4096
	STOR T2,MSSEG,(W1)	;SAVE IN MESSAGE
	STOR T2,LLISN,(T1)	;LAST SEG SENT
	CALL TWOBYT		;PUT IN DATA PART
	DECR LLMIC,(T1)		;ONE LESS PIECE OF QUOTA
	MOVE T4,SIMCNT		;GET COUNT
	MOVE T3,SIMPTR		;GET POINTER
	TLC T3,-1
	TLCN T3,-1
	HRLI T3,(<POINT 7,>)	;FORM DEFAULT
	MOVEM T3,SIMPTR		;SAVE UPDATED POINTER
	JRST MSTSN2		;GO SEND THEM
MSTSN1:	CALL @SIMRTN		;GET NEXT BYTE
	CALL ONEBYT		;STORE IN MESSAGE
MSTSN2:	SOJGE T4,MSTSN1		;DO THEM ALL
	LOAD T2,LLLNK,(T1)	;GET LINK ADDRESS
	STOR T2,MSLLA,(W1)	;SAVE IN MESSAGE
	MOVEI T2,MSLSI		;GET TYPE OF THIS MESSAGE
	STOR T2,MSTOM,(W1)	;SAVE IN MESSAGE
	MOVE T2,W1		;GET MESSAGE
	CALL SNDSEG		;SEND IT
	MOVE T3,SIMPTR		;RETURN UPDATED POINTER
	RETSKP			;DONE, RETURN SUCCESS

	ENDAV.			;END ACVAR
;MTOPR ROUTINE TO RETURN OBJECT-DESCRIPTOR.
;RETURNS OBJECT-DESCRIPTOR IN STRING POINTED TO BY USER AC3
;RETURNS USER,GROUP CODE IN AC4 (OR A ZERO IN AC4 IF NONE).

NTRCOB::JE LLFOB,(T1),NTRCB1	;MAKE SURE IT IS AN OBJECT
	LOAD T2,LLSTA,(T1)	;GET STATE
	CAIE T2,LLSCIR		;RECIEVED A CI?
	CAIN T2,LLSRUN		;OR RUNNING?
	SKIPA			;YES
NTRCB1:	JRST [	CALL BLKULK	;NO. UNLOCK BLOCK
		JRST MTOBJ1]	;AND DONE
	MOVE T2,LLUSGP(T1)	;GET USER,GROUP
	UMOVEM T2,4		;RETURN IT
	LOAD T2,LLFNM,(T1)	;GET OBJ NUMBER USED IN CI
	MOVE T3,[-OBJENT,,OBJPRO+1] ;SET UP FOR SEARCH
NTRCB2:	HRRZ T4,0(T3)		;GET OBJECT NUMBER
	CAIN T4,0(T2)		;THIS THE ONE?
	JRST [	HLRZ T2,0(T3)	;YES. GET POINTER TO NAME
		JRST NTRCB3]	;AND PROCEED
	AOBJN T3,NTRCB2		;NO. LOOK AT NEXT
	STKVAR <NTRCBN>		;NOT FOUND
	MOVEI T3,12		;CONVERT OBJECT NUMBER TO TEXT
	HRROI T1,NTRCBN
	NOUT
	 JFCL
	MOVE T1,FILLLB(JFN)	;GET BACK LL BLOCK
	MOVEI T2,NTRCBN		;GET POINTER TO NUMBER
NTRCB3:	CALL NTACPY		;PUT OBJECT STRING IN USER SPACE
	LOAD T3,LLFDS,(T1)	;GET DESCRIPTOR
	SKIPN 0(T3)		;HAVE ONE?
	JRST MTDON		;NO. ALL DONE THEN
	MOVEI T2,[ASCIZ /-/]	;YES. PUT IN PUNCTUATION
	CALL NTACPY
	LOAD T2,LLFDS,(T1)	;GET BACK DESCRIPTOR STRING
	CALLRET NTCPY		;AND DONE

	ENDSV.
;MTOPR FUNCTION TO REFUSE A CONNECTION
;*************** NOTE *******************
;THIS CODE HAS A RACE IN THAT THE LINK IS IMMEDIATELY CONVERTED
;INTO A "LISTENER". THEREFORE, WHEN THE DC ARRIVES, THERE
;IS POTENTIAL CONFUSION OVER THE OWNER. THE
;PROBABILITY OF FAILURE IS <1/(HOSTS*2**16)> WHERE,
;"HOSTS" = # OF HOSTS ON THE NET.

NTRJCT:	CALL NTRFCI		;SEND DI
	 JRST SQOBAD		;NEED TO BLOCK
	CALL FLUSH		;KILL OF BUFFERS (IF ANY)
	CALL CLRBLK		;RESET LL BLOCK
	 JRST SQOBAD		;FAILED
	MOVEI T2,LLSLIS		;GET NEW STATE
	STOR T2,LLSTA,(T1)	;SET IT BACK TO LISTENING
	CALLRET NTMTGD		;AND DONE

;MTOPR FUNCTION TO CLOSE A CONNECTION

NTMTCZ::LOAD T2,LLSTA,(T1)	;GET CURRENT STATE
	CAIN T2,LLSCIR		;REALLY REJECTING A CONNECTION?
	CALLRET NTRJCT		;YES. GO DO IT
	CAIN T2,LLSDIQ		;DI QUEUED?
	JRST NTMCZ0		;YES. GO ON THEN
	CAIE T2,LLSCCS		;CONNECT SENT?
	CAIN T2,LLSRUN		;OR RUNNING?
	SKIPA			;YES, GO
	JRST NTRCB1		;NO. CAN'T DISCONNECT THEN
	UMOVE T2,2		;GET   REASON,,.MOCLZ
	HLRZS T2		;GET TYPE OF CLOSE
	SKIPE T2		;SYNCHRONOUS DISCONNECT?
	JRST [	CALL FLUSH	;NO, ABORT CLOSE. CLEAN OUT MESSAGES
		JRST NTMCZ0]	;AND SEND THE MESSAGE
	JE LLQOU,(T1),NTMCZ0	;IF QUEUER EMPTY, GO ON.
;	CALL MOVSEG		;PICK UP ACKS
;	 JRST OUTWAT		;NEED TO BLOCK
	MOVEI T2,CHKEMP		;WAIT FOR ALL ACKS
	JRST OUTWAT		; AND GO DO IT

;READY TO SEND THE MESSAGE

NTMCZ0:	MOVEI T2,LLSDIQ		;SET STATE
	STOR T2,LLSTA,(T1)	;""
	CALL NTRFCI		;SEND DI
	 JRST SQOBAD		;MUST WAIT
	MOVEI T2,LLSDIS		;NEW STATE
	STOR T2,LLSTA,(T1)	;STORE IT
	CALLRET NTMTGD		;AND DONE

;ROUTINE TO ACCEPT A CONNECTION

NTACPT::STKVAR <<OPTDAT,4>>
	LOAD T2,LLSTA,(T1)	;GET STATE
	CAIE T2,LLSCIR		;PROPER STATE
	JRST NTRCB1		;NO. ERROR
	MOVEI T3,OPTDAT		;MOVE OPTDATA IF ANY
	UMOVE T2,4		;GET COUNT
	UMOVE T4,3		;GET USER'S POINTER
	CALL NTMVOP		;GET OPTDATA ARG
	 JRST SQOBAD		;TOO LONG
	CALL CNFCOM		;GO CONFIRM IT
	 JRST SQOBAD		;NEED TO WAIT
	CALLRET NTMTGD		;DONE

;MTOPR TO RETURN MAX SEGMENT SIZE FOR THE LINK

MTGSS::	CALL MTRNCK		;MUST BE RUNNING
	 JRST SQOBAD		;NOT
	LOAD T2,LLSWG,(T1)	;GET MAX SEG SIZE
	UMOVEM T2,3		;RETURN TO USER
	CALLRET NTMTGD		;AND DONE
;COMMON ROUTINE USED TO SET UP FOR CALL TO SNDDI TO DISCONNECT
;OR REFUSE A CONNECTION.

NTRFCI:	STKVAR <<OPTDAT,4>>	;GET SOME SPACE TO HOLD USER DATA
	MOVEI T3,OPTDAT		;WHERE TO MOVE OPTDATA TO
	UMOVE T2,4		;GET COUNT
	UMOVE T4,3		;GET USER'S POINTER
	CALL NTMVOP		;DO IT
	 RETBAD()		;TOO LONG
	XCTU [HLRZ T2,2]	;GET REASON
	MOVEI T4,CNMRFL+CNMDI	;GET PROPER FLAGS
	CALL SNDDI		;SEND THE DI
	 JRST [	TQO <BLKF>	;SCHED TEST ALREADY IN T1, NOTE BLOCK NEEDED
		RET ]		;COME BACK AGAIN LATER
	CALL SNDCTL		;SEND THE MESSAGE
	RETSKP			;AND DONE

;ROUTINE TO COPY OPTDATA TO A BUFFER AND RETURN PROPER OPTDATA
;ARG
;	T2/ INPUT BYTE COUNT
;	T3/ BUFFER ADDRESS
;	T4/ INPUT POINTER
;RETURNS:	+1 TOO LONG
;		+2 DONE

NTMVOP::ACVAR <W1,W2,W3>
	STKVAR <NMVCNT,NMVPTR>
	TLC T4,-1		;CHECK FOR SPECIAL POINTER
	TLCN T4,-1		;IS IT?
	HRLI T4,(<POINT 7,>)	;YES. CONVERT IT THEN
	MOVEM T4,NMVPTR		;SAVE POINTER TO INPUT
	MOVEM T2,NMVCNT		;SAVE COUNT OF BYTES
	MOVE W3,T3		;SAVE BUFFER ADDRESS
	SETZM T3		;ASSUME NO DATA
	MOVE T4,NMVCNT		;GET COUNT
	JUMPE T4,RSKP		;IF NONE, NO ARG
	SKIPL T4		;COUNT MUST BE POSITIVE
	CAILE T4,MAXOPT		;WITHING LIMITS
	RETBAD (DCNX12)		;NO. TOO LONG
	STOR T4,CNTFLD,W3	;BUILD RETURN ARG
	MOVE W2,[POINT 8,0(W3)]	;GET POINTER TO SOURCE
	MOVE T3,NMVPTR		;GET USER'S POINTER
NTMVO1:	XCTBU [ILDB W1,T3]	;GET BYTE
	IDPB W1,W2		;STASH IT
	SOJG T4,NTMVO1		;COPY THEM ALL
	MOVE T3,W3		;GET ARG
	RETSKP			;AND DONE

	ENDAV.			;END ACVAR
SUBTTL	Routines to CLose a Logical Link


NETCLZ::ACVAR <W1,W2>		;GET SOME WORK REGISTERS
	MOVE W2,T1		;SAVE ENTRY FLAGS
	CALL NETUOU		;UNDO OUTPUT
NETCL1:	MOVE T1,FILLLB(JFN)	;GET LL BLOCK ADDRESS
	CALL BLKLLK		;LOCK THE BLOCK
	 JRST [	TXNN W2,CZ%ABT	;ABORT?
		JRST WATBLK	;NO. CONVENTIONAL WAIT THEN
		MDISMS		;YES. WAIT HERE
		JRST NETCL1]	;AND TRY AGAIN
;	CALL MOVSEG		;PICK UP LATENT ACKS
;	 MOVE T1,FILLLB(JFN)	;GET BACK LL BLOCK ADDRESS
	IFQN. LLTTA,(T1)	;SET HOST IN EFFECT?
	  CALL TTCLSH		;(T1/) YES, CLEAR IT
	ENDIF.
	LOAD T2,LLSTA,(T1)	;GET CURRENT STATE
	JRST @CLZSTA-1(T2)	;GO DO PROPER THING
;STATE ROUTINES OF NETCLZ
;LINK IN RUN STATE

CLZRUN:	TXNE W2,CZ%ABT		;WANT ABORT?
CLZDI:	JRST [	MOVEI T2,.DCX9	;YES. SAY USER ABORT
		JRST CLZEMP]	;AND GO SEND DI,ETC...
	LOAD T3,LLBSZ,(T1)	;GET BYTE SIZE
	CALL MAKPTR		;COMPUTE MAX BYTES IN BUFFER
	MOVE T1,FILLLB(JFN)	;GET BACK POINTER
	HLRZ T3,FILBCT(JFN)	;SEE IF ANY BYTES
	SUBI T2,0(T3)		;COMPUTE BYTES TO BE SENT
	TMNN LLFLO,(T1)		; FLOW NOW TO F/S?
	JRST CLZCMS		;YES, WAIT FOR ACKS
	JUMPE T2,CLZCMS		;NO, ANY BYTES TO SEND?
	SETONE LLFEM,(T1)	;YES, SAY EOM IN THIS BUFFER
	CALL OUTRR		;GO FORCE OUT DATA
	 RETBAD()		;COULDN'T. WAIT A WHILE
	MOVE T1,FILLLB(JFN)	;RESTORE LL BLOCK ADDRESS

;ALL DATA OUT. WAIT FOR ACKS

CLZCMS:	SETZ T2,		;SYNCHRONOUS DI
	JE LLQOU,(T1),CLZEMP	;IF ALL ACK'ED, READY TO GO
	MOVEI T2,CHKEMP		;WAIT FOR EMPTY
	JRST OUTWAT		;AND ARRANGE FOR THE WAIT

CLZEMP:	STOR T2,LLRSN,(T1)	;SAVE REASON CODE
CLZDIQ:	SETZM T2		;ASSUME SYNCHRONOUS CLOSE
	TXNE W2,CZ%ABT		;ABORT CLOSE ?
	SETOM T2		;YES, NOTE SO
	SETZM T3		;NO OPTIONAL DATA
	CALL CLZSDI		;GO SEND DI FOR CLOSE
	 JRST [	TXNE W2,CZ%ABT	;ABORT?
		JRST CLZABT	;YES. GO RELEASE BLOCK THEN
		TQO <BLKF>	;COULD NOT SEND DI, MUST TRY AGAIN LATER
		JRST SQOBAD ]	;BLOCK AND TRY AGAIN
CLZWDC:	TXNE W2,CZ%ABT		;ABORT CLOSE?
	JRST [	SETONE LLSDE,(T1) ;YES. DISSOCIATE PROCESS AND LINK
		CALL BLKULK	;UNLOCK THE LL BLOCK
		JRST CLZDN1]	;AND GO FINISH UP
	MOVEI T2,CHKDCR		;WAIT FOR DC TO COME BACK
	JRST OUTWAT		;ALSO, REQUEST BLOCK
;MORE CLOSE ROUTINES
;DC HAS ARRIVED. FIND OUT IF IT WHAT WE WANTED

CLZDIR:				;CLOSE IN DI RECEIVED STATE
CLZABT:

REPEAT 0,<
	LOAD T2,LLRSN,(T1)	;GET REASON
	SKIPE T2		;NON-SPECIAL ERROR?
	CAIN T2,.DCX42		;OR REPLY TO DI?
	JRST CLZDON		;YES. GOOD CODE
	TXNN W2,CZ%ABT		;NOT. ARE WE ABORTING?
	JRST [	CALL BLKULK	;NO. SYNCH DI DIDN'T WORK
		RETBAD (DCNX11)] ;SAY SO
>

CLZDON:	CALL FLUSH		;CLEAN UP Q'S
	LLLOCK			;LOCK THE TREE
	CALL DELNOD		;GET RID OF NODE
	LLLULK
	OKINT			;MATCH BLKLOK THAT IS NEVER MATCHED
CLZDN1:	DECR DCCUR		;GIVING BACK A LINK
	HLRZ T1,FILWND(JFN)	;GET OUTPUT WINDOW
	SKIPE T1
	CALL RELPAG		;RELEASE IT
	HRRZ T1,FILWND(JFN)	;GET INPUT WINDOW
	SKIPE T1
	CALL RELPAG		;RELEASE IT
	SETZM FILBFO(JFN)
	SETZM FILBFI(JFN)
	RETSKP			;AND DONE

	ENDAV.			;END ACVAR
;CLZSDI - ROUTINE TO SEND A DI FOR A CLOSE
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS
;	    T2/	0 IF SYNCHRONOUS CLOSE, -1 IF ABORT
;	    T3/	COUNT OF BYTES IN OPTIONAL DATA (0 IF NONE)
;	    T4/	ADDRESS OF OPTIONAL DATA BUFFER
;		CALL CLZSDI
;RETURNS: +1	 FAILED, COULD NOT SEND DI
;	  +2	SUCCESS, WITH DI SEND

CLZSDI::ASUBR <CDILLB,CDIFLG,CDICNT,CDIBUF>
	STKVAR <<CDIOPT,4>>

	MOVE T1,CDILLB		;GET LOGICAL LINK BLOCK ADDRESS
	MOVEI T2,LLSDIQ		;DI IS NOW QUEUED
	STOR T2,LLSTA,(T1)	;MARK STATE CHANGE
	SETZM T3		;START BY ASSUMING NO OPTIONAL DATA
	SKIPE CDICNT		;ANY OPTIONAL DATA ?
	JRST [	MOVEI T3,CDIOPT	;YES, GET DESTINATION BUFFER ADDRESS
		MOVE T2,CDICNT	;GET NUMBER OF BYTES IN OPTIONAL DATA
		MOVE T4,CDIBUF	;GET SOURCE BUFFER ADDRESS
		HRLI T4,(POINT 8,) ;AND FORM A POINTER TO OPTIONAL DATA
		CALL NTMVOP	;CHECK OPTIONAL DATA, SETUP T3 WITH COUNT
		 RETBAD ()	;FAILED, RETURN ERROR TO USER
		JRST .+1]	;T3 SET UP, CONTINUE WITH SETUP FOR DI MESSAGE
	LOAD T2,LLRSN,(T1)	;GET OUR REASON
	MOVEI T4,CNMRFL+CNMDI	;IS A DI
	CALL SNDDI		;GO SEND DI
	 JRST [	SKIPN CDIFLG	;ABORT ?
		RETBAD ()	;NO. BLOCK THEN
		TQZ <BLKF>	;YES. UNDO BLOCK
		BUG (CLZDIN)
		MOVE T1,CDILLB	;GET BACK LOGICAL LINK BLOCK ADDRESS
		RETBAD ()]	;AND DONE
	CALL SNDCTL		;SEND THE MESSAGE
CLZDQ1:	MOVEI T2,LLSDIS		;SAY DI IS SENT
	STOR T2,LLSTA,(T1)
	RETSKP			;DONE, RETURN SUCCESS
;ROUTINE TO SEND A DI OR A DC

;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T2/ REASON
;		T3/ <COUNT>B5+PTR TO USER DATA
;		T4/ FLAGS
;RETURNS:	+1/ COULDN'T. TEST ROUTINE IN T1
;		+2/ ALL SENT

SNDDI:	ASUBR <LLBLK,DISRSN,DIUDAT,DIFLGS>
	STKVAR <LLMSGB>
	MOVX T1,DILEN+MSHDR	;GET A BLOCK FOR THE DI
	CALL GETRES		;GET IT
	 JRST TIMWAT		;FAILED
	MOVEM T1,LLMSGB		;SAVE BLOCK ADDRESS
	MOVE T1,LLBLK		;RETRIEVE LL BLOCK ADDRESS
	LOAD T3,LLLNK,(T1)	;GET LL ID
	MOVE T2,LLMSGB		;RETRIEVE MESSAGE ADDRESS
	STOR T3,MSLLA,(T2)	;PUT LL ID IN MESSAGE HEADER
	MOVE T3,DIFLGS		;GET THE MESSAGE FLAGS
	STOR T3,MSMFL,(T2)	;PUT FLAGS IN MESSAGE HEADER
	MOVEI T3,MSHDR(T2)	;GET TO START OF DATA PORTION
	HRLI T3,(<POINT 8,>)	;MAKE A BYTE POINTER
	MOVEM T3,LLBPTR(T1)	;SAVE POINTER IN LL BLOCK
	SETZM LLBPCT(T1)	;INIT THE BYTE COUNT
	MOVE T2,DIFLGS		;GET FLAGS
	CALL RTHDCI		;PUT ON ROUTING HEADER AND FLAGS
	CALL PUTLLR		;PUT IN LL ADDRESSES
	MOVE T2,DISRSN		;GET REASON
	CALL TWOBYT		;PUT IT IN
	MOVE T3,DIFLGS		;SEE IF DI OR DC
	CAIN T3,CNMRFL+CNMDC	;DC?
	JRST SNDDI1		;YES. NO OPTDATA THEN
	MOVE T3,DIUDAT		;GET USER DATA
	LOAD T2,CNTFLD,T3 	;YES. GET COUNT
	SETZRO CNTFLD,T3 	;CLEAR THOSE BITS
	CALL MVBNRY		;PUT IN THE DATA
SNDDI1:	MOVE T2,LLMSGB		;GET BACK BLOCK ADDRESS
	RETSKP			;AND DONE
;ROUTINES CALLED FROM FILE SYSTEM TO SWITCH THE SENSE OF THE
;JFN. FIRST, ROUTINE TO SWITCH JFN TO INPUT SENSE

NETINP::CALL NETUOU		;GO UNDO OUTPUT IF NECESSARY
	CALL NETUIN		;UNDO INPUT
	MOVE T1,FILLLB(JFN)	;GET LL BLOCK
	CALL BLKLLK		;LOCK IT UP
	 JRST [	MDISMS		;WAIT FOR LOCK
		JRST NETINP]	;AND TRY AGAIN
	TQO <FILINP>		;NOW WILL SWITCH TO INPUT
	LOAD T3,LLSTA,(T1)	;GET STATE
	CAIN T3,LLSDIS		;DID USER TERMINATE LINK ?
	JRST [	CALL BLKULK	;YES, UNLOCK LOGICAL LINK BLOCK
		SETZM T1	;NOTE NO MORE INPUT AVAILABLE
		RET ]		;AND DONE
	CAIE T3,LLSRUN		;RUNNING?
	CAIN T3,LLSDIR		;OR STILL AVAILBALE FOR INPUT?
	SKIPA			;YES
	JRST NETIN2		;NO. GO ON
	HRRZ T3,FILBCT(JFN)	;GET COUNT OF BYTES
	TMNE LLFLI,(T1)		;IS FLOW FROM NETWORK?
	SKIPN T3		;NO. NEED BYTES?
	CALL NETSET		;YES. GO GET SOME BYTES
	 MOVE T1,FILLLB(JFN)	;GET BACK LL BLOCK ADDRESS
	TQZ <BLKF>		;IGNORE BLOCKING IF SET
NETIN2:	CALL BLKULK		;FREE LOCK
	MOVE T2,FILBFI(JFN)	;GET INPUT BYTE POINTER
	HRRZ T1,FILBCT(JFN)	;GET COUNT
	MOVE T3,FILLLB(JFN)	;GET LL BLOCK
	TMNE LLFLI,(T3)		;IS INPUT FLOW TO THE F/S?
	SKIPE LLMSI(T3)		;YES. FREE OF INT MESSAGES
	CALL [	SETZB T1,FILLEN(JFN) ;NO. NO BYTES THEN
		TQZ <FILINP>	;AND SAY NO GOOD DATA IN JFN BLOCK
		RET]		;DONE
NETSCM:	MOVEM T1,FILCNT(JFN)	;TO THE JFN
	MOVEM T2,FILBYT(JFN)	;STORE NEW POINTER
	SETZM FILBYN(JFN)	;ZERO BYTE NUMBER
	JUMPE T1,R		;IF NO COUNT, RETURN NOW
	TMNN LLFIM,(T3)		;EOM IN THE INPUT BUFFER?
	AOS T1			;NO. MAKE SINR COME BACK THEN
	MOVEM T1,FILLEN(JFN)	;AND MAKE COUNT THE LENGTH
	RET			;DONE

;ROUTINE TO SET UP FOR OUTPUT

NETOUP::CALL NETUIN		;UNDO INPUT IF NECESSARY
	TQOE <FILOUP>		;NOW DOING OUTPUT?
	RET			;YES. ALL DONE
	MOVE T2,FILBFO(JFN)	;GET POINTER
	HLRZ T1,FILBCT(JFN)	;GET COUNT
	MOVE T3,FILLLB(JFN)	;GET LL BLOCK
	TMNN LLFLO,(T3)		;IS OUTPUT FLOW FROM THE F/S?
	SETZM T1		;NO.
	JRST NETSCM		;AND DONE
SUBTTL	Sequential I/O JSYS's

;WORKER ROUTINE TO FORCE OUT ALL DATA.

OUTRR::	STKVAR <MSIZE,MBLOCK,MLODR>
;	CALL MOVSEG		;PICK UP ACKS,ETC...
;	 JRST OUTWAT		;ERROR OCCURRED
	CALL NETUOU		;UNDO OUTPUT
	MOVE T1,FILLLB(JFN)	;GET LL BLOCK
	CALL SKPFLO		;IS FLOW FROM THE FILE-SYSTEM
	 JRST OUTR0E		;NO. ALL SET TO GO THEN

;FLOW IS FROM THE FILE SYSTEM. COMPUTE BYTES NOW IN OUTPUT BUFFER
;AND SWITCH FLOW TO THE NETWORK

	CALL CLRFLO		;SWITCH FLOW TO THE NETWORK
	CALL GETBSZ		;GET BYTE SIZE FOR THIS LINK
	HLRZ T1,FILWND(JFN)	;GET WINDOW ADDRESS
	CALL MAKPTR		;GET MAX BYTES IN BUFFER
	MOVEM T1,FILBFO(JFN)	;PUT IN STARTING BYTE POINTER
	HLRZ T3,FILBCT(JFN)	;GET REMAINING COUNT
	SUBI T2,0(T3)		;COMPUTE BYTES IN THE BUFFER
	MOVE T1,FILLLB(JFN)	;get logical link block address
	CALL GETBSZ		;GO GET BYTE SIZE FOR THIS LINK
	CAIN T3,44		;WORD MODE?
	JRST [	IMULI T2,44	;YES. COMPUTE TOTAL BITS
		ADDI T2,7	;ROUND UP
		LSH T2,-3	;AND NOW COMPUTE FULL BYTES
		JRST .+1]	;AND CONTINUE
	MOVE T1,FILLLB(JFN)	;GET LL BLOCK ADDRESS
	TMNN LLFEM,(T1)		;EOM?
	JUMPE T2,RSKP		;NO, DONE
	HRLM T2,FILBCT(JFN)	;STORE COUNT TO SEND
OUTR0E:	MOVE T1,FILLLB(JFN)	;GET LL BLOCK ADDRESS
	TMNN LLFEM,(T1)		;EOM?
	JRST OUTR00		;NO, GO BACK FOR MORE
	JRST OUTRR3		;YES, CONTINUE OUTPUT PROCESSING
	; ..
;OUTRR CONTINUED.... TRY TO MAKE A MESSAGE

OUTR00:	MOVE T1,FILLLB(JFN)	;GET BACK LL BLOCK ADDRESS
OUTRR1:	HLRZ T2,FILBCT(JFN)	;SEE IF ANY MORE BYTES
	JUMPE T2,[CALL SETFLO	;NONE - SWITCH FLOW TO FILE-SYSTEM
		CALL GETBSZ	;GET BYTE SIZE
		HLRZ T1,FILWND(JFN) ;GET BUFFER PAGE
		CALL MAKPTR	;MAKE OUTPUT POINTER
		MOVEM T1,FILBFO(JFN) ;SET UP NEW POINTER
		HRLM T2,FILBCT(JFN) ;AND COUNT
		RETSKP]		;AND DONE
OUTRR3:	CALL SNDCHK		;GO SEE IF ANOTHER SEGMENT CAN BE SENT
OUTWAT:	 JRST [	TQNE <ERRF>	;ERROR?
		JRST SQOBAD	;YES. GO AWAY
		CALL MAKTST	;MAKE A STANDARD TEST WORD
		TQO <BLKF>	;REQUEST BLOCK
		CALLRET SQOBAD]	;AND FINISH UP

;CAN SEND SOME DATA

OUTRR2:	HLRZ T3,FILBCT(JFN)	;GET # OF BYTES REMAINING
	CALL GETMXS		;GO GET MAX SEGMENT SIZE
	CAILE T3,0(T4)		;CAN WE SEND IT ALL?
	MOVEI T3,0(T4)		;NO. SO SEND MAX AMOUNT
	MOVEM T3,MSIZE		;SAVE # OF BYTES TO SEND
	MOVEI T1,<<MSHDR+DTMLEN>*4+3>(T3) ;COMPUTE BYTES REQUIRED
	LSH T1,-2		;CONVERT TO WORDS
	CALL GETRES		;GET ONE
	 JRST [	CALL GENWAT	;GET A WAIT
		CALLRET SQOBAD]	;AND DONE
	; ..
;OUTRR CONTINUED... ADJUST COUNTS IN JFN BLOCK

	MOVEM T1,MBLOCK		;SAVE BLOCK ADDRESS
	MOVEI T2,MSHDR(T1)	;GET BEGINNING OF DATA STORAGE
	HRLI T2,(<POINT 8,>)	;FORM BYTE POINTER
	MOVE T1,FILLLB(JFN)	;GET BACK LL BLOCK
	MOVEM T2,LLBPTR(T1)	;SAVE WORK POINTER
	SETZM LLBPCT(T1)	;INIT COUNT
	MOVE T3,MSIZE		;GET # OF BYTES TO GO
	HLRZ T2,FILBCT(JFN)	;GET # NOW IN BUFFER
	SUBI T2,0(T3)		;COMPUTE # LEFT
	HRLM T2,FILBCT(JFN)	;SAVE FOR NEXT ROUND
	CALL MAKFLG		;GO MAKE FLAGS FOR THIS MESSAGE
	MOVE T3,MBLOCK		;GET MESSAGE BLOCK ADDRESS
	MOVE T4,MSIZE		;GET MESSAGE COUNT
	CALL MAKMSG		;GO ASSEMBLE NON-DATA PARTS OF MESSAGE
	LOAD T2,LLBSZ,(T1)	;GET BYTE SIZE
	CAIN T2,44		;WORD MODE?
	JRST OUTWRD		;YES. GO DO IT
OUTRR5:	MOVE T2,LLBPTR(T1)	;GET DESTINATION
	MOVE T1,FILBFO(JFN)	;GET SOURCE
	MOVE T3,T4		;COUNT
	CALL NETMOV		;MOVE THE BYTES
	MOVEM T1,FILBFO(JFN)	;UPDATE SOURCE POINTER
	MOVE T1,FILLLB(JFN)	;RESTORE LL BLOCK POINTER
OUTRR7:	MOVE T2,MBLOCK		;GET BACK BLOCK
	MOVEI T3,MSDAT		;GET TYPE OF THIS MESSAGE
	STOR T3,MSTOM,(T2)	;TO THE MESSAGE
	MOVE T4,MSIZE		;GET NO. OF DATA BYTES
	ADDI T4,2		;INCLUDE SEGNUM BYTES IN THE COUNT
	STOR T4,MSDTC,(T2);	;PUT NO. OF DATA BYTES IN THE MESSAGE
	CALL SNDSEG		;GO SEND A SEGMENT. ROUTINE
				;PLUGS IN LL ADDRESS AND MESSAGE SIZE
	JRST OUTR00		;AND TRY FOR ANOTHER SEGMENT
;CODE TO MOVE 36 BIT BYTES INTO A NETWORK MESSAGE.

OUTWRD:	MOVEM P3,MLODR		;SAVE A WORK REG
OUTWR0:	CAIGE T4,11		;HAVE AT LEAST 2 MORE WORDS?
	JRST [	MOVE T2,@FILBFO(JFN) ;NO. GET LAST WORD
		AOS FILBFO(JFN)
		SETZ T3,	;TO GEN NULLS
		MOVEI P3,5	;5 MORE BYTES TO MOVE
		JRST OUTWR1]	;GO DO IT
	DMOVE T2,@FILBFO(JFN)	;GET TWO MORE WORDS
	MOVEI P3,2		;THE INCREMENTER
	ADDM P3,FILBFO(JFN)
	MOVEI P3,11		;MOVE 9 BYTES
OUTWR1:	SUBI T4,11		;TAKE SOME BYTES
OUTWR2:	ROTC T2,10		;GET NEXT BYTE RIGHT JUSTIFIED
	IDPB T3,LLBPTR(T1)	;STORE IT
	SOJG P3,OUTWR2		;DO ALL BYTES
	JUMPG T4,OUTWR0		;GO DO MORE DATA
	MOVE P3,MLODR		;RESTORE REG
	JRST OUTRR7		;AND CONTINUE
;MAKMSG - ROUTINE TO ASSEMBLE THE NON-DATA PORTIONS OF A MESSAGE
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS
;	    T2/	MESSAGE FLAGS BYTE
;	    T3/	MESSAGE BLOCK ADDRESS
;	    T4/	MESSAGE SIZE
;		CALL MAKMSG
;RETURNS: +1 ALWAYS, WITH NON-DATA PORTIONS OF MESSAGE ASSEMBLED
;
; PRESERVES LOGICAL LINK BLOCK ADDRESS IN T1

	RESCD

MAKMSG::STKVAR <MBLOCK>
	MOVEM T3,MBLOCK		;LOCAL STORAGE FOR LL BLOCK ADDRESS
	STOR T2,MSMFL,(T3)	;SAVE MESSAGE FLAGS
	CALL RTHDCI		;PUT ON ROUTE HEADER AND FLAGS
	CALL PUTLLA		;PUT IN LL ADDRESSES
	TMNE LLFNA,(T1)		;THIS LL NEED AN ACK?
	CALL MAKACK		;YES, PUT IT IN
	MOVE T3,MBLOCK		;GET ADDRESS OF MESSAGE BLOCK
	MOVE T2,LLBPTR(T1)	;GET CURRENT BYTE POINTER
	MOVEM T2,MSBPTR(T3)	;SAVE IN MESSAGE BLOCK
	LOAD T2,LLDSN,(T1)	;GET LAST SEG SENT
	AOS T2			;NEXT ONE
	ANDI T2,7777		;ONLY 12 BITS
	STOR T2,LLDSN,(T1)	;PUT IT BACK
	STOR T2,MSSEG,(T3)	;SAVE SEG # IN DATA BLOCK
	CALL TWOBYT		;PUT IN SEGNUM
	ADDM T4,LLBPCT(T1)	;AND COUNT UP MESSAGE SIZE
	RET			;DONE, RETURN
;MAKFLG - ROUTINE TO MAKE THE FLAGS BYTE FOR A MESSAGE
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS
;	    T2/	NUMBER OF BYTES LEFT TO SEND IN SUBSEQUENT MESSAGES
;		CALL MAKFLG
;RETURNS: +1 ALWAYS, WITH T2/ MESSAGE FLAGS BYTE
;
; PRESERVES LOGICAL LINK BLOCK ADDRESS IN T1

MAKFLG::MOVEI T4,DATMFL		;GET BASIC MESSAGE FLAGS
	LOAD T3,LLMFC,(T1)	;GET TYPE OF FLOW CONTROL ON THIS LINK
	JN LLBOM,(T1),[
		SETZRO LLBOM,(T1) ;IS THIS START OF MESSAGE?
		TXO T4,DATBOM     ;YES. SET BOM THEN
		JRST MKFL10]      ;KEEP BOM
MKFL10:	TMNE LLFEM,(T1)		;WANT EOM?
	SKIPE T2		;IS THIS LAST SEGMENT OF MESSAGE?
	JRST [	CAIN T3,2	;MESSAGE FLOW CONTROL?
		JRST MKFL30	;YES. SKIP FLOW ADJUSTMENT
		JRST MKFL20]	;NO. ADJUST FLOW COUNTER
	SETZRO LLFEM,(T1)	;YES. TURN OFF EOM
	SETONE LLBOM,(T1)	;AND NEXT ONE IS BOM
	TXO T4,DATEOM		;AND SET EOM

MKFL20:	JUMPE T3,MKFL30		;IF NO FLOW CONTROL, SKIP ADJUSTMENT
	DECR LLMSM,(T1)		;ADJUST FLOW CONTROL
MKFL30:	MOVE T2,T4		;COPY MESSAGE FLAGS
	RET


;MAKE THE ACKNUM (PIGGYBACKED ACK) FIELD IN A DATA SEGMENT
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;RETURNS:	+1
;PRESERVES T1

MAKACK:	LOAD T2,LLIDN,(T1)	;GET LAST DATA SEGMENT RECEIVED
	TXO T2,ACKIND		;PUT IN ACKNUM INDICATOR
	CALL TWOBYT		;PUT ACKNUM FIELD IN MESSAGE
	SETZRO <LLFNA,LLFNN>,(T1)  ;CLEAR THE "NEED TO ACK/NACK" FLAGS
	RET
;SNDCHK - ROUTINE TO SEE IF ANOTHER SEGMENT CAN BE SENT ON A LOGICAL LINK
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS
;		CALL SNDCHK
;RETURNS: +1	 FAILED, WITH T2/ ADDRESS OF SCHEDULER TEST ROUTINE
;	  +2	SUCCESS, ANOTHER SEGMENT CAN BE SENT
;

SNDCHK::JN LLBRP,(T1),[MOVEI T2,CHKBRP ;IF FLOW CONTROL OFF, WAIT
 NSBP01:	RET]		;FAIL

	JN LLQUN,(T1),[
 NSBP02:	MOVEI T2,CHKSWD ;IF ANY NAK'ED SEGS
		RET ]		;FAIL
	MOVEI T2,.RESNP		;GET DECNET RESIDENT FREE SPACE POOL NUMBER
	MOVE T2,RESUTB(T2)	;GET NUMBER OF BLOCKS LEFT
	CAIG T2,RESHLD		;SPACE GETTING LOW?
	JRST [	MOVEI T2,NETRES	;YES, MUST WAIT
		RET]
	LOAD T2,LLQOU,(T1)	;GET SEGS NOW IN THE QUEUER
	LOAD T3,LLMQO,(T1)	;GET MAX OUTPUT QUEUE LENGTH
NSBP10:	CAMLE T2,T3		;CAN WE PUT ANOTHER ONE IN?
	JRST [	MOVEI T2,CHKQTA ;WAIT FOR QUEUER COUNT TO COME DOWN
 NSBP03:	RET ]		;FAIL
	LOAD T3,LLMFC,(T1)	;GET TYPE OF FLOW CONTROL
	SKIPN T3		;IF NO FLOW CONTROL, ALL SET
NSBP04:	RETSKP			;NO FLOW CONTROL
	LOAD T4,LLMSM,(T1)	;GET CURRENT FLOW COUNT
	JUMPE T4,[
 NSBP05:	MOVEI T2,CHKSCT ;WAIT FOR SOME COUNT TO APPEAR
		RET ]		;FAIL
	TMNN <LLNLS,LLALS>,(T1)	;NEED TO ACK LS?
	IFSKP.			;YES, CAN'T SEND DATA THEN
	   MOVEI T2,CHKLSA	;RETURN WITH SCHEDULER TEST
	   RET
	ENDIF.
	CAIE T3,2		;MESSAGE FLOW CONTROL?
	TRNN T4,200		;NO. SEGMENT. IS COUNT POSITIVE?
NSBP06:	RETSKP			;YES, CAN SEND A SEGMENT NOW.
NSBP07:	MOVEI T2,CHKSCP		;WAIT FOR COUNT TO GO POSITIVE
	RET			;RETURN SCHED TEST
;ROUTINE TO MAKE A STANDARD TEST WORD

MAKTST::LOAD T1,LLLNK,(T1)	;GET LL ADDRESS
	HRLS T1			;TO THE LH
	HRRI T1,0(T2)		;TEST ROUTINE
	RET			;DONE

;ROUTINE TO ARRANGE FOR A TIMED WAIT OF 1/2 SEC. THIS IS USED
;WHEN FREE SPACE IS EXHAUSTED.

GENWAT:	TQO <BLKF>		;NEED TO BLOCK
TIMWAT::MOVE T2,TODCLK		;GET NOW
	ANDI T2,377777
	ADDI T2,^D500		;WAIT 1/2 SEC FOR FREE SPACE
	MOVSI T1,0(T2)		;TIME TO THE LH
	HRRI T1,BLOCKM		;WAIT THIS LONG
	RET			;AND GO BLOCK

	SWAPCD
;ROUTINES OF NETSQO GOTTEN TO BY STATE TRANSITION TABLE

;SET UP BLOCK UNTIL LINK IS CONNECTED

SQOLIS:	MOVEI T2,CHKCON		;WAIT UNTIL CONNECTED
	JRST OUTWAT		;AND GO ARRANGE FOR THE BLOCK

;IMPLICIT CONFIRM

SQOCNF:	SETZM T3		;NO OPTDATA
	CALL CNFCOM		;GO CONFORM CONNECTION
	 JRST SQOBAD		;FAILED
	JRST NETSQ1		;AND COMPLETE OUTPUT REQUEST

;LINK HAS BEEN CLOSED BY PROCESS OR NSP. GIVE ERROR

SQOABT:	SKIPA T1,[DCNX11]	;NSP ABORT
SQODIS:	MOVEI T1,DCNX8		;ILLEGAL USER OPERATION
	TQO <ERRF>		;SAY HAVE AN ERROR
	JRST SQOBAD		;DONE

;FOREIGN HOST HAS DISCONNECTED

SQODIR:	TQO <ERRF>		;USER ERROR
	MOVEI T1,DCNX11		;GIVE ERROR
	JRST SQOBAD		;AND DONE
SQOEOF:	TQO <EOFF>		;NO. SAY EOF
	JRST SQOBAD		;DONE
;ROUTINE TO BUILD BASIC CC MESSAGE
;	T1/ LL BLOCK ADDRESS
;	T3/ <COUNT>B5+OPTDATA STRING
;RETURNS	+1 NO FREE SPACE. NEED TO BLOCK
;		+2 READY. T2/ BLOCK ADDRESS

SNDCC:	ASUBR <SAVLL,SAVBLK,SAVOPT>
	MOVEI T1,MSHDR+CCLEN	;GET ENOUGH SPACE
	CALL GETRES		;GET IT
	 RET			;FAILED. WAIT FOR A WHILE
	MOVEM T1,SAVBLK
	MOVE T1,SAVLL		;RETRIEVE LL BLOCK ADDRESS
	LOAD T3,LLLNK,(T1)	;GET LL ID
	MOVE T2,SAVBLK		;RETRIEVE MESSAGE ADDRESS
	STOR T3,MSLLA,(T2)	;PUT LL ID IN MESSAGE HEADER
	MOVEI T3,CNMRFL+CNMCF	;GET CC FLAGS
	STOR T3,MSMFL,(T2)	;PUT FLAGS IN MESSAGE HEADER
	MOVEI T3,MSHDR(T2)	;GET START OF DATA
	HRLI T3,(<POINT 8,>)	;MAKE A BYTE POINTER
	MOVEM T3,LLBPTR(T1)	;PUT IT IN LL BLOCK
	SETZM LLBPCT(T1)	;INIT THE BYTE COUNT
	MOVEI T2,CNMRFL+CNMCF	;GET CC FLAGS
	CALL RTHDCI		;PUT IN ROUTE HEADER AND FLAGS
	CALL DOSRVS		;PUT IN LL ADDRESSES AND STANDARD SERVICES
	MOVE T3,SAVOPT		;GET OPTDATA ARG
	LOAD T2,CNTFLD,T3	;GET COUNT
	SETZRO CNTFLD,T3	;CLEAR OUT COUNT BITS
	CALL MVBNRY		;PUT IN THE DATA
	MOVE T2,SAVBLK		;GET BLOCK
	RETSKP			;AND DONE

;COMMON ERROR RETURN

SQOBAD:	EXCH T1,FILLLB(JFN)	;SAVE ERROR. GET BLOCK ADDRESS
	CALL BLKULK		;FREE BLOCK
   IFN NSPSW,<
	CALL CHKLLB
   >
	EXCH T1,FILLLB(JFN)	;GET BACK ERROR
	RETBAD			;AND DONE

;IMPLICIT CONFIRM FROM SOUTR

SQOCN2:	SETZM T3		;NO OPTDATA
	CALL CNFCOM		;GO CONFIRM IT
	 JRST SQOBAD		;FAILED
	JRST NETSR1		;AND GO ON

;ROUTINE TO DO IMPLICIT CONFIRM

CNFCOM:	STKVAR <CNFLNK>
	MOVEM T1,CNFLNK		;SAVE LINK BLOCK ADDRESS
	JN LLTRN,(T1),SQOCN1	;IF ONLY NEED LS, GO DO IT
	CALL SNDCC		;GO BUILD CONNECT CONFIRM
	 JRST GENWAT		;BLOCK UNTIL FREE SPACE
	CALL SNDCTL		;SEND IT
	TMNE LLLOC,(T1)		;IS THIS A LOCAL LINK?
	 JRST SQOCN1		;YES, "CC SENT" DOESN'T EXIST FOR LOCALS
	LOAD T2,LLLKP,(T1)	;GET NODE'S VERSION
	CAIN T2,.NSP31		;IS IT NSP 3.1?
	JRST SQOCN1		;YES, MOVE ON
	MOVEI T2,LLSCCS		;STATE IS NOW
	STOR T2,LLSTA,(T1)	; CC SENT
	RETSKP			;WAIT FOR RESPONSE TO CC

SQOCN1:	CALL TURNON		;TRY TO SEND IT
	 JRST [	EXCH T1,CNFLNK		;SAVE SCHED TEST, GET LINK BLOCK ADR
		SETONE LLTRN,(T1) ;SAY STILL NEED LS
		MOVE T1,CNFLNK	;RESTORE SCHED TEST
		JRST GENWAT]	;AND GO WAIT AWHILE
	SETZRO LLTRN,(T1)	;DON'T NEED LS ANYMORE
	MOVEI T2,LLSRUN		;NOW IN RUN STATE
	STOR T2,LLSTA,(T1)	;SAY SO
	MOVEI T2,1		;INITIAL LS/INT REQ COUNT
	STOR T2,LLMIC,(T1)	;STORE IT
	RETSKP			;DONE
;COLLECTION OF SCHEDULER TEST ROUTINES USED BY NETSQO AND OTHERS

	RESCD			;MUST ALL BE RESIDENT
;BLOCK UNTIL CONNECTED

CHKCON:	SETOM T2		;ANY MATCH
	CALL LLLKUP		;GO FIND LL BLOCK
	 JRST 1(4)		;THIS SHOULDN'T HAPPEN
	LOAD T2,LLSTA,(T1)	;GET CURRENT STATE
	CAIN T2,LLSLIS		;LISTENING?
	JRST 0(T4)		;YES, NOT CONNECTED
	CAIN T2,LLSCIS		;CI SENT?
	JRST 0(T4)		;YES, NOT CONNETCED
	CAIN T2,LLSCCS		;CC SENT?
	JRST 0(T4)		;YES, NOT CONNECTED
	JRST 1(T4)		;MUST BE CONNECTED

;WAIT UNTIL BLOCK LOCK IS FREE

CHKLOK:	SETOM T2		;ANY MATCH
	CALL LLLKUP		;FIND LL BLOCK
	 JRST 1(4)		;CAN'T HAPPEN
	JN LLRCT,(T1),0(4)	;IF STILL NON-ZERO, MUST WAIT
	JRST 1(4)		;IS FREE

;WAIT UNITL QUEUER WILL TAKE SOME MORE MESSAGES

CHKQTA:	CALL CHKSET		;GET LL BLOCK, MAKE SURE STILL RUNNING
	 JRST 1(4)		;SOMETHING WRONG WITH LINK
	LOAD T2,LLQOU,(T1)	;GET QUEUER COUNT
	LOAD T3,LLMQO,(T1)	;GET MAX QUEUE LENGTH
	CAMLE T2,T3		;CAN TAKE SOME MORE?
	JRST 0(4)		;NO. WAIT SOME MORE
	JRST 1(4)		;YES.

;WAIT UNTIL SOME ACKS COME IN

;**;[2927]REPLACE 4 LINES WITH 8 LINES AT CHKSCT:	DSC	22-MAR-83

CHKSCT:	SETOM T2		;[2927]ANY REMOTE LINK FOR NOW
	CALL LLLKUP		;[2927]GET LL BLOCK ADDRESS
	 JRST 1(T4)		;[2927]NOT THERE ANYMORE, WAKE
	LOAD T2,LLSTA,(T1)	;[2927]GET STATE OF LL
	CAIE T2,LLSRUN		;[2927]RUNNING?
	JRST 1(4)		;[2927]NO, WAKE
	JN LLMSM,(T1),1(4)	;[2927]YES, IF SOME ACKS, WAKE UP
	JRST 0(4)		;[2927]STILL NO ACKS. WAIT SOME MORE

;WAIT UNTIL SEG ACK COUNT IS POSITIVE

CHKSCP:	CALL CHKSET		;VERIFY LINK STATE
	 JRST 1(4)		;LINK CHANGED STATE
	LOAD T2,LLMSM,(T1)	;GET SEG COUNT
	TRNE T2,177		;IS IT ZERO?
	TRNE T2,200		;NO. IS IT NEGATIVE?
	JRST 0(4)		;YES. MUST WAIT SOME MORE
	JRST 1(4)		;NO. CAN SEND SOME MORE DATA
;ROUTINE TO WAIT FOR MESSAGES TO ARRIVE

CHKRAW:	CALL CHKSET		;FORCE WAKE?
	 JRST 1(4)		;YES.
	TMNN LLFLI,(T1)		;ANYTHING IN FILE SYSTEM BUFFER?
	SKIPE LLOMSG(T1)	;ANYTHING ON ORDERED Q?
	JRST 1(4)		;YES. WAKE UP THEN
	JRST 0(4)		;NOTHING TO DO YET

;COMMON ROUTINE TO FIND LL BLOCK AND VERIFY THAT LL IS RUNNING

CHKSET:	SETOM T2		;ANY LINK
	CALL LLLKUP		;GO FIND BLOCK
	 RET			;NOT THERE. SOMETHING TERRIBLE HAPPENED
	LOAD T2,LLSTA,(T1)	;GET STATE
	SKIPN LLOMSG(T1)		;MESSAGES ON QUEUE?
	CAIE T2,LLSRUN		;IS IT RUNNING?
	RET			;WAKE UP
	RETSKP			;YES. ALL FINE

;CHECK IF RESENDS ARE ALL DONE

CHKSWD:	CALL CHKSET		;GO VERIFY LINK STATE
	 JRST 1(4)		;CHANGED. WAKE UP
	JE LLQUN,(T1),1(4)	;ALL NAK'ED SEGS NOW SENT?
	JRST 0(4)		;STILL RESENDS. WAIT

;TESTS FOR CLOSF

CHKDCR::SETOM T2		;ANY MATCH
	CALL LLLKUP		;FIND LL BLOCK
	 JRST 1(4)		;IF NO MORE LINK, THAT'S GOOD ENOUGH
	LOAD T2,LLSTA,(T1)	;GET STATE
	CAIE T2,LLSABT		;DC RECEIVED?
	CAIN T2,LLSDIR		;OR DI RECEIVED?
	JRST 1(4)		;YES. AWAKE
	JRST 0(4)		;NO. KEEP WAITING

CHKEMP::CALL CHKSET		;MAKE SURE ALL IS SET
	 JRST 1(4)		;NOT. A STATE CHANGE OCCURRED
	JE LLQOU,(T1),1(4)	;HAVE ALL ACKS ARRIVED?
	JRST 0(4)		;NO

;WAIT FOR BACK-PRESSURE

CHKBRP:	CALL CHKSET		;MAKE SURE ALL IS SET
	 JRST 1(4)		;NO. AWAKE
	JE LLBRP,(T1),1(4)	;IF NOW ON, AWAKE
	JRST 0(4)		;NO YET ON


;WAIT FOR RESIDENT FREE SPACE TO BECOME LESS CONGESTED

NETRES:	SETOM T2		;SEARCH ALL LINKS
	CALL LLLKUP		;LL STILL THERE?
	 JRST 1(4)		;NO, WAKE UP
	MOVEI T2,.RESNP		;GET DECNET RESIDENT FREE SPACE POOL NUMBER
	MOVE T2,RESUTB(T2)	;GET NUMBER OF BLOCKS LEFT
	CAIG T2,RESHLD		;SPACE STILL LOW?
	JRST 0(T4)		;YES
	JRST 1(T4)		;NO, WAKE UP


;WAIT UNTIL ACKING OF LS MESSAGES IS NO LONGER NECESSARY

CHKLSA:	SETOM T2		;ANY MATCH
	CALL LLLKUP		;FIND LL BLOCK
	 JRST 1(4)		;BADNESS, WAKE UP
	TMNN <LLNLS,LLALS>,(T1)	;NEED LS ACK?
	JRST 1(4)		;NO, WAKE UP
	JRST 0(4)		;YES, KEEP WAITING
;ROUTINES FOR SEQUENTIAL INPUT

;ROUTINE TO TAKE SEGMENTS OFF OF THE RAW DATA QUEUE AND
;PUT THEM ON THE ORDERED DATA QUEUE

REPEAT 0,<

MOVSEG::ACVAR <W1,W2,W3>
	STKVAR <MSGLLB>
	MOVEM T1,MSGLLB		;SAVE LOGICAL LINK BLOCK ADDRESS
	TMNE LLFNN,(T1)		;NEED A NACK?
	CALL MOVNAK		;YES. SEND NACK
MOVSE1:	SKIPN T2,LLMSG(T1)	;HAVE ANY?
	RETSKP			;NO. MUST BE DONE THEN
	NOSKD1			;PREVENT SCHEDULING
	MOVE T2,LLMSG(T1)	;GET HEADER AGAIN IN CASE IT CHANGED
	LOAD T3,MSLNK,(T2)	;GET LINK
	MOVEM T3,LLMSG(T1)	;NEW LINK
	OKSKD1			;AND ALLOW SCHEDULING
	LOAD T3,MSMFL,(T2)	;GET FLAGS
	TXNE T3,ACKFLM		;IS IT AN ACK?
	JRST [	CALL MOVACK	;YES. GO DO THE ACK THEN
		 RETBAD()	;ERROR OCCURRED
		JRST MOVSE1]	;AND DONE
	DECR LLDRW,(T1)		;ONE LESS DATA SEG ON Q
	MOVEI T3,MSDAT		;IS A DATA SEGMENT
	CALL VERSEG		;GO VERIFY CORRECTNESS OF MESSAGE
	 JRST [	MOVE W1,T3	;SAVE FLAG FROM VERSEG
		DECR LLDMT,(T1)	;ONE LESS DATA SEGMENT
		MOVE T1,T2	;GET SEGMENT ADDRESS
		CALL RELRES	;FREE IT UP
		MOVE T1,MSGLLB	;GET BACK LL BLOCK
		JUMPE W1,BADSEG	;IF PROTOCOL ERROR, GO SHUT LINK
		LOAD T2,LLIDN,(T1) ;GET LAST ACKED SEG
		MOVEI T3,MSDAT	;ON THE DATA CHANNEL
		CALL SNDACK	;ACK IT AGAIN
		 NOP		; IGNORE ERROR
		MOVE T1,MSGLLB	;RESTORE ADDRESS
		JRST MOVSE1]	;AND PROCEED
	; ..
	; ..

;MESSAGE IS GOOD. PUT IT ON THE ORDERED QUEUE

	LOAD T4,LLMQI,(T1)	;GET MAXIMUM INPUT QUEUE LENGTH
	CAMLE T3,T4		;SEE IF REASONABLE TO KEEP IT?
	JRST [	DECR LLDMT,(T1)	;NO. REMOVE SEG
		JE LLIMS,(T1),BADSEG ;IF NOT MESSAGE CONTROL, ERROR
		MOVE T1,T2	;NO. IS BEYOND QUOTA
		CALL RELRES	;FREE THE BLOCK
		MOVE T1,MSGLLB	;GET BACK LL BLOCK
		CALL MOVNAK	;AND SEND THE NACK
		JRST MOVSE1]	;DONE
	SKIPN T3,LLOMSG(T1)	;ANYTHING ON THE QUEUE?
	JRST [	MOVEM T2,LLOMSG(T1) ;NO. MAKE THIS THE QUEUE
		SETZRO MSLNK,(T2) ;TIE IT OFF
		JRST MOVSE1]	;AND DONE
	SETZ W1,		;AT THE TOP
	LOAD W2,MSSEG,(T2)	;GET SEG NUMBER
	; ..
;MOVSEG CONTINUED...

MOVSEL:	LOAD T4,MSSEG,(T3)	;GET THIS ONE'S NUMBER
	CAIN W2,0(T4)		;SAME?
	JRST [	MOVE T1,T2	;YES
		CALL RELRES	;THROW IT AWAY
		MOVE T1,MSGLLB	;GET LL BLOCK ADDRESS
		JRST MOVSE1]	;AND GO AGAIN
	SUBI T4,0(W2)		;COMPUTE THE DIFFERENCE
	MOVM W3,T4		;GET MAGNITUDE OF DIFFERENCE
	CAILE W3,MAXDIF		;IS GREATER THAN MAX DIFFERENCE?
	TLC T4,(1B0)		;YES. FLIP SIGN THEN
	JUMPL T4,[MOVE W1,T3	;IF LESS, INSERT AFTER
		LOAD T3,MSLNK,(T3) ;GET LINK
		JUMPN T3,MOVSEL	;AND GO LOOK SOME MORE
		JRST MOVSE2]	;AND GO INSERT IT
	JUMPE W1,[MOVE T4,LLOMSG(T1) ;GET OLD HEAD
		MOVEM T2,LLOMSG(T1) ;NEW HEAD
		STOR T4,MSLNK,(T2) ;AND FINISH LINK
		JRST MOVSE1]	;DONE
MOVSE2:	LOAD T4,MSLNK,(W1)	;GET OLD LINK
	STOR T2,MSLNK,(W1)	;INSERT IT
	STOR T4,MSLNK,(T2)	;FINISH UP
	JRST MOVSE1		;AND DONE

;ROUTINE TO SEND A NACK FOR THE LINK

MOVNAK:	STKVAR <MVNLLB>
	MOVEM T1,MVNLLB		;SAVE LOGICAL LINK BLOCK ADDRESS
	LOAD T2,LLIDN,(T1)	;GET SEG NUMBER
	TXO T2,ACKBIT		;MAKE IT A NACK
	MOVEI T3,MSDAT		;ON THE DATA CHANNEL
	CALL SNDACK		;SEND THE NACK
	 JRST [	MOVE T1,MVNLLB	;GET BACK LL BLOCK ADDRESS
		CALLRET DATINR]	;BUT MAKE IT RETRY SOON
	SETZRO <LLFNN,LLFNA>,(T1) ;CLEAR FLAGS
	RET			;AND DONE

	ENDAV.			;END ACVAR
;LOCAL ROUTINE TO HANDLE AN ACK FOUND ON LLOMSG QUEUE
;	T1/ LL BLOCK ADDRESS
;	T2/ MESSAGE BLOCK ADDRESS

MOVACK:	TRVAR <MSGCNT,MSGBYP,MSGBLK,MSGLL>
	MOVEM T1,MSGLL		;SAVE LL BLOCK
	MOVEM T2,MSGBLK		;SAVE DATA BLOCK
	LOAD T3,MSDTC,(T2)	;GET DATA COUNT
	MOVEM T3,MSGCNT
	MOVE T3,MSBPTR(T2)	;GET POINTER TO DATA
	MOVEM T3,MSGBYP		;SET UP POINTER
	LOAD T2,MSMFL,(T2)	;GET FLAGS
	CALL ACKDO		;GO DO THA ACTUAL ACK
	 JRST BADSEG		;BADLY FORMED SEGMENT ENCOUNTERED
	MOVE T1,MSGBLK		;GET BLOCK ADDRESS
	CALL RELRES		;FREE IT UP
	MOVE T1,MSGLL		;GET LL ADDRESS
	RETSKP			;AND DONE
>				;END REPEAT 0 AT MOVSEG

;WORKER ROUTINE TO DO ACK. CALLED FROM BOTH PROCESS CONTEXT AND FROM
;NSPTSK.
;	T1/ LL BLOCK ADDRESS
;	T2/ MESSAGE FLAGS

ACKDO:	MOVE T4,T2		;SAVE FLAGS
	CALL GETTWO		;GET ACKNUM
	 RET			;BAD
	MOVEI T3,MSDAT		;IS A DATA ACK
	TRNE T4,ACKLSI		;ACKING DATA?
	MOVEI T3,MSLSI		;NO.
	CALL ACKCHN		;GO DO IT
	RETSKP			;AND DONE

;A BADLY FORMED SEGMENT WAS ENCOUNTERED

BADSEG:	MOVEI T2,LLSDIQ		;CHANGE LINK STATE
	STOR T2,LLSTA,(T1)
	CALL FLUSH		;RELEASE ALL PENDING MESSAGES
	MOVEI T2,.DCX40		;DATA LOSE ERROR
	STOR T2,LLRSN,(T1)	;THE ABORT REASON
	CALL DATINR		;GIVE INT
	SETZM T3		;NO USER DATA
	MOVEI T4,CNMRFL+CNMDI	;A DI
	CALL SNDDI		;GO SEND IT
	 CALLRET GENWAT		;NO FREE SPACE
	CALL SNDCTL		;SEND CONTROL MESSAGE
	MOVEI T2,LLSDIS		;NEW STATE
	STOR T2,LLSTA,(T1)
	CALLRET SEGERR		;AND GIVE ERROR

	SWAPCD
;ROUTINE TO DO SEQUENTIAL INPUT.

NETSQI::MOVE T1,FILLLB(JFN)	;GET LL BLOCK ADDRESS
	CALL BLKLLK		;LOCK IT UP
	 JRST WATBLK		;GO WAIT FOR THE LOCK
	LOAD T2,LLSTA,(T1)	;GET STATE
	JRST @SQISTA-1(T2)	;GO DO PROPER THING

SQI1:	SKIPE LLMSI(T1)		;have pending interrupt message?
	JRST [	MOVEI T1,DCNX2	;yes. illegal to do this input then
		TQO <ERRF>	;make it a file sys error
		JRST SQOBAD]	;and tell the process
	SOSL FILCNT(JFN)	;ANY MORE BYTES?
	JRST [	ILDB T2,FILBYT(JFN) ;YES. GET ONE
		AOS FILBYN(JFN)	;INDICATE WE TOOK ONE
		CALL BLKULK	;FREE THE BLOCK
		MOVE T1,T2	;GET BYTE IN PROPER PLACE
		RET]		;AND DONE
	JE LLFLI,(T1),SQI11	;IF FLOW FROM NETWORK...
	SETZRO LLFIM,(T1)	;CLEAR FLAG
SQI11:	CALL NETUIN		;UNDO INPUT
	MOVE T1,FILLLB(JFN)	;GET BACK LL BLOCK POINTER
	CALL NETSET		;GO TRY TO GET SOME BYTES
	 JRST [	TQO <BLKF>	;REQUEST BLOCK
		CALLRET SQOBAD]	;AND FINISH UP
	CALL BLKULK		;FOUND SOME. FREE THE LOCK
	CALL NETINP		;SET UP FOR INPUT
	JRST NETSQI		;AND TRY AGAIN

;ROUTINE TO SET BLKF AND RETURN

WATBLK:	TQO <BLKF>
	RETBAD()

;STATE TRANSITION ROUTINES FOR SEQUENTIAL INPUT

;DI RECEIVED.

SQIDIR:	JN LLFDI,(T1),[
		SKIPE FILCNT(JFN) ;SYNCHRONOUS?
		JRST SQI1	;GO GET REMAINING BYTES
		CALL NETSET	;SEE IF ANY MORE
		 JRST SQOEOF	;NO. GIVE EOF THEN
		JRST SQI1]	;YES. GO GET THEM
	CALL FLUSH		;NO . GO FLUSH ALL QUEUES
	TQO <ERRF>		;AN ERROR
	MOVEI T1,DCNX11		;ABORT ERROR
	JRST SQOBAD		;AND GIVE ERROR TO USER

;NEED IMPLICIT CONFIRM

SQICNF:	SETZM T3		;NO OPTDATA
	CALL CNFCOM		;GO DO CONFIRM
	 JRST SQOBAD		;NEED TO BLOCK
	JRST SQI1		;AND PROCEED
;ROUTINE TO SCAN INPUT QUEUES AND GET BYTES TO DELIVER TO PROGRAM

NETSET:	STKVAR <SQICNT>
	SETZM SQICNT		;NONE YET
	TMNN LLFLI,(T1)		;IS FLOW FROM THE NETWORK?
	JRST SQI22		;YES. ALL SET TO GO THEN
	SETZRO LLFIM,(T1)	;NO LONGER EOM
	SETZRO LLFLI,(T1)	;NO. SET FLOW FROM THE NETWORK
	LOAD T3,LLBSZ,(T1)	;GET BYTE SIZE
	HRRZ T1,FILWND(JFN)	;GET WINDOW PAGE
	CALL MAKINP		;GO GET INPUT POINTER
	MOVEM T1,FILBFI(JFN)	;SAVE BYTE POINTER
	SETZM SQICNT		;SAVE CURRENT COUNT
SQI22:	MOVE T1,FILLLB(JFN)	;GET ADDRESS OF LOGICAL LINK BLOCK
	LOAD T2,LLLSC,(T1)	;GET NO. OF SEGS RECEIVED SINCE LAST LS WAS SENT
	CAIGE T2,FLOHLD		;OVER THE THRESHOLD?
	IFSKP.			;YES
	   CALL SQILS		;SEND LS
	    JRST CHKFRE		;FAILED, WAIT A WHILE
	ENDIF.
SQI2:	MOVE T2,FILBFI(JFN)	;GET BUFFER ADDRESS
	MOVEI T3,4000		;MAX NUMBER OF BYTES IN JFN BUFFERS
	CALL MOVMSG		;GO REMOVE MESSAGES FROM QUEUE AND PUT IN BUFFER
	 RETBAD ()		;FAILED
	MOVEM T1,FILBFI(JFN)	;STORE NEW BUFFER POINTER
	MOVEM T2,SQICNT		;SAVE COUNT OF BYTES MOVED
	MOVE T1,FILLLB(JFN)	;RESTORE LOGICAL LINK BLOCK ADDRESS
	SKIPE T2		;ANY BYTES IN SEGMENT?
	JRST SQIEMP		;YES, ONWARD
	TMNE LLFIM,(T1)		;NO, EOM?
	IFNSK.			;YES, A NULL MESSAGE
	   SETZRO LLFIM,(T1)	;TURN OFF EOM
	   TQO <NSPNUL>		;SET THE FILSTS WORD
	   JRST SQIEM1		;FINISH PROCESSING THE MESSAGE
	ENDIF.
	; ..
;NETSQI CONTINUED....
;GOT ALL MESSAGES MOVED.

SQIEMP:	SKIPG SQICNT		;GET ANY BYTES?
	JRST SQINOB		;NO. NOTHING TO DO
SQIEM1:	LOAD T3,LLBSZ,(T1)	;GET BYTE SIZE
	HRRZ T1,FILWND(JFN)	;GET WINDOW ADDRESS
	CALL MAKPTR		;MAKE A POINTER
	MOVEM T1,FILBFI(JFN)	;TO THE BLOCK
	MOVE T4,FILLLB(JFN)
	LOAD T3,LLBSZ,(T4)	;GET BYTE SIZE
	MOVE T2,SQICNT		;GET COUNT WE FOUND
	CAIN T3,44		;WORD MODE?
	JRST [	IDIVI T2,11	;YES. COMPUTE BYTES
		LSH T2,1	;""
		JUMPE T3,.+1	;AN ODD WORD ON THE END?
		AOJA T2,.+1]	;YES. COUNT IT
	HRRM T2,FILBCT(JFN)	;SAVE IT
	MOVE T1,FILLLB(JFN)	;GET ADDRESS OF LOGICAL LINK BLOCK
	SETONE LLFLI,(T1)	;FLOW IS NOW TO F/S
	RETSKP			;ALL DONE. WITH GOOD DATA

;COULDN'T FIND ANY BYTES

SQINOB:	SKIPE LLOMSG(T1)		;HAVE ANY NOW?
	JRST SQI2		;AND TRY AGAIN
	MOVEI T2,CHKRAW		;THE BLOCK ROUTINE
	CALLRET MAKTST		;GO ARRANGE FOR THE BLOCK
;MOVMSG - ROUTINE TO REMOVE SEGMENTS FROM LLOMSG QUEUE AND PLACE INTO
;	  THE DESTINATION BUFFER.
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;	    T2/	BUFFER POINTER
;	    T3/	MAX # OF BYTES TO PUT INTO BUFFER
;		CALL MOVMSG
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, WITH T1/ UPDATE BUFFER POINTER
;			      T2/ COUNT OF BYTES MOVED
;			      T3/ -1 IF SOME DATA WOULD NOT FIT IN BUFFER
;
; NOTE:  TRVAR'S MSGCNT AND MSGBYP ARE USED BY ROUTINES TO EXTRACT FIELDS
;	 FROM MESSAGES (E.G. GETTWO).

MOVMSG:	TRVAR <MSGCNT,MSGBYP>
	STKVAR <MVMLLB,MVMBFI,MVMCNT,MVMMAX,MVMFLG>
	MOVEM T1,MVMLLB		;SAVE LOGICAL LINK BLOCK ADDRESS
	MOVEM T2,MVMBFI		;SAVE BUFFER ADDRESS
	MOVEM T3,MVMMAX		;SAVE MAX # OF BYTES TO BE PUT INTO BUFFER
	SETZM MVMCNT		;INITIALIZE COUNT
	SETZM MVMFLG		;ASSUME ALL DATA WILL FIT
MVM010:
;	CALL MOVSEG		;NO INPUT. GET ANY SEGS
;	 RETBAD()		;ERROR
	SKIPN LLOMSG(T1)	;ARE THERE ANY SEGMENTS?
	JRST MVMX		;NO, DONE
	HRRZ T2,LLOMSG(T1)	;GET THE HEAD SEGMENT
	LOAD T3,MSDTC,(T2)	;GET COUNT OF BYTES
	MOVEM T3,MSGCNT		;STASH IT
	MOVE T3,MSBPTR(T2)	;GET POINTER TO DATA
	MOVEM T3,MSGBYP		;SET UP POINTER
	CALL GETTWO		;GET NEXT FIELD
	 JFCL
	TXNE T2,ACKIND		;IS THIS ACKNUM?
	 CALL GETTWO		;YES. SO SKIP SEGNUM NOW
	 JFCL
	; ..
;NOW POSITIONED TO DATA PORTION OF SEGMENT. MOVE DATA INTO
;DESTINATION BUFFER

	MOVE T4,MSGCNT		;GET REMAINING COUNT
	ADD T4,MVMCNT		;COMPUTE BYTES TO BE IN BUFFER
	CAMLE T4,MVMMAX		;WILL THEY FIT?
	JRST [	SETOM T3	;NOTE NOT ALL DATA WOULD FIT
		JRST MVMY]	;EXIT
	MOVEM T4,MVMCNT		;YES. UPDATE COUNT
	HRRZ T2,LLOMSG(T1)	;GET MESSAGE ADDRESS
	LOAD T2,MSMFL,(T2)	;GET FLAGS
	TXNN T2,DATEOM		;IS THIS THE END-OF-MESSAGE?
	JRST SQI3		;NO
	SETONE LLFIM,(T1)	;YES
SQI3:	JE LLIMS,(T1),SQI4	;JUMP IF NOT MESSAGE INTERFACE
	TMNN LLFIM,(T1)		;AT EOM?
	JRST SQI5		;YES
SQI4:	INCR LLLSC,(T1)		;NEED ANOTHER BUFFER SENT
SQI5:	MOVE T4,MSGCNT		;GET BACK THE COUNT
	LOAD T2,LLBSZ,(T1)	;GET BYTE SIZE
	CAIN T2,44		;WORD MODE?
	JRST [	CALL SQIWRD	;YES, GO MOVE WORDS THEN
		JRST SQIMV1 ]	;AND DONE
SQIMOV:	MOVE T3,T4		;GET COUNT
	MOVE T1,MSGBYP		;GET SOURCE POINTER
	MOVE T2,MVMBFI		;GET DESTINATION
	CALL NETMOV		;MOVE THE BYTES
	MOVEM T2,MVMBFI		;UPDATE DESTINATION POINTER
	MOVE T1,MVMLLB		;RETRIEVE LL BLOCK
SQIMV1:	NOSKD1
	HRRZ T2,LLOMSG(T1)	;GET EXPENDED MESSAGE
	LOAD T3,MSLNK,(T2)	;GET NEXT
	SKIPN T3		;QUEUE NOW EMPTY
	HRLM T3,LLOMSG(T1)	;YES
	HRRM T3,LLOMSG(T1)	;NEW QUEUE HEAD
	OKSKD1
	MOVE T1,T2		;GET BACK MESSAGE
	CALL RELRES		;FREE IT
	MOVE T1,MVMLLB		;GET BACK LL ADDRESS
	DECR LLDMT,(T1)		;ONE LESS MESSAGE ON QUEUE
	JE LLFIM,(T1),MVM010	;HAVE EOM?
MVMX:	SETZM T3		;NO PROBLEM FITTING ALL DATA IN BUFFER
MVMY:	MOVE T1,MVMBFI		;NO, GET UPDATED POINTER
	MOVE T2,MVMCNT		;AND COUNT
	RETSKP			;DONE, RETURN SUCCESS
;ROUTINE TO MOVE WORDS FROM THE NETWORK TO AN INPUT BUFFER

SQIWRD:	STKVAR <<MDPTR,2>>
	DMOVEM Q1,MDPTR		;SAVE WORK REGS
SQIWR1:	SETZB Q1,Q2		;INIT WORDS
	MOVEI T3,11		;GET MAX BYTE COUNT
	CAIGE T4,11		;ENOUGH FOR FULL 2 WORDS?
	MOVE T3,T4		;NO. GET WHAT IS LEFT THEN
	SUBI T4,11		;TAKE SOME BYTES
SQIWR2:	LSHC Q1,10		;SHIFT BYTES
	ILDB T2,MSGBYP		;GET NEXT BYTE FROM NET BUFFER
	DPB T2,[POINT 8,Q2,35]	;STASH IT
	SOJG T3,SQIWR2		;DO THEM ALL
	JUMPL T4,[LSHC Q1,-4	;ALIGN ODD WORD
		MOVEM Q2,@FILBFI(JFN) ;STORE ODD WORD
		AOS FILBFI(JFN)	;MOVE TO NEXT WORD
		JRST SQIWR3]	;AND DONE
	DMOVEM Q1,@FILBFI(JFN)	;STORE BOTH WORDS
	MOVEI Q1,2		;INCREMENTER
	ADDM Q1,FILBFI(JFN)
	JUMPG T4,SQIWR1		;DO MORE
SQIWR3:	DMOVE Q1,MDPTR		;RESTORE REGS
	RET			;ALL DONE

;ERROR ROUTINE FOR BADLY FORMED SEGMENT ENCOUNTERED

SEGERR:	TQO <ERRF>		;SET FILE SYSTEM ERROR
	RETBAD (DCNX11)		;AND RETURN WITH ERROR INDICATOR

;ROUTINE TO ANALYZE FAILURE TO SEND ACK OR LS MESSAGE. IF IT IS
;A FREE SPACE FAILURE, THEN A DATA INT IS ISSUED TO INSURE THE PROCESS
;TRIES AGAIN SOON

CHKFRE:	TQO <BLKF>		;NOTE BLOCK NEEDED
	HRRZ T3,T1		;GET TEST ROUTINE
	CAIE T3,BLOCKM		;A FREE SPACE FAILURE?
	RET			;NO. DONE THEN
	EXCH T1,FILLLB(JFN)	;YES. GET LL BLOCK
	CALL DATINR		;REQEUST DATA INT
   IFN NSPSW,<
	CALL CHKLLB
   >
	EXCH T1,FILLLB(JFN)	;RESTORE TEST ROUTINE
	RET			;AND DONE
;SQILS - ROUTINE TO SEND ANY LS MESSAGES NEEDED AFTER INPUT HAS BEEN PROCESSED
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL SQILS
;RETURNS: +1	 FAILED TO SEND LS
;	  +2	SUCCESS,  T1 PRESERVED

	RESCD

SQILS::	STKVAR <SQLLLB>
	MOVEM T1,SQLLLB		;SAVE BLOCK ADDRESS
	LOAD T2,LLLSC,(T1)	;GET SEGS TO REQUEST
	JUMPE T2,RSKP		;IF NONE, JUMP OFF
	MOVEI T3,MSDAT		;ON THE DATA CHANNEL
	SETONE LLLSA,(T1)	;TELL SCHED TRYING FOR LS SEND
	CALL SNDLS		;SEND MESSAGE
	 RET			;FAILED, RETURN FAILURE
	MOVE T1,SQLLLB		;RESTORE LINK BLOCK ADDRESS
	SETZRO <LLLSC,LLLSA>,(T1) ;CLEAR ALL LS INDICATORS
	RETSKP			;DONE, RETURN SUCCESS
;NOW DEFINE STATE TRANSITION TABLES

;FOR SEQUENTIAL OUTPUT

	SWAPCD			;ALL OF THESE ARE SWAPPABLE

SQOSTA::IFIW!SQOLIS		;LISTENING - BLOCK UNTIL CONNECTED
	IFIW!SQOLIS		;CIS - SAME HERE
	IFIW!SQOCNF		;CIR - GO CONFIRM CIR
	IFIW!NETSQ1		;RUN - ALL SET TO GO
	IFIW!SQODIS		;DIS - LINK IS CLOSED. GIVE ERROR
	IFIW!SQODIS		;DIQ - SAME HERE
	IFIW!SQODIR		;DIR - SEE IF ABORT OR CLOSE
	IFIW!SQOLIS		;CC SENT - BLOCK UNTIL CONNECTED
	IFIW!SQOABT		;ABORTED -

;FOR SOUTR CALL

SQOOTR::IFIW!SQOLIS		;LISTENING - BLOCK UNTIL CONNECTED
	IFIW!SQOLIS		;CIS - BLOCK UNTIL CONNECTED
	IFIW!SQOCN2		;CIR - GO CONFIRM
	IFIW!NETSR1		;RUN - NORMAL STUFF
	IFIW!SQODIS		;DIS - LINK IS CLOSED
	IFIW!SQODIS		;DIQ - ""
	IFIW!SQODIR		;DIR -
	IFIW!SQOLIS		;CC SENT - BLOCK UNTIL CONNECTED
	IFIW!SQOABT		;ABORTED -

;FOR SEQUENTIAL INPUT

SQISTA:	IFIW!SQOLIS		;LISTENING - WAIT FOR CONNECT
	IFIW!SQOLIS		;CIS - WAIT FOR CONNECT
	IFIW!SQICNF		;CIR - CONFIRM CONNECTION
	IFIW!SQI1		;RUN - ALL SET
	IFIW!SQODIS		;DIS - GIVE ERROR
	IFIW!SQODIS		;DIQ - GIVE ERROR
	IFIW!SQIDIR		;DIR -
	IFIW!SQOLIS		;CC SENT - BLOCK UNTIL CONNECTED
	IFIW!SQOABT		;ABORTED -

;TABLE FOR CC RECEIVED

CCREC:	IFIW!CCJECT		;LISTENING - CAN'T CONFIRM A LISTENER
	IFIW!CCGUD		;CIS - GOOD CC
	IFIW!CCDON		;CIR - IGNORE IT
	IFIW!CCDON		;RUN - IGNORE IT
	IFIW!CCDON		;DIS - IGNORE IT
	IFIW!CCDON		;DIQ - IGNORE IT
	IFIW!CCDON		;DIR - IGNORE IT
	IFIW!CCDON		;CC SENT - IGNORE IT
	IFIW!CCJECT		;ABORTED -

;TABLE FOR DI RECEIVED

DIREC:	IFIW!CCJECT		;LISTENING - ILLEGAL ADDRESS
	IFIW!CONREJ		;CIS - CONNECT BEING REJECTED
	IFIW!CCDON		;CIR - IGNORE
	IFIW!DIMSG2		;RUN - CLOSING DOWN THE LINK
	IFIW!DIDIDC		;DIS - CLOSE LINK
	IFIW!DIMSG2		;DIQ - ABORT IT
	IFIW!DIMSG2		;DIR - ABORT IT
	IFIW!DIMSG2		;CC SENT - CONNECT BEING REJECTED
	IFIW!CCJECT		;ABORTED -

;TABLE FOR DC RECEIVED

DCREC:	IFIW!CCDON		;LISTENING - IGNORE FOR LISTENER
	IFIW!CHKIDL		;CIS - CHECK FOR VALID DC
	IFIW!CCDON		;CIR - IGNORE
	IFIW!DCRUN		;RUN - SHUTTING DOWN
	IFIW!DCGUD		;DIS - VALID REPLY TO DI SENT
	IFIW!DCABT		;DIQ - ABORT THE LINK
	IFIW!DCABT		;DIR - ABORT THE LINK
	IFIW!DCABT		;CC SENT - GET RID OF LINK
	IFIW!CCDON		;ABORTED - IGNORE IT

;CLOSF

CLZSTA:	IFIW!CLZDON		;LISTENING - JUST GET RID OF A LISTENER
	IFIW!CLZDON		;CIS - SAME FOR CIS
	IFIW!CLZDI		;CIR - NEED TO REFUSE CONNECTION
	IFIW!CLZRUN		;RUN - NORMAL STATE
	IFIW!CLZWDC		;DIS - WAIT FOR DC
	IFIW!CLZDIQ		;DIQ -
	IFIW!CLZDIR		;DIR -
	IFIW!CLZRUN		;CC SENT -
	IFIW!CLZABT		;ABORTED -

;ACK RECEIVED

ACKSTA:	IFIW!CCJECT		;LISTENING -
	IFIW!ACKCIS		;CIS -
	IFIW!CCDON		;CIR -
	IFIW!ACKRUN		;RUN -
	IFIW!CCDON		;DIS -
	IFIW!CCDON		;DIQ -
	IFIW!CCDON		;DIR -
	IFIW!ACKCCS		;CC SENT -
	IFIW!CCDON		;ABORTED -

;DATA,INT OR LS MESSAGE

DATSTA:	IFIW!CCJECT		;LISTENING - ERROR
	IFIW!CCDON		;CIS - IGNORE
	IFIW!CCDON		;CIR - IGNORE
	IFIW!DATRUN		;RUN - GOOD MESSAGE
    REPEAT 3,<
	IFIW!CCDON>		;DIS,DIQ,DIR - IGNORE
	IFIW!DATCCS		;CC SENT - OPEN THE LINK
	IFIW!CCDON		;ABORTED
SUBTTL	NSP Error Code to TOPS20 Error Code Translation

;NSPERR - ROUTINE TO CONVERT AN NSP ERROR CODE INTO A TOPS20 ERROR CODE
;
;ACCEPTS IN T1/	NSP ERROR CODE
;		CALL NSPERR
;RETURNS: +1	 FAILED, NO SUCH NSP ERROR CODE
;	  +2	SUCCESS, WITH T1/ TOPS20 ERROR CODE

NSPERR::MOVSI T4,-ERRLEN	;SET UP TO LOOP THRU ERROR TABLE

NSPER1:	HLRZ T2,ERRTAB(T4)	;GET AN NSP ERROR CODE
	CAMN T2,T1		;FOUND NSP ERROR CODE TO BE TRANSLATED ?
	JRST NSPER2		;YES, GO GET CORRESPONDING TOPS20 CODE
	AOBJN T4,NSPER1		;NO, LOOP OVER ENTIRE TABLE
	RETBAD (MONX03)		;NO SUCH NSP ERROR CODE, RETURN FAILURE

; HERE HAVING FOUND THE NSP ERROR CODE

NSPER2:	HRRZ T1,ERRTAB(T4)	;GET CORRESPONDING TOPS20 ERROR CODE
	RETSKP			;DONE, RETURN SUCCESS



; TABLE OF NSP/TOPS20 ERROR CODE CORRESPONDENCE

ERRTAB:	.DCX0,,NSPX00
	.DCX1,,NSPX01
	.DCX2,,NSPX02
	.DCX3,,NSPX03
	.DCX4,,NSPX04
	.DCX5,,NSPX05
	.DCX6,,NSPX06
	.DCX7,,NSPX07
	.DCX8,,NSPX08
	.DCX9,,NSPX09
	.DCX24,,NSPX10
	.DCX32,,NSPX11
	.DCX33,,NSPX12
	.DCX34,,NSPX13
	.DCX35,,NSPX14
	.DCX36,,NSPX15
	.DCX37,,NSPX16
	.DCX38,,NSPX17
	.DCX39,,NSPX18
	.DCX40,,NSPX19
	.DCX41,,NSPX20
	.DCX42,,NSPX21
	.DCX43,,NSPX22
ERRLEN==.-ERRTAB
SUBTTL	NSP Background Task - Main Dispatching Loop


;THIS CODE IS THE REQUEST QUEUER AND THE BACKGROUND NSP
;TASK. THE QUEUER IS RESPONSIBLE FOR "ROUTING" ALL MESSAGES
;TO EITHER THE NETWORK (VIA THE DTE OR WHATEVER ELSE CONNECTS
;US TO THE NETWORK) OR TO ANOTHER LOGICAL LINK ON THE SAME HOST.
;ALSO, IT IS RESPONSIBLE FOR RETRANSMITTING ANY NACK'ED MESSAGES.

;THE BACKGORUND PROCESS RUNS AS A FORK OF JOB 0 AND IS RESPONSIBLE
;FOR PARSING ALL CONTROL MESSAGE, COMPLETING ALL CONNECTS, PROCESSING
;ACK AND LINK SERVICE MESSAGES, ACTING AS A SERVICE OF NETSQI FOR
;ACTING ON ACKS THAT ARE PIGGY-BACKED ONTO DATA SEGMENTS, AND FOR
;GENERATING PROCESS INTERRUPTS. ALSO, THIS PROCESS WILL EVOLVE OVER
;TIME TO HANDLE ALL ROUTING STRATEGIES.

	SWAPCD			;ALL OF THIS CODE IS SWAPPABLE

TSKINI:	MOVX T1,UMODF
	MOVEM T1,FFL		;ESTABLISH USUAL JSYS CONTEXT
	SETZM FPC		;SET PC
	MCENTR			;GET INTO MONITOR CONTEXT
	SE1ENT			;MAKE IT RUN IN PROPER SECTION
	TRVAR <MSGCNT,MSGBYP,MSGSRC,MSGDST,MSGBLK,MSGLLB,MSGOBJ,<MSGDDC,5>,<MSGHSN,2>,MSGHNC,MSGW1,MSGW2,MSGSOB,<MSGSDC,5>,<MSGDML,LKSIZE>,MSGLCL,MSGLKP>
	MOVEI T1,MAXQ		;DON'T ALLOW THIS FORK TO BE "COMPUTE-BOUND"
	MOVEM T1,JOBBIT		;BY PREVENTING MAXQ SCHEDULING BEHAVIOR

;TOP OF LOOP

NSPTSK:	SKIPE MSGQ		;ANYTHING ON THE QUEUE?
	JRST [	CALL DOMSGQ	;YES, DO ONE
		JRST NSPTSK]	;TRY AGAIN UNTIL DONE
	CALL NSPTMR		;CHECK THE RESEND QUEUE
	CALL NSPINA		;CHECK ON INACTIVITY TIMERS
REPEAT 0,<
	SKIPE KDPFLG		;DOES KMC11 WANT SERVICE
	CALL KDPTSK		;YES SO CHECK IT
	CALL OUTCHK		;TIME TO SEND PREVOUSLY BLOCKED OUTPUT ?
	 CALL OUTSND		;YES, GO SEND REMAINING OUTPUT
	NOP			;NOOP FOR PERFORMANCE ANALYSIS
	CALL DOATSQ		;HANDLE THE ATS QUEUES IF THERE ARE ANY
>
	CALL MCBCQ		;CHECK ANY MCB LINKS TO CLEAN UP
	SKIPE NSPMCB		;ANY DEAD MCB'S TO CLEAN UP?
	CALL MCBDED		;YES - GO CLEAN THEM UP
	MOVEI T1,NSPTST		;REST UNTIL WORK TO DO
	HDISMS (^D1500)		;WAIT, BUT STAY IN BALSET
	JRST NSPTSK		;AND TRY AGAIN
;SEE IF ANY LL BLOCKS LEFT BY TTY TO CLOSE AND CLEAN UP

MCBCQ:	SAVEAC <JFN,STS,DEV,F1>
	STKVAR <MCBCLL>		;STORAGE FOR LL BLOCK ADDRESS
	SETOM INNSPT		;SET "IN BACKGROUND TASK" INDICATOR
	SETZ F1,		;MAKE AOBJN
	HRLI F1,-NTTMCB		; WORD
MCBCQ1:	SKIPN T1,ULLCZQ(F1)	;A LINK ID HERE?
	JRST MCBCQ2		;NO
	LLLOCK			;YES, LOCK THE LL TREE
	SETO T2,		;ANY LINK
	CALL LLLKUP		;FIND THE LL BLOCK
	IFNSK.
	   LLLULK		;DOESN'T EXIST ANYMORE, GIVE UP TREE LOCK
	   JRST MCBCQ3		;ELIMINATE THIS LINK ID
	ENDIF.
	MOVEM T1,MCBCLL		;STASH THE LL BLOCK ADDRESS
	CALL BLKLOK		;GET LL BLOCK LOCK
	IFNSK.
	   LLLULK		;CAN'T RIGHT NOW, GIVE UP LL TREE LOCK
	   JRST MCBCQ2		;MOVE ON
	ENDIF.
	LLLULK			;GIVE UP LL TREE LOCK
	MOVEI T2,MLJFN+1
	CALL ASGJFR		;ASSIGN DUMMY JFN BLOCK
	IFNSK.
	   MOVE T1,MCBCLL	;RETRIEVE LL BLOCK ADDRESS
	   CALL BLKULK		;GIVE UP LL BLOCK LOCK
	   JRST MCBCQ2		;MOVE ON
	ENDIF.
	MOVEI JFN,-JFN0+1(T1)	;SETUP JFN, OFFSET SO FILXXX REFERENCES WORK
	EXCH T1,MCBCLL		;SAVE ACTUAL BLOCK, GET LL
	MOVEM T1,FILLLB(JFN)	;PUT LL IN JFN BLOCK
	SETZ STS,		;FAKE STATUS BITS
	MOVEI DEV,DCNDTB	;DITTO DEV
	SETZM FILWND(JFN)	;NO WINDOWS
	CALL CLZDON		;GET RID OF LL
	 NOP			;+1 RETURN DOES NOT EXIST
	NOINT
	MOVEI T1,JSBFRE
	MOVE T2,MCBCLL		;DUMMY BLOCK
	CALL RELFRE		;RELEASE IT
	OKINT
MCBCQ3:	SETZM ULLCZQ(F1)	;GET RID OF THIS ENTRY
MCBCQ2:	AOBJN F1,MCBCQ1		;MORE TO DO?
	SETZM INNSPT		;CLEAR "IN BACKGROUND TASK" INDICATOR
	RET			;NO, DONE
;TEST ROUTINE FOR NSPTSK

	RESCD

NSPTST::
  REPEAT 0,<
	CALL CKATSQ		;CHECK THE ATS QUEUES
	 JRST 1(T4)		;NEED TO DO SOMETHING
	SKIPE KDPFLG		;DOES KMC11 WANT SERVICE
	JRST 1(4)		;YES
	CALL OUTCHK		;CHECK "RETRY BLOCKED OUTPUT" TIMER
	 JRST 1(4)		;YES, WAKE UP
  >
	MOVE T1,LSTTMR		;GET LAST TIME RESEND QUEUE WAS CHECKED
	ADDI T1,CKNSTM		;ADD CHECKING INTERVAL
	CAMG T1,TODCLK		;TIME TO CHECK AGAIN?
	JRST 1(4)		;YES
	SKIPE MSGQ		;ANY MESSAGES TO DO?
	JRST 1(4)		;YES, WAKE UP
  REPEAT 0,<			;SHOULDN'T NEED ANY OF THIS
	MOVE T1,LSTINT		;GET LAST TIME INACTIVITY TIMERS WERE CHECKED
	ADDI T1,CKINTM		;ADD CHECKING INTERVAL
	CAMG T1,TODCLK		;TIME TO DO CHECKS AGAIN?
	JRST 1(T4)		;YES
   	SKIPE NSPMCB		;ANY DEAD LINES TO CLEAN UP?
	JRST 1(4)		;YES, WAKE UP
	SKIPE ULLCZQ		;LL'S TO CLEAN UP?
	JRST 1(T4)		;YES
  >
	JRST 0(4)		;NO, WAIT SOME MORE
SUBTTL NSP Background Task - NSP Message Timer

	SWAPCD

NSPTMR:	MOVE T1,LSTTMR		;GET LAST TIME QUEUE WAS CHECKED
	ADDI T1,CKNSTM		;ADD CHECKING INTERVAL
	CAMLE T1,TODCLK		;TIME TO CHECK AGAIN?
	RET			;NO
	MOVE T1,TODCLK		;YES, GET TIME
	MOVEM T1,LSTTMR		;SAVE AS NEXT TIME CHECKING IS NEEDED
	SKIPN NSSNTQ		;ANYTHING ON QUEUE?
	RET			;NO, DONE
	ACVAR <W1,W2,W3>	;W1 = LOOP COUNTER FOR MESSAGES PROCESSED
				;W2 = ADDRESS OF NEXT SEGMENT
				;W3 = TIMED OUT SEGMENT'S NUMBER
	MOVEI W1,4		;MAX NUMBER OF SEGMENTS TO PROCESS
	STKVAR <MSGADR,LLBLK>	;ADDRESS OF MESSAGE
				;LL BLOCK ADDRESS
	LLLOCK			;USE LL TREE LOCK TO PREVENT RACES
	SETOM INNSPT		;WE ARE NOW IN THE TIMER
NSPTM5:	SKIPN T2,NSSNTQ		;GET FIRST MESSAGE ON THE SENT QUEUE
	JRST [	SETZM INNSPT	;NO LONGER IN TIMER
		CALLRET ULOKLL]	;GIVE UP TREE LOCK
	MOVEM T2,MSGADR		;STASH THE MESSAGE ADDRESS
	LOAD T1,MSLLA,(T2)	;GET THE LL ID
	SETOM T2		;ANY MATCH
	CALL LLLKUP		;GET THE LL BLOCK ADDRESS
	 JRST [
;		BUG (NSPGON)
		MOVE T1,MSGADR	;LINK GONE, GET BACK MESSAGE ADDRESS
		CALL UNQTIM	;REMOVE IT FROM TIMER QUEUE
		CALL RELRES	;DONE WITH IT
		JRST NSPTM3]	;MOVE ON
	MOVEM T1,LLBLK		;SAVE THE LL BLOCK ADDRESS
	CALL BLKLOK		;LOCK THE LL BLOCK
	 JRST [	SETZM INNSPT	;CAN'T, NO LONGER IN TIMER
		CALLRET ULOKLL]	;GIVE UP TREE LOCK
	LOAD T3,LLLKP,(T1)	;GET NODE'S VERSION
	CAIN T3,.NSP31		;IS IT NSP 3.1?
	JRST NSPTM7		;YES, DON'T TIME IT
;**;[2963]  Add 1 line after NSPTM5:+19			DML	19-MAY-83
	MOVE T2,MSGADR		;[2963] RETRIEVE THE MESSAGE ADDRESS
	TMNN LLBRP,(T1)		;NO, IS FLOW TURNED OFF?
	IFSKP.			;YES
	   LOAD T4,MSTOM,(T2)	;GET TYPE OF MSG
	   CAIN T4,MSDAT	;IS IT NORMAL DATA?
	   JRST NSPTM7		;YES, CAN'T RESEND NORMAL DATA WHEN FLOW IS OFF
	ENDIF.
	MOVE T3,LLTIMO(T1)	;GET TIME OUT VALUE FOR LINK
	IMUL T3,NSLDFS		;SCALE IT BY
	IDIVI T3,^D16		; LOCAL DELAY FACTOR
;**;[2963]  Delete 1 line at NSPTM5:+29			DML	19-MAY-83
	ADD T3,MSTIM(T2)	;ADD TIME STAMP OF THE MESSAGE
	CAMG T3,TODCLK		;TIMED OUT ?
	JRST NSPTMO		;YES
	CALL BLKULK		;NO, UNLOCK THE LL BLOCK
	SETZM INNSPT		;NO LONGER IN TIMER
	CALLRET ULOKLL		;GIVE UP TREE LOCK

NSPTMO:	CALL DATINR		;GIVE INTERRUPT TO USER
	LOAD T4,LLHSN,(T1)	;GET THE REMOTE NODE NUMBER
	ADD T4,[NSTIMO]		;OFFSET INTO COUNTER TABLE
	AOS (T4)		;INCR THE COUNT
	LOAD T4,MSTRY,(T2)	;GET NUMBER OF TIMES ALREADY RETRIED DUE TO TIME OUT
	CAMGE T4,NSTRYS		;ALREADY TRIED ENOUGH TIMES?
	JRST NSPTM2		;NO, DO IT AGAIN
	MOVEI T2,.DCX38		;REASON IS TIMED OUT
	STOR T2,LLRSN,(T1)	;SAVE IT
	MOVEI T2,LLSABT		;YES, SAY LINK ABORTED
	STOR T2,LLSTA,(T1)  	; IS ABORTED
	LOAD T4,LLHSN,(T1)	;GET THE REMOTE NODE NUMBER
	BUG (NSPLAT,<<T4,NODE>>)
	CALL CHKLLT		;CHECK FOR TTY ON THIS LINK
	CALL FLUSH		;GET RID OF THE LINK'S MESSAGES
	TMNN LLSDE,(T1)		;LINK DISASSOCIATED?
	JRST NSPTM7		;NO, GO TRY FOR MORE
	OKINT			;YES, MATCH THE NOINT IN BLKLOK
	CALL DELNOD		;GET RID OF THE LL BLOCK
	JRST NSPTM3		;MOVE ON

NSPTM2:	INCR MSTRY,(T2)		;ANOTHER TRY
	LOAD W3,MSSEG,(T2)	;SAVE SEGMENT # OF TIMED OUT MESSAGE
	LOAD W2,MSLNK,(T2)	;GET ADDRESS OF NEXT SEGMENT
NSPTM8:	SETZ T3,		;NO PREVIOUS MESSAGE
	MOVEI T4,LLSEGQ(T1)	;GET HEAD OF LL'S QUEUE
	CALL UNQSEG		;REMOVE CURRENT MESSAGE FROM QUEUE
	LLLULK			;GIVE UP LOCK WHILE TRYING TO SEND MESSAGE
	CALL SNDSE0		;AND SEND IT AGAIN
	LLLOCK			;GET LOCK AGAIN
	MOVE T1,LLBLK		;RETRIEVE THE LL BLOCK ADDR
	SKIPE W2		;ANY MORE TO RESEND?
	IFNSK.			;YES
	   MOVE T2,W2		;GET ADDRESS OF NEXT SEGMENT
	   LOAD W2,MSSEG,(T2)	;GET ITS SEGMENT NUMBER
	   CAMG W2,W3		;DONE THEM ALL YET?
	   JRST NSPTM7		;YES, MOVE ON
	   LOAD W2,MSLNK,(T2)	;NO, GET NEXT MESSAGE
	   JRST NSPTM8		;GO DO IT
	ENDIF.
NSPTM7:	CALL BLKULK		;UNLOCK THE LL BLOCK
NSPTM3:	SOSGE W1		;HAVE WE DONE OUR QUOTA?
	JRST NSPTM6		;YES, ALL DONE
	SKIPE NSSNTQ		;NO, ANYTHING ON THE QUEUE?
	JRST NSPTM5		;YES, GO DO SOME MORE
NSPTM6:	SETZM INNSPT		;NO LONGER IN TIMER
	CALLRET ULOKLL		;GIVE UP TREE LOCK

	ENDSV.
	ENDAV.
SUBTTL NSP BACKGROUND TASK - INACTIVITY TIMER CHECK

NSPINA:	MOVE T1,LSTINT		;GET LAST TIME INACTIVITY TIMERS WERE CHECKED
	ADDI T1,CKINTM		;ADD CHECKING INTERVAL
	CAMLE T1,TODCLK		;TIME TO DO CHECKS AGAIN?
	RET			;NO
	MOVE T1,TODCLK		;YES, GET TIME
	MOVEM T1,LSTINT		;SAY WE ARE CHECKING NOW
	SKIPN LLHEAD		;ANY LINKS?
	RET			;NO, NOTHING TO DO
	LLLOCK			;LOCK THE LL TREE
	SETOM INNSPI		;NOW IN INACTIVITY TIMER
	MOVE T1,[INACOR]	;GET ADDRESS OF COROUTINE
	SETO T2,		;ALL LINKS
	CALL OBJSRC		;SEARCH THE LL TREE
	 JFCL			;DONE THEM ALL
	SETZM INNSPI		;NO LONGER IN INACTIVITY TIMER
	CALLRET ULOKLL		;UNLOCK THE LL TREE AND RETURN

;**;[2933]REORDER CODE AT INACOR:	DSC	22-MAR-83

INACOR:	SAVET
	STKVAR <INALLB>		;LL BLOCK ADDRESS
	MOVEM T1,INALLB		;SAVE THE LL BLOCK ADDRESS
	CALL BLKLOK		;LOCK THE LL BLOCK
	 RET			;CAN'T, BETTER LUCK NEXT TIME
	LOAD T2,LLSTA,(T1)	;GET STATE OF LINK
	CAIE T2,LLSRUN		;RUNNING?
	JRST INACOD		;NO
	LOAD T2,LLLKP,(T1)	;GET NSP VERSION
	CAIE T2,.NSP31		;NSP 3.1?
	SKIPN T2,LLINAC(T1)	;NO, INACTIVITY TIMER ON?
	JRST INACOD		;NO
	CAMLE T2,TODCLK		;YES, TIMED OUT?
	JRST INACOD		;NO
	SETZ T2,		;NO NEW PERMISSIONS
	MOVEI T3,MSDAT		;ON THE DATA CHANNEL
	CALL SNDLS		;FIRE OFF A LS MSG TO SEE IF THE OTHER
	 JRST [MOVE T1,INALLB	;COULDN'T SEND IT
	       CALLRET BLKULK]	;DONE WITH THIS LL
	MOVE T1,INALLB		;RETRIEVE THE LL BLOCK ADDRESS
	SETZM LLINAC(T1)	;OK, TURN OFF INACTIVITY TIMER
	SETZRO <LLLSA>,(T1)  	;CLEAR THE LS INDICATORS
INACOD:	CALLRET BLKULK		;DONE WITH THIS LL

	ENDSV.
SUBTTL NSP Background Task - Node Counters Bookkeeping

	RESCD

;ROUTINE TO DO NSP INPUT BOOKKEEPING - UPDATES THE FOLLOWING NSP COUNTERS
;	MESSAGES RECEIVED
;	BYTES RECEIVED
;ACCEPTS:	1/  LL BLOCK ADDRESS
;		2/  MESSAGE ADDRESS
;RETURNS:	+1
;
;PRESERVES T1,T2

NSINBK:	SAVEAC <T1,T2>
	LOAD T3,LLHSN,(T1)	;GET NODE NUMBER
	ADD T3,[NSMSGR]		;OFFSET INTO "MESSAGES RECEIVED" TABLE
	AOS (T3)		;INCR THE COUNT
	LOAD T3,LLHSN,(T1)	;GET NODE NUMBER
	ADD T3,[NSBYTR]		;OFFSET INTO "BYTES RECEIVED" TABLE
	LOAD T4,MSCNT,(T2)	;GET NUMBER OF BYTES IN MESSAGE
	ADDM T4,(T3)		;UPDATE THE COUNT
	RET


;ROUTINE TO DO NSP OUTPUT BOOKKEEPING - UPDATES THE FOLLOWING COUNTERS
;	MESSAGES SENT
;	BYTES SENT
;ACCEPTS:	1/ LL BLOCK ADDRESS
;RETURNS:	+1
;
;PRESERVES T1,T2

NSOUBK:	SAVEAC <T1,T2>
	LOAD T2,LLHSN,(T1)	;GET THE NODE NUMBER
	ADD T2,[NSMSGS]		;OFFSET INTO "SENT MESSAGES" TABLE
	AOS (T2)		;INCR THE COUNTER
	LOAD T2,LLHSN,(T1)	;GET THE NODE NUMBER
	ADD T2,[NSBYTS]		;OFFSET INTO "SENT BYTES" TABLE
	MOVE T4,LLBPCT(T1)	;GET THE NUMBER OF BYTES IN MESSAGE
	ADDM T4,(T2)		;UPDATE THE COUNTER
	RET
SUBTTL NSP Background Task


;OUTCHK - ROUTINE TO DETERMINE IF PREVIOUSLY BLOCKED OUTPUT SHOULD BE
;	  RETRIED.
;
;CALL:		CALL OUTCHK
;RETURNS: +1	 TIME TO CHECK THE "OUTPUT REMAINING" QUEUE
;	  +2	NOT TIME TO RETRY YET

REPEAT 0,<
OUTCHK:	SKIPN OUTTIM		;ANY TIMER SET ?
	RETSKP			;NO
	SAVET
	MOVE T1,OUTTIM		;GET NEXT TIME TO WAKE UP
	CAMG T1,TODCLK		;TIMER EXPIRE ?
	RET			;YES, INDICATE SO
	RETSKP			;NO, NOTE NOT TIME YET
>
SUBTTL	NSP Background Task - MSGQ Processing

	SWAPCD

DOMSGQ:	NOSKD1			;GET SET TO PULL A MESSAGE OFF
	CHNOFF DLSCHN		;TURN OFF DTE
	HRRZ T1,MSGQ		;GET TOP MOST ENTRY
	LOAD T2,MSLNK,(T1)	;GET LINK
	HRRM T2,MSGQ		;STASH IT
	SKIPN T2		;WAS A MESSAGE THERE?
	SETZM MSGQ		;NO. CLEAR ENTIRE HEADER
	CHNON DLSCHN		;TURN ON DTE
	OKSKD1			;AND ALLOW SCHEDULING
	SETZM MSGLCL		;ASSUME LOCAL IN TRVAR
	TMNN MSLCL,(T1)		;DID IT COME FROM DRIVER?
	JRST [SKIPL T3,NSPLPB	;YES, IS THERE A LOOPBACK LINE RUNNING?
	      JRST DOMSG1	;NO
	      HRRZS T3		;GET RID OF LOOPBACK FLAGS
	      LOAD T4,MSPRT,(T1);GET PORT OF MESSAGE
	      CAME T3,T4	;IS IT THE LOOPER?
	      JRST DOMSG1	;NO
	      SETONE MSLCL,(T1)	;YES, SAY LOCAL IN THE MESSAGE BLOCK
	      JRST .+1]
	SETOM MSGLCL		;SAY LOCAL IN TRVAR
DOMSG1:	MOVEM T1,MSGBLK		;SAVE BLOCK ADDRESS
	LOAD T2,MSCNT,(T1)	;GET BYTE COUNT OF THE MESSAGE
	MOVEM T2,MSGCNT		;SAVE IT
	ADDI T1,MSHDR		;GET TO START OF DATA
	HRLI T1,(<POINT 8,>)	;FORM BYTE POINTER
	MOVEM T1,MSGBYP		;AND SET UP BYTE POINTER
	; ..
;MESSAGE ALL SET UP. GET MESSAGE FLAGS

;HAVE A MESSAGE. SEE WHAT IT IS

	SETZM MSGHSN		;ASSUME NO HOST NAME
	GETBYM (MSGCNT,MSGBYP,BADMSG)		;GET BYTE. IF BADLY FORMED, REJECT MSG
	TRNE T2,1		;IS THIS A PHASE III TRANSPORT MSG?
	JRST TOSMSG		;YES, IGNORE IT
	TRNN T2,2		;IS THIS A ROUTING HEADER?
	JRST DOMSG		;NO. GO HANDLE MESSAGE THEN
	TRNE T2,100		;MUST BE ASCII NAME
	TRNE T2,60		;VALID ROUTING HEADER?
	JRST INVHDR		;NO.
	CALL SKPFLD		;SKIP OUR NAME
	 JRST BADMSG		;BADLY FORMED
	MOVEI T3,MSGHSN		;GET LOCATION OF REMOTE HOST NAME
	MOVEI T4,MAXHST		;MAXIMUM NUMBER OF CHARS. IN NAME
	CALL GTASCI		;AND GET ASCII FIELD
	 JRST BADMSG		;BADLY FORMED MESSAGE
	MOVEM T2,MSGHNC		;SAVE NO. OF CHARS. IN HOST NAME
	GETBYM (MSGCNT,MSGBYP,BADMSG)		;BADLY FORMED
DOMSG:	MOVE T3,MSGBLK		;GET MESSAGE BLOCK
	STOR T2,MSMFL,(T3)	;SAVE FLAGS
	LDB T4,[POINT 3,T2,31]	;EXTRACT SUBTYPE
	LDB T3,[POINT 2,T2,33]	;EXTRACT TYPE OF MESSAGE
	JRST @MSGTYP(T3)	;GO DO MESSAGE

MSGTYP:	IFIW!DATMSG		;DATA MESSAGE
	IFIW!ACKMSG		;AN ACK MESSAGE
	IFIW!CTLMSG		;A CONTROL MESSAGE
	IFIW!BADMSG		;BADLY FORMED MESSAGE

CTLMSG:	JRST @.+1(T4)		;GET TO PROPER TYPE OF MESSAGE
	IFIW!TOSMSG		;A NOOP. IGNORE IT
	IFIW!CIMSG		;CONNECT-INITIATE
	IFIW!CCMSG		;CONNECT-CONFIRM
	IFIW!DIMSG		;DI MESSAGE
	IFIW!DCMSG		;DC MESSAGE
	IFIW!STRMSG		;A STARTUP MESSAGE
	IFIW!BADMSG		;BADLY FORMED MESSAGE
	IFIW!BADMSG		;BADLY FORMED MESSAGE
;RECEIVED A MESSAGE WITH AN INVALID ROUTING HEADER.

INVHDR:	MOVE T1,MSGBLK		;GET MESSAGE
	LOAD T1,MSPRT,(T1)	;GET PORT I.D.
	BUG (NSPRTH,<<T1,LINE>,<T2,BADBYT>>)
	JRST TOSMSG		;DONE

;RECEIVED AN UNINTELLIGIBLE MESSAGE

BADMSG:	BUG (NSPBAD)
TOSMSG:	MOVE T1,MSGBLK		;GET MESSAGE ADDRESS
	CALLRET RELRES		;GIVE BACK SPACE
;GOT A STARTUP MESSAGE

STRMSG:	SKIPE MSGHSN		;ALREADY PARSED A NODE NAME?
	JRST BADNOD		;YES, UNREADABLE MESSAGE.  THROW IT AWAY
	SETZM Q2		;INITIALIZE "VERIFICATION REQUESTED" FLAG
	MOVE T2,MSGBLK		;POINT TO MSG BLOCK AGAIN
	LOAD Q1,MSPRT,(T2)	;GET PORT MESSAGE CAME FROM
	JN INIRCV,MCBDTE(Q1),BADSTR	;IF ALREADY RUNNING, ERROR
	GETBYM (MSGCNT,MSGBYP,BADSTR)		;GET STARUP TYPE
	CAIE T2,STRTYP		;THE EXPECTED ONE?
	JRST BADSTR		;NO
	CALL GETEXT		;GET NODE NUMBER
	 JRST BADSTR
	MOVEM T2,ITSNUM(Q1)	;SAVE NODE NUMBER
	MOVEI T3,(Q1)		;GET PORT
	ADDI T3,ITSNAM(Q1)	;POINT TO NAME FOR NEIGHBOR(2 WDS / PORT)
	MOVEI T4,MAXHST
	CALL GTASCI		;GET IT
	 JRST BADSTR		;BAD
	STOR T2,NAMCN,MCBDTE(Q1) ;STORE COUNT OF BYTES IN NAME
	GETBYM (MSGCNT,MSGBYP,BADSTR)		;GET SUPPORTED FUNCTIONS
	TRC T2,OURNED
	MOVX T1,NOTMCB		;NEIGHBOR IS NOT AN MCB
	ANDCAM T1,MCBDTE(Q1)	;ASSUME NEIGHBOR IS AN MCB
	TRNE T2,OURNED		;DOES IT SUPPORT ALL REQUIRED FUNCTIONS?
	IORM T1,MCBDTE(Q1)	;REMEMBER NOT AN MCB
	GETBYM (MSGCNT,MSGBYP,BADSTR)		;GET ITS REQUIRED FUNCS
	TXNE T2,VERIF		;WANT SECURITY MESSAGE?
	SETOM Q2		;NOTE VERIFICATION REQUESTED
	CALL GETTWO		;GET MAX BLOCK SIZE
	 JRST BADSTR		;BAD
	MOVEM T2,MSGW1		;SAVE IT
	CALL GETTWO		;GET NSP MAX
	 JRST BADSTR
	CAMLE T2,MSGW1		;VALID?
	JRST BADSTR		;NO
	SUBI T2,NSPOVR		;YES. ACCOUNT FOR NSP OVERHEAD BYTES
	MOVEM T2,NSPMAX(Q1)	;SET UP NSPMAX (MAX USER BYTES IN A SEGMENT)
	MOVEI T4,10		;BYTES TO IGNORE
STRMS1:	GETBYM (MSGCNT,MSGBYP,BADSTR)		;GET A BYTE
	SOJG T4,STRMS1		;SKIP BYTES
	MOVE T3,Q1		;GET PORT
	IMULI T3,^D9		;ITSID IS 9 WORDS/PORT
	ADDI T3,ITSID		;WHERE TO PUT IS ID
	MOVEI T4,^D36
	CALL GTASCI		;GET IT
	 JRST BADSTR
	HRRM Q1,MCBDTE(Q1)	;SAVE PORT WE INITED ON
	LOAD T1,NAMCN,MCBDTE(Q1) ;GET LENGTH OF ITS NAME
	CAME T1,OURCNT		;SAME LENGTH AS OURS ?
	JRST STRMS6		;NAMES ARE NOT THE SAME
	MOVEI T1,(Q1)		;COPY PORT NUMBER
	ADDI T1,ITSNAM(Q1)	;POINT TO PORTS NAME
	MOVEI T2,OURNAM		;POINT TO OUR NAME
	CALL CMPSTR		;SEE IF SAME NAME
	JRST STRMS6		;NAMES ARE NOT THE SAME
	SKIPE T1,NSPLPB		;GET PORT FOR LOOPBACK
	CAIE Q1,(T1)		;IS THIS PORT INTENDED FOR LOOPBACK ?
	JRST BADSTR		;NOT SUPPOSED TO BE IN LOOPBACK
	SETONE ND%LPR,NSPLPB	;LOOPBACK NOW RUNNING
	JRST STRMS7		;WE ARE NOW IN LOOPBACK MODE

STRMS6:	SKIPN T1,NSPLPB		;GET PORT FOR LOOPBACK
	JRST STRMS7		;NO PORT SCHEDULED FOR LOOPBACK
	CAIN Q1,(T1)		;IS THIS PORT SCHEDULED FOR LOOPBACK ?
	JRST BADSTR		;FLUSH THE PORT
STRMS7:	SETONE INIRCV,MCBDTE(Q1) ;NOTE INIT MSG RECEIVED
	JUMPN Q2,[
		JE INISNT,MCBDTE(Q1),[
			SETONE REQVER,MCBDTE(Q1)
			JRST .+1]
		MOVE T1,Q1	;VERIFICATION WANTED, GET PORT NUMBER
		CALL NODVER	;SEND VERIFICATION MESSAGE
		JRST .+1 ]	;DONE, CONTINUE
	MOVE T1,ITSNUM(Q1)	;GET PORT'S NODE NUMBER
	MOVX T2,.NDSON		;SAY IT'S REACHABLE
	MOVEI T3,3		;IT'S PHASE III
	CALL ADDNOD
	 BUG(NSPSTR)
	JRST TOSMSG		;AND GO TO IT

BADSTR:	CALL PROOFF		;TURN OFF FE
	BUG (ILLSTR,<<Q1,DTE>>)
	JRST BADMSG		;DON'T INIT





;ROUTINE USED BY STRMSG TO TURN OFF AN MCB IF NODE INIT
;FAILS

PROOFF:	MOVE T1,MSGBLK		;GET MESSAGE
	LOAD T3,MSPRT,(T1)	;GET PORT I.D.
	MOVEI T2,T3		;POINT TO ARG BLOCK
	MOVEI T1,.BTTPR		;TURN OFF PROTOCOL
	BOOT			;DO IT
	 ERJMP .+1		;?
	RET			;DONE
;ROUTINE USED TO SHUT ALL LINKS TO AN MCB THAT HAS DIED.
;ACCEPTS:	T1/ PORT NUMBER

DEDMCB::SKIPL MCBDTE(T1)	;WAS THAT OURS
	RET			;NO
	SKIPL T1		;IS PORT NUMBER OUT OF RANGE
	CAIL T1,DCN
	JRST [	BUG (NSPBPN,<<T1,BADDTE>>)
		RET]
	MOVE T1,BITS(T1)	;GET THE PROPER BIT NUMBER
	IORM T1,NSPMCB		;AND SET IT. THIS WILL WAKE NSP BCKGRND TASK
	RET
;ROUTINE TO CLOSE ALL LINKS ON ALL DEAD MCB'S

MCBDED:	TRVAR <WAITER,DEDPRT,<DEDDUM,15>,MSGW1>  ;MONUMENT TO HACKERY
MCBDE1:	SKIPE T1,NSPMCB		;GET VECTOR OF DEAD MCB'S
	JFFO T1,GOTMCB		;IS THERE ANY MORE WORK
	RET			;NO - ALL DONE
GOTMCB:	MOVE T1,BITS(T2)	;CLEAR BIT WE'RE WORKING ON
	ANDCAM T1,NSPMCB	;AND SAVE
	MOVEM T2,DEDPRT		;SAVE PORT
	SETZRO <INISNT,INIRCV,REQVER>,MCBDTE(T2)

   IFN DN20SW,<			;CHECK FOR MULTIPLE MCBS
	CAIE T2,1		;WAS IT THE PRIMARY MCB?
	JRST DEDMC3		;NO
   >

;RESET TOPOLOGY

	SETZM NODTBL		;CLEAR
	HRLI T1,NODTBL		; REACHABLE
	HRRI T1,NODTBL+1	;  NODES
	MOVEI T2,NODTSZ		;   TABLE
	BLT T1,NODTBL(T2)	;
	MOVE T1,OURNUM		;GET OUR NODE NUMBER
	MOVE T2,[POINT 2,NODTBL]  ;POINT TO BEGINNING OF TABLE
	ADJBP T1,T2		;OFFSET TO US
	MOVEI T2,2		;WE'RE PHASE II
	DPB T2,T1		;SAY SO
;
DEDMC3:	MOVE T2,DEDPRT		;GET PORT NUMBER

   IFN DN20SW,<			;CHECK FOR OTHER MCBS
	CAIE T2,1		;WAS IT THE PRIMARY MCB?
	JRST DEDMC4		;NO
	SKIPL MCBDTE(T2)	;IS ANOTHER MCB RUNNING?
	JRST DEDMC4		;NO
	MOVE T1,[440200,,NODTBL]  ;BP TO REACH TABLE
	MOVE T3,ITSNUM(T2)	;GET NODE NUMBER
	ADJBP T3,T1		;OFFSET INTO REACH
	MOVEI T1,3		;SAY PHASE III
	DPB T1,T3		;UPDATE TABLE
   >

DEDMC4:	MOVE T1,ITSNUM(T2)	;GET ITS NODE NUMBER
	SETZM ITSNUM(T2)	;CLEAR IT
	MOVEI T2,.NDSOF		;NODE IS OFF
	CALL ADDNOD		;REMOVE IT
	 JFCL
	MOVE T2,DEDPRT		;GET BACK PORT NUMBER
	IMULI T2,2		;POINT AT RIGHT PLACE
	SETZM ITSNAM(T2)	;CLEAR NAME
	SETZM ITSNAM+1(T2)	; ENTRY
	MOVEI T2,.DCX39		;GET ERROR
	MOVEM T2,MSGW1		;SAVE REASON
DEDMC1:	LLLOCK			;LOCK TREE
	MOVE T1,[DEDCOR]	;COROUTINE
	SETOM T2		;ALL LINKS
	CALL OBJSRC
	 JRST [	LLLULK		;UNLOCK THE TREE
		JRST  MCBDE1]	;SEE IF ANY MORE MCB'S
	SKIPN T1,WAITER		;IS WAIT TEST IS ZERO THEN WE AREN'T DONE
	JRST DEDMC1		;YES - START AT TOP OF TREE AGAIN
	MDISMS			;NO - WAIT FOR LINK
	JRST DEDMC1		;AND PROCEED
;COROUTINE TO DO THE WORK FOR MCBDED

DEDCOR:	SAVET
	LOAD T2,LLSTA,(T1)	;GET THE LINK'S STATE
	CAIG T2,LLSLIS		;IS IT LISTENING?
	RET			;YES, NO CLEANUP NEEDED
	JN LLLOC,(T1),R		;IF LOCAL, NOTHING TO DO
	JN LLDED,(T1),R		;IF ALREADY PROCESSED, NOTHING TO DO
	LOAD T2,LLPRT,(T1)	;GET THE LNK'S PORT NUMBER
	CAME T2,DEDPRT		;THE DEAD ONE?
	RET			;NO, ALL DONE
	CALL BLKLOK		;YES. LOCK THE LL BLOCK
	 JRST [	LLLULK		;CAN'T.  UNLOCK TREE
		MOVEM T1,WAITER	;STORE WAIT
		RETSKP]		;AND STOP NOW
	LLLULK			;UNLOCK THE TREE
	LOAD T2,LLSTA,(T1)	;GET STATE AGAIN
	SETONE LLDED,(T1)	;INDICATE THIS BLOCK PROCESSED FOR DEAD MCB
	CAIG T2,LLSCCS		;NEED TO CHANGE STATE?
	XCT [	CALL RJECT	;YES. FOR CIS
		CALL RJECT1	;FOR CIR
		CALL SHUTLK	;FOR RUNNING
		CALL RJECT1	;FOR DI SENT
		CALL RJECT1	;FOR QUEUED
		CALL RJECT1	;FOR DI REC
		CALL RJECT1]-2(T2) ;AND, FINALLY, FOR CC SENT
	SETZM WAITER		;FLAG INDICATES "CONTINUE AT TOP OF TREE"
	JN LLSDE,(T1),[	OKINT		;IF DISASSOCIATED
			CALL FLUSH  	;GET RID OF ALL MESSAGES
			LLLOCK		;LOCK UP THE LL TREE
			CALL DELNOD 	;RELEASE NODE
			LLLULK		;GIVE UP THE TREE LOCK
			RETSKP]		;NEED TO START AT TOP OF TREE
DEDMC2:	CALL BLKULK		;RELEASE BLOCK AND RETURN
	RETSKP			;NEED TO START AT TOP OF TREE
;ROUTINES TO HANDLE CONTROL MESSAGES

;PROCESS A CONNECT-INITIATE
;**;[2932]RE-DO CIMSG: LOGIC	DSC	22-MAR-83
CIMSG:	STKVAR <NDNUM>		;TEMP STORAGE FOR NODE NUMBER
	CALL GETLLA		;GET LL ADDRESSES
	 JRST BADMSG		;BADLY FORMED
	SKIPE MSGDST		;IS DEST ADDR 0?
	JRST [	MOVEI T2,.DCX21	;ILLEGAL DEST ADDR
		JRST CIDC]	;AND GO BOMB IT OUT
	CALL CIPSRV		;GO DO OTHER FIELDS
	 JRST [	MOVEI T2,.DCX35
		JRST CIDC]	;AND BOMB IT OUT
	GETBYM (MSGCNT,MSGBYP,INVPRC)		;GET FORMAT OF DEST OBJECT
	CAILE T2,OBJTWO		;IS IT A FORMAT WE UNDERSTAND?
INVPRC:	 JRST [	MOVEI T2,.DCX5
		JRST CIDC]	;AND ERROR
	MOVE T4,T2		;SAVE OBJECT TYPE
	GETBYM (MSGCNT,MSGBYP,INVPRC)		;GET OBJECT NUMBER
	MOVEM T2,MSGOBJ		;SAVE OBJECT #
	SETZM MSGDDC		;ASSUME NO DESCRIPTOR
	CAIN T4,OBJZRO		;ANY MORE?
	JRST DSCNO		;NO
	CAIE T4,OBJONE		;A GROUP CODE INCLUDED?
	JRST [	CALL GETTWO	;YES. GET GOUP
		 JRST INVPRC	;INVALID
		CALL GETTWO	;GET USER CODE
		 JRST INVPRC	;INVALID
		JRST .+1]	;ALL READY TO GO
	MOVEI T3,MSGDDC		;DESCRIPTOR BLOCK
	MOVEI T4,MAXDSC
	CALL GTASCI		;MOVE DESCRIPTOR STRING
	 JRST INVPRC
DSCNO:	GETBYM (MSGCNT,MSGBYP,INVPRC)		;GET SOURCE OBJECT TYPE
	CAILE T2,OBJTWO		;VALID?
	 JRST INVPRC
	MOVE T4,T2		;SAVE IT
	GETBYM (MSGCNT,MSGBYP,INVPRC)		;GET OBJECT #
	MOVEM T2,MSGSOB		;SAVE SOURCE OBJECT #
	SETZM MSGSDC		;ASSUME NO DESCRIPTOR
	SETZM MSGDML		;ASSUME NO GROUP,USER
	CAIN T4,OBJTWO		;DOES IT INCLUDE A GROUP?
	JRST [	CALL GETTWO	;YES. GET GROUP
		 JRST INVPRC	;BAD
		HRLM T2,MSGDML	;SAVE IT
		CALL GETTWO	;GET USER
		 JRST INVPRC
		HRRM T2,MSGDML	;SAVE IT
		JRST .+1]	;AND PROCEED
	CAIGE T4,OBJONE		;HAVE A DESCRIPTOR?
	JRST DSCNO1		;NO. GO FIND MATCH
	MOVEI T3,MSGSDC		;MOVE DESCRIPTOR
	MOVEI T4,MAXDSC
	CALL GTASCI		;GET IT
	 JRST INVPRC
	; ..
;CIMSG CONTINUED .....

DSCNO1:	MOVE T2,MSGBLK		;POINT TO MSG BLOCK AGAIN
	LOAD T2,MSPRT,(T2)	;GET PORT MESSAGE CAME FROM
	TMNE NTSHUT,MCBDTE(T2)	;SHUTTING DOWN?
	SKIPE MSGLCL		;YES. IS THIS A FOREIGN HOST?
	JRST DSCNO2		;NO. ALLOW IT.
	MOVEI T2,.DCX3		;"NODE SHUTTING DOWN"
	JRST CIDC		;AND REJECT THE CONNECT
DSCNO2:	SKIPN MSGLCL		;LOCAL CONNECTION?
	IFSKP.
	   MOVE T2,OURNUM	;YES
	ELSE.
	   CALL NAMNUM		;NUMERIC NODE NAME?
	   IFNSK.
	      CALL DSCCNV	;NO, CONVERT NAME TO NUMBER
	       JRST BADNOD	;COULDN'T
	      JRST DSCNO4	;MOVE ON
	   ENDIF.
	   MOVEI T1,MSGHSN	;CONVERT
	   HRROS T1		; HOST STRING
	   MOVEI T3,^D10	;  TO A
	   NIN			;   NUMBER
	    JRST BADNOD		;MUST BE FUNNY
;**;[2985]Add 2 lines at DSCNO2: +15L	RWW	5-JUL-83
	   CAILE T2,BIGNOD	;[2985]Is this a legit node?
	   JRST BADNOD		;[2985]No,
	ENDIF.
DSCNO4:	MOVEM T2,NDNUM		;STASH NODE NUMBER
	ADD T2,[NSCONR]		;OFFSET INTO "CONNECTS RECEIVED" TABLE
	AOS (T2)		;INCR THE COUNT
	MOVE T2,NDNUM		;RETRIEVE NODE NUMBER
	ADD T2,[NSMSGR]		;GET "MESSAGES RECEIVED" TABLE
	AOS (T2)		;COUNT THIS ONE
	MOVE T2,NDNUM		;RETRIEVE NODE NUMBER
	ADD T2,[NSBYTR]		;GET "BYTES RECEIVED" TABLE
	MOVE T3,MSGBLK		;RETRIEVE MESSAGE ADDR
	LOAD T3,MSCNT,(T3)	;GET NUMBER OF BYTES IN MESSAGE
	ADDM T3,(T2)		;ADD THEM IN
DSCNO5:	MOVEI T1,CICOR		;COROUTINE ADDRESS
	MOVEI T2,1		;LOOK FOR LISTENING OBJECT ONLY
	LLLOCK			;LOCK THE TREE
	CALL OBJSRC		;GO LOOK FOR AVAILABLE OBJECT
	 JRST [	CAIE T2,.DCX4		;OBJECT EXIST?
		IFSKP.
		   MOVE T3,NDNUM	;NO, RETRIEVE NODE NUMBER
		   ADD T3,[NSRCNE]	;GET "CONNECT RESOURCE ERROR" TABLE
		   AOS (T3)		;COUNT IT
		ENDIF.
		LLLULK			;RELEASE TREE
		JRST CIDC]
	CALL BLKLOK		;LOCK THE BLOCK
	 JRST [	LLLULK		;COULDN'T.
		MDISMS		;WAIT HERE
		JRST DSCNO5]	;AND TRY AGAIN
	LLLULK			;AND FREE THE TREE
	MOVEI T2,LLSCIR		;HAVE A CONNECT-INITIATE
	STOR T2,LLSTA,(T1)	;NOTE STATE CHANGE
	MOVEM T1,MSGLLB		;SAVE BLOCK
	MOVE T2,MSGOBJ		;GET OBJECT USED IN CONNECT
	STOR T2,LLSOB,(T1)	;SAVE IT
	MOVE T2,MSGDML		;GET GROUP,USER
	MOVEM T2,LLUSGP(T1)	;SAVE IN LL BLOCK
	SKIPN MSGLCL		;LOCAL CONNECTION?
	IFSKP.
	   SETONE LLLOC,(T1)	;YES, NOTE THIS IS A LOCAL LINK
	   MOVE T2,OURNUM	;GET OUR NODE NUMBER
	   STOR T2,LLHSN,(T1)	;PUT IT IN LL BLOCK
	ELSE.
	   MOVE T2,NDNUM	;RETRIEVE NODE NUMBER
	   MOVE T1,MSGLLB	;GET LL BLOCK ADDRESS
	   STOR T2,LLHSN,(T1)	;PUT NODE NUMBER IN LL BLOCK
	   LOAD T1,LLHST,(T1)	;PLACE TO PUT HOST'S NAME STRING
	   HRROS T1		;MAKE A BP TO IT
	   MOVEI T3,^D10	;IN DECIMAL
	   NOUT
	    JFCL
	   MOVE T1,MSGLLB	;GET BACK BLOCK ADDRESS
	   MOVE T2,MSGBLK	;GET MESSAGE
	   LOAD T2,MSPRT,(T2)	;GET PORT #
	   STOR T2,LLPRT,(T1)	;SAVE IN LL BLOCK
	ENDIF.
	CALL FILLIN		;GO FILL IN COMMON QUANTITIES
	MOVE T2,MSGSOB		;GET SOURCE OBJECT
	STOR T2,LLFNM,(T1)	;SAVE IT
	LOAD T1,LLFDS,(T1)	;GET DESCRIPTOR STRING
	SKIPN T2,MSGSDC		;HAVE A DESCRIPTOR?
	JRST [	CALL RELBLK	;FREE THE BLOCK
		MOVE T1,MSGLLB	;GET BACK LL BLOCK
		SETZRO LLFDS,(T1) ;CLEAR IT
		JRST DSCMOV]
	SETOM T3		;UNTIL A NULL
	MOVEI T2,MSGSDC		;GET POINTER TO STRING
	CALL MOVSTR		;MOVE IT
	MOVE T1,MSGLLB		;GET BACK BLOCK ADDRESS
	; ..
;CIMSG CONTINUED. FOUND BLOCK. GET OPTIONAL ACCESS CONTROL STUFF

DSCMOV:	GETBYM (MSGCNT,MSGBYP,NODATA)		;GET MENU BYTE
	MOVEM T2,MSGW1		;SAVE MENU
	TRNN T2,1		;HAVE ACCESS CONTROL?
	JRST NOUSER		;NO. CHECK FOR OPDATA
	LOAD T3,LLUSR,(T1)	;WHERE TO PUT USER DATA
	MOVEI T4,MAXUAP		;MAX SIZE OF USERID
	CALL GTASCI		;GET IT
	 JRST BADUDT		;BADLY FORMED
	LOAD T3,LLPSW,(T1)	;WHERE TO PUT PASSWORD
	MOVEI T4,MAXUAP		;MAX SIZE OF PASSWORD
	CALL GTBNRY		;GET OCTETS
	 JRST BADUDT		;BADLY FORMED
	STOR T2,LLPCT,(T1)	;SAVE COUNT
	LOAD T3,LLACT,(T1)	;GET ACCOUNT DATA
	MOVEI T4,MAXUAP		;MAX SIZE OF ACCOUNT
	CALL GTASCI		;GET IT
	 JRST BADUDT		;BADLY FORMED
NOUSER:	MOVE T2,MSGW1		;GET BACK MENU
	TRNN T2,2		;HAVE OPTDATA?
	JRST NODATA		;NO. ALL DONE
	LOAD T3,LLOPT,(T1)	;WHERE TO PUT IT
	MOVEI T4,MAXOPT
	CALL GTBNRY		;GET OCTETS
	 JRST BADUDT		;BADLY FORMED
	STOR T2,LLUCT,(T1)	;SAVE COUNT
NODATA:	CALL INTTST		;GO SEE IF THIS IS CONNECTED TO AN INTERNAL LINK
DSCMV1:	CALL CONINT		;GIVE INTERRUPT
	CALL BLKULK		;RELEASE THE BLOCK
	MOVE T1,MSGBLK		;GET BACK MESSAGE BLOCK
	CALL RELRES		;FREE THE BLOCK
	RET			;RETURN TO BACKGROUND TASK DISPATCHER

	ENDSV.

;RECEIVED A MESSAGE FROM A NODE WHOSE NAME WE DON'T RECOGNIZE
;**;[2932]REPLACE 8 LINES WITH 3 LINES AT BADNOD:	DSC	22-MAR-83
BADNOD:	BUG (NSPNOD)		;[2932]BUGINF
	MOVEI T2,.DCX7		;[2932]UNSPECIFIED ERROR
	JRST CIDC		;[2932]GO SEND DC
;TRY TO CONVERT THE NODE NAME TO A NODE NUMBER
;USES TRVAR MSGHSN,MSGHNC,MSGLLB
;RETURNS	+1  NO NAME ASSIGNED TO NODE NUMBER
;		+2  T2/ NODE NUMBER

DSCCNV:	SAVEQ
	MOVNI Q3,BIGNOD		;MAKE
	HRLS Q3			; AOBJN
	HRRI Q3,1		;  WORD
	SETZB T3,Q2		;PERMANENT VALUES THROUGH EXTEND LOOP
DSCCN1:	MOVE T1,[POINT 7,MSGHSN]  ;BP TO HOST NAME IN MSG
	MOVE T2,[POINT 6,]	;BP TO ENTRY
	HRRI T2,NODMAP(Q3)	; IN NODE NAME MAPPING TABLE
	MOVE T3,MSGHNC		;GET NUMBER OF CHARS. IN HOST NODE NAME
	TLO T3,400000		;SPECIAL CALL TO COMPAR
	MOVNI T4,40		;COMPARE ASCII TO SIXBIT
	CALL COMPAR		;DO THEY MATCH?
	IFSKP.
	   HRRZ T2,Q3		;YES, POSITION NODE NUMBER
	   RETSKP
	ENDIF.
	AOBJN Q3,DSCCN1		;NO, TRY ANOTHER
	RET			;DIDN'T FIND IT


;SEE IF IT'S A NODE NAME OR A NUMERIC NAME
;RETURNS:	+1  NOT NUMERIC
;		+2  NUMERIC

NAMNUM:	MOVE T1,[440700,,MSGHSN]  ;BP TO NAME IN MSG
	MOVE T2,MSGHNC		;GET NUMBER OF CHARS. IN NAME
NAMNU1:	ILDB T3,T1		;GET A CHAR.
	CAIL T3,"0"		;IS IT
	CAILE T3,"9"		; NUMERIC?
	RET			;NO
	SOJG T2,NAMNU1		;YES, ANY MORE TO CHECK
	RETSKP			;NO, NAME IS NUMERIC
;COROUTINE OF CIMSG TO FIND THE PROPER LISTENING OBJECT

CICOR:	SAVET			;SAVE ALL TEMPS
	SKIPN T2,MSGOBJ		;WANT TASK NAME MATCH?
	JRST [	LOAD T2,LLTSK,(T1) ;YES. PICK UP STRING
		JRST CICOR1]	;AND GO TRY
	OPSTR <CAME T2,>,LLNAM,(T1) ;IS THIS THE CORRECT OBJECT?
	RET			;NO.
	LOAD T2,LLDSC,(T1)	;YES. CHECK DESCRIPTOR STRINGS
CICOR1:	MOVEI T1,MSGDDC		;GET REQUESTED DESCRIPTOR
	CALL CMPSTR		;GO COMPARE STRINGS
	 RET			;NOT THE ONE
	RETSKP			;FOUND IT!!!!

;COMMON ROUTINE TO FETCH LL ADDRESSES FROM MESSAGES AND STORE IN
;PROPER TRVAR'S

	RESCD			;USED BY INT LEVEL
GETLLA:	CALL GETTWO		;GET DEST LL
	 RET			;BADLY FORMED
	MOVEM T2,MSGDST		;SAVE IT
	CALL GETTWO		;GET SOURCE
	 RET			;BADLY FORMED
	MOVEM T2,MSGSRC
	RETSKP			;GO THEM

;COMMON ROUTINE TO FILL IN LL BLOCK AFTER SUCCESSFUL CONNECTION

	SWAPCD			;IS SWAPPABLE
FILLIN:	MOVE T2,MSGLKP		;GET LINK PRIORITY
	STOR T2,LLLKP,(T1)	;SAVE IT IN LL BLOCK
	MOVE T2,MSGW1		;GET FC OPTION
	STOR T2,LLMFC,(T1)	;SAVE IT IN LL BLOCK
	MOVE T2,MSGW2		;GET SEGSIZE
	MOVE T3,MSGBLK		;GET MESSAGE ADDRESS
	LOAD T3,MSMFL,(T3)	;GET MESSAGE FLAGS
	CAIE T3,CIMMFL		;A CI?
	JRST [	LOAD T4,LLSWG,(T1)	;NO, A CC.  GET SEGSIZ OF CI
		CAMLE T2,T4		;OUR'S LESS?
		MOVE T2,T4		;NO, USE SEGSIZ OF CI
		TMNE LLLOC,(T1)		;LOCAL CONNECTION?
		JRST FILLI2		;YES, NO FURTHER CHECK NEEDED
		LOAD T4,LLPRT,(T1)	;GET PORT NUMBER
		CAMLE T2,NSPMAX(T4)	;OUR'S LESS THAN PORT'S?
		MOVE T2,NSPMAX(T4)	;NO, USE PORT'S SEGSIZ
		JRST FILLI2]
FILLI2:	LOAD T3,LLBSZ,(T1)	;GET BYTE SIZE
	CAIE T3,44		;WORD MODE?
	JRST FILLI1		;NO.
	IDIVI T2,11		;YES. MAKE IT EVEN # OF WORDS THEN
	IMULI T2,11		;""
FILLI1:	STOR T2,LLSWG,(T1)	;SAVE IT
	MOVE T2,MSGSRC		;GET FOREIGN LINK I.D.
	STOR T2,LLHLK,(T1)	;SAVE IT
	RET			;AND DONE
;COMMON ROUTINE TO GEN CONNECT INTERRUPT

CONINT:	SAVET			;SAVE TEMPS
	STKVAR <CNTLLB,CNTSTS>
	MOVEM T1,CNTLLB		;SAVE LOGICAL LINK BLOCK ADDRESS
	JN LLINT,(T1),CONIN1	;IF INTERNAL LINK GO NOTIFY DRIVER OF CONNECT
	LOAD T2,LLFRK,(T1)	;GET OWNING FORK
	OPSTR <SKIPN T1,>,LLPIC,(T1) ;HAVE A CONNECT PI?
	RET			;NONE TO DO
	SOS T1			;GET PROPER CHANNEL
	CALLRET PSIRQ		;GEN INTERRUPT

; HERE FOR INTERNAL LINKS

CONIN1:	CALL RDSTS		;GO GET LINK STATUS
	MOVEM T3,CNTSTS		;SAVE STATUS
	HRRZ T1,CNTSTS		;GET NSP ERROR CODE
	CALL NSPERR		;CONVERT TO TOPS20 ERROR CODE
	 JFCL			;USE TRANSLATION ROUTINE'S ERROR CODE
	HRR T2,T1		;GET TOPS20 ERROR CODE
	HLL T2,CNTSTS		;GET STATUS FLAGS
	MOVE T1,CNTLLB		;RESTORE LOGICAL LINK BLOCK ADDRESS
	LOAD T4,LLVEC,(T1)	;GET ADDRESS OF DRIVER FUNCTION VECTOR
	LOAD T1,LLDRV,(T1)	;GET DRIVER CORRELATION CODE
	CALL @.NSCND(T4)	;NOTIFY DRIVER OF CONNECTION
	RET			;DONE, RETURN
;INTTST - ROUTINE TO DETERMINE IF CONNECTED TO AN INTERNAL LINK
;
;ACCEPTS IN TRVARS MSGLCL/ LOCAL-FOREIGN FLAG
;		   MSGSRC/ LINK ID OF SOURCE OF CI MESSAGE
;		   MSGLLB/ LOGICAL LINK BLOCK ADDRESS OF DESTINATION LINK
;		CALL INTTST
;RETURNS: +1 ALWAYS, WITH LLCIL SET IF CONNECTED TO AN INTERNAL LINK

INTTST:	ACVAR <W1>

	SAVET			;PRESERVE LOCAL AC'S
	SKIPN MSGLCL		;LOCAL CONNECTION ?
	RET			;NO, DONE

; LOCK SOURCE LOGICAL LINK BLOCK AND SEE IF IT IS AN INTERNAL LINK

INTT10:	LLLOCK			;LOCK LOGICAL LINK TREE
	MOVE T1,MSGSRC		;GET SOURCE LINK ID
	SETOM T2		;NO SPECIAL CRITERIA
	CALL LLLKUP		;FIND THE LINK ADDRESS
	 JRST [	LLLULK		;FAILED, UNLOCK THE TREE
		RET ]		;RETURN, LINK MUST HAVE DISAPPEARED
	MOVEM T1,W1		;SAVE LOGICAL LINK BLOCK ADDRESS OF SOURCE
	CALL BLKLOK		;LOCK THE SOURCE LINK BLOCK
	 JRST [	LLLULK		;CANNOT LOCK IT, UNLOCK THE TREE
		MDISMS		;WAIT UNTIL AVAILABLE
		JRST INTT10 ]	;GO TRY TO LOCK BLOCK AGAIN
	LLLULK			;UNLOCK LOGICAL LINK TREE
	JE LLINT,(W1),INTT20	;IF SOURCE IS NOT AN INTERNAL LINK, WE ARE DONE
	MOVE T4,MSGLLB		;GET LOGICAL LINK BLOCK ADDRESS OF DESTINATION
	SETONE LLCIL,(T4)	;NOTE CONNECTED TO AN INTERNAL LINK

; HERE WHEN DONE, UNLOCK BLOCK AND RETURN

INTT20:	MOVE T1,W1		;RESTORE LOGICAL LINK BLOCK ADDRESS
	CALL BLKULK		;UNLOCK THE BLOCK
	RET			;DONE, RETURN

	ENDAV.			;END ACVAR
;PROCESS A CONNECT-CONFIRM

CCMSG:	CALL GETLLA		;GET LINK ADDRESSES
	 JRST BADMSG		;BADLY FORMED
	SETZM MSGSOB		;ASSUME WE LIKE SERVICES
	CALL CIPSRV		;GET SERVICES INFO
	 SETOM MSGSOB		;DIDN'T LIKE IT. REMEMBER THIS
CCMSG1:	MOVE T1,MSGDST		;GET OUR ALLEGED NAME
	SETOM T2		;ANY MATCH
	LLLOCK			;LOCK THE TREE
	CALL LLLKUP		;AND LOOK UP THE BLOCK
	 JRST [	LLLULK		;FREE THE TREE
		MOVEI T2,.DCX41	;NO MATCH
		JRST CIDC]	;GO DC THE LINK
	MOVEM T1,MSGLLB		;SAVE LINK BLOCK ADR
	CALL BLKLOK		;LOCK BLOCK LOCK
	 JRST [	LLLULK		;FREE TREE LOCK
		MDISMS		;WAIT HERE A WHILE
		JRST CCMSG1]	;AND TRY AGAIN
	LLLULK			;FREE THE TREE
	MOVE T2,MSGBLK		;GET MESSAGE ADDRESS
	CALL NSINBK		;DO BOOKKEEPING
	JN LLFOB,(T1),CCJECT	;CAN'T BE AN OBJECT
	LOAD T2,LLSTA,(T1)	;GET STATE
	JRST @CCREC-1(T2)	;GO DO RIGHT THING

;EXPECTING A CC.

CCGUD:	SKIPN MSGSOB		;DID WE LIKE SERVICES?
	JRST CCGUD1		;YES
	MOVEI T2,LLSABT		;NEED TO CLOSE LINK
	STOR T2,LLSTA,(T1)	;SAY LINK IS DEAD
	CALL CONINT		;GET AN INTERRUPT
	MOVEI T2,.DCX35		;SERVICES MISMATCH
	JRST CCJEC1		;AND SEND A DC
CCGUD1:	SKIPG MSGSRC		;A VALID SOURCE I.D.?
	JRST [	SETZM MSGW1	;NO.
		CALL RJECT	;SHUT DOWN LINK
		JRST CCDON]	;AND GIVE UP
	CALL FILLIN		;FILL IN NECESSARY INFORMATION
	CALL TURNON		;GO SEND INTIAL LS MESSAGE
	 JRST [	EXCH T1,MSGLLB	;SAVE SCHED TEST, GET LINK BLOCK ADR
		CALL BLKULK	;FREE THIS BLOCK
		MOVE T1,MSGLLB	;RESTORE SCHED TEST
		CALL GENWAT	;WAIT HERE FOR A WHILE
		MDISMS		;UNTIL FREE SPACE IS AVAILABLE
		JRST CCMSG1]	;AND DO IT AGAIN
	MOVEI T2,LLSRUN		;NOW WE ARE RUNNING
	STOR T2,LLSTA,(T1)	;SAY SO
	SETONE LLLWC,(T1)	;NOTE THAT A GOOD CC WAS RECEIVED
	LOAD T3,LLOPT,(T1)	;SEE IF ANY OPTDATA
	MOVEI T4,MAXOPT
	CALL GTBNRY
	 JRST [	JUMPE T2,CCGUD2	;IF NO OPTDATA, OK
		JRST BADUDT]	;BAD MESSAGE
	STOR T2,LLUCT,(T1)	;YES. SAVE COUNT
CCGUD2:	MOVEI T2,1		;INITIAL COUNT FOR LS/INT
	STOR T2,LLMIC,(T1)	;STASH IT
	JRST DSCMV1		;AND GO INTERRUPT, ETC.
;CCMSG CONTINUED...
;DON'T LIKE IT

CCJECT:	MOVEI T2,.DCX41		;ILLEGAL DEST ADDRESS
CCJEC1:	CALL BLKULK		;FREE THE BLOCK
	JRST CIDC		;AND SEND DC

CCDON:	CALL BLKULK		;FREE THE BLOCK
	JRST TOSMSG		;IGNORE THE MESSAGE

;ROUTINES TO SEND DC'S FOR CONNECT ERRORS

CIDC:	SKIPE MSGLCL		;IS IT LOCAL?
	JRST [SKIPL NSPLPB	;YES, IS THERE A RUNNING LOOPBACK LINE?
	      JRST CIDCLC	;NO
	      JRST .+1]		;YES
	MOVEM T2,MSGW1		;SAVE CODE
CIDCT:	MOVEI T1,MSGDML		;USE DUMMY LINK BLOCK
	MOVEI T3,CNMRFL+CNMDC	;FLAGS
	MOVE T2,MSGW1		;GET REASON
	CALL SNDDC		;BUILD THE DC MESSAGE
	 JRST [	MDISMS		;WAIT A WHILE
		JRST CIDCT]	;AND TRY AGAIN
	CALL SNDCTL		;SEND IT
	JRST TOSMSG		;AND DONE

CIDCLC:	MOVE T1,MSGDST
	EXCH T1,MSGSRC		;EXCHANGE SOURCE AND DEST
	MOVEM T1,MSGDST		;""
	JRST DCMSG4		;AND GO DO DC

;ROUTINE TO HANDLE ACCESS INFORMATION ERRORS

BADUDT:	CALL CONINT		;INT PROCESS
	MOVEI T2,.DCX43		;SAY BAD OPTDATA
	STOR T2,LLRSN,(T1)	;AND STASH IT
	MOVEI T3,LLSABT		;NEW STATE
	STOR T3,LLSTA,(T1)
	CALL BLKULK		;FREE BLOCK
	JRST CIDC		;AND SEND DC
;ROUTINE TO BUILD A DI OR DC MESSAGE FOR NSPTSK
;ACCEPTS:	T1/ ADDRESS OF DUMMY LL BLOCK
;		T2/ REASON
;		T3/ FLAGS
;RETURNS:	+1 FAILED. NEED TO BLOCK
;		+2 ALL SENT

SNDDC:	SKIPE T4,MSGHSN		;ANY HOST NAME ?
	MOVEI T4,MSGHSN		;YES, GET ADDRESS OF HOST NAME
	STOR T4,LLHST,(T1)	;STORE IT
	MOVE T4,MSGSRC		;GET SOURCE NAME
	STOR T4,LLHLK,(T1)	;SAVE AS REMOTE NAME
	MOVE T4,MSGDST		;GET OUR NAME
	STOR T4,LLLNK,(T1)	;SAVE IT
	MOVE T4,T3		;MOVE FLAGS
	MOVE T3,MSGBLK		;GET MESSAGE
	LOAD T3,MSPRT,(T3)	;GET PORT
	STOR T3,LLPRT,(T1)	;SAVE IN LL BLOCK
	SETZM T3		;NO USER DATA
	CALL SNDDI		;BUILD THE MESSAGE
	 JRST [	TQO <BLKF>	;NOTE BLOCK NEEDED
		RET ]		;AND RETURN
	RETSKP			;DONE, RETURN SUCCESS
;RECEIVED AN ACK

ACKMSG:	CAIL T4,2		;VALID SUBTYPE?
	JRST TOSMSG		;NO, IGNORE IT
	CALL GETLLA		;GET LINK ADDRESSES
	 JRST BADMSG		;BADLY FORMED
	MOVE T1,MSGBLK		;GET BLOCK ADDRESS
	MOVE T3,MSGBYP		;GET CURRENT POINTER
	MOVEM T3,MSBPTR(T1)	;SAVE POINTER
	MOVE T3,MSGCNT		;GET CURRENT COUNT
	STOR T3,MSDTC,(T1)	;SAVE IT
ACKMS1:	LLLOCK			;LOCK THE TREE
	MOVE T1,MSGDST		;GET OUR NAME
	MOVE T2,MSGSRC
	CALL LLLKUP		;LOOK UP THE NAME
	 JRST [	LLLULK		;NOT FOUND
		MOVEI T2,.DCX41	;INVALID ADDRESS
		JRST CIDC]	;SEND A DC TO SHUT OFF THIS NOISE
	CALL BLKLOK		;FOUND IT. LOCK IT
	 JRST [	LLLULK		;CAN'T
		MDISMS		;WAIT A WHILE
		JRST ACKMS1]	;AND TRY AGAIN
	LLLULK
	MOVEM T1,MSGLLB		;SAVE LOGICAL LINK BLOCK ADDRESS
	MOVE T2,MSGBLK		;GET MESSAGE ADDRESS
	CALL NSINBK		;DO BOOKKEEPING
	LOAD T2,LLSTA,(T1)	;GET CURRENT STATE
	JRST @ACKSTA-1(T2)	;GO HANDLE IT

;IN CIS STATE

ACKCIS:	CALL GETTWO		;GET ACK VALUE
	 JRST ACKINV		;NOT VALID
	TXNE T2,ACKBIT		;ACK OR NACK?
	JRST CCDON		;A NACK. IGNORE IT
	JUMPN T2,ACKINV		;AN ACK. MUST BE FOR SEG # 0
	MOVE T2,MSGBLK		;GET FLAGS
	LOAD T2,MSMFL,(T2)	;""
	SKIPN MSGSRC		;MUST NOT HAVE A SOURCE NAME YET
	TXNE T2,ACKLSI		;AND MUST BE FOR DATA SUBCHANNEL
	JRST ACKINV		;NOT
	JRST CCDON		;A VALID ACK. IGNORE IT HOWEVER

ACKINV:	MOVEI T2,.DCX41		;INVALID.
	MOVEM T2,MSGW1		;SET UP ERROR CODE
	CALL RJECT		;ABORT THE LINK
	JRST CCJEC1		;SEND THE DC
;IN CC SENT STATE

ACKCCS:	STKVAR <LLBLK>		;TEMP STORAGE FOR LL BLOCK ADDRESS
	MOVEM T1,LLBLK		;SAVE IT
ACKCC4:	CALL TURNON		;TRY TO SEND INITIAL LS MESSAGE
	 JRST[ PUSH P,T1	;SAVE SCHEDULER TEST
	       MOVE T1,LLBLK	;RETRIEVE LL BLOCK ADDRESS
	       SETONE LLTRN,(T1)  ;STILL NEED LS
	       CALL BLKULK	;UNLOCK THE LL BLOCK
	       POP P,T1		;RETRIEVE SCHEDULER TEST
	       CALL GENWAT	;AND WAIT HERE
	       MDISMS		;UNTIL FREE SPACE IS AVAILABLE
ACKCC5:	       MOVE T1,LLBLK	;GET LL BLOCK ADDRESS
	       CALL BLKLLK	;LOCK THE BLOCK
	        JRST [MDISMS	;CAN'T, WAIT
	              JRST ACKCC5]  ;AND TRY TO LOCK AGAIN
	       JRST ACKCC4]	;TRY TO SEND MESSAGE AGAIN
	SETZRO LLTRN,(T1)	;DON'T NEED LS ANYMORE
	MOVEI T2,LLSRUN		;NOW IN
	STOR T2,LLSTA,(T1)	; RUN STATE
	MOVEI T2,1		;SET INITIAL LS/INT
	STOR T2,LLMIC,(T1)	; REQUEST COUNT
ACKCC3:	HRRZ T2,LLSEGQ(T1)	;GET ADDRESS OF FIRST MESSAGE ON LINK'S QUEUE
	JUMPE T2,ACKRUN		;IF NONE, ALL SET
	SETZ T3,		;NO PREVIOUS MESSAGE YET
ACKCC1:	LOAD T4,MSMFL,(T2)	;GET MESSAGE TYPE
	CAIN T4,CNMRFL+CNMCF	;IS IT A CC?
	JRST ACKCC2		;YES, GO REMOVE IT FROM THE QUEUE
	MOVE T3,T2		;MAKE THIS ONE PREVIOUS
	OPSTR <SKIPE T2,>,MSLNK,(T2)  ;GET ADDRESS OF NEXT
	JRST ACKCC1		;GO TRY IT
	JRST ACKRUN		;NO MORE TO TRY
ACKCC2:	MOVEI T4,LLSEGQ(T1)	;GET ADDRESS OF LINK'S SEGMENT QUEUE
	CALL UNQSEG		;REMOVE THE CC FROM THE SENT QUEUE
	MOVE T1,T2		;GET MESSAGE ADDRESS IN NECESSARY PLACE
	CALL RELRES		;GIVE BACK THE SPACE
	MOVE T1,LLBLK		;GET BACK THE LL BLOCK ADDRESS

;IN RUN STATE
;**;[2931]REWRITE ACKRUN LOGIC	DSC	22-MAR-83
ACKRUN:	MOVE T2,MSGBLK		;GET MESSAGE
	LOAD T2,MSMFL,(T2)	;GET FLAGS
	CALL ACKDO		;GO DO THE ACTUAL ACK
	 JRST ABTMSG		;BADLY FORMED MESSAGE
	JN LLINT,(T1),[
		CALL SQILS	;INTERNAL LINK, TRY LS SEND AGAIN
		MOVE T1,MSGLLB	;FAILED, RESTORE LINK BLOCK ADDRESS
		JRST CCDON]
	TMNE LLLSA,(T1)		;WANT TO RETRY A LS SEND?
	CALL DATINR		;YES. MAKE PROCESS WAKE NOW THEN
	JRST CCDON		;AND DONE

	ENDSV.
DIMSG:	CALL GETLLA		;GET LINK ADDRESSES
	 JRST BADMSG		;BAD MESSAGE
	CALL GETTWO		;GET REASON CODE
	 SETOM T2		;BADLY FORMED MESSAGE
	MOVEM T2,MSGW1		;SAVE REASON CODE
DIMSG1:	MOVE T1,MSGDST		;GET OUR NAME
	SETOM T2		;MATCH ANY LINK
	MOVEI T3,MSGHSN		;GET HOST NAME
	LLLOCK			;LOCK THE TREE
	CALL LLLKUP		;FIND THE LINK
	 JRST [	LLLULK		;FREE THE TREE
		MOVEI T2,.DCX41	;INVALID LINK I.D.
		JRST CIDC]	;AND SEND A DC
	MOVEM T1,MSGLLB		;SAVE BLOCK ADDRESS
	CALL BLKLOK		;LOCK THE BLOCK
	 JRST [	LLLULK		;FREE THE TREE
		MDISMS		;WAIT HERE FOR A WHILE
		JRST DIMSG1]	;AND TRY AGAIN
	LLLULK			;FREE THE TREE
	MOVE T2,MSGBLK		;GET MESSAGE ADDRESS
	CALL NSINBK		;DO BOOKKEEPING
	LOAD T3,LLOPT,(T1)	;GET OPTDATA, IF ANY
	MOVEI T4,MAXOPT
	CALL GTBNRY		;GO GET IT
	 SETZM T2		;NONE THERE.
	STOR T2,LLUCT,(T1)	;SAVE COUNT OF DATA
	LOAD T2,LLSTA,(T1)	;GET CURRENT STATE
	JRST @DIREC-1(T2)	;GO DO STATE ACTION

;DI RECIEVED WHEN IN CI SENT STATE

CONREJ:	CALL RJECT		;SET STATE OF LINK
	JRST DCDCS		;SEND DC

;HERE FOR DI RECEIVED WHEN IN DIS STATE

DIDIDC:	TMNE LLLOC,(T1)		;LOCAL MESSAGES AREN'T
	 JRST DIMSG2		; ON SENT QUEUE
	HRRZ T2,LLSEGQ(T1)	;GET ADDRESS OF FIRST MESSAGE IN QUEUE
	SETZ T3,		;NO PREVIOUS MESSAGE YET
DIDID1:	LOAD T4,MSMFL,(T2)	;GET MESSAGE TYPE
	CAIN T4,CNMRFL+CNMDI	;IS IT A DI?
	JRST DIDID2		;YES
	MOVE T3,T2		;NO, MAKE THIS MESSAGE PREVIOUS
	LOAD T2,MSLNK,(T2)	;GET ADDRESS OF NEXT MESSAGE
	JRST DIDID1		;GO TRY THIS ONE
DIDID2:	MOVEI T4,LLSEGQ(T1)	;GET ADDRESS OF SEGMENT QUEUE HEAD
	CALL UNQSEG		;REMOVE SEGMENT FROM QUEUE
	MOVE T1,T2		;GET ADDRESS OF OLD DI
	CALL RELRES		;GIVE BACK THE SPACE
	MOVE T1,MSGLLB		;RETRIEVE LL BLOCK ADDRESS
;DI RECEIVED IN RUN, DIQ, DIR, OR CCS

DIMSG2:	CALL CHKFRN		;SOURCE ADDR MUST MATCH
	 JRST CCJECT		;DOESN'T, SEND DC
	CALL SHUTLK		;SHUT DOWN LINK

;COMMON POINT FOR DI RECEIVED - RESPONSE IS ALWAYS REASON CODE 42

DCDCS:	STKVAR <DILLB>
	MOVEM T1,DILLB		;PRESERVE LL BLOCK ADDRESS
	MOVEI T2,.DCX42		;SAY REPLY TO DI
	CALL CIDC		;SEND DC
;**;[2940]CHANGE 1 LINE AT DCDCS: + 4L	DSC	29-MAR-83
	MOVE T1,DILLB		;[2940]GET BACK LL BLOCK ADDRESS
	TMNE LLSDE,(T1)		;DISASSOCIATED?
	IFSKP.
	   CALL BLKULK		;NO, UNLOCK LL
	   RET			;DONE
	ENDIF.
	CALL FLUSH		;YES, GET RID OF ALL MESSAGES
	LLLOCK			;LOCK THE LL TREE
	CALL DELNOD		;GET RID OF THIS LL
	LLLULK			;UNLOCK THE TREE
;**;[2930]ADD 1 LINE AT DCDCS: + 8L	DSC	22-MAR-83
	OKINT			;[2930]MATCH THE NOINT DONE IN BLKLOK
	DECR DCCUR		;GIVE BACK A LINK
	RET

	ENDSV.
;ROUTINES TO CHANGE LINK STATE WHEN DI OR DC IS RECIEVED

;FOR DI OR DC RECEIVED IN CIS STATE

RJECT:	MOVEI T2,LLSABT		;CONNECTION IS ABORTED
	STOR T2,LLSTA,(T1)	;SAY SO
	MOVE T2,MSGW1		;GET REASON CODE
	STOR T2,LLRSN,(T1)	;SAVE IN THE LL BLOCK
	CALLRET CONINT		;GIVE CONNECTION INTERRUPT

;FOR DI OR DC RECIEVED IN NON-RUN STATE

RJECT1:	MOVEI T2,LLSABT		;SAY LINK NOW ABORTED
	STOR T2,LLSTA,(T1)
	MOVE T2,MSGW1		;GET REASON
	STOR T2,LLRSN,(T1)	;STORE IN BLOCK
	CALL FLUSH		;CLEAR OUT LINK'S QUEUES
	CALL CHKLLT		;CHECK FOR TTY ON THIS LINK
	CALLRET TELDIS		;NOTIFY DRIVER IF THIS IS AN INTERNAL LINK

;FOR DI OR DC RECEIVED IN RUN STATE

SHTLK1:	SKIPA T3,[LLSDIS]	;NEW STATE
SHUTLK:	MOVEI T3,LLSDIR		;NEW STATE
	MOVE T2,MSGW1		;GET REASON
	STOR T2,LLRSN,(T1)	;SAVE IT
	STOR T3,LLSTA,(T1)	;SAVE NEW STATE
	CALL DATINR		;GIVE INT IF NECESSARY
	SKIPE MSGW1		;SYNCHRONOUS DI?
	JRST [	SETZRO LLFDI,(T1) ;NO. CLEAR THIS JUST IN CASE
		CALL FLUSH	;AND CLEAN UP LINK
		JRST SHUT10]	;GO NOTIFY DRIVER IF INTERNAL LINK
	SETONE LLFDI,(T1)	;YES. SAY SO
SHUT10:	CALL CHKLLT		;CHECK FOR TTY ON THIS LL
	CALLRET TELDIS		;NOTIFY DRIVER IF AN INTERNAL LINK



;ROUTINE USED BY DIMSG TO VERIFY SOURCE ADDR
;	T1/ LINK ADDRESS
;RETURNS:	+1 NOT A MATCH
;		+2 A MATCH

CHKFRN:	LOAD T2,LLHLK,(T1)	;GET FOREIGN HOST I.D.
	CAME T2,MSGSRC		;IS THIS WHO SENT IT?
	RET			;NO
	RETSKP			;YES
;TELDIS - ROUTINE TO NOTIFY A DRIVER OF A DISCONNECT ON AN INTERNAL LINK
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL TELDIS
;RETURNS: +1 ALWAYS, WITH DRIVER NOTIFIED

TELDIS:	SAVET
	STKVAR <TDSLLB,TDSSTS>
	MOVEM T1,TDSLLB		;SAVE LOGICAL LINK BLOCK ADDRESS
	JE LLINT,(T1),R		;DONE IF NOT AN INTERNAL LINK
	JN LLSDE,(T1),R		;DONE IF LINK DISSOCIATED FROM PROCESS
	CALL RDSTS		;GO GET LINK STATUS
	MOVEM T3,TDSSTS		;SAVE STATUS
	HRRZ T1,TDSSTS		;GET NSP ERROR CODE
	CALL NSPERR		;CONVERT TO TOPS20 ERROR CODE
	 JFCL			;FAILED, USE ERROR CODE FROM TRANSLATION ROUTINE
	HRR T2,T1		;GET TOPS20 ERROR CODE
	HLL T2,TDSSTS		;GET STATUS BITS
	MOVE T1,TDSLLB		;RESTORE LOGICAL LINK BLOCK ADDRESS
	LOAD T4,LLVEC,(T1)	;GET ADDRESS OF DRIVER FUNCTION VECTOR
	LOAD T1,LLDRV,(T1)	;GET DRIVER CORRELATION CODE
	CALLRET @.NSDIS(T4)	;NOTIFY DRIVER OF DISCONNECT
;RECEIVED A DC MESSAGE

DCMSG:	CALL GETLLA		;GET LINK ADDRESSES
	 JRST BADMSG		;BADLY FORMED
	CALL GETTWO		;GET REASON
	 SETOM T2		;NONE THERE
DCMSG4:	MOVEM T2,MSGW1		;SAVE IT
DCMSG1:	MOVE T1,MSGDST		;GET OUR NAME
	MOVE T2,MSGSRC		;GET SOURCE ADDRESS
	LLLOCK			;LOCK THE TREE
	CALL LLLKUP		;FIND THE LINK
	 JRST [	LLLULK		;FREE THE TREE
		JRST TOSMSG]	;IGNORE THE MESSAGE
	MOVEM T1,MSGLLB		;SAVE THE LL BLOCK ADDRESS
	CALL BLKLOK		;LOCK THE BLOCK
	 JRST [	LLLULK		;CAN'T. FREE TREE
		MDISMS		;WAIT HERE
		JRST DCMSG1]	;AND TRY AGAIN
	LLLULK			;FREE TREE
	LOAD T2,LLSTA,(T1)	;GET STATE
	JRST @DCREC-1(T2)	;AND GO DO RIGHT THING

CHKIDL:	SKIPN MSGSRC		;SOURCE NODE FIELD MBZ, IS IT?
	CALL RJECT		;YES, GO SET PROPER LINK STATE
	JRST CCDON		;AND DONE


;RECEIVED DC IN DIS STATE - MUST REMOVE THE DI FROM THE SENT QUEUE
;BEFORE CLOSING THE LINK

DCGUD:	TMNE LLLOC,(T1)		;LOCAL MESSAGES AREN'T
	 JRST DCABT		; ON SENT QUEUE
	HRRZ T2,LLSEGQ(T1)	;GET ADDRESS OF FIRST MESSAGE IN QUEUE
	SETZ T3,		;NO PREVIOUS MESSAGE YET
DCGUD1:	LOAD T4,MSMFL,(T2)	;GET MESSAGE TYPE
	CAIN T4,CNMRFL+CNMDI	;IS IT A DI?
	JRST DCGUD2		;YES
	MOVE T3,T2		;NO, MAKE THIS MESSAGE PREVIOUS
	LOAD T2,MSLNK,(T2)	;GET ADDRESS OF NEXT MESSAGE
	JRST DCGUD1		;GO TRY THIS ONE
DCGUD2:	MOVEI T4,LLSEGQ(T1)	;GET ADDRESS OF SEGMENT QUEUE HEAD
	CALL UNQSEG		;REMOVE SEGMENT FROM QUEUE
	MOVE T1,T2		;GET ADDRESS OF OLD DI
	CALL RELRES		;GIVE BACK THE SPACE
	MOVE T1,MSGLLB		;RETRIEVE THE LL BLOCK ADDRESS

;RECEIVED DC IN NON-RUN STATE

DCABT:	JN LLSDE,(T1),[
		CALL RELLNK	;IF DISASSOCIATED
		JRST TOSMSG]	;JUST GIVE UP QUIETLY
	CALL RJECT1		;SET PROPER LINK STATE
	JRST CCDON		;AND DONE

;DC RECEIVED IN RUN STATE

DCRUN:	SKIPN T2,MSGW1		;AN ABORT?
	MOVEI T2,.DCX9		;NO. MAKE IT ONE THEN
	MOVEM T2,MSGW1
	CALL SHUTLK		;BEGIN LINK SHUT DOWN
	JRST CCDON		;AND DONE



;UTILITY ROUTINE TO RELEASE A DISASSOCIATED NODE

RELLNK:	OKINT			;DO THE OKINT TO MATCH THE NOINT IN BLKLOK
	CALL FLUSH		;GET RID OF ALL MESSAGES
	LLLOCK			;LOCK UP THE TREE
	CALL DELNOD		;FREE LL BLOCK
	LLLULK			;GIVE UP THE LOCK
	RET			;DONE
;DATA MESSAGE RECEIVED

DATMSG:	CAIE T4,5		;VALID
	CAIN T4,7		; SUBTYPE?
	JRST BADMSG		;NO, IGNORE IT
	MOVEM T4,MSGW1		;SAVE SUBTYPE
	CALL GETLLA		;GET LINK ADDRESSES
	 JRST BADMSG		;BADLY FORMED
DATMS1:	LLLOCK			;LOCK TREE
	MOVE T1,MSGDST		;GET OUR NAME
	MOVE T2,MSGSRC		;GET REMOTE'S NAME
	CALL LLLKUP		;LOOK IT UP
	 JRST [	LLLULK		;FREE TREE
		MOVEI T2,.DCX41	;INVALID ADDRESS
		JRST CIDC]	;SEND A DC
	CALL BLKLOK		;LOCK UP THE BLOCK
	 JRST [	LLLULK		;FREE TREE
		MDISMS		;WAIT FOR BLOCK
		JRST DATMS1]	;AND TRY AGAIN
	LLLULK			;HAVE THE BLOCK
	MOVEM T1,MSGLLB		;SAVE LL BLOCK
	MOVE T2,MSGBLK		;GET MESSAGE ADDRESS
	CALL NSINBK		;DO BOOKKEEPING
	LOAD T2,LLSTA,(T1)	;GET STATE
	JRST @DATSTA-1(T2)	;GO DO IT

;IN CC SENT STATE

DATCCS:	STKVAR <LLBLK>		;TEMP STORAGE FOR LL BLOCK ADDRESS
	MOVEM T1,LLBLK		;SAVE IT
DATCC4:	CALL TURNON		;TRY TO SEND LS MESSAGE
	 JRST [ PUSH P,T1	;SAVE SCHEDULER TEST
	       MOVE T1,LLBLK	;RETRIEVE LL BLOCK ADDRESS
	       SETONE LLTRN,(T1)  ;STILL NEED LS
	       CALL BLKULK	;UNLOCK THE LL BLOCK
	       POP P,T1		;RETRIEVE SCHEDULER TEST
	       CALL GENWAT	;AND WAIT HERE
	       MDISMS		;UNTIL FREE SPACE IS AVAILABLE
DATCC6:	       MOVE T1,LLBLK	;GET LL BLOCK ADDRESS
	       CALL BLKLLK	;LOCK THE BLOCK
	        JRST [MDISMS	;CAN'T, WAIT
	              JRST DATCC6]  ;AND TRY TO LOCK AGAIN
	       JRST DATCC4]	;TRY TO SEND MESSAGE AGAIN
	SETZRO LLTRN,(T1)	;DON'T NEED LS ANYMORE
	MOVEI T2,LLSRUN		;NOW IN
	STOR T2,LLSTA,(T1)	; RUN STATE
	MOVEI T2,1		;SET INITIAL LS/INT
	STOR T2,LLMIC,(T1)	; REQUEST COUNT
DATCC5:	HRRZ T2,LLSEGQ(T1)	;GET ADDRESS OF FIRST MESSAGE ON LINK'S QUEUE
	JUMPE T2,DATCC3		;IF NONE, ALL SET
	SETZ T3,		;NO PREVIOUS MESSAGE YET
DATCC1:	LOAD T4,MSMFL,(T2)	;GET MESSAGE TYPE
	CAIN T4,CNMRFL+CNMCF	;IS IT A CC?
	JRST DATCC2		;YES, GO REMOVE IT FROM THE QUEUE
	MOVE T3,T2		;MAKE THIS ONE PREVIOUS
	OPSTR <SKIPE T2,>,MSLNK,(T2)  ;GET ADDRESS OF NEXT
	JRST DATCC1		;GO TRY IT
	JRST DATCC3		;NO MORE TO TRY
DATCC2:	MOVEI T4,LLSEGQ(T1)	;GET ADDRESS OF LINK'S SEGMENT QUEUE
	CALL UNQSEG		;REMOVE THE CC FROM THE SENT QUEUE
	MOVE T1,T2		;GET MESSAGE ADDRESS IN NECESSARY PLACE
	CALL RELRES		;GIVE UP THE SPACE
	MOVE T1,LLBLK		;GET BACK LL BLOCK ADDRESS
DATCC3:	MOVE T2,MSGBLK		;RETRIEVE ADDRESS OF INCOMING DATA MESSAGE
				; AND PROCEED WITH LINK RUNNING
;IN RUN STATE
;**;[2931]REWRITE DATRUN	DSC	22-MAR-83
DATRUN:	MOVE T4,MSGW1		;GET BACK SUBTYPE
	TXNE T4,1		;DATA MESSAGE?
	JRST INTLS		;NO.
	CALL SETCNT		;SET COUNTS IN MESSAGE HEADER
	MOVE T2,MSGBLK		;GET MESSAGE BLOCK
	CALL ONRAWQ		;PUT IT ON THE Q
DATDON:	JN LLINT,(T1),INTRUN	;IF THIS IS AN INTERNAL LINK, GO ASSEMBLE DATA
	CALL BLKULK		;NOT INTERNAL, FREE BLOCK
	RET			;RETURN TO BACKGROUND TASK DISPATCHER

	ENDSV.

; HERE FOR INTERNAL LINKS - ASSEMBLE DATA INTO DRIVER'S BUFFER

INTRUN:	CALL INTSET		;GO DO INPUT FOR INTERNAL LINK
	 JFCL			;FAILED, IGNORE FAILURE FOR NOW
	CALL BLKULK		;UNLOCK THE LOGICAL LINK BLOCK
	RET			;AND RETURN TO BACKGROUND TASK'S DISPATCHER
; NOT A DATA MESSAGE - MUST BE INTERRUPT OR LINK SERVICES MESSAGE

	RESCD

;**;[2933]DELETE 3 LINES AT INTLS:	DSC	22-MAR-83

INTLS:	CALL GETTWO		;GET ACK NUMBER
	 JRST LSIDON		;NO GOOD
	TXZE T2,ACKIND		;AN ACK?
	JRST [	MOVEI T3,MSLSI	;GET PROPER CHANNEL
		CALL ACKCHN	;DO ACK
		CALL GETTWO	;GET SEGNUM
		 JRST LSIDON	;BADLY FORMED
		JRST .+1]
	MOVE T3,MSGBLK		;GET BLOCK ADDRESS
	STOR T2,MSSEG,(T3)	;SAVE SEG #
	LOAD T3,LLIIN,(T1)	;GET EXPECTED NUMBER
	AOS T3
	ANDI T3,7777		;COMPUTE IT
	SUBI T3,0(T2)		;COMPUTE DIFFERENCE
	ANDI T3,7777
	JUMPE T3,LSINT1		;IF EXACT ONE, MOVE ON
	SKIPL T3		;NOT THE ONE, OLD OR TOO NEW?
	IFSKP.			;TOO NEW
	   LOAD T3,LLLKP,(T1)	;GET NODE'S VERSION
	   CAIE T3,.NSP31	;NSP 3.1?
	   JRST LSIDON		;NO, FORGET IT
	   SETONE LLNLS,(T1)	;SAY NEED A NAK IN LL BLOCK
	   SETZRO LLALS,(T1)	;NOT AN ACK
	ELSE.
	   SETONE LLALS,(T1)	;NEED AN ACK
	ENDIF.
	CALL ONSRVQ		;PUT LL ON "NEEDS SERVICE" QUEUE
	JRST LSIDON		;AND DONE

;HAVE A GOOD INT OR LS MESSAGE

LSINT1:	STOR T2,LLIIN,(T1)	;STORE SEG #
	MOVE T4,MSGBLK		;GET BACK MESSAGE ADDRESS
	LOAD T4,MSMFL,(T4)	;GET MESSAGE FLAGS
	CAIE T4,DATFLI+DATINT	;INT OR LS?
	JRST LSMSG		;LS
	SKIPE LLMSI(T1)		;INT, ALREADY HAVE AN INTERRUPT MESSAGE?
	 JRST LSIDON		;YES, CAN'T HAVE THAT
	CALL SETCNT		;GO SET COUNTS IN BLOCK
	MOVE T2,MSGBLK		;GET BLOCK
	SETZRO MSLNK,(T2)	;CLEAR LINK WORD
	MOVEM T2,LLMSI(T1)	;STORE IT
	CALL INTINT		;GO INTERRUPT PROCESS
	SETONE LLALS,(T1)	;NEED AN ACK
	SKIPN INSKED		;IN SCHEDULER?
	IFSKP.			;
	   CALL ONSRVQ		;YES, PUT LL ON "NEEDS SERVICE" QUEUE
	   RET			;DONE
	ENDIF.
	CALLRET BLKULK		;NO, UNLOCK LL AND RETURN
;HAVE A LS MESSAGE

LSMSG:	SETONE LLALS,(T1)	;NEED AN ACK
	CALL ONSRVQ		;PUT LL ON "NEEDS SERVICE" QUEUE
	GETBYM (MSGCNT,MSGBYP,LSIDON)		;GET LSFLAGS BYTE
	TXNN T2,3		;CHANGING BACK-PRESSURE?
	JRST LSMSG1		;NO
	TRNE T2,1		;STOPPING?
	JRST [	SETONE LLBRP,(T1) ;YES. SAY SO
		JRST LSMSG1]	;AND PROCEED
	SETZRO LLBRP,(T1)	;NO. START IT UP
LSMSG1:	MOVE T3,T2		;SAVE FIELD
	GETBYM (MSGCNT,MSGBYP,LSIDON)		;GET NEXT
	TXNE T3,4		;DATA COUNTS?
	JRST [	OPSTR <ADD T2,>,LLMIC,(T1) ;NO. COMPUTE NEW VALUE
		TXNE T2,200	;WITHIN RANGE?
		JRST LSIDON	;NO
		STOR T2,LLMIC,(T1) ;YES. STORE IT
		JRST LSIDON]	;AND DONE
	LOAD T3,LLMFC,(T1)	;GET FLOW CONTROL TYPE
	JUMPE T3,LSIDN1		;IF NONE, GO ON
	TRNE T2,200		;IS THE COUNT NEGATIVE?
	CAIE T3,2		;YES. IS FLOW CONTROL MESSAGE TYPE?
	SKIPA			;NO. IS GOOD THEN
	JRST LSIDON		;YES. LINK ERROR
	OPSTR <ADD T2,>,LLMSM,(T1) ;ADD IN THE NUMBER
	STOR T2,LLMSM,(T1)	;SAVE NEW VALUE
	TXNN T2,200		;IS THE COUNT NEGATIVE?
	JUMPN T2,[MOVEI T2,CHKSCT ;NO. HAVE SOME COUNT MORE
		PUSH P,T1	;SAVE LL BLOCK
		LOAD T1,LLFRK,(T1) ;GET FORK NUMBER
		CALL NETWKF	;WAKE UP THE PROCESS
		POP P,T1	;GET BACK LL BLOCK
		JRST .+1]	;AND PROCEED
LSIDN1:	CALL RESEND		;SEE IF CAN RESEND ANYTHING
LSIDON:	CALL CHKLLT		;CHECK FOR TTY ON THIS LL
;	JN LLINT,(T1),[
;		CALL INTOUT	;IF INTERNAL LINK SEND ANY OUTPUT STILL LEFT
;		 JFCL		;IGNORE FAILURE HERE
;		JRST .+1]	;CONTINUE
	SKIPN INSKED		;IN SCHEDULER?
	IFSKP.			;YES
	   MOVE T2,MSGBLK	;GET MESSAGE ADDRESS
	   SETONE MSSKD,(T2)	;SET THE RELEASE INDICATOR
	   RET			;DONE
	ENDIF.
	CALL BLKULK		;NO, FREE THE LL LOCK
	JRST TOSMSG		;AND DONE
;INTSET - ROUTINE TO DO INPUT ON INTERNAL LINKS
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL INTSET
;RETURNS: +1	 FAILED
;	  +2	SUCCESS

	SWAPCD

INTSET::SAVET
	STKVAR <INSLLB,INSCNT,INSFLG>
	MOVEM T1,INSLLB		;SAVE LOGICAL LINK BLOCK ADDRESS
	SETZM INSFLG		;INITIALIZE "ALL DATA FIT IN BUFFER" FLAG

; SET UP INPUT BUFFER IF NOT ALREADY SET UP, AND PUT SEGMENTS ON ORDERED QUEUE

INS010:	MOVE T1,INSLLB		;GET LOGICAL LINK BLOCK ADDRESS
	SETZRO LLFIM,(T1)	;START BY ASSUMING NOT END OF MESSAGE
;	CALL MOVSEG		;PLACE SEGMENTS ON ORDERED MESSAGE QUEUE
;	 RET			;FAILED, RETURN ERROR
	MOVE T1,INSLLB		;RESTORE LOGICAL LINK BLOCK
	SKIPN LLOMSG(T1)	;ANY MESSAGES TO PROCESS ?
	RETSKP			;NO, DONE.
	MOVE T1,INSLLB		;GET LOGICAL LINK BLOCK ADDRESS
	CALL SETIBF		;SET UP BUFFER IF REQUIRED
	 RETSKP			;FAILED, WAIT FOR BUFFER FROM DRIVER

; IF TRUNCATING CURRENT NSP MESSAGE, DISCARD THIS SEGMENT

	MOVE T1,INSLLB		;GET ADDRESS OF LOGICAL LINK BLOCK
	JN LLTRM,(T1),[
		CALL TRNMSG	;GO DISCARD THIS SEGMENT
		 RET		;FAILED
		JRST INS030]	;GO SEND ANY ACK'S OR LS MESSAGES NEEDED

; COPY DATA IN RECEIVED SEGMENTS INTO DRIVER'S BUFFER

	MOVE T1,INSLLB		;GET LOGICAL LINK BLOCK ADDRESS
	LOAD T2,LLBPI,(T1)	;GET CURRENT BUFFER POINTER
	LOAD T3,LLICT,(T1)	;GET MAX NUMBER OF CHARACTERS IN INPUT BUFFER
	CALL MOVMSG		;GO COPY DATA INTO DRIVER'S BUFFER
	 RET			;FAILED, RETURN ERROR
	MOVE T4,INSLLB		;RESTORE LOGICAL LINK BLOCK ADDRESS
	MOVEM T2,INSCNT		;SAVE NUMBER OF BYTES THAT WERE INPUT
	MOVEM T3,INSFLG		;SAVE FLAG NOTING WHETHER ALL DATA FIT IN BUFFER
	STOR T1,LLBPI,(T4)	;STORE NEW BUFFER POINTER
	SKIPG INSCNT		;ANY BYTES INPUT ?
	JRST INS020		;NO, DO NOT UPDATE COUNT
	LOAD T3,LLICT,(T4)	;GET PREVIOUS COUNT
	SUB T3,T2		;COMPUTE NUMBER OF BYTES LEFT IN BUFFER
	STOR T3,LLICT,(T4)	;UPDATE NUMBER OF BYTES REMAINING
	; ..
	; ..

; IF SEGMENT DID NOT FIT IN BUFFER, SEE IF DRIVER WANTED TO TRUNCATE

INS020:	MOVE T2,INSFLG		;GET FLAG INDICATING IF ALL DATA FIT IN BUFFER
	CAMN T2,[-1]		;DID LAST SEGMENT FIT IN THE BUFFER ?
	JRST [	JE LLTRC,(T4),.+1 ;NO. JUST CONTINUE IF NOT TRUNCATING MESSAGES
		SETONE LLTRM,(T4) ;REMAINDER OF THIS MESSAGE NOT NEEDED
		JRST .+1]	;AND CONTINUE

; CALL DRIVER IF EITHER BUFFER WAS FILLED OR A COMPLETE MESSAGE WAS RECEIVED

	MOVE T1,INSLLB		;GET ADDRESS OF LOGICAL LINK BLOCK
	MOVE T2,INSCNT		;GET NUMBER OF BYTES INPUT
	MOVE T3,INSFLG		;GET FLAG NOTING IF ALL DATA FIT IN BUFFER
	CALL TELDAT		;NOTIFY DRIVER THAT DATA HAS ARRIVED

; IF NO BYTES WERE INPUT, ALL DONE.  RETURN TO DISPATCHER

	SKIPN INSCNT		;WERE ANY BYTES INPUT ?
	RETSKP			;NO, ALL DONE THEN

; SEND ANY ACK MESSAGES OR LINK SERVICES MESSAGES NEEDED

INS030:	MOVE T1,INSLLB		;GET ADDRESS OF LOGICAL LINK BLOCK
	CALL SQIACK		;SEND ANY ACK'S NEEDED
	 RET			;FAILED, RETURN ERROR
	MOVE T1,INSLLB		;GET ADDRESS OF LOGICAL LINK BLOCK AGAIN
	CALL SQILS		;SEND ANY LINK SERVICES MESSAGES NEEDED
	 JFCL			;IGNORE FAILURE, ACK'S WILL CAUSE RETRY
	JRST INS010		;GO SEE IF THERE ARE MORE MESSAGES TO PROCESS
;TELDAT - ROUTINE TO ADVISE THE DRIVER IF A COMPLETE MESSAGE HAS ARRIVED
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;	    T2/	NUMBER OF BYTES INPUT, -1 IF NOT ENOUGH ROOM IN BUFFER
;		CALL TELDAT
;RETURNS: +1 ALWAYS, WITH DRIVER NOTIFIED IF NEEDED

TELDAT:	STKVAR <TLDLLB,TLDCNT,TLDFLG>
	MOVEM T1,TLDLLB		;SAVE LOGICAL LINK BLOCK ADDRESS
	MOVEM T2,TLDCNT		;SAVE COUNT OF BYTES INPUT
	MOVEM T3,TLDFLG		;SAVE FLAG NOTING IF ALL DATA FIT IN BUFFER

; DETERMINE IF DRIVER MUST BE NOTIFIED

	MOVE T4,TLDLLB		;GET LOGICAL LINK BLOCK ADDRESS
	LOAD T3,LLICT,(T4)	;GET # OF BYTES LEFT IN BUFFER
	JUMPE T3,TLDT10		;IF NONE, BETTER TELL DRIVER !
	MOVE T2,TLDFLG		;GET FLAG
	CAME T2,[-1]		;INSUFFICIENT ROOM IN BUFFER FOR THIS MSG ?
	JRST [	JE LLFIM,(T1),R	;NO, RETURN UNLESS A COMPLETE MESSAGE RECEIVED
		JRST TLDT10 ]	;...

; COMPUTE NUMBER OF BYTES IN BUFFER AND NOTIFY DRIVER OF DATA ARRIVAL

TLDT10:	LOAD T4,LLVEC,(T1)	;GET ADDRESS OF DRIVER FUNCTION VECTOR
	LOAD T3,LLIIC,(T1)	;YES, GET INITIAL COUNT OF BYTES IN BUFFER
	LOAD T2,LLICT,(T1)	;GET CURRENT COUNT OF BYTES LEFT FOR INPUT
	SUB T3,T2		;COMPUTE NUMBER OF BYTES ALREADY INPUT
	JN LLFIM,(T1),[TXO T3,NS%MSG ;BUFFER BEING RETURNED BECAUSE EOM SEEN
		       JRST .+1] ;...
	LOAD T2,LLBFI,(T1)	;GET ADDRESS OF DRIVER'S BUFFER
	LOAD T1,LLDRV,(T1)	;GET DRIVER CORRELATION CODE
	CALL @.NSDAT(T4)	;ADVISE DRIVER THAT INPUT HAS ARRIVED
	MOVE T4,TLDLLB		;RESTORE LOGICAL LINK BLOCK ADDRESS
	JUMPN T1,[JN LLFIM,(T4),.+1	;ONLY SET TRUNCATE IF NOT FULL MSG
		  SETONE LLTRM,(T4) ;NOTE TRUNCATION IF DRIVER REQUESTED IT
		  JRST .+1]	;...

; UPDATE APPROPRIATE COUNTS AND RETURN

	MOVE T1,TLDLLB		;RESTORE LOGICAL LINK BLOCK ADDRESS
	SETZRO <LLICT,LLIIC>,(T1) ;CLEAR BYTE COUNTS
	SETZRO LLBFI,(T1)	;NOTE WE NO LONGER HAVE AN INPUT BUFFER
	RET			;DONE, RETURN
;TRNMSG - ROUTINE TO DISCARD A SEGMENT BECAUSE MESSAGE IS BEING TRUNCATED
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL TRNMSG
;RETURNS: +1	 FAILED
;	  +2	SUCCESS, SEGMENT THROWN AWAY

TRNMSG:	STKVAR <TMSLLB>
	MOVEM T1,TMSLLB		;SAVE LOGICAL LINK BLOCK ADDRESS

TRNM10:	MOVE T1,TMSLLB		;GET LOGICAL LINK BLOCK ADDRESS
	MOVE T2,[POINT 0,0,2]	;GET NUL POINTER (THROW BYTES AWAY)
	MOVX T3,.INFIN		;NO LIMIT ON NUMBER TO DISCARD
	CALL MOVMSG		;DISCARD THE DATA
	 RET			;FAILED
	MOVE T1,TMSLLB		;RESTORE LOGICAL LINK BLOCK ADDRESS
	JE LLFIM,(T1),RSKP	;IF STILL DON'T HAVE ENTIRE MESSAGE THEN DONE
	SETZRO LLTRM,(T1)	;MESSAGE ENTIRELY DISCARDED, STOP TRUNCATING
	RETSKP			;DONE, RETURN SUCCESS
;SETIBF - ROUTINE TO SET UP AN INPUT BUFFER FOR AN INTERNAL LINK
;
;ACCEPTS IN T1/	LOGICAL LINK BLOCK ADDRESS (LINK ASSUMED LOCKED)
;		CALL SETIBF
;RETURNS: +1	 FAILED, COULD NOT SET UP BUFFER NOW
;	  +2	SUCCESS, WITH BUFFER INFO STORED IN LINK BLOCK

SETIBF:	JN LLBFI,(T1),RSKP	;IF ALREADY HAVE A BUFFER THEN DONE
	JN LLDRB,(T1),R		;FAIL IFDRIVER ALREADY REFUSED TO PROVIDE BFR
	ASUBR <SBFLLB>
	LOAD T4,LLVEC,(T1)	;GET DRIVER FUNCTION VECTOR ADDRESS
	LOAD T1,LLDRV,(T1)	;GET DRIVER CORRELATION CODE FOR THIS LINK
	CALL @.NSBFR(T4)	;REQUEST DRIVER TO SUPPLY A BUFFER
	 JRST [	MOVE T1,SBFLLB	;RESTORE LOGICAL LINK BLOCK ADDRESS
		SETONE LLDRB,(T1) ;NOTE THAT DRIVER REFUSED TO PROVIDE BUFFER
		RET ]		;AND DONE
	MOVE T4,SBFLLB		;RESTORE LOGICAL LINK BLOCK ADDRESS
	STOR T1,LLBFI,(T4)	;STORE BUFFER ADDRESS
	STOR T2,LLICT,(T4)	;STORE COUNT OF BYTES CURRENTLY LEFT IN BUFFER
	STOR T2,LLIIC,(T4)	;ALSO STORE AS INITIAL COUNT OF BYTES IN BUFFER
	HRLI T1,(POINT 8,)	;FORM POINTER TO FIRST BYTE IN THIS BUFFER
	STOR T1,LLBPI,(T4)	;SAVE AS POINTER TO NEXT BYTE TO BE INPUT
	TXNE T2,NS%TRN		;DRIVER WANT MESSAGES TRUNCATED IF TOO LONG ?
	JRST [	SETONE LLTRC,(T4) ;YES, NOTE TRUNCATION DESIRED
		JRST .+1 ]	;AND CONTINUE
	RETSKP			;DONE, RETURN WITH BUFFER INFO IN LINK BLOCK
;ROUTINES USED BY DATMSG.....

;KILL OFF LINK AFTER PROTOCOL ERROR.

ABTMSG:	MOVEI T2,.DCX40		;DATA LOSS
	MOVEM T2,MSGW1		;SAVE CODE
	CALL SHTLK1		;SHUT IT OFF
	MOVEM T1,MSGLLB		;SAVE LL BLOCK
	MOVEI T4,CNMRFL+CNMDI	;SEND A DI
	SETZM T3		;NO OPTDATA
	CALL SNDDI		;GO DO IT
	 JRST [	TQO <BLKF>		;NOTE BLOCK NEEDED
		MOVE T1,MSGLLB	;RESTORE BLOCK ADDRESS
		MOVEI T2,LLSDIQ	;NEW STATE
		STOR T2,LLSTA,(T1)
		JRST LSIDON]	;AND DONE
	CALL SNDCTL		;SEND THE MESSAGE
	JRST LSIDON		;DONE

;ROUTINE TO FILL IN MESSAGE COUNTS IN MESSAGE BLOCK

SETCNT:	MOVE T3,MSGBLK		;GET BLOCK ADDRESS
	MOVE T4,MSGBYP		;GET CURRENT BYTE POINTER
	MOVEM T4,MSBPTR(T3)	;SAVE IT
	MOVE T4,MSGCNT		;GET CURRENT COUNT
	STOR T4,MSDTC,(T3)	;SAVE IT
	RET			;AND DONE
;ROUTINE TO SEND INTIAL LS MESSAGE TO OTHER END OF THE LINK.
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;RETURNS:	+1 FAILED. MESSAGES NOT SENT
;			T1/ SCHEDULER TEST WORD
;		+2 SUCCESS. MESSAGES SENT
;			T1/ LL BLOCK ADDRESS (UNCHANGED)

TURNON:	JE LLOPI,(T1),RSKP	;IF NOT OPEN FOR READ, DON'T SEND LS
	MOVEI T3,MSDAT		;ON THE DATA SUBCHANNEL
	LOAD T2,LLMQI,(T1)	;GET MAX QUEUE VALUE
	TMNE LLIMS,(T1)		;MESSAGE?
	MOVEI T2,1		;YES. ONE MESSAGE THEN
	CALLRET SNDLS		;SEND IT OFF
;COLLECTION OF ROUTINES TO GET FIELDS FROM A MESSAGE
;MOST ARE RESIDENT BECAUSE THEY ARE USED BY THE CHANNEL 7 CODE

	RESCD			;CALLED FROM SCHEDULER

;GET TWO BYTE FIELD
;CLOBBERS T3, PRESERVES T4

GETTWO:	GETBYM (MSGCNT,MSGBYP,R)		;GET A BYTE, RETURN IF NONE
	LSHC T2,-10		;SAVE LOW ORDER BYTE
	GETBYM (MSGCNT,MSGBYP,R)		;GET NEXT ONE
	LSHC T2,10		;COMBINE BYTES
	RETSKP			;AND DONE

;COPY ASCII STRING
;	T3/ POINTER TO COPY TO
;	T4/ MAX COUNT OF STRING
;RETURNS:
;	+1 FAILURE. BAD MESSAGE
;	+2 SUCCESS. T2/ COUNT OF BYTES COPIED

GTBNRY:	SKIPA T2,[POINT 8,0(T3)] ;ENTRY FOR OCTET COPY
GTASCI:	MOVE T2,[POINT 7,0(T3)]	;ENTRY FOR ASCII COPY
GTASC0:	ACVAR <W1,W2>		;ENTRY FOR SKPFLD
	MOVE W1,T2		;SAVE POINTER
	GETBYM (MSGCNT,MSGBYP,[SETZM T2		;GET COUNT FIELD
			       RET])		;DONE
	CAMLE T2,T4		;WITHIN RANGE?
	RET			;NO.
	MOVE W2,T2		;SAVE COUNT
	SKIPN T4,T2		;SAVE COUNT
	JRST GTASCD		;NO COUNT
GTASC1:	GETBYM (MSGCNT,MSGBYP,R)
	IDPB T2,W1		;SAVE IT
	SOJG T4,GTASC1		;DO ALLOF THEM
GTASCD:	SETZ T2,		;GET A NULL
	IDPB T2,W1		;TIE OFF STRING
	MOVE T2,W2		;RETURN COUNT
	RETSKP			;AND DONE

	ENDAV.			;END ACVAR
;MORE BYTE MANIPULATION ROUTINES

;SKIP AN IMAGE FIELD

SKPFLD:	GETBYM (MSGCNT,MSGBYP,R)		;GET IMAGE COUNT
	JUMPE T2,RSKP		;IF NO BYTES, DONE
	MOVN T4,T2		;GET NEG OF COUNT
	ADDB T4,MSGCNT		;COMPUTE RESIDUE
	JUMPL T4,R		;IF MESSAGE TOO SMALL, ERROR
	ADJBP T2,MSGBYP		;MODIFY BYTE POINTER
	MOVEM T2,MSGBYP		;AND UPDATE IT
	RETSKP			;DONE

;GET AN EXTENSIBLE FIELD

GETEXT:	SETZB T3,T4		;INIT ACCUMULATOR AND COUNTER
GETEX1:	GETBYM (MSGCNT,MSGBYP,R)		;GET NEXT BYTE
	AOS T4			;GOT ANOTHER ONE
	LSHC T2,-7		;PUT DATA PART IN ACCUMULATOR
	TXZE T2,1		;WAS IT EXTENDED?
	JRST GETEX1		;YES. GET NEXT THEN
	IMULI T4,7		;COMPUTE GOOD BITS IN ACCUMULATOR
	LSHC T2,0(T4)		;PUT FIELD IN T2
	RETSKP			;AND DONE


;MAKE AN EXTENSIBLE FIELD
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T3/ THE VALUE
;RETURNS:	+1
;PRESERVES T1

MAKEXT:	MOVEI T2,177		;GET EXTENSIBLE FIELD MASK
	AND T2,T3		;GET A BYTE'S WORTH
	LSH T3,-7		;ADJUST THE REMAINING QUANTITY
	SKIPE T3		;MORE BYTES TO COME?
	TXO T2,NSPEXT		;YES, PUT IN EXTENSIBLE FLAG BIT
	CALL ONEBYT		;PUT BYTE IN MESSAGE
	JUMPN T3,MAKEXT		;IF MORE, GO DO IT
	RET			;DONE
;ROUTINE USED BY CI AND CC TO PROCESS COMMON FIELDS

	SWAPCD			;SWAPPABLE

CIPSRV:	GETBYM (MSGCNT,MSGBYP,R)		;GET SERVICES
	TXC T2,1
	TRNE T2,363		;MUST BE NORMAL LINK AND NO MSG ACK
	RET			;NO. CAN'T HAVE IT
	LSH T2,-2		;GET FCOPT FIELD
	CAIN T2,3		;A VALID FLOW CONTROL?
	RET			;NO.
	MOVEM T2,MSGW1		;YES. SAVE IT
	GETBYM (MSGCNT,MSGBYP,R)		;GET LINK PRI
	MOVEM T2,MSGLKP		;SAVE IT
	CALL GETTWO		;GET SEGSIZE
	 RET			;BAD
	MOVEM T2,MSGW2		;SAVE IT
	RETSKP			;ALL GOOD
;REQUEST QUEUER ROUTINES
;SEND CONTROL MESSAGE
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T2/ MESSAGE BLOCK
;RETURNS:	+1 ALWAYS

	RESCD

SNDCTL:	SAVET			;SAVE ALL REGISTERS
	ASUBR <SAVLL,SAVMSG>	;SAVE ARGS
	MOVE T3,LLBPCT(T1)	;GET MESSAGE COUNT
	STOR T3,MSCNT,(T2)	;STORE IN THE BLOCK
	TMNE LLLOC,(T1)		;LOCAL?
	 JRST CTLLCL		;YES. GO HANDLE IT
SNDSG0:	CALL NSOUBK		;DO NSP OUTPUT BOOKKEEPING
	LOAD T4,MSMFL,(T2)	;GET MESSAGE TYPE
	TRNN T4,ACKFLM		;IS IT AN ACK?
	IFSKP.
	   MOVEI T4,ACKPST	;YES, GET POSTING ROUTINE
	   CALL SNDRDY		;GET READY FOR DRVIER
	   JRST SNDMSG		;GO
	ENDIF.
	CAIE T4,CNMRFL+CNMDI	;IS IT A DI?
	IFSKP.
	   CALL ONSEGQ		;YES, PUT IT ON RESEND QUEUE
	   MOVEI T4,SEGPST	;GET POSTING ROUTINE
	   CALL SNDRDY		;GET READY FOR DRIVER
	   JRST SNDMSG		;GO
	ENDIF.
	CAIE T4,CNMRFL+CNMCF	;IS IT A CC?
	IFSKP.
	   LOAD T4,LLLKP,(T1)  ;YES, GET NSP VERSION
	   CAIN T4,.NSP31	;NSP 3.1?
	   IFSKP.
	       CALL ONSEGQ	;NO, PUT IT ON RESEND QUEUE
	       MOVEI T4,SEGPST	;GET POSTING ROUTINE
	       CALL SNDRDY	;GET READY FOR DRIVER
	       JRST SNDMSG	;GO
	   ENDIF.
	   MOVEI T4,RELRES	;YES, PHASE II - GET POSTING ROUTINE
	   CALL SNDRDY		;GET READY FOR DRVIER
	   JRST SNDMSG		;GO
	ENDIF.
	LOAD T3,MSCNT,(T2)	;GET BYTE COUNT
	LOAD T1,LLPRT,(T1)	;GET PORT NUMBER
;	HRLI T1,MSGPST		;POSTING ADDRESS
SNDSG1:	HRLI T1,RELRES		;MAKE DRIVER RELEASE THE BLOCK
SNDMSG:	STKVAR <SAVPST,SAVFF>
	MOVEM F,SAVFF		;SAVE F
	MOVE F,T2		;UNIQUE CODE FOR POST
	TMNE MSMS1,(T2)		;SENT THIS MESSAGE ONCE YET?
	TXO T3,1B0		;YES. TELL DRIVER OF THIS THEN
	SETONE MSMS1,(T2)	;SAY SENT IT ONCE
	MOVEI T2,MSHDR(T2)	;GET DATA PORTION OF MESSAGE
	HRLI T2,(<POINT 8,>)	;MAKE A BYTE POINTER
	HLRZM T1,SAVPST		;SAVE POSTING ADDRESS
	CALL DCNMSO		;SEND THE MESSAGE
	 JRST [	MOVE T1,F	;FAILED. PORT MUST BE TURNED OFF.
				;SET UP FOR POST IF ANY
		SKIPE T2,SAVPST	;WANT A POST ON DONE?
		CALL 0(T2)	;YES. DO IT THEN
		JRST .+1]	;AND GO FINISH UP
	MOVE F,SAVFF		;RESTORE F
	RET			;AND DONE

	ENDSV.

;CONNECTION IS TO A TASK ON THIS NODE

CTLLCL:	SETONE MSLCL,(T2)	;REMEMBER IS LOCAL
	SKIPGE T4,NSPLPB	;IS THERE A RUNNING LOOPBACK LINE?
	JRST [STOR T4,LLPRT,(T1);YES, SAY WHICH PORT
	      JRST SNDSG0]	;GIVE "LOCAL MESSAGE" TO DRIVER FOR LOOPBACK
	CALL NSOUBK		;DO NSP BOOKKEEPING
	CALLRET ONMSQ		;AND GO DO IT


;GET ACS READY FOR CALL TO DRVIER
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T2/ MESSAGE ADDRESS
;		T4/ POSTING ROUTINE ADDRESS
;RETURNS +1	T1/ POSTING ROUTINE ADDRESS ,, PORT NUMBER
;		T2/ MESSAGE ADDRESS
;		T3/ BYTE COUNT

SNDRDY:	LOAD T3,MSCNT,(T2)	;GET BYTE COUNT OF MESSAGE
	LOAD T1,LLPRT,(T1)	;GET PORT NUMBER
	HRLI T1,(T4)		;INSERT POSTING ROUTINE
	RET
;VARIOUS QUEUENING ROUTINES USED BY INT, SCHED, AND PROCESS LEVELS

;ROUTINE TO PUT A MESSGE ON NSPTSK'S QUEUE

ONMSGQ:	MOVEI T3,MSGQ		;GET QUEUE HEAD
	CALLRET PUTONQ		;PUT DATA ON

;ROUTINE TO QUEUE UP EXPENDED MESSAGE BLOCKS FROM DTESRV

   REPEAT 0,<			;NOT USED PRESETNLY
MSGPST:	MOVE T2,RMSGQ		;GET OLD HEAD
	MOVEM T1,RMSGQ		;MAKE NEW HEAD
	STOR T2,MSLNK,(T1)	;LINK IN
	RET			;AND DONE
   >				;END OF REPEAT 0

;ROUTINE CALLED FROM INTERRUPT LEVEL TO PUT A MESSAGE ON THE SCHEDULER'S
;QUEUE
;		T2/ DATA ADDRESS

NSPQ::	MOVEI T2,-MSHDR(T2)	;GET POINTER TO HEADER
	MOVE T4,TODCLK		;GET TOD
	MOVEM T4,MSTIM(T2)	;PUT IT IN MESSAGE HEADER
	SKIPE T4,SMSGQ		;QUEUE NOW EMPTY?
	IFSKP.			;
	   HRRM T2,SMSGQ	;YES, MAKE US FIRST
	   HRLM T2,SMSGQ	;AND LAST
	   RET
	ENDIF.
	HLRZS T4		;GET LAST MSG ON QUEUE
	MOVEM T2,MSNXT(T4)	;MAKE LAST MSG POINT AHEAD TO US
	MOVEM T4,MSPRV(T2)	;MAKE US POINT BACK TO IT
	HRLM T2,SMSGQ		;MAKE QUEUE HEAD POINT TO US
	RET
;ROUTINE TO LINK A MESSAGE INTO NSSNTQ (THE TIMER) QUEUE
;
;CALL:	T2/ ADDRESS OF MESSAGE

ONTIMQ:	SAVET
	SKIPE INSKED		;IN SCHEDULER?
	JRST ONTMQ3		;YES
	SKIPN INNSPT		;IN RETRANSMISSION TIMER
	SKIPE INNSPI		; OR INACTIVITY TIMER?
	SKIPA			;YES, THEN ALREADY HAVE THE TREE LOCK
	LLLOCK			;NO, THEN USE TREE LOCK TO PREVENT RACES
ONTMQ3:	SKIPE T4,NSSNTQ		;TIMER QUEUE EMPTY?
	IFSKP.			;YES
	   MOVEM T2,NSSNTQ	;MAKE THIS MSG FIRST ON Q
	   JRST ONTMQ4		;DONE
	ENDIF.
	SETZM T3		;NO, SAY NO PREVIOUS MSG YET
ONTMQ1:	MOVE T1,MSTIM(T4)	;GET TIME STAMP OF NEXT MSG
	CAMG T1,MSTIM(T2)	;OLDER THAN US?
	JRST ONTMQ2		;YES
	SKIPE T3		;NO, ARE WE AT BEGINNING OF QUEUE?
	IFSKP.			;YES
	   MOVEM T2,NSSNTQ	;PUT US AT HEAD OF THE QUEUE
	ELSE.			;NO
	   MOVEM T2,MSNXT(T3)	;LINK US TO
	   MOVEM T3,MSPRV(T2)	; PREVIOUS ENTRY
	ENDIF.
	MOVEM T4,MSNXT(T2)	;LINK US TO
	MOVEM T2,MSPRV(T4)	; NEXT ENTRY
	JRST ONTMQ4		;DONE

ONTMQ2:	SKIPN T1,MSNXT(T4)	;ARE WE AT END OF QUEUE?
	IFSKP.			;NO
	   MOVE T3,T4		;MAKE NEXT PREVIOUS
	   MOVE T4,MSNXT(T4)	;AND GET THE NEXT
	   JRST ONTMQ1		;TRY AGAIN
	ENDIF.
	MOVEM T2,MSNXT(T4)	;YES, PUT US ON
	MOVEM T4,MSPRV(T2)	; END OF QUEUE
ONTMQ4:	SKIPE INSKED		;IN SCHEDULER?
	RET			;YES
	SKIPN INNSPT		;IN RETRANSMISSION TIMER OR
	SKIPE INNSPI		; OR INACTIVITY TIMER?
	SKIPA			;YES, DON'T GIVE UP LOCK HERE
	LLLULK			;NO, GIVE UP TREE LOCK
	RET			;DONE
;ROUTINE TO REMOVE A MESSAGE FROM NSSNTQ (THE TIMER) QUEUE
;
;CALL:	1/ ADDRESS OF MESSAGE

UNQTIM:	SAVET
	ASUBR <MSGADR>		;TEMP STORAGE FOR MESSAGE ADDRESS
	SKIPE INSKED		;IN SHCEDULER?
	JRST UNQTM2		;YES
	SKIPN INNSPT		;IN RETRANSMISSION TIMER
	SKIPE INNSPI		; OR INACTIVITY TIMER?
	SKIPA			;YES, THEN ALREADY HAVE THE TREE LOCK
	LLLOCK			;NO, THEN USE TREE LOCK TO PREVENT RACES
UNQTM2:	MOVE T1,MSGADR		;RETRIEVE THE MESSAGE ADDRESS
	SKIPE T2,MSPRV(T1)	;ARE WE FIRST ON THE QUEUE?
	IFSKP.			;YES
	   SKIPE T3,MSNXT(T1)   ;ARE WE ALSO LAST ON THE QUEUE?
	   IFSKP.		;YES
	      SETZM NSSNTQ  	;RESET THE QUEUE HEADER
	   ELSE.
	      SETZM MSPRV(T3)	;NO, MAKE NEXT THE HEAD
	      SETZM MSNXT(T1)	;NO NEXT (IN CASE MESSAGE IN REQUEUED)
	      MOVEM T3,NSSNTQ	;MAKE QUEUE HEAD POINT TO US
	   ENDIF.
	   JRST UNQTM1		;DONE
	ENDIF.
	SKIPE T3,MSNXT(T1)	;NO, ARE WE LAST ON THE QUEUE?
	IFSKP.			;YES
	   SETZM MSNXT(T2)	;THEN PREVIOUS NO LONGER HAS NEXT
	   SETZM MSPRV(T1)	;WE HAVE NO MORE PREVIOUS (IN CASE OF REQUEUE)
	ELSE.
	   MOVEM T3,MSNXT(T2)	;NO, MAKE PREVIOUS POINT TO NEXT
	   MOVEM T2,MSPRV(T3)	;AND NEXT POINT TO PREVIOUS
	   SETZM MSPRV(T1)	;WE HAVE NO MORE PREVIOUS
	   SETZM MSNXT(T1)	; NOR NEXT (IN CASE OF REQUEUE)
	ENDIF.
UNQTM1:	SKIPE INSKED		;IN SCHEDULER?
	RET			;RET
	SKIPN INNSPT		;IN RETRANSMISSION TIMER OR
	SKIPE INNSPI		; OR INACTIVITY TIMER?
	SKIPA			;YES, DON'T GIVE UP LOCK HERE
	LLLULK			;NO, GIVE UP TREE LOCK
	RET			;DONE
;ROUTINE TO SEND A DATA,LS, OR INT MESSAGE
;ACCEPTS:	T1/ LL BLOCK
;		T2/ MESSAGE BLOCK

SNDSEG::ASUBR <SNLBLK,SNMSG>
	MOVE T3,LLBPCT(T1)	;GET BYTE COUNT
	STOR T3,MSCNT,(T2)	;TO THE MESSAGE
	LOAD T3,LLLNK,(T1)	;GET LINK I.D.
	STOR T3,MSLLA,(T2)	;TO THE MESSAGE
	TMNE LLLOC,(T1)		;LOCAL?
	 JRST SNDLCL		;YES.
LPBSEG:	CALL ONSEGQ		;PUT IT ON THE SEG QUEUE
SNDSE2:	CALL NSOUBK		;DO NSP BOOKKEEPING
	LOAD T3,MSCNT,(T2)	;GET COUNT
	LOAD T1,LLPRT,(T1)	;PORT I.D.
	HRLI T1,SEGPST		;POSTING ADDRESS
	SETONE MSPST,(T2)	;SAY WAITING FOR POST
	CALL SNDMSG		;SEND IT
SNDSE1:	MOVE T1,SNLBLK		;GET BLOCK ADDRESS
	RET			;AND DONE

	ENDAS.

;ROUTINE TO PUT A DATA,LS, OR INT SEGEMENT ON THE SEND Q
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T2/ MESSAGE BLOCK
;RETURNS:	+1

ONSEGQ:	INCR LLQOU,(T1)		;ONE MORE ON Q
	MOVE T3,TODCLK		;GET THE TIME
	MOVEM T3,MSTIM(T2)	;PUT TIME STAMP IN MESSAGE HEADER
	MOVEI T3,LLSEGQ(T1)	;GET HEADER
	LOAD T4,LLLKP,(T1)	;GET NODE'S VERSION
	CAIN T4,.NSP31		;NSP 3.1?
	JRST ONSEG0		;YES
	SKIPN (T3)		;NO, QUEUE CURRENTLY EMPTY?
	CALL ONTIMQ		;YES, TIE IN TO TIMER QUEUE
ONSEG0:	CALLRET PUTONQ		;PUT SEG ON THE Q

;LOCAL ROUTINE TO PUT MESSAGE ON INPUT QUEUE

ONMSQ:	NOSKD1			;NO SCHEDULING
	CALL ONMSGQ		;PUT MESSAGE ON THE QUEUE
	OKSKD1			;AND SCHEDULING
	RET			;AND DONE

;ENTRY USED TO RESEND A NACKED OR TIMED OUT MESSAGE

SNDSE0:	ASUBR <SNLBLK,SNMSG>
	CALLRET LPBSEG		;SEND IT
;SNDSEG CONTINUED...
;ROUTINE TO SEND SEGMENT TO A LOCAL CONNECTION

SNDLCL:	STKVAR <SRCLLB,DESLLB>
	MOVEM T1,SRCLLB		;SAVE THE SOURCE LL BLOCK ADDRESS
	SETONE MSLCL,(T2)	;SAY IS LOCAL
	SKIPGE T4,NSPLPB	;IS THERE A RUNNING LOOPBACK LINE?
	JRST [STOR T4,LLPRT,(T1);YES, SAY WHICH PORT
	      JRST LPBSEG]	;GIVE "LOCAL MESSAGE" TO DRIVER FOR LOOPING
	LOAD T3,MSMFL,(T2)	;GET FLAGS
	TXNE T3,DATFLI		;IS THIS AN INTERRUPT MESSAGE?
	JRST SNDBAD		;YES. GO HANDLE VIA NSPTSK
	LOAD T2,LLLNK,(T1)	;GET OUR I.D.
	LOAD T1,LLHLK,(T1)	;GET I.D. OF OTHER PROCESS
	LLLOCK			;LOCK UP THE TREE
	CALL LLLKUP		;GO FIND ENTRY
	 JRST [	LLLULK		;RELEASE THE TREE
		JRST SNDBAD ]	;NOT THERE
	LLLULK			;RELEASE THE TREE
	MOVEM T1,DESLLB		;SAVE DESTINATION LL BLOCK ADDRESS
	MOVE T2,SNMSG		;GET MESSAGE BLOCK
	NOSKD1			;PROTECT LINK STATE
	JN LLINT,(T1),SNDBA1	;IF INTERNAL LINK, PUT ON BACKGOUND TASK'S QUEUE
	LOAD T3,LLSTA,(T1)	;GET STATE OF THE LINK
	CAIE T3,LLSRUN		;RUNNING?
	JRST SNDBA1		;NO.
	MOVE T1,SRCLLB		;RETRIEVE SOURCE LL BLOCK ADDRESS
	CALL NSOUBK		;DO NSP OUTPUT BOOKKEEPING
	MOVE T1,DESLLB		;RETRIEVE DESTINATION LL BLOCK ADDRESS
	CALL NSINBK		;DO NSP INPUT BOOKKEEPING
	CALL ONRAWQ		;GO PUT ON THE QUEUE
	OKSKD1			;ALL DONE
	JRST SNDSE1		;GO Q IT UP ON SEG Q

;ERROR ROUTINES

SNDBA1:	OKSKD1
SNDBAD:	MOVE T2,SNMSG		;GET MESSAGE ADDRESS
	CALL ONMSQ		;PUT DATA MESSAGE ON NSPTSK'S Q
	JRST SNDSE1		;AND DONE FOR NOW
;ROUTINE TO HANDLE ACK OR NACK FOR A SUBCHANNEL.
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T2/ ACK OR NACK #
;		T3/ SUBCHANNEL OF THE ACK/NACK
;RETURNS:	+1 ALWAYS. ALL REGS PRESERVED

ACKCHN:	TMNE LLLOC,(T1)		;LOCAL?
	 JRST [SKIPL NSPLPB	;YES, IS THERE A RUNNING LOOPBACK LINE?
	       JRST ACKDON	;NO
	       JRST .+1]	;YES, MESSAGE MUST BE QUEUED AS REMOTE
	SAVET			;SAVE ALL REGS
	ACVAR <W1,W2,W3>	;GET WORK REGS
	STKVAR <LLBLK,ACKNO,ACKCHL,LNKADR>
	MOVEM T1,LLBLK		;SAVE LL BLOCK
	MOVEM T3,ACKCHL		;SAVE CHANNEL
	MOVEM T2,ACKNO
	TRZN T2,ACKBIT		;IS IT A NACK?
	IFSKP.			;YES
	   CALL ACKCHN		;DO THE ACK PROCESSING
	   LOAD T3,LLLKP,(T1)	;GET NODE'S VERSION
	   CAIE T3,.NSP31	;NSP 3.1?
	   RET			;NO
	   JRST DONACK		;YES, PHASE II LINK, SEE IF RESENDS ARE NEEDED
	ENDIF.
	ANDI T2,7777		;GET SEG NUMBER ONLY
	MOVEM T2,ACKNO		;SAVE ACK NUMBER
ACKLP1:	SKIPN W1,LLSEGQ(T1)	;HAVE ANY SEGS?
	JRST ACKDON		;NO. ALL DONE THEN
	SETZ W2,		;NO PREVIOUS
	HRRZS W1		;GET TOP SEG
; ..
;ACKCHN CONTINUED...
;LOOP TO PROCESS QUEUE

ACKLOP:	LOAD T3,MSTOM,(W1)	;GET TYPE
	CAME T3,ACKCHL		;IS THIS THE PROPER SUBCHANLEL?
	JRST ACKNXT		;NO. GO ON
	LOAD T3,MSSEG,(W1)	;GET SEGMENT #
	SUB T3,ACKNO		;COMPUTE "AGE"
	ANDI T3,7777		;MOD 4096
	SKIPE T3		;IS IT THE VERY ONE WE ARE DOING?
	CAILE T3,MAXDIF		;NO. IS IT ACKABLE ANYWAY?
	SKIPA			;YES. ACK IT THEN
	JRST ACKNXT		;NO.
	PUSH P,T2		;TEMPORARILY STASH
	PUSH P,T3		; SOME ACS
	MOVE T2,TODCLK		;GET CURRENT TIME
	SUB T2,MSTIM(W1)	;CALC ROUND TRIP TIME OF MESSAGE
	MOVE T4,LLTIMO(T1)	;GET OLD TIME
	SUB T2,T4		;GET DIFFERENCE
	IDIV T2,NSLDWS		;WEIGHT THE DIFFERENCE
	ADD T2,T4		;MAKE THE NEW TIME
	CAIG T2,^D1000		;IS IT REAL SMALL?
	MOVEI T2,^D1000		;YES, IMPOSE THE MINIMUM
	MOVEM T2,LLTIMO(T1)	;SAVE THE NEW TIME OUT VALUE
	MOVEI T4,LLSEGQ(T1)	;THE Q ADDRESS
	DMOVE T2,W1		;GET ARGUMENTS IN PROPER ACS FOR CALL
	CALL UNQSEG		;REMOVE SEGEMENT
	POP P,T3		;RETRIEVE THE
	POP P,T2		; STASHED ACS
	EXCH T1,W1		;GET BACK MESSAGE ADDRESS
	CALL RELRES		;FREE IT
	MOVE T1,W1
	JUMPE W2,ACKLP1		;IF AT THE HEAD, START OVER
	LOAD W1,MSLNK,(W2)	;GET THE ONE TO DO NEXT
	JUMPN W1,ACKLOP		;DO IT IF ONE THERE
	JRST ACKDON		;ALL DONE

ACKNXT:	MOVE W2,W1		;SAVE PREVIOUS
	LOAD W1,MSLNK,(W1)	;GET NEXT
	JUMPN W1,ACKLOP		;DO ALL
ACKDON:	CALL CHKLLT		;CHECK FOR TTY ON THIS LL
;	JN LLINT,(T1),[
;		CALL INTOUT	;IF INTERNAL LINK SEND ANY OUTPUT STILL LEFT
;		 JFCL		;IGNORE FAILURE HERE
;		JRST .+1]	;CONTINUE
	RET			;AND DONE
;ROUTINE TO PROCESS A NACK
;	T1/ BLOCK ADDRESS
;	NACK NUMBER IN THE STKVAR "ACKNO"

DONACK:	AOS T2,ACKNO		;GET THE ACK #
	ANDI T2,7777		;AND GET MODULO 4096
	MOVEM T2,ACKNO		;SAVE IT
	SETZ W2,		;NO HEAD
DONAC2:	SKIPN W1,LLSEGQ(T1)	;HAVE ANY SEGS?
	RET			;NO. ALL DONE
	HRRZS W1		;GET FIRST MESSAGE
DONAC1:	LOAD T3,MSTOM,(W1)	;GET MESSAGE TYPE
	CAME T3,ACKCHL		;THE CORRECT CHANNEL?
	JRST DONNXT		;NO
	LOAD T3,MSSEG,(W1)	;GET SEG #
	SUB T3,ACKNO		;COMPUTE "AGE"
	ANDI T3,7777		;""
	CAILE T3,MAXDIF		;IS IT ONE BEING NACKED?
	JRST DONNXT		;NO
	AOS NAKCNT		;COUNT THIS SEGMENT
	MOVE T3,ACKCHL		;YES. GET CHANNEL
	CAIE T3,MSDAT		;DATA?
	JRST DONRES		;NO. RESEND NOW
	LOAD T3,LLMFC,(T1)	;GET FLOW CONTROL TYPE
	CAIN T3,1		;SEGMENT?
	JRST [	INCR LLMSM,(T1)	;YES. ACCOUNT FOR THE MACK
		JRST .+1]
	JN LLBRP,(T1),[
		CAIE T3,2	;MESSAGE FLOW CONTROL?
		JRST DONRQ	;NO. GO ARRANGE FOR REQUEUE
		LOAD T3,MSMFL,(W1) ;YES. GET MESSAGE FLAGS
		JXE T3,DATEOM,DONRQ ;IS THIS THE EOM?
		INCR LLMSM,(T1)	;YES. INCREMENT REQUEST COUNT
		JRST DONRQ]	;AND REQUEUE IT
	CAIE T3,1		;YES. SEGMENT?
	JRST DONRES		;NO. RESEND NOW
	LOAD T3,LLMSM,(T1)	;GET SEG COUNT TO SEND
	SKIPE T3		;ANY THERE?
	TXNE T3,200		;AND IS IT POSITIVE?
	JRST DONRQ		;NO.
	DECR LLMSM,(T1)		;YES. COUNT DOWN
DONRES:	PUSH P,T2		; TEMPORARILY STASH
	PUSH P,T3		; ACS
	MOVEI T4,LLSEGQ(T1)	;GET THE SEG Q HEAD
	DMOVE T2,W1		;GET ARGUMENTS IN PROPER ACS FOR CALL
	CALL UNQSEG		;REMOVE SEG FROM QUEUE
	POP P,T3		;RETRIEVE
	POP P,T2		; STASHED ACS
	MOVE T2,W1		;GET SEG
	SETZRO MSTRY,(T2)	;RESET THE TIME OUT RETRY COUNT
	CALL SNDSE0		;RESEND IT NOW
DONNXT:	MOVE W2,W1		;NEW HEAD
	LOAD W1,MSLNK,(W2)	;GET NEXT
	JUMPN W1,DONAC1		;IF MORE, DO IT
	RET			;DONE

DONRQ:	SETONE MSNAK,(W1)	;REMEMBER IS NAKED
	INCR LLQUN,(T1)		;AND ACCOUNT FOR IT
	JRST DONNXT		;AND CONTINUE DOWN Q

	ENDAV.			;END ACVAR
;ROUTINE TO TAKE A SEGMENT OFF OF A SEGMENT Q
;
;ACCEPTS:	T1/ ADDRESS OF LL BLOCK
;		T2/ ADDRESS OF MESSAGE
;		T3/ ADDRESS OF PREVIOUS MESSAGE ON SEGMENT QUEUE
;		T4/ ADDRESS OF LINK'S SEGMENT QUEUE HEAD
;RETURNS:	+1

UNQSEG:	SAVET
	ACVAR <LLB>		;AC FOR LL BLOCK ADDRESS
	MOVEM T1,LLB		;SAVE IT
	DECR LLQOU,(LLB)	;ONE LESS ON SEG Q
	LOAD T1,MSLNK,(T2)	;GET ADDRESS OF NEXT SEG
	JUMPE T3,UNQSG1		;IF AT HEAD OF QUEUE, NO BACKWARD LINKING
	STOR T1,MSLNK,(T3)	;MAKE PREVIOUS POINT TO NEXT
	SKIPN T1		;IS THERE A NEXT?
	HRLM T3,(T4)		;NO, MAKE THIS TAIL OF QUEUE
	RET
UNQSG1:	HRRM T1,(T4)		;SET NEXT SEGMENT TO BE QUEUE HEAD
	EXCH T1,T2		;T1/ SEG TO BE ELIMINATED;  T2/ NEXT SEG
	LOAD T3,LLLKP,(LLB)	;GET NODE'S VERSION
	CAIE T3,.NSP31		;NSP 3.1?
	CALL UNQTIM		;NO, REMOVE MESSAGE FROM NSSNTQ QUEUE
	SKIPE T2		;IS THERE A NEXT?
	IFSKP.			;NO
	   SETZM (T4)		;RESET QUEUE HEADER
	   RET			;DONE
	ENDIF.
	CAIE T3,.NSP31		;NSP 3.1?
	CALL ONTIMQ		;NO, GO PUT IT ON NSSNTQ
	RET

	ENDAV.
;ROUTINE TO PUT A DATA MESSAGE ON A SEGMENT Q
;	T2/ THE MESSAGE
;	T3/ THE QUEUE ADDRESS
;PRESERVES T1,T2,T4

PUTONQ:	SAVEAC <T4>
	SKIPN T4,0(T3)		;HAVE A QUEUE?
	JRST [	HRRM T2,0(T3)	;NO MAKE ONE
		HRLM T2,0(T3)
		JRST PUTOND]	;DONE
	HLRZS T4		;GET TAIL
	STOR T2,MSLNK,(T4)	;LINK THIS IN
	HRLM T2,0(T3)		;AND MAKE IT THE TAIL
PUTOND:	SETZRO MSLNK,(T2)	;TIE IT OFF
	RET			;AND DONE
;ROUTINE TO RESEND NACK'ED SEGMENTS
;ACCEPTS:	T1/ BLOCK ADDRESS
; BLOCK MUST BE LOCKED

RESEND:	JE LLQUN,(T1),R		;ANY NAKED SEGS?
	JN LLBRP,(T1),R		;YES. IS FLOW ON?
	JE LLMFC,(T1),RSEND0	;IF NO FLOW CONTROL, GO RESEND NOW
	LOAD T3,LLMSM,(T1)	;GET COUNT
	SKIPE T3		;IF ZERO
	TXNE T3,200		;OR IF NEG
	RET			;CAN'T RESEND
RSEND0:	HRRZ T2,LLSEGQ(T1)	;GET HEAD OF Q
RSEND1:	SKIPE T2		;ANYTHING THERE?
	IFSKP.			;
	   BUG (NSPRSN)		;NO, SHOULDN'T HAPPEN!  TELL THE WORLD
	   RET			;GO AWAY
	ENDIF.
	TMNN MSNAK,(T2)		;IS THIS A NAKED SEG?
	JRST [	LOAD T2,MSLNK,(T2) ;NO. GET NEXT
		JRST RSEND1]	;AND PROCEED
	DECR LLQUN,(T1)		;ONE LESS NAKED SEG
	LOAD T3,LLMFC,(T1)	;GET TYPE OF FLOW CONTROL
	JUMPE T3,RSEND3		;IF NO FLOW CONTROL, SEND IT NOW
	CAIE T3,2		;MESSAGE FLOW CONTROL?
	JRST RSEND2		;NO. SEND IT NOW THEN
	LOAD T3,MSMFL,(T2)	;GET MESSAGE FLAGS
	JXE T3,DATEOM,RSEND3	;IS THIS EOM?
RSEND2:	DECR LLMSM,(T1)		;YES. DOWNCOUNT REQUEST COUNT
RSEND3:	SETZRO MSNAK,(T2)	;NO LONGER A NACKED SEG
	CALL SNDSE0		;AND RESEND IT
	JRST RESEND		;AND DO IT AGAIN
;ROUTINE TO FLUSH ALL QUEUES FOR A LL
;FLUSHES: SEGQ,RSEGQ,LLOMSG,LLOMSG
;	T1/ LL BLOCK  - MUST BE LOCKED
;RETURNS +1 ALWAYS

FLUSH::	SETZRO <LLQUN,LLQOU>,(T1) ;CLEAR COUNTS
	MOVEI T2,LLOMSG(T1)	;GET ORDERED QUEUE
	CALL PRUNE		;KILL IT
	MOVEI T2,LLMSI(T1)	;INT MESSAGES
	CALL PRUNE		;KILL THIS AS WELL
	SKIPN T2,LLSEGQ(T1)	;GET FIRST MSG ON LL'S QUEUE
	RET			;QUEUE IS EMPTY, DONE
	LOAD T3,LLLKP,(T1)	;GET NODE'S VERSION
	CAIN T3,.NSP31		;NSP 3.1?
	JRST FLUSH1		;YES, THEN NOT ON TIMER'S Q
	PUSH P,T1		;SAVE ADDRESS OF LL BLOCK
	HRRZ T1,T2		;GET ADDRESS OF MESSAGE
	CALL UNQTIM		;TAKE MSG OF TIMER'S QUEUE
	POP P,T1		;RETRIEVE ADDRESS OF LL BLOCK
FLUSH1:	MOVEI T2,LLSEGQ(T1)	;GET SENT Q
	CALLRET PRUNE		;GET RID OF THEM

;WORKER ROUTINE TO FLUSH A LINK Q

PRUNE:	SAVET			;SAVE ALL REGS
	HRRZ T1,0(T2)		;GET HEAD
	SETZM 0(T2)		;CLEAR Q
PRUNE1:	JUMPE T1,R		;IF AT THE END, DONE
	LOAD T2,MSLNK,(T1)	;GET NEXT
	PUSH P,T2		;SAVE IT
	JN MSPST,(T1),CHKPST	;IF POSTING ON, GO CHECK OUT MESSAGE
PRUNE2:	CALL RELRES		;RELEASE NODE
PRUNE3:	POP P,T1		;GET BACK NEXT
	JRST PRUNE1		;AND DO IT

;MESSAGE NEEDS TO BE PRUNED BUT POSTING IS STILL OUTSTANDING.

CHKPST:	PIOFF			;OWN MACHINE WHILE CHECKING MESSAGE
	JE MSPST,(T1),CHKPS1	;IF NO LONGER NEEDED, GO ON
	SETONE MSRLS,(T1)	;IS STILL NEEDED. REQUEST RELEASE WHENEVER
	PION			;ALLOW INTS AGAIN
	JRST PRUNE3		;DON'T RELEASE IT
CHKPS1:	PION			;ALLOW INTS
	JRST PRUNE2		;AND RELEASE IT
;ROUTINE TO SEND AN ACK MESSAGE.
;	T1/ LL BLOCK
;	T2/ SEGMENT # TO ACK
;	T3/ SUBCHANNEL TO ACK
;RETURNS:	+1  FAILED
;		+2  SUCCESS
;ALL REGS PRESERVED

SNDACK:	ASUBR <LLBLK,ACKNO,ACKTYP>
NSBP09:	TMNE LLLOC,(T1)		;LOCAL?
	 JRST [	SKIPGE NSPLPB	;YES, IS THERE A RUNNING LOOPBACK LINE?
	        JRST ACKRMT	;YES, GIVE MESSAGE TO DRIVER
	        JE LLCIL,(T1),RSKP ;NO, DONE IF NOT CONNECTED TO INTERNAL LINK
;		CALL SKDOUT	;INTERNAL LINK, SCHEDULE OUTPUT
		RETSKP ]	;DONE, RETURN
	JRST ACKRMT		;NEED TO SEND A MESSAGE

;ROUTINE TO ACK THE LS/INT CHANNEL

ACKLI:	LOAD T2,LLIIN,(T1)	;GET SEG TO ACK/NAK
	TMNN LLALS,(T1)		;NEED AN ACK?
	TXO T2,ACKBIT		;NO, TURN ON NAK BIT IN MESSAGE
	MOVEI T3,MSLSI		;THE CHANNEL I.D.
	CALL SNDACK		;SEND ACK
	 RET			;FAILED
	SETZRO <LLNLS,LLALS>,(T1)  ;DON'T NEED ACK OR NACK ANYMORE
	CALL CHKLLT		;CHECK FOR NVT LINK
	RETSKP			;OK
;SNDACK CONTINUED.....
;SEND ACK TO REMOTE NODE.

ACKRMT:	STKVAR <MSGBL>		;PLACE TO SAVE MESSAGE BLOCK
	MOVEI T3,AKLSTL-1	;GET LENGTH OF ACK LIST
ACKRM1:	SKIPE T2,ACKLST(T3)	;GET THE ENTRY
	IFSKP.			;NONE THERE
	   SOJGE T3,ACKRM1	;END OF LIST?
	   CALLRET TIMWAT	;YES, RETURN TEST ROUTINE
	ENDIF.
	JN MSACK,(T2),[SOJGE T3,ACKRM1  ;IF BUFFER IN USE, ARE THERE MORE?
		       CALLRET TIMWAT]	;NO, RETURN TEST ROUTINE
	SETONE MSACK,(T2)	;BLOCK NOW BEING USED
	MOVEM T2,MSGBL		;SAVE THE BUFFER ADDRESS
	MOVE T1,LLBLK		;GET BACK LL BLOCK ADDRESS
	SETZM LLBPCT(T1)	;INIT MESSAGE COUNT
	ADDI T2,MSHDR		;GET TO DATA PART
	HRLI T2,(<POINT 8,>)
	MOVEM T2,LLBPTR(T1)	;INIT POINTER
	MOVEI T2,ACKFLM		;BASIC ACK MESSAGE
	MOVE T3,ACKTYP		;GET SUBCHANNEL
	CAIN T3,MSLSI		;LS/INT SUBCHANNEL?
	ADDI T2,ACKLSI		;YES.
	MOVE T3,MSGBL		;RETRIEVE MESSAGE ADDRESS
	STOR T2,MSMFL,(T3)	;SAVE MESSAGE FLAGS IN MESSAGE HEADER
	CALL RTHDCI		;PUT ON ROUTING HEADER AND FLAGS
	CALL PUTLLA		;PUT IN LL ADDRESSES
	MOVE T2,ACKNO		;GET SEG TO ACK
	TXO T2,ACKIND		;SET ACK INDICATOR
	CALL TWOBYT		;PUT IT IN
	MOVE T2,MSGBL		;GET MESSAGE
REPEAT 0,<
	HRRZ T3,LLBPTR(T1)	;GET BYTE PTR
	CAIL T3,0(T2)		;WITHIN RANGE OF MSG BLOCK?
	CAILE T3,ACKLEN+MSHDR(T2)
	JSR BUGHLT
>;END REPEAT 0
	CALL SNDCTL		;SEND IT
	RETSKP			;AND DONE
;ROUTINE TO BUILD AND SEND A NODE INIT
;	T1/ PORT I.D.

NODINI::TRVAR <<LLDUM,LKSIZE>,NODMSG,NODPRT>
	MOVEM T1,NODPRT		;SAVE PORT I.D.
	MOVEI T1,NDISIZ+MSHDR	;REQUIRES BLOCK SIZE
	CALL GETRES		;GET A BLOCK
	 RETBAD			;COULDN'T
	MOVEM T1,NODMSG		;SAVE BLOCK
	MOVEI T2,MSHDR(T1)	;POINT TO DATA PART
	HRLI T2,(<POINT 8,>)
	MOVEI T1,LLDUM		;DUMMY LL BLOCK
	SETZM LLBPCT(T1)	;INIT COUNT
	MOVEM T2,LLBPTR(T1)	;SET UP BYTE POINTER
	MOVEI T2,CNMRFL+NDIFLG	;MESSAGE FLAGS
	CALL ONEBYT
	MOVEI T2,STRTYP		;NOD INIT MESSAGE
	CALL ONEBYT
	MOVE T3,OURNUM		;GET LOCAL NUMBER
	CALL MAKEXT		;PUT IT IN MESSAGE
	MOVEI T3,OURNAM		;OUR NAME
	CALL ASCIIZ		;PUT IT IN
	MOVEI T2,OURCAP		;SUPPORTED CAPS
	CALL ONEBYT
	MOVEI T2,OURREQ		;REQUIRED CAPS
	CALL ONEBYT
	MOVEI T2,BLKSIZ		;GET OUR DLL BLOCK SIZE
	CALL TWOBYT
	MOVE T2,SEGSZ		;OUR NSP SEGMENT SIZE
	CALL TWOBYT
	MOVEI T2,MAXLNK		;MAX LINKS
	CALL TWOBYT
	MOVEI T2,ROUVER		;ROUTING VERSION
	CALL ONEBYT
	MOVEI T2,ROUECO		;ROUTING ECO LEVEL
	CALL ONEBYT
	MOVEI T2,ROUCST		;CUSTOMER MODS
	CALL ONEBYT
	MOVEI T2,COMVER		;NSP VERSION
	CALL ONEBYT
	MOVEI T2,COMECO		;NSP ECO LEVEL
	CALL ONEBYT
	MOVEI T2,COMCST		;CUST MODS TO NSP
	CALL ONEBYT
	SETZ T2,		;NO TEXT YET
	CALL ONEBYT
	MOVE T2,NODMSG		;MESSAGE BLOCK
	MOVE T3,NODPRT		;GET PORT I.D.
	STOR T3,LLPRT,(T1)	;SAVE IN LL BLOCK
	MOVE T3,LLBPCT(T1)	;COUNT
	MOVE T1,NODPRT		;GET PORT NUMBER
	CALL SNDSG1		;SEND NODE INIT MESSAGE
	MOVE T1,NODPRT		;GET PORT NUMBER AGAIN
	SETONE INISNT,MCBDTE(T1) ;SAY NOTE INIT MSG SENT
	JE REQVER,MCBDTE(T1),RSKP ;DONE IF NO VERIFICATION MSG NEEDED
	CALL NODVER		;SEND VERIFICATION MSG
	MOVE T1,NODPRT		;RESTORE PORT ID
	SETZRO REQVER,MCBDTE(T1) ;NOTE VERIFICATION NO LONGER NEEDED
	RETSKP			;DONE, RETURN
;NODVER - ROUTINE TO ASSEMBLE AND SEND A NODE VERIFICATION MESSAGE
;
;ACCEPTS IN T1/	PORT ID
;		CALL NODVER
;RETURNS: +1 ALWAYS

NODVER:	TRVAR <<LLDUM,LKSIZE>,NODMSG,NODPRT>
	MOVEM T1,NODPRT		;SAVE PORT I.D.

; INITIALIZE MESSAGE BLOCK

	MOVEI T1,NDISIZ+MSHDR	;REQUIRES BLOCK SIZE
	CALL GETRES		;GET A BLOCK
	 RETBAD			;COULDN'T
	MOVEM T1,NODMSG		;SAVE BLOCK
	MOVEI T2,MSHDR(T1)	;POINT TO DATA PART
	HRLI T2,(<POINT 8,>)
	MOVEI T1,LLDUM		;DUMMY LL BLOCK
	SETZM LLBPCT(T1)	;INIT COUNT
	MOVEM T2,LLBPTR(T1)	;SET UP BYTE POINTER

; ASSEMBLE MESSAGE FLAGS AND STARTTYPE FIELDS

	MOVEI T2,CNMRFL+NDIFLG	;MESSAGE FLAGS
	CALL ONEBYT
	MOVEI T2,VERTYP		;NOD VERIFICATION MESSAGE
	CALL ONEBYT

; ADD PASSWORD TO MESSAGE

	MOVSI T4,-10		;8 BYTES
	MOVE T3,[POINT 7,[ASCII/DECNET20/]]
NDVER1:	ILDB T2,T3		;GET NEXT BYTE
	CALL ONEBYT		;ADD TO MESSAGE
	AOBJN T4,NDVER1		;DO ALL 8 BYTES

; SEND THE MESSAGE

	MOVE T2,NODMSG		;MESSAGE BLOCK
	MOVE T3,NODPRT		;GET PORT I.D.
	STOR T3,LLPRT,(T1)	;SAVE IN LL BLOCK
	MOVE T3,LLBPCT(T1)	;COUNT
	MOVE T1,NODPRT		;GET PORT NUMBER AGAIN
	CALLRET SNDSG1		;SEND IT
;ROUTINE TO SEND AN LS MESSAGE

;ACCEPTS:
;	T1/ LL BLOCK ADDRESS
;	T2/ COUNT OF SEGS TO REQUEST
;	T3/ SUBCHANNEL

;	CALL SNDLS

;RETURNS +1: FAILURE
;		T1/ SCHEDULER TEST WORD
;	 +2: SUCCESS
;		T1/ LL BLOCK ADDRESS (UNCHANGED)

SNDLS::	ASUBR <SNDLBL,SNDLCT,SNDLTP,SNDLMS>
	TMNE LLLOC,(T1)		;LOCAL?
	 JRST [SKIPL NSPLPB	;YES, IS THERE A RUNNING LOOPBACK LINE?
	       JRST SNDLSL	;NO
	       JRST .+1]	;YES, MESSAGE MUST GO TO DRIVER
	LOAD T2,LLQOU,(T1)	;GET SEGS IN QUEUER
	LOAD T3,LLMQO,(T1)	;GET MAXIMUM OUTPUT QUEUE LENGTH
	CAILE T2,1(T3)		;ROOM FOR THIS ONE?
	JRST [	MOVEI T2,CHKQTA	;NO. MUST WAIT UNTIL THERE IS
		CALLRET MAKTST]	;""
	MOVEI T1,MSHDR+LSLEN	;GET FREE SPACE
	CALL GETRES		;GET SOME
	 JRST TIMWAT		;NONE.
	MOVEM T1,SNDLMS		;SAVE BLOCK ADDRESS
	MOVEI T2,MSHDR(T1)	;POINT TO DATA PORTION
	HRLI T2,(<POINT 8,>)
	MOVE T1,SNDLBL		;GET BACK LL BLOCK
	MOVEM T2,LLBPTR(T1)
	SETZM LLBPCT(T1)
	MOVEI T2,DATFLI		;GET FLAGS
	CALL RTHDCI		;PUT ON ROUTE HEADER AND FLAGS
	CALL PUTLLA		;PUT IN ADDRESSES
	TMNE LLALS,(T1)		;THIS LINK NEED AN ACK?
	CALL MAKLSA		;YES, PUT IT IN
	LOAD T2,LLISN,(T1)	;GET SEG #
	AOS T2			;NEXT ONE
	ANDI T2,SEGMSK
	STOR T2,LLISN,(T1)
	MOVE T4,SNDLMS		;GET MESSAGE ADDRESS
	STOR T2,MSSEG,(T4)	;SAVE SEG #
	STOR T1,MSLLA,(T4)	;SAVE LINK ADDRESS
	MOVEI T3,MSLSI		;SAY THIS IS A LS MSG
	STOR T3,MSTOM,(T4)	;""
	MOVEI T3,DATFLI		;GET LS MESSAGE TYPE
	STOR T3,MSMFL,(T4)	;PUT IT IN HEADER OF MESSAGE
	CALL TWOBYT		;PUT IN SEG #
	SETZM T2		;ASSUME DATA CHANNEL
	MOVE T3,SNDLTP		;GET SUBCHANNEL
	CAIE T3,MSDAT		;DATA?
	MOVEI T2,4		;NO. LS/INT
	CALL ONEBYT
	MOVE T2,SNDLCT		;GET COUNT
	CALL ONEBYT
	MOVE T2,SNDLMS		;GET MESSAGE
	CALL SNDSEG		;SEND THE DATA
	RETSKP			;AND DONE


;MAKE THE ACKNUM (PIGGYBACKED ACK) FIELD IN A LS MESSAGE
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;RETURNS:	+1
;PRESERVES T1

MAKLSA:	LOAD T2,LLIIN,(T1)	;GET LAST LS MESSAGE RECEIVED
	TXO T2,ACKIND		;PUT IN ACKNUM INDICATOR
	CALL TWOBYT		;PUT ACKNUM FIELD IN MESSAGE
	SETZRO <LLALS,LLNLS>,(T1)  ;CLEAR THE "NEED TO ACK/NACK" FLAGS
	CALL CHKLLT		;CHECK FOR NVT LINK
	RET
;SNDLS CONTINUED...
;SEND ON A LOCAL CONNECTION

SNDLSL:	SAVEAC <T1>		;SAVE LL BLOCK
	SETOM T2		;ANY MATCH IS OKAY
	LOAD T1,LLHLK,(T1)	;GET OTHER ADDRESS
	LLLOCK
	CALL LLLKUP		;GET BLOCK ADDRESS
	 JRST [	LLLULK		;?
		RETSKP]		;OTHER ONE WENT AWAY
	MOVE T2,SNDLCT		;GET COUNT
	MOVE T3,SNDLTP		;GET SUBCHANNEL
	NOSKD1
	CAIE T3,MSDAT		;DATA
	JRST [	OPSTRM <ADDM T2,>,LLMIC,(T1) ;NO
		JRST SNDLS1]	;GO WRAP UP
	OPSTRM <ADDM T2,>,LLMSM,(T1) ;YES
SNDLS1:	CALL CHKLLT		;CHECK FOR TTY ON THIS LL
	OKSKD1
	LLLULK			;FREE TREE
	JE LLINT,(T1),RSKP	;SENDER OF LS CONNECTED TO AN INTERNAL LINK ?
;	CALL SKDOUT		;YES, NOTE CAN SEND MORE NOW
	RETSKP			;DONE
;ROUTINES CALLED FROM INT LEVEL TO GET AND QUEUE UP BUFFERS

;GET A BUFFER
;	T1/ PORT # (E.G. DTE#)
;	T2/ # OF BYTES REQUIRED
;RETURNS:
;	+1 COULDN'T GET BLOCK
;	+2 T1=BLOCK ADDRESS.

NSPSPC::ASUBR <PRTNO,PRTCNT>
	MOVEI T3,.RESNP		;GET DECNET POOL NUMBER
	MOVE T3,RESUTB(T3)	;GET NUMBER OF BLOCKS LEFT
	CAIG T3,RESHLD		;LOW ON SPACE?
	RETBAD			;YES, DON'T TAKE THIS MESSAGE NOW
	MOVEI T1,MSHDR*4+3(T2)	;GET # OF BYTES
	LSH T1,-2		;CONVERT TO WORDS
	HRLI T1,.RESP1		;PRIORITY 1
	MOVE T2,[RS%SE0+.RESNP]	;FROM THE NET POOL
	CALL ASGRES		;GET THE SPACE
	 RETBAD			;COULDN'T
	MOVE T2,PRTNO		;GET PORT I.D.
	STOR T2,MSPRT,(T1)	;SAVE IT
	MOVE T2,PRTCNT		;GET COUNT OF BYTES IN MESSAGE
	STOR T2,MSCNT,(T1)	;SAVE IT
	ADDI T1,MSHDR		;POINT TO DATA PORTION
	RETSKP			;AND RETURN WITH BLOCK
SUBTTL	NSP Background Task - Output on Internal Links

;OUTSND - ROUTINE TO CHECK "OUTPUT REMAINING" QUEUE AND SEND ANY REMAINING DATA
;
;	  CALLED PERIODICALLY FROM NSP BACKGROUND TASK DISPATCHER (NSPTSK)

REPEAT 0,<
	SWAPCD

OUTSND:	SAVEPQ
	SETZM OUTTIM		;RESET TIME AT WHICH TASK SHOULD AWAKEN
	LOCK OUTLOK		;LOCK THE QUEUE WHILE PROCESSING ENTRIES
	HRRZ Q1,OUTQUE		;GET ADR OF FIRST LINK BLOCK TO PROCESS
	MOVEI Q2,0		;INITIALIZE "PREVIOUS BLOCK" ADDRESS

; LOCK THE LOGICAL LINK BLOCK AND SEND REMAINING OUTPUT

OUTCK0:	JUMPE Q1,[UNLOCK OUTLOK	;IF END OF QUEUE, UNLOCK THE QUEUE
		  RET]		; AND RETURN
	MOVE T1,Q1		;GET ADR OF CURRENT LOGICAL LINK BLOCK
	CALL BLKLLK		;GO LOCK THE LOGICAL LINK
	 JRST [	CALL SKDOUT	;FAILED, SCHEDULE OUTPUT FOR LATER
		MOVE Q2,Q1	;MAKE PREVIOUS BLOCK THE CURRENT
		LOAD Q1,LLOUT,(Q1) ;MAKE CURRENT BLOCK THE NEXT ONE
		JRST OUTCK0 ]	;GO DO OUTPUT FOR NEXT LOGICAL LINK
	MOVE T1,Q1		;GET ADR OF CURRENT LOGICAL LINK BLOCK
	CALL INTOUT		;DO REMAINING OUTPUT FOR THIS LINK
	 JRST [	CALL SKDOUT	;FAILED, SCHEDULE OUTPUT FOR LATER
		JRST OUTCK1 ]	;GO DO OUTPUT FOR NEXT LOGICAL LINK
	JN LLOCT,(Q1),[	CALL SKDOUT  ;IF MORE OUTPUT, SCHEDULE FOR LATER
			JRST OUTCK1] ;GO HANDLE NEXT BLOCK ON QUEUE

; ALL REMAINING OUTPUT SENT, REMOVE THE BLOCK FROM THE QUEUE

	SETZRO LLQUE,(Q1)	;NOTE BLOCK NO LONGER ON QUEUE
	HLRZ T4,OUTQUE		;GET POINTER TO TAIL OF QUEUE
	CAMN T4,Q1		;PROCESSING TAIL OF QUEUE ?
	HRLM Q2,OUTQUE		;YES, SAVE PREVIOUS BLOCK AS NEW TAIL
	LOAD T4,LLOUT,(Q1)	;GET ADDRESS OF NEXT BLOCK ON QUEUE
	SETZRO LLOUT,(Q1)	;CLEAR ADR OF NEXT BLOCK ON QUEUE
	SKIPN Q2		;PROCESSING HEAD OF QUEUE ?
	JRST [	HRRM T4,OUTQUE	;YES, SAVE NEXT BLOCK AS NEW HEAD
		JRST OUTCK1 ]	; AND GO DO OUTPUT FOR NEXT LOGICAL LINK
	STOR T4,LLOUT,(Q2)	;NO, SAVE ADR OF NEXT BLOCK IN PREVIOUS

OUTCK1:	MOVE Q2,Q1		;MAKE CURRENT BLOCK THE PREVIOUS
	MOVE T1,Q1		;GET ADDRESS OF CURRENT LINK BLOCK
	LOAD Q1,LLOUT,(T1)	;GET ADDRESS OF NEXT BLOCK ON QUEUE
	CALL BLKULK		;UNLOCK THE CURRENT BLOCK
	JRST OUTCK0		;GO PROCESS NEXT BLOCK ON QUEUE
;SKDOUT - ROUTINE TO SCHEDULE OUTPUT FOR AN INTERNAL LINK
;
;CALL:		CALL SKDOUT
;RETURNS: +1 ALWAYS, WITH ALL AC'S PRESERVED

	RESCD

SKDOUT::SAVET
	MOVE T4,TODCLK		;GET CURRENT TIME
	ADD T4,OUTIVL		;GET TIME INTERVAL TO WAIT BEFORE TRYING AGAIN
	MOVEM T4,OUTTIM		;SCHEDULE WAKEUP AT LATER TIME
	RET			;DONE, RETURN
;INTOUT - ROUTINE TO PERFORM OUTPUT FOR AN INTERNAL LINK
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL INTOUT
;RETURNS: +1	 FAILED, MORE OUTPUT WILL HAVE TO BE DONE LATER
;	  +2	SUCCESS, ALL REMAINING OUTPUT HAS BEEN SENT
;
; ASSUMES LOGICAL LINK BLOCK IS LOCKED. PRESERVES LINK BLOCK ADR IN T1

INTOUT:	ASUBR <INOLLB>

; PROCESS ANY OUTSTANDING ACK'S FOR THIS LINK

	MOVE T1,INOLLB		;GET LOGICAL LINK BLOCK ADDRESS
;	CALL MOVSEG		;PROCESS OUTSTANDING ACK'S
;	 RET			;FAILED, TRY AGAIN LATER
	MOVE T1,INOLLB		;GET LOGICAL LINK BLOCK ADDRESS
	JE LLOCT,(T1),RSKP	;IF NO DATA LEFT, ALL DONE

; CHECK TO SEE IF THERE IS ANY MORE OUTPUT TO SEND

INO020:	MOVE T1,INOLLB		;GET ADDRESS OF LOGICAL LINK BLOCK
	JN LLOCT,(T1),INO025	;IF DATA LEFT, GO TRY TO SEND IT
	MOVE T1,INOLLB		;GET LOGICAL LINK BLOCK ADDRESS
	CALL TELOBE		;GO TELL DRIVER THAT OUTPUT BUFFER NOW EMPTY
	MOVE T1,INOLLB		;GET ADDRESS OF LOGICAL LINK BLOCK
	CALL TELOOK		;GO ADVISE DRIVER OUTPUT CAN BE DONE
	MOVE T1,INOLLB		;RESTORE LOGICAL LINK BLOCK ADDRESS
	RETSKP			;DONE, RETURN

;CHECK TO SEE IF ANY SEGMENTS CAN BE SENT NOW

INO025:	MOVE T1,INOLLB		;GET LOGICAL LINK BLOCK ADDRESS
	CALL SNDCHK		;CAN ANY SEGMENTS BE SENT ?
	 RET			;NO, TRY AGAIN LATER
	MOVE T1,INOLLB		;YES, GET LOGICAL LINK BLOCK ADDRESS
;	CALL OUTSEG		;SEND THE SEGMENT
	 RET			;FAILED, TRY AGAIN LATER
	JRST INO020		;CHECK TO SEE IF ANOTHER SEGMENT CAN BE SENT
;TELOOK - ROUTINE TO CHECK TO SEE IF NECESSARY TO NOTIFY DRIVER THAT
;	  OUTPUT MAY NOW BE SENT
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL TELOOK
;RETURNS: +1 ALWAYS, DRIVER NOTIFIED THRU FUNCTION VECTOR IF NEEDED

TELOOK:	JE LLNDO,(T1),R		;RETURN IF DRIVER DOES NOT NEED NOTIFICATION
	SETZRO LLNDO,(T1)	;NO LONGER NEED NOTIFICATION FLAG LIT
	LOAD T4,LLVEC,(T1)	;GET DRIVER FUNCTION VECTOR ADDRESS
	MOVX T2,.NSOMO		;GET "OUTPUT CAN BE SENT" TYPE CODE
	LOAD T1,LLDRV,(T1)	;GET DRIVER'S CORRELATION CODE
	CALLRET @.NSOOK(T4)	;NOTIFY DRIVER AND RETURN



;TELOBE - ROUTINE TO NOTIFY THE DRIVER THAT AN OUTPUT BUFFER IS NOW EMPTY
;
;ACCEPTS IN T1/	ADDRESS OF LOGICAL LINK BLOCK
;		CALL TELOBE
;RETURNS: +1 ALWAYS, WITH DRIVER NOTIFIED THRU ITS FUNCTION VECTOR

TELOBE::ASUBR <OBELLB>
	LOAD T4,LLVEC,(T1)	;DATA SENT, GET DRIVER FCN VECTOR ADR
	LOAD T2,LLBFO,(T1)	;GET DRIVER'S BUFFER ADDRESS
	LOAD T1,LLDRV,(T1)	;GET DRIVER CORRELATION CODE
	CALL @.NSOBE(T4)	;TELL DRIVER IT CAN HAVE BUFFER BACK
	MOVE T1,OBELLB		;GET LOGICAL LINK BLOCK ADDRESS
	SETZRO LLBFO,(T1)	;NOTE THAT BUFFER IS NOW GONE
	RET			;DONE, RETURN.
>
SUBTTL Routine Needed by TTYSRV

;GET THE NEXT SEGMENT ON THE INCOMING MESSAGE QUEUE
;ACCEPTS:	T1/ LL BLOCK
;RETURNS:	+1 - NO SEGMENT AVAILABLE
;		+2 - T2/ SEGMENT ADDRESS
;PRESERVES T1

	RESCD

TTGETS::SKIPN T2,LLOMSG(T1)	;ANY SEGMENTS?
	RET			;NO, DONE
	HRRZS T2		;YES, JUST THE HEAD SEGMENT
	RETSKP


;REMOVE A SEGMENT FROM THE INCOMING MESSAGE QUEUE
;ACCEPTS:	T1/ LL BLOCK
;		T2/ SEGMENT ADDRESS
;RETURNS:	+1 ALWAYS

TTREMS::LOAD T3,MSLNK,(T2)	;GET NEXT SEGMENT ON QUEUE
	SKIPN T3		;ANY MORE?
	HRLM T3,LLOMSG(T1)	;NO, MAKE IT THE TAIL
	HRRM T3,LLOMSG(T1)	;MAKE IT THE HEAD
	RET
SUBTTL	Scheduler Interface
;ROUTINE CALLED BY THE SCHEDULER EVERY 20 MS TO PROCESS MESSAGES
;ARRIVED FROM THE NETWORK

NSPCH7::ACVAR <W1>		;GET A WORK REG
	STKVAR <MB>		;MESSAGE ADDRESS
	MOVEI W1,15		;DO A LIMITED # PER PASS
	SKIPL LLLLCK		;LL TREE LOCK AVAILABLE
	RET			;NO
	SKIPN T1,SMSGQ		;ANY MSGS ON Q?
	JRST LLSRVR		;NO, GO SEE IF ANY LINKS NEED SERVICE
	HRRZS T1		;YES, GET FIRST MSG
NSPCH0:	MOVEM T1,MB		;SAVE MESSAGE ADDRESS
	CALL NSPMSG		;GO PROCESS THE MSG
	IFNSK.			;COULDN'T, WE'LL DO IT LATER
	   MOVE T1,MB		;RETRIEVE MESSAGE ADDRESS
	   CALL NSPNXT		;ANY MORE MSGS?
	    JRST LLSRVR		;NO
	   JRST NSPCH0		;YES
	ENDIF.
	MOVE T1,MB		;RETRIEVE MESSAGE ADDRESS
	CALL NSPREM		;REMOVE THIS MSG FROM Q
	 JRST LLSRVR		;NO MORE TO DO
	SOJGE W1,NSPCH0		;GO DO MORE
	JRST LLSRVR

	ENDSV.
	ENDAV.			;END ACVAR


;Get the next message on SMSGQ
;
;ACCEPTS:	T1/ Address of current message
;RETURNS:	+1  No more messages
;		+2  T1/ Address of next message

NSPNXT:	CHNOFF DLSCHN		;TURN OFF NET
	MOVE T1,MSNXT(T1)	;GET NEXT MSG
	CHNON DLSCHN		;TURN ON NET
	JUMPE T1,R		;RETURN NO NEXT MSG
	RETSKP			;THERE IS ANOTHER MSG
;Remove a message from SMSGQ and get the next message on the queue
;
;ACCEPTS:	T1/ Address of message to be removed
;RETURNS:	+1  Message removed, no more messages on queue
;		+2  Message removed, T1/ Address of next message

NSPREM:	ASUBR <MSG,NXT>
	CHNOFF DLSCHN		;TURN OFF NET
	SKIPN T2,MSPRV(T1)	;ARE WE FIRST ON Q?
	IFNSK.			;YES
	   SKIPN T3,MSNXT(T1)	;ARE WE ALSO LAST ON Q?
	   IFNSK.		;YES
	      SETZM SMSGQ	;INIT THE Q HEADER
	      SETZM NXT		;NO NEXT MESSAGE
	      JRST NSPRE1	;DONE
	   ENDIF.
	   SETZM MSPRV(T3)	;NO, MAKE NEXT MSG THE FIRST
	   HRRM T3,SMSGQ	;MAKE Q HEADER POINT TO US
	   MOVEM T3,NXT		;RETURN WITH NEXT
	   JRST NSPRE1
	ENDIF.
	SKIPN T3,MSNXT(T1)	;NO, WE ARE NOT FIRST.  ARE WE LAST?
	IFNSK.			;YES
	   SETZM MSNXT(T2)	;PREVIOUS NO LONGER HAS NEXT
	   HRLM T2,SMSGQ	;MAKE Q HEADER POINT TO PREVIOUS
	   SETZM NXT		;NO NEXT MESSAGE
	   JRST NSPRE1		;DONE
	ENDIF.
	MOVEM T3,MSNXT(T2)	;NO, NOT FIRST OR LAST. MAKE PREVIOUS POINT AHEAD TO NEXT
	MOVEM T2,MSPRV(T3)	;MAKE NEXT POINT BACK TO PREVIOUS
	MOVEM T3,NXT		;RETURN NEXT MSG
NSPRE1:	MOVE T1,MSG		;RETRIEVE MESSAGE ADDRESS
	JE MSSKD,(T1),NSPRE2	;NEED TO RELEASE IT?
	CALL RELRES		;YES
NSPRE2:	CHNON DLSCHN		;TURN ON NET
	MOVE T1,NXT		;GET NEXT MESSAGE ON Q
	JUMPE T1,R		;RETURN NO NEXT MSG
	RETSKP			;THERE IS ANOTHER MSG

	ENDAS.
;ROUTINE TO QUEUE UP A RECEIVED MESSAGE.
;	T1/ BLOCK ADDRESS

NSPMSG::TRVAR <MSGCNT,MSGBYP,MSGSRC,MSGDST,MSGBLK,<NSPDUM,12>,MSGW1>
	STKVAR <LLB>		;LL BLOCK
	MOVEI T2,MSHDR(T1)	;GET TO DATA PORTION
	MOVEM T1,MSGBLK		;SAVE BLOCK ADDRESS
	HRLI T2,(<POINT 8,>)
	MOVEM T2,MSGBYP		;SAVE BYTE POINTER
	LOAD T1,MSCNT,(T1)	;GET BYTE COUNT
	MOVEM T1,MSGCNT		;SET UP COUNT
	GETBYM (MSGCNT,MSGBYP,NSPMSE)		;GET FIRST BYTE
	TRNE T2,201		;A ROUTE HEADER?
	JRST NSPMSE		;YES, BUT IN ERROR
	TRNN T2,2		;IS THIS FLAGS OR ROUTE HEADER?
	JRST NSPMS1		;FLAGS, GO DO MESSAGE
	TRNE T2,100
	TRNE T2,60		;VALID HEADER?
	JRST NSPMSE		;NO
	CALL SKPFLD		;SKIP HOST NAME
	 JRST NSPMSE		;SOMETHING WRONG
	CALL SKPFLD		;SKIP OTHER HOST NAME
	 JRST NSPMSE		;SOMETHING WRONG
	GETBYM (MSGCNT,MSGBYP,NSPMSE)		;GET FLAGS
NSPMS1:	MOVE T1,MSGBLK		;GET MESSAGE ADDRESS
	STOR T2,MSMFL,(T1)	;SAVE MESSAGE FLAGS
	TRNE T2,CNMRFL		;IS IT A CONTROL MESSAGE?
	JRST NSPMSE		;YES, GIVE IT TO BACKGROUND TASK
	CALL GETLLA		;GET LINK NUMBERS
	 JRST NSPMSE		;BAD MESSAGE
	; ..
	; ..

; MESSAGE PARSED - PLACE MESSAGE ON APPROPRIATE QUEUE FOR LATER HANDLING

	MOVE T1,MSGDST		;GET OUR NAME
	MOVE T2,MSGSRC		;GET ITS NAME
	LOCK LLLLCK		;GET LL TREE LOCK
	CALL LLLKUP		;FIND THE LINK
	IFNSK.			;COULDN'T
	   UNLOCK LLLLCK	;GIVE UP TREE LOCK
	   JRST NSPMSE		;GIVE MSG TO BACKGROUND TASK
	ENDIF.
	TMNN LLDED,(T1)		;HAS DN20 CRASHED?
	IFSKP.
	   UNLOCK LLLLCK	;YES, GIVE BACK THE BIG LOCK
	   MOVE T2,MSGBLK	;GET BACK MESSAGE ADDRESS
	   SETONE MSSKD,(T2)	;TELL SCHEDULER TO TOSS THE NESSAGE
	   RETSKP		;DONE
	ENDIF.
	CALL BLKLOK		;GET LL LOCK
	IFNSK.			;COULDN'T
	   UNLOCK LLLLCK	;GIVE UP TREE LOCK
	   RET
	ENDIF.
	UNLOCK LLLLCK		;GIVE UP TREE LOCK
	LOAD T2,LLSTA,(T1)	;GET STATE OF LL
	CAIN T2,LLSRUN		;RUNNING?
	IFSKP.			;NO
	   CALL BLKULK		;GIVE UP LL LOCK
	   JRST NSPMSE		;GIVE MESSAGE TO BACKGROUND TASK
	ENDIF.
	MOVE T2,TODCLK		;YES, GET THE TIME
	ADD T2,NSINAC		;ADD INACTIVITY TIMEOUT VALUE
	MOVEM T2,LLINAC(T1)	;PUT NEW TIME IN LL BLOCK
	MOVE T2,MSGBLK		;RETRIEVE ADDRESS OF MESSAGE
	MOVE T3,MSGCNT		;GET REMAINING COUNT
	STOR T3,MSDTC,(T2)	;SAVE RESIDUAL COUNT
	MOVE T3,MSGBYP
	MOVEM T3,MSBPTR(T2)	;SAVE RESIDUAL BYTE POINTER
	MOVEM T1,LLB		;SAVE LL BLOCK
	LOAD T4,MSMFL,(T2)	;GET MESSAGE FLAGS
	TRNN T4,ACKFLM		;AN ACK?
	IFSKP.			;YES
	   CALL GETTWO		;GET THE ACK NUMBER
	    JRST NSPMS3		;COULDN'T
	   CAIE T4,ACKFLM	;A DATA ACK?
	   IFSKP.		;YES
	      MOVEI T3,MSDAT	;GET ITS INDICATOR
	   ELSE.		;NO, MUST BE LS/INT ACK
	      MOVEI T3,MSLSI	;GET ITS INDICATOR
	   ENDIF.
	   CALL ACKCHN		;PROCESS THE ACK
	   MOVE T2,MSGBLK	;RETRIEVE MESSAGE ADDRESS
	   SETONE MSSKD,(T2)	;SET THE RELEASE INDICATOR
	   JRST NSPGUD		;DONE
	ENDIF.
	TRNN T4,DATFLI		;IS IT LS OR INT MESSAGE?
	IFSKP.			;YES
	   CALL INTLS		;PROCESS IT
	ELSE.			;NO, MUST BE A DATA SEGMENT
	   CALL NSINBK		;DO BOOKKEEPING
	   CALL ONRAWQ		;PROCESS IT
	ENDIF.
NSPGUD:	MOVE T1,LLB		;RETRIEVE LL BLOCK ADDRESS
	CALL BLKULK		;UNLOCK IT
	RETSKP

NSPMS3:	MOVE T1,LLB		;GET BACK LL BLOCK
	CALL BLKULK		;FREE THE LL BLOCK
NSPMSE:	MOVE T2,MSGBLK		;GET BLOCK ADDRESS
	CALL ONMSGQ		;PUT IN ON THE TASK'S Q
	RETSKP			;FINISHED WITH MSG

	ENDSV.
	ENDTV.
;PUT A DATA SEGMENT MESSAGE ON A LINK'S INCOMING QUEUE
;	T1/ LL BLOCK ADDRESS
;	T2/ MESSAGE BLOCK
;RETURNS:	+1

ONRAWQ:	NOSKD1			;HOLD OFF SCHEDULER
	LOAD T3,LLDMT,(T1)	;ACCOUNT FOR ONE MORE DATA MESSAGE
	AOS T3
	LOAD T4,LLMQI,(T1)	;GET MAXIMUM INPUT QUEUE LENGTH
	CAMG T3,T4		;TOO MANY ON Q?
	IFSKP.			;YES
	   LOAD T3,LLLKP,(T1)	;GET NODE'S VERSION
	   CAIE T3,.NSP31	;NSP 3.1?
	   JRST ONRAWF		;NO, DONE
	   SETONE LLFNN,(T1)	;PHASE II, SAY THIS LL NEEDS A NACK
	   SETZRO LLFNA,(T1)	;NOT AN ACK
	   CALL ONSRVQ		;PUT LL ON "NEEDS SERVICE" QUEUE
	   JRST ONRAWF		;DONE
	ENDIF.
	MOVEI T3,MSDAT		;DATA MESSAGE
	CALL VERSEG		;VERIFY NEW SEGMENT
	 JRST ONRAWF		;FLUNKED
	SETONE LLFNA,(T1)	;THIS LL NEEDS AN ACK
	INCR LLDMT,(T1)		;SAY WE HAVE ANOTHER MESSAGE IN QUEUE
	LOAD T3,LLDMT,(T1)	;GET NUMBER OF SEGMENTS ON Q
	CAIN T3,1		;WAS Q PREVIOUSLY EMPTY?
	CALL DATINR		;YES, GIVE INT
	MOVEI T3,LLOMSG(T1)	;THE ORDERED MESSAGE QUEUE
	CALL PUTONQ		;PUT ON NEW SEGMENT
	CALL ONSRVQ		;PUT LL ON "NEEDS SERVICE" QUEUE
	CALL CHKLLT		;CHECK FOR TTY ON THIS LL
	OKSKD1
	RET			;AND DONE


ONRAWF:	SETONE MSSKD,(T2)	;TELL SCHEDULER TO RELEASE THE MESSAGE
	CALL DATINR		;REQUEST INT
	OKSKD1
	RET
;GIVE DATA INTERUPT

DATINR:	SAVEAC <T1,T2>		;SAVE VOLATILE REGS
	LOAD T2,LLFRK,(T1)	;GET FORK I.D.
	OPSTR <SOSL T1,>,LLDRC,(T1) ;WANT DATA INT?
	CALL PSIRQ		;YES. GIVE IT
	RET			;AND DONE

;POSTING ADDRESS FOR SEGMENTS. T1= MESSAGE ADDRESS

SEGPST:	JN MSRLS,(T1),RELRES	;IF "RELEASED", GO DO IT
	SETZRO MSPST,(T1)	;NOT. SAY POSTED
	RET			;AND DONE


;POSTING ADDRESS FOR ACKS
;ACCEPTS:	T1/ MESSAGE ADDRESS
;RETURNS:	+1

ACKPST::SETZM (T1)		;CLEAR
	HRL T2,T1		; OUT
	HRRI T2,1(T1)		;  THE
	BLT T2,ACKLEN+MSHDR-1(T1)  ;  BLOCK
	RET
;ROUTINE TO VERIFY A DATA SEGMENT
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;		T2/ SEGMENT ADDRESS
;RETURNS:	+1 BAD OR WRONG SEGMENT
;		+2 GOOD

VERSEG:	TRVAR <MSGCNT,MSGBYP,MSGBLK>
	MOVE T3,MSBPTR(T2)	;GET POINTER TO DATA
	MOVEM T3,MSGBYP		;TO THE POINTER
	LOAD T3,MSDTC,(T2)	;GET COUNT
	MOVEM T3,MSGCNT		;SAVE COUNT
	MOVEM T2,MSGBLK		;SAVE MESSAGE BLOCK
	CALL GETTWO		;GET ACKNUM
	 JRST VERBDY		;BAD
	TRZN T2,ACKIND		;IS THIS AN ACKNUM?
	JRST GOTSEG
	MOVEI T3,MSDAT		;DATE MESSAGE
	CALL ACKCHN		;AND GO HANDLE THE ACK
	CALL GETTWO		;GET SEGNUM
	 JRST VERBDY		;BAD
GOTSEG:	MOVE T3,T2		;SAVE SEGMENT #
	LOAD T4,LLIDN,(T1)	;GET LAST SEG RECEIVED
	AOS T4			;MAKE NEXT EXPECTED
	ANDI T4,7777		;12 BITS ONLY
	CAMN T3,T4		;THIS THE RIGHT ONE?
	IFSKP. 			;NO
	   CAML T3,T4		;TOO NEW?
	   IFSKP.		;NO, OLD.
	      SETONE LLFNA,(T1)	;SAY THIS LL NEEDS AN ACK
	   ELSE.		;TOO NEW
	      LOAD T4,LLLKP,(T1)  ;GET NODE'S VERSION
	      CAIE T4,.NSP31	;NSP 3.1?
	      JRST VERBDY	;NO, FORGET IT
	      SETONE LLFNN,(T1)	;PHASE II, SAY LL NEEDS TO NAK
	      SETZRO LLFNA,(T1)	;NOT AN ACK
	   ENDIF.
	   CALL ONSRVQ		;PUT LL ON NEEDS SERVICE QUEUE
	   JRST VERBDY		;DONE
	ENDIF.
	STOR T3,LLIDN,(T1)	;YES, UPDATE SEGMENT NUMBER
	MOVE T2,MSGBLK		;GET MESSAGE ADDRESS
	STOR T3,MSSEG,(T2)	;SAVE SEGMENT #
	RETSKP			;SEG IS GOOD

VERBDY:	MOVE T2,MSGBLK		;GET BACK BLOCK ADDRESS
	RET			;AND DONE
;PROCESS "LINKS THAT NEED SERVICE" QUEUE

LLSRVR:	STKVAR <LLB>		;LL BLOCK ADDRESS
	SKIPL LLLLCK		;LL TREE LOCK AVAILABLE?
	RET			;NO
	MOVE T1,LSTLLS		;GET LAST TIME LINKS WERE SERVICED
	ADDI T1,^D200		;ADD INTERVAL
	CAMLE T1,TODCLK		;TIME TO DO IT AGAIN?
	RET			;NO, GO AWAY
	MOVE T1,TODCLK		;GET CURRENT TIME
	MOVEM T1,LSTLLS		;LINKS BEING SERVICED NOW
	SKIPN T1,LLSRVQ		;ANYTHING TO DO?
	RET			;NO, BYE
	HRRZS T1		;GET FIRST LL BLOCK
	LOCK LLLLCK		;GET LOCK ON LL TREE
LLSRV2:	MOVEM T1,LLB		;STASH LL BLOCK
	CALL BLKLOK		;LOCK THE LL
	IFNSK.			;COULDN'T
	   MOVE T1,LLB		;RETRIEVE LL BLOCK
	   JRST LLSRV3
	ENDIF.
	TMNN <LLFNN,LLFNA>,(T1)	;THIS LINK NEED A DATA ACK OR NACK?
	IFSKP.			;YES
	   CALL ACKNSP		;SEND IT
	    JRST LLSRV6		;COULDN'T
	ENDIF.
	TMNN <LLNLS,LLALS>,(T1)  ;THIS LINK NEED A LS ACK OR NACK?
	JRST LLSRV4		;NO
	CALL ACKLI		;YES, SEND IT
	IFNSK.			;COULDN'T
LLSRV6:	   MOVE T1,LLB		;RETRIEVE LL BLOCK ADDRESS
	   JRST LLSRV5		;MOVE ON
	ENDIF.
LLSRV4:	CALL UNQSRV		;REMOVE LL FROM Q
LLSRV5:	CALL BLKULK		;UNLOCK LL
LLSRV3:	LOAD T1,LLNSR,(T1)	;GET NEXT LL
	SKIPE T1		;ANY MORE?
	JRST LLSRV2		;YES
	UNLOCK LLLLCK		;GIVE UP LL TREE LOCK
	RET			;ALL DONE

	ENDSV.
;ROUTINE TO PUT AN LL BLOCK ON THE "NEEDS SERVICE" LIST
;ACCEPTS:	T1/ LL BLOCK ADDRESS
;RETURNS:	+1 ALWAYS
;PRESERVES T1,T2,T3

ONSRVQ:	NOSKED			;DON'T LET THE SCHEDULER RUN
	TMNE LLISR,(T1)		;ALREADY ON QUEUE?
	JRST ONSRV1		;YES, NOTHING TO DO
	SAVEAC <T2,T3>
	SETONE LLISR,(T1)	;NO, SAY NOW IN QUEUE
	SKIPE T2,LLSRVQ		;QUEUE CURRENTLY EMPTY?
	IFSKP.			;YES
	   HRRM T1,LLSRVQ	;MAKE QUEUE HEAD POINT TO US
	   HRLM T1,LLSRVQ	;MAKE QUEUE TAIL POINT TO US
	   SETZRO <LLPSR,LLNSR>,(T1)	;CLEAR ALL POINTERS
	   JRST ONSRV1		;DONE
	ENDIF.
	HLRZ T3,T2		;NO, GET LAST QUEUE ENTRY
	STOR T3,LLPSR,(T1)	;MAKE IT PREVIOUS TO US
	SETZRO LLNSR,(T1)	;WE ARE AT THE END
	STOR T1,LLNSR,(T3)	;MAKE IT POINT AHEAD TO US
	HRLM T1,LLSRVQ		;MAKE US TAIL OF QUEUE
ONSRV1:	OKSKED			;ALLOW SCHEDULER TO RUN AGAIN
	RET
;ROUTINE TO REMOVE AN LL FROM THE "NEEDS SERVICE" QUEUE
;ACCEPTS:	1/ LL BLOCK ADDRESS
;RETURNS:	+1 ALWAYS
;PRESRVES T1,T2,T3

UNQSRV:	NOSKED			;DON'T LET SCHEDULER RUN
	TMNN LLISR,(T1)		;NOW IN QUEUE?
	JRST UNQSR1		;NO, NOTHING TO DO
	SAVEAC <T1,T2,T3>
	SETZRO LLISR,(T1)	;YES, SAY NO LONGER IN QUEUE
	LOAD T2,LLPSR,(T1)	;GET PREVIOUS LL
	SKIPE T2		;ARE WE THE FIRST?
	IFSKP.			;YES
	   LOAD T3,LLNSR,(T1)	;GET NEXT LL
	   SKIPE T3		;ARE WE LAST?
	   IFSKP.		;YES
	      SETZM LLSRVQ	;RESET QUEUE HEADER
	      JRST UNQSR1	;DONE
	   ENDIF.
	   SETZRO LLPSR,(T3)	;NO, MAKE NEXT FIRST
	   HRRM T3,LLSRVQ	;MAKE Q HEADER POINT TO NEXT
	   JRST UNQSR1		;DONE
	ENDIF.
	LOAD T3,LLNSR,(T1)	;GET NEXT LL
	SKIPE T3		;ARE WE LAST?
	IFSKP.			;YES
	   SETZRO LLNSR,(T2)	;MAKE PREVIOUS LAST
	   HRLM T2,LLSRVQ	;MAKE Q HEADER POINT TO PREVIOUS
	   JRST UNQSR1		;DONE
	ENDIF.
	STOR T3,LLNSR,(T2)	;MAKE PREVIOUS POINT AHEAD TO NEXT
	STOR T2,LLPSR,(T3)	;MAKE NEXT POINT BACK TO PREVIOUS
UNQSR1:	OKSKED			;ALLOW SCHEDULER TO RUN AGAIN
	RET			;DONE
;ROUTINE TO SEND ANY DATA SEGMENT ACK'S NEEDED
;ACCEPTS:	T1/ ADDRESS OF LOGICAL LINK BLOCK
;RETURNS:	+1 FAILED, COULD NOT SEND THE ACK
;		+2 SUCCESS

ACKNSP:	STKVAR <SQASEG>
	LOAD T2,LLIDN,(T1)	;GET LAST SEGMENT RECEIVED
	MOVEM T2,SQASEG		;STASH SEG NUMBER
	MOVEI T3,MSDAT		;ON THE DATA CHANNEL
	TMNN LLFNA,(T1)		;NEED AN ACK?
	TXO T2,ACKBIT		;NO, TURN ON THE NACK BIT
	CALL SNDACK		;SEND IT
	 RET			;COULDN'T
	MOVE T2,SQASEG		;RETRIEVE SEG NUMBER
	STOR T2,LLLAK,(T1)	;SAY IT HAS BEEN ACKED
	SETZRO <LLFNA,LLFNN>,(T1) ;CLEAR ACK FLAGS
	RETSKP			;DONE, RETURN SUCCESS


;TEMPORARY DUMMY ENTRY POINT FOR TTYSRV

SQIACK::RETSKP
SUBTTL	The NODE JSYS

	SWAPCD			;IS SWAPPABLE
.NODE::	MCENT			;MONITOR CONTEXT ENTRY

; VALIDATE FUNCTION CODE AND DISPATCH TO PROCESSING ROUTINE

	UMOVE T1,1		;GET FUNCTION CODE FROM USER
	CAIL T1,0		;FUNCTION CODE WITHIN
	CAIL T1,NDTLEN		; VALID RANGE ?
	ITERR (ARGX02)		;NO, RETURN "INVALID FUNCTION" ERROR
	MOVE T4,NODTAB(T1)	;GET ADDRESS OF PROCESSING ROUTINE
	CALL (T4)		;DISPATCH TO PROPER ROUTINE
	 ITERR ()		;FAILED, RETURN ERROR CODE
	MRETNG			;SUCCESS, DONE.

; TABLE OF NODE JSYS FUNCTIONS

NODTAB:	EXP NDSLN		;(0) SET LOCAL NODE NAME
	EXP NDGLN		;(1) GET LOCAL NODE NAME
	EXP NDSNM		;(2) SET LOCAL NODE NUMBER
	EXP NDGNM		;(3) GET LOCAL NODE NUMBER
	EXP NDSLP		;(4) SET LOOPBACK PORT
	EXP NDCLP		;(5) CLEAR LOOPBACK PORT
	EXP NDFLP		;(6) FIND LOOPBACK PORT
	EXP NDSNT		;(7) SET NETWORK TOPOLOGY INFO
	EXP NDGNT		;(10) GET NETWORK TOPOLOGY INFO
	EXP NDSIC		;(11) SET ITERRUPT CHANNEL FOR TOPOLOGY CHANGE
	EXP NDCIC		;(12) CLEAR ITERRUPT CHANNEL FOR TOPOLOGY CHANGE
	EXP NDGVR		;(13) GET NSP VERSION INFORMATION
	EXP NDGLI		;(14) GET LINE INFORMATION
	EXP NDVFY		;(15) VERIFY NODE NAME
	EXP NDRNM		;(16) RETURN A NODE NAME

NDTLEN==.-NODTAB
;NDSLN - ROUTINE TO SET THE LOCAL NODE NAME

NDSLN:	STKVAR <<NODNAM,WPN>>
	MOVE T1,CAPENB		;GET CURRENTLY ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR	;WHEEL OR OPERATOR CAPABILITY REQUIRED
	RETBAD (CAPX1)		;NOT ENOUGH CAPABILITY, RETURN ERROR

; COPY THE NODE NAME STRING FROM THE USER ADDRESS SPACE

	UMOVE T2,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK
	UMOVE T1,.NDNOD(T2)	;GET POINTER TO STRING IN USER SPACE
	MOVEI T2,NODNAM		;WE'LL WRITE PARSED NAME TO "NODNAM"
	CALL PARNDU		;MAKE SURE NODE NAME IS KOSHER
	 RETBAD			;FAILED, TELL CALLER WHY
	MOVEM B,OURCNT		;REMEMBER LENGTH OF NAME
	DMOVE T1,NODNAM		;GET NODE NAME *** DMOVE IS CHEATING BECAUSE IT ASSUMES WPN=2!
	DMOVEM T1,OURNAM	;STORE FOR NSP

;NOW FIX THE NODE NAME MAPPING TABLE

	MOVE T2,[MOVSO -40]	;SET UP OPERATOR
	MOVEM T2,P3		; FOR EXTEND
	MOVE Q3,OURNUM		;GET OUR NODE NUMBER
	NOINT
	LOCK NMAPLK		;LOCK THE NODE MAPPING TABLE
	SETZM NODMAP(Q3)	;NULLIFY THE CURRENT NODE NAME
	MOVE T1,OURCNT		;GET CHAR. COUNT OF NEW NAME
	MOVE T2,[440700,,OURNAM]  ;BYTE POINTER TO NEW NAME
	SETZB T3,Q2		;SINGLE WORD BYTE POINTERS
	MOVE T4,OURCNT		;GET CHAR. COUNT OF NEW NAME
	HRLI Q1,440600		;BYTE POINTER TO NEW
	HRRI Q1,NODMAP(Q3)	; NAME'S DESTINATION
	EXTEND T1,P3		;MOVE THE NEW NAME
	 JFCL
	UNLOCK NMAPLK		;UNLOCK THE NODE MAPPING TABLE
	OKINT
	RETSKP			;SUCCESS RETURN

	ENDSV.
;NDGLN - RETURN LOCAL NODE NAME

NDGLN:	UMOVE T2,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK
	UMOVE T1,.NDNOD(T2)	;GET BYTE POINTER TO DEPOSIT NODE NAME
	MOVE T3,T2		;KEEP 30-BIT ADDRESS IN T3 FOR RETURNING
				; UPDATED BYTE POINTER TO USER
	HRROI T2,OURNAM-1	;GET POINTER TO SOURCE STRING
	CALL CPYTU1		;COPY STRING TO USER SPACE, RETURN POINTER
	RETSKP			;DONE, RETURN SUCCESS

;SET LOCAL NODE NUMBER

NDSNM:	MOVE T1,CAPENB		;GET CURRENTLY ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR	;WHEEL OR OPERATOR CAPABILITY REQUIRED
	RETBAD (CAPX1)		;NOT ENOUGH CAPABILITY, RETURN ERROR
	UMOVE T2,2
	UMOVE T2,0(T2)		;GET NUMBER
	CAIL T2,1
	CAILE T2,BIGNOD		;WITHIN RANGE?
	RETBAD (NSPX25)		;NO
	MOVE T4,OURNUM		;SAVE THE CURRENT NUMBER
	MOVEM T2,OURNUM		;SET THE NEW NODE NUMBER

;NOW FIX THE NODE NAME MAPPING TABLE

	MOVE T1,T4		;RETRIEVE THE CURRENT NUMBER
	NOINT
	LOCK NMAPLK		;LOCK THE NODE MAPPING TABLE
	MOVE T3,NODMAP(T1)	;GET THE CURRENT NODE NAME
	SETZM NODMAP(T1)	;NULLIFY IT
	MOVEM T3,NODMAP(T2)	;MOVE NAME TO NEW NODE ADDRESS
	UNLOCK NMAPLK		;UNLOCK THE NODE MAPPING TABLE

;NOW FIX THE REACHABLE NODES TABLE

	LOCK NODLOK		;LOCK THE REACHABLE NODES TABLE
	MOVE T3,[POINT 2,NODTBL]  ;MAKE BYTE POINTER TO THE TABLE
	ADJBP T1,T3		;POINT TO THE CURRENT
	SETZ T4,		; AND
	DPB T4,T1		;  SAY NO LONGER REACHABLE
	ADJBP T2,T3		;POINT TO THE NEW
	MOVEI T4,2		;WE ARE PHASE II
	DPB T4,T2		;SAY THE NEW IS REACHABLE
	UNLOCK NODLOK		;UNLOCK THE REACHABLE NODES TABLE
	OKINT
	RETSKP

;GET LOCAL NODE NUMBER

NDGNM:	UMOVE T2,2
	MOVE T3,OURNUM
	UMOVEM T3,0(T2)		;STORE NUMBER
	RETSKP			;DONE
;SET LOOPBACK PORT

NDSLP:	MOVE T1,CAPENB		;GET CURRENTLY ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR!SC%MNT ;WHEEL OPERATOR OR MAINTENANCE CAPABILITY REQUIRED
	RETBAD (CAPX2)		;WHEEL, OPERATOR, or MAINTENANCE capability required
	UMOVE T2,2		;GET ADDRESS OF USERS ARGUMENT BLOCK
	UMOVE T3,.NDPRT(T2)	;GET PORT WANTS TO SET IN LOOPBACK
	SKIPE T2,NSPLPB		;IS ANOTHER PORT ALREADY ASSIGNED ?
	JRST [	CAIE T3,(T2)	;IS IT SAME PORT ?
		RETBAD (NODX03)	;Another line already looped
		RETSKP	]	;ALL DONE
	MOVEI T1,.BTSTS		;WANT TO GET PORT STATUS
	MOVEI T2,T3		;ADDRESS OF ARGUMENT BLOCK
	BOOT			;GET ARGUMENT STATUS
	ERJMP [RETBAD (ARGX19)]	;Invalid unit number
	CAME T4,[EXP -1]	;IS PORT TURNED OFF
	RETBAD (NODX02)		;Line not turned off
	HRLI T3,(ND%LPA)	;HAVE A PORT FOR LOOPBACK NOW
	MOVEM T3,NSPLPB		;REMEMBER WHICH PORT WILL BE LOOPED
	RETSKP

;CLEAR LOOPBACK PORT

NDCLP:	MOVE T1,CAPENB		;GET CURRENTLY ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR!SC%MNT ;WHEEL OPERATOR OR MAINTENANCE CAPABILITY REQUIRED
	RETBAD (CAPX2)		;WHEEL, OPERATOR, or MAINTENANCE capability required
	SKIPN T1,NSPLPB		;GET LOOPBACK PORT NUMBER
	RETSKP			;NONE SO DONE
	UMOVE T2,2		;GET ADDRESS OF USERS ARGUMENT BLOCK
	UMOVE T3,.NDPRT(T2)	;GET PORT TO CLEAR LOOPBACK
	CAIE T3,(T1)		;SAME PORT AS IS LOOPED BACK ?
	RETBAD (ARGX19)		;Invalid unit number
	MOVEI T1,.BTTPR		;TERMINATE PROTOCOL
	MOVEI T2,T3		;ADDRESS OF ARGUMENT BLOCK
	BOOT			;DISABLE LINE
	ERJMP .+1		;CAN'T TURN OFF ?
	SETZM NSPLPB		;NOTHING IS LOOPED BACK NOW
	RETSKP

;FIND LOOPBACK PORT

NDFLP:	UMOVE T2,2		;GET ADR OF USERS ARGUMENT BLOCK
	MOVE T1,NSPLPB		;GET LOOPED BACK LINE
	UMOVEM T1,.NDPRT(T2)	;GIVE ANSWER TO USER
	RETSKP
; SET NETWORK TOPOLOGY INFO

NDSNT:	STKVAR <NEWTOP,NODES,TMPTOP,USRMSK>
	MOVE T1,CAPENB		;GET CURRENTLY ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR	;WHEEL, OPERATOR CAPABILITY REQUIRED
	RETBAD (CAPX1)		;WHEEL OR OPERATOR capability required
	UMOVE T2,2		;GET ADDR OF USER'S ARGUMENT BLOCK
	UMOVE T1,.NDNNO(T2)	;GET THE NUMBER OF NODES
	CAILE T1,BIGNOD		;CAN WE HANDLE THIS MANY NODES?
	RETBAD (NSPX25)		;NO, FAIL
	MOVEM T1,NODES		;SAVE THE NUMBER OF NODES BEING REPORTED
	UMOVE T1,.NDMSK(T2)	;GET USER'S ADDRESS OF TOPOLOGY MESSAGE
	MOVEM T1,USRMSK		;SAVE IT
	NOINT			;NO INTERRUPTIONS WHILE GETTING SPACE
	MOVEI T1,<BIGNOD+17>/20	;ENOUGH WORDS FOR TOPOLOGY MESSAGE
	CALL GETBLK		;GET SWAPPABLE FREE SPACE
	 RETBAD (MONX06,<OKINT>)  ;ERROR - "NO MORE SWAPPABLE FREE SPACE"
	MOVEM T1,TMPTOP		;SAVE THE ADDRESS
	MOVEI T1,<BIGNOD+21>/22	;ENOUGH WORDS FOR TOPOLOGY BIT MASK
	CALL GETBLK		;GET SWAPPABLE FREE SPACE
	 JRST [	MOVE T1,TMPTOP	;GET ADDR
		CALL RELBLK	;RELEASE THE SPACE
		RETBAD (MONX06,<OKINT>)]	;ERROR - NO MORE SPACE
	MOVEM T1,NEWTOP		;SAVE THE ADDR
	MOVE T3,TMPTOP		;GET DESTINATION IN CORRECT AC FOR BLT
	MOVE T1,NODES		;GET NUMBER OF NODES
	ADDI T1,17		;CALC NUMBER OF
	IDIVI T1,20		; WORDS TO BLT
	MOVE T2,USRMSK		;RETRIEVE USER'S ADDRESS
	CALL BLTUM1		;GET USER'S NEW TOPOLOGY BIT MASK
	MOVE T1,NODES		;GET NUMBER OF NODES
	ADDI T1,3		;CALC NUMBER OF
	IDIVI T1,4		; 8-BIT BYTES
	MOVE T2,TMPTOP		;GET ADDR OF COPIED MESSAGE
	HRLI T2,441000		;MAKE A BP
	MOVE T3,NEWTOP		;GET ADDR FOR BIT MASK
	HRLI T3,440200		;MAKE A BP
NDXLT:	ILDB T4,T2		;GET A BYTE FROM THE MESSAGE
	MOVEI Q1,4		;NUMBER OF NODES REPRESENTED IN A MESSAGE BYTE
NDXLT1:	IDPB T4,T3		;MAKE ENTRY IN BIT MASK
	SOJLE Q1,NDXLT2		;ANY MORE IN THIS BYTE?
	LSH T4,-2		;YES
	JRST NDXLT1		;CONTINUE
NDXLT2:	SOJG T1,NDXLT		;ANY MORE BYTES IN MESSAGE?
	LOCK NODLOK		;LOCK THE REACHABLE NODES TABLE

   IFN DN20SW,<			;CHECK FOR OTHER MCBS
	MOVEI T4,2		;NEXT DTE TO CHECK
NDXLT4:	SKIPL MCBDTE(T4)	;IS IT UP?
	JRST NDXLT3		;NO
	MOVE T2,NEWTOP		;MAKE BP
	HRLI T2,440200		; TO NEW TOPOLOGY
	MOVE T1,ITSNUM(T4)	;GET ITS NODE NUMBER
	ADJBP T1,T2		;POINT TO ITS ENTRY IN REACH TABLE
	MOVEI T3,3		;IT'S PHASE 3
	DPB T3,T1		;PUT IT IN
NDXLT3:	CAIGE T4,3		;CHEKCED ALL DTES YET?
	IFNSK.			;NO
	   AOS T4		;MAKE NEXT DTE
	   JRST NDXLT4		;TRY IT
	ENDIF.
   >

	MOVE T1,NEWTOP		;GET THE ADDRESS
	HRLI T1,440200		;MAKE A BYTE POINTER
	MOVE T2,[POINT 2,NODTBL]  ;BYTE POINTER TO EXISTING TOPOLOGY
	MOVE T3,NODES		;NUMBER OF BYTES TO COMPARE
	SETZ T4,		;NO OFFSET DURING COMPARISON
	CALL COMPAR		;HAS TOPOLOGY CHANGED?
	 SKIPA			;YES
	JRST NDSNTR		;NO, THEN NOTHING TO DO
	MOVE T1,NEWTOP		;RETRIEVE ADDRESS OF NEW TOPOLOGY
	MOVE T2,NODES		;GET NUMBER OF NODES
	ADDI T2,21		;CALC NUMBER OF
	IDIVI T2,22		; WORDS TO SEARCH
	MOVNS T2		;MAKE
	HRLZS T2		; AOBJN WORD
NDSNTL:	MOVE T3,(T1)		;GET A WORD FROM NEW TOPOLOGY
	MOVEM T3,NODTBL(T2)	;MOVE IT TO REACHABLE NODES TABLE
	AOS T1			;INCR SOURCE POINTER
	AOBJN T2,NDSNTL		;DO THEM ALL
	CALL ADDTEL		;INFORM INTERESTED USERS OF NEW TOPOLOGY
	 JFCL			;NO SUCH RETURN
NDSNTR:	MOVE T1,TMPTOP		;GET ADDR
	CALL RELBLK		;RELEASE THE SPACE
	MOVE T1,NEWTOP		;GET ADDR
	CALL RELBLK		;RELEASE THE SPACE
	UNLOCK NODLOK		;DONE WITH THE LOCK
	OKINT			;
	RETSKP			;EVERYTHING OK

	ENDSV.
; SET INTERRUPT CHANNEL FOR NETWORK TOPOLOGY CHANGE
NDSIC:	UMOVE T3,T2		;GET USER BLOCK ADDRESS
	XCTU [ MOVEI T1,.NDCHN(T3)]	;POINT TO CHANNEL NUMBER WORD
	UMOVE T1,(T1)		;GET THE CHANNEL NUMBER
	SKIPGE T1		;VALIDATE CHANNEL NUMBER
	RETBAD (ARGX13)		;NEGATIVE CHANNEL NUMBERS ARE ILLEGAL
	CAILE T1,^D35		;CHANNEL NUMBER TOO HIGH
	RETBAD (ARGX13)		;NEGATIVE CHANNEL NUMBERS ARE ILLEGAL
	CAIL T1,.ICAOV		;SKIP IF GOOD NUMBER
	CAILE T1,.ICNXP		;SKIP IF BAD NUMBER
	JRST CHANOK		;CHANNEL NUMBER OK.
	RETBAD (ARGX13)		;BAD CHANNEL NUMBER

CHANOK:	SETZ T4,		;T4 WILL HOLD ADDRESS OF FREE ENTRY
	MOVEI T2,NTCTAB		;POINT TO TOP OF TABLE OF WAITING FORKS

;HERE TO DETERMINE IF FORK ALREADY HAS SET THE INTERRUPT ONCE

CHNOK1:	SKIPN (T2)		;SKIP IF ENTRY IS BEING USED
	 JRST [	MOVE T4,T2	;SAVE FOR FORK NOT CURRENTLY ACTIVATED
		JRST CHNOK2]	;TRY NEXT ENTRY
	LOAD T3,NTCFRK,(T2)	;GET THE FORK NUMBER
	CAMN T3,FORKX		;DOES THIS ENTRY BELONG TO THIS FORK
	JRST [	STOR T1,NTCCHN,(T2)	;YES. PUT NEW CHANNEL NUMBER IN
		RETSKP]
CHNOK2:	CAIE T2,NTCTAB+<NTCMAX-1>	;HAVE WE LOOKED AT WHOLE TABLE
	AOJA T2,CHNOK1		;NO - KEEP LOOKING
	SKIPN T4		;DID WE FIND AN ENTRY?
	RETBAD (NSPX26)		;ERROR - TABLE OF TOPOLOGY WATCHERS IS FULL
	STOR T1,NTCCHN,(T4)	;SAVE THE CHANNEL NUMBER
	MOVE T1,FORKX		;NOW GET THE FORK NUMBER
	STOR T1,NTCFRK,(T4)	;AND SAVE
	SETONE FKNTC,(T1)	;FLAG IN FORK DATA BASE
	RETSKP

;NDCIC - CLEAR INTERRUPT CHANNEL FOR NETWORK TOPOLOGY CHANGE

NDCIC:
NTCOFF::MOVEI T1,NTCTAB		;FIND THE FORK'S ENTRY
NDCIC1:	LOAD T2,NTCFRK,(T1)	;GET THE FORK NUMBER FOR THIS ENTRY
	CAMN T2,FORKX		;THIS FORKS ENTRY
	JRST [	SETZM (T1)	;CLEAR ENTRY
		MOVE T1,FORKX	;GET FORK INDEX
		SETZRO FKNTC,(T1)	;CLEAR THE ITEM IN FORK DATA BASE
		RETSKP]
	CAIE T1,NTCTAB+<NTCMAX-1>	;AT END OF TABLE
	AOJA T1,NDCIC1		;NO - KEEP LOOKING
	RETSKP			;INDICATE SUCCESS EVEN WHEN NEVER SET
;NDGVR - GET NSP VERSION INVORMATION

NDGVR:	UMOVE T3,T2		;GET THE USER BLOCK POINTER
	MOVX T2,2		;GET NUMBER OF VERSIONS TO RETURN
	UMOVEM T2,.NDNVR(T3)	;STORE IN USER ARGUMENT BLOCK
	UMOVE T1,.NDCVR(T3)	;GET THE ADDRESS OF THE COMMUNICATION BLOCK
	MOVEI T2,COMVER		;COMMUNICATION VERSION NUMBER
	UMOVEM T2,.NDVER(T1)	;SAVE IN USER SPACE
	MOVEI T2,COMECO		;COMMUNICATION ECO
	UMOVEM T2,.NDECO(T1)	;SAVE IN USER SPACE
	MOVEI T2,COMCST		;GET THE CUSTOMER CHANGE NUMBER
	UMOVEM T2,.NDCST(T1)	;SAVE IN USER SPACE

;NOW GIVE USER THE ROUTING VERSION INFORMATION

	UMOVE T1,.NDRVR(T3)	;GET THE ADDRESS OF THE ROUTING BLOCK
	MOVEI T2,ROUVER		;ROUTING VERSION NUMBER
	UMOVEM T2,.NDVER(T1)	;SAVE IN USER SPACE
	MOVEI T2,ROUECO		;ROUTING ECO
	UMOVEM T2,.NDECO(T1)	;SAVE IN USER SPACE
	MOVEI T2,ROUCST		;GET THE CUSTOMER CHANGE NUMBER
	UMOVEM T2,.NDCST(T1)	;SAVE IN USER SPACE
	RETSKP			;RETURN
; GET NETWORK TOPOPLOGY INFORMATION

NDGNT:	TRVAR <GNTBLK,GNTRET,GNTCNT,GNTPTR,PTRAOB>

; SET UP TO LOOP OVER EACH NODE

	UMOVE T4,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK
	MOVEM T4,GNTBLK		;SAVE ADDRESS OF USER'S ARG BLOCK
	UMOVE T1,.NDNND(T4)	;GET NUMBER OF WORDS IN BLOCK
	ADD T1,T4		;COMPUTE LAST ADDRESS TO USE
	MOVEM T1,GNTCNT		;SAVE LAST ADDRESS IN USER SPACE TO STORE INTO
	MOVEI Q1,.NDBK1(T4)	;SET UP ADDRESS OF NEXT POINTER TO USE
	SETZ T2,		;INIT THE "NUMBER OF NODES FOUND" COUNTER
	MOVNI T1,BIGNOD		;MAKE
	MOVSS T1		; AOBJN
	HRRI T1,1		;  WORD
	MOVE T3,[POINT 2,NODTBL]  ;BYTE POINTER TO REACH TABLE
	NOINT			;NO INTERRUPTIONS
	LOCK NMAPLK		; WHILE
	LOCK NODLOK		;  TABLES LOCKED
NDGN02:	ILDB Q2,T3		;GET INFO
	SKIPE Q2		;REACHABLE?
	AOS T2			;YES. COUNT IT
       	AOBJN T1,NDGN02		;GET NEXT NODE INFO

;end of list
	IFE. T2      		;IF NONE REACHABLE, DONE
	  UNLOCK NODLOK		;UNLOCK
	  UNLOCK NMAPLK		; TABLES
	  OKINT			;ALLOW INTERRUPTS
	  RETSKP		;DONE.
	ENDIF.

;REACHABLE NODES HAVE BEEN COUNTED

	MOVE Q2,Q1		;COPY STARTING ADDRESS OF NODE BLOCK POINTERS
	ADD Q2,T2		;COMPUTE STARTING ADDRESS OF NODE BLOCK AREA
	CAMLE Q2,GNTCNT		;ENOUGH ROOM FOR ALL THE NODE BLOCK POINTERS ?
	IFNSK. <
	  MOVX T1,ARGX04	;GET "ARG BLOCK TOO SMALL"
	  JRST NDGNXX>		;FAIL
	MOVX T1,.NDNBS		;GET SIZE OF A NODE BLOCK
	UMOVEM T1,.NDCNT(T4)	;STORE IN USER ARG BLOCK

;LOOP OVER EACH NODE

	SETZM GNTRET		;INIT THE "NUMBER RETURNED"
	MOVNI T2,BIGNOD		;MAKE
	MOVSS T2		; AOBJN
	HRRI T2,1		;  WORD (node number in LH)
	MOVE T1,[POINT 2,NODTBL]  ;BYTE POINTER TO REACH TABLE
	MOVEM T1,GNTPTR		;SAVE POINTER
NDGN10:	ILDB Q3,GNTPTR		;GET INFO
	SKIPN Q3		;REACHABLE ?
	JRST NDGN20		;NO.
	HRRZ Q3,T2		;YES. GET NODE NUMBER
	SKIPN NODMAP(Q3)	;DOES THIS NODE HAVE A NAME?
	JRST NDGN20		;NO, DON'T RETURN ANYTHING TO USER
	UMOVEM Q2,(Q1)		;STORE POINTER TO NODE BLOCK
	 ERJMP NDGNXX		;FAILED, CLEAN UP AND RETURN ERROR
	MOVEI T1,.NDNBS(Q2)	;COMPUTE ADDRESS AFTER THIS NODE BLOCK
	CAML T1,GNTCNT		;ENOUGH ROOM FOR THIS NODE BLOCK AND NAME ?
	IFNSK. <
	  MOVX T1,ARGX04	;NO, GET "ARG BLOCK TOO SMALL"
	  JRST NDGNXX>		;GO CLEAN UP AND FAIL RETURN
	MOVX T1,.NDSON		;GET NODE STATE ("ON" IF IN KNOWN NODE TABLE)
	UMOVEM T1,.NDSTA(Q2)	;STORE STATE IN NODE BLOCK IN USER SPACE
	HRRI T3,.NDNBS(Q2)	;GET ADDRESS WHERE NAME WILL GO
	HRLI T3,(POINT 7,)	;FORM POINTER TO NODE NAME DESTINATION
	UMOVEM T3,.NDNAM(Q2)	;STORE POINTER TO NODE NAME IN USER SPACE
	MOVEI T1,NODMAP(Q3)	;GET ADDRESS OF NODE NAME
	HRLI T1,440600		;MAKE A BYTE POINTER TO THE SOURCE STRING
	MOVEM T2,PTRAOB		;SAVE AOBJN WORD (NUMBER OF NODES NOT YET PROCESSED IN RH)
	MOVEI T2,40		;CONVERT SIXBIT ASCII TO 7-BIT ASCII
	MOVEI T4,6		;MAX OF 6 CHARACTERS TO BE MOVED
	CALL STONOD		;STORE NODE NAME STRING IN USER SPACE
	 JRST NDGNXX		;FAILURE.
	MOVE T2,PTRAOB		;RETRIEVE THE AOBJN WORD
	ADDI Q1,1		;INCREMENT ADDRESS OF NEXT NODE BLOCK POINTER
	HRRI Q2,1(T3)		;GET ADDRESS OF NEXT NODE BLOCK
	AOS GNTRET		;INCR THE "NUMBER RETURNED"
NDGN20:	AOBJN T2,NDGN10		;LOOP OVER EACH NODE

; HERE WHEN ALL INFO RETURNED TO USER SUCCESSFULLY

	CALL NDGNRE		;FINISH UP
	RETSKP			;DONE, RETURN SUCCESS

; HERE ON AN ERROR

NDGNXX: CALLRET NDGNRE		;FINISH UP WITH FAILURE RETURN

;RETURN NUMBER OF NODES REPORTED AND CLEAN UP LOCKS
;RETURNS:	+1

NDGNRE:	MOVE T1,GNTRET		;GET NUMBER OF BLOCKS RETURNED
	MOVE T2,GNTBLK		;GET ADDR OF USER'S ARG BLOCK
	XCTU [HRLM T1,.NDNND(T2)]  ;RETURN THE INFO
	UNLOCK NODLOK 		;UNLOCK REACH TABLE
	UNLOCK NMAPLK		;UNLOCK THE MAPPING TABLE
	OKINT			;PERMIT INTERRUPTS AGAIN
	RET

	ENDTV.			;end TRVAR
; GET LINE INFORMATION INFORMATION

NDGLI:	STKVAR <LITCNT>

; SET UP TO LOOP OVER EACH NODE

	XCTU [HRRZ T2,2]	;GET ADDRESS OF USER'S ARGUMENT BLOCK
	XCTU [HRRZ T1,.NDNLN(T2)]	;GET NUMBER OF WORDS IN BLOCK
	ADD T1,T2		;COMPUTE LAST ADDRESS TO USE
	MOVEM T1,LITCNT		;SAVE LAST ADDRESS IN USER SPACE TO STORE INTO
	MOVEI Q1,.NDNLN+1(T2)	;SET UP ADDRESS OF NEXT POINTER TO USE
	MOVEI T3,DCN		;GET MAXIMUM NUMBER OF POSSIBLE LINES
	JUMPE T3,[SETZM T4	;IF NO INFO, RETURN 0
		  JRST NDLI40 ]	; IN THE USER ARGUMENT BLOCK
	UMOVE T4,2		;GET ADDRESS OF USER'S ARGUMENT BLOCK
	XCTU [HRLM T3,.NDNLN(T4)] ;STORE COUNT OF ITEMS RETURNED
	MOVE Q2,Q1		;COPY STARTING ADDRESS OF LINE BLOCK POINTERS
	ADD Q2,T3		;COMPUTE STARTING ADDRESS OF LINE BLOCK AREA
	CAMLE Q2,LITCNT		;ENOUGH ROOM FOR ALL THE LINE BLOCK POINTERS ?
	RETBAD (ARGX04)		;NO, FAIL
	MOVN Q3,T3		;COMPUTE -NUMBER OF LINES
	HRLZ Q3,Q3		;FORM AOBJN POINTER TO LINE TABLE

; LOOP OVER EACH KNOWN LINE

NDLI10:	UMOVEM Q2,(Q1)		;STORE POINTER TO LINE BLOCK
	MOVEI T1,.NDLSZ+2(Q2)	;COMPUTE ADDRESS AFTER THIS LINE BLOCK
	CAMLE T1,LITCNT		;ENOUGH ROOM FOR THIS LINE BLOCK AND NAME ?
	RETBAD(ARGX04)		;NO, FAIL
	MOVEI T1,.BTSTS		;USE BOOT JSYS TO GET STATUS OF LINE
	MOVEI T2,3		;HAVE IT PUT DATA IN AC'S
	HRRZ T3,Q3		;GET LINE NUMBER
	UMOVEM T3,.NDLNM(Q2)	;SAVE THE PORT NUMBER
	BOOT
	 ERJMP [ MOVE T1,LSTERR	;GET THE LAST ERROR MESSAGE
		 RETBAD()]
	MOVEI T3,.NDLON		;TRANSLATE BOOT CODE TO NODE JSYS CODE
	CAIE T4,.VNMCB		;IS IT RUNNING MCB
	CAIN T4,.VNDDC		;NO - IS IT RUNNING DDCMP
	JRST NDLI11		;YES - THEN IT IS ON
	MOVEI T3,.NDLCN		;IS IT CONTROLLER LOOPBACK?
	CAIN T4,.VNCNL		;???
	JRST NDLI11		;YES
	MOVEI T3,.NDLCB		;CABLE LOOPBACK?
	CAIN T4,.VNCBL		;??
	JRST NDLI11		;YES
	MOVEI T3,.NDLOF		;SEE IF IT'S OFF
NDLI11:	UMOVEM T3,.NDLST(Q2)	;STORE STATE IN LINE BLOCK IN USER SPACE
	HRRI T3,.NDLSZ(Q2)	;GET ADDRESS WHERE NAME WILL GO
	HRLI T3,(POINT 7,)	;FORM POINTER TO LINE NAME DESTINATION
	UMOVEM T3,.NDLND(Q2)	;STORE POINTER TO LINE NAME IN USER SPACE
	HRRZ T1,Q3		;ITSNAM INDEX IS TWICE THE LINE NUMBER
	LSH T1,1
	HRRI T1,ITSNAM(T1)	;GET ADDRESS OF LINE NAME STRING
	HRLI T1,(POINT 7,)	;FORM POINTER TO LINE NAME
	SETZB T2,T4		;NO OFFSET, STRING ENDS WITH A NULL
	CALL STONOD		;STORE LINE NAME STRING IN USER SPACE
	 JRST NDLI40		;FAILED
	ADDI Q1,1		;INCREMENT ADDRESS OF NEXT LINE BLOCK POINTER
	HRRI Q2,1(T3)		;GET ADDRESS OF NEXT LINE BLOCK
	AOBJN Q3,NDLI10		;LOOP OVER EACH LINE NAME TO BE RETURNED

; HERE WHEN ALL INFO RETURNED TO USER

NDLI40:	RETSKP			;DONE, RETURN SUCCESS

	ENDSV.

;STONOD - ROUTINE TO STORE NODE NAME STRING IN USER SPACE
;
;ACCEPTS IN T1/	BYTE POINTER TO SOURCE STRING
;	    T2/ OFFSET TO BE ADDED TO EACH CHARACTER
;	    T3/	BYTE POINTER TO DESTINATION IN USER SPACE
;	    T4/ MAX CHAR COUNT IF STRING DOESN'T END WITH NULL
;		CALL STONOD
;RETURNS: +1	 FAILED
;	  +2	SUCCESS

STONOD:	SAVEAC <P6>
STONO1:	ILDB P6,T1		;GET A BYTE
	JUMPE P6,STONO2		;IF NULL, ALL DONE
	SKIPE T2		;ANY OFFSET?
	ADD P6,T2		;YES
	XCTBU [IDPB P6,T3]	;STORE BYTE
	 ERJMP R		;FAILED, RETURN ERROR
	SKIPG T4		;COUNTING CHARS?
	JRST STONO1		;NO
	SOJG T4,STONO1		;YES - ANY MORE?
	SETZ P6,		;NO, MAKE A NULL
STONO2:	XCTBU [IDPB P6,T3]	;APPEND A NULL
	 ERJMP R		;FAILED, RETURN ERROR
	RETSKP			;DONE, RETURN SUCCESS
; NDVFY - VERIFY NODE NAME IS IN MONITOR'S DATABASE OF REACHABLE NODES
;NOTE:  IT MUST FIRST BE IN THE NODE NAME MAPPING TABLE

NDVFY:	SAVEAC (Q1)
	STKVAR <<NDVNOD,WPN>,VFYSTR,VFYARG>

; GET NODE NAME FROM USER SPACE

	UMOVE Q1,T2		;GET ADDRESS OF USER ARGUMENT BLOCK
	MOVEM Q1,VFYARG		;SAVE IT FOR LATER
	UMOVE T1,.NDNAM(Q1)	;GET POINTER TO NODE NAME IN USER SPACE
	MOVEI T2,NDVNOD		;GET ADDRESS OF DESTINATION FOR NAME
	CALL PARNDU		;GET THE NODE NAME FROM USER SPACE
	 RETBAD ()		;FAILED

; VERIFY THAT THE NODE IS IN NAME MAPPING TABLE

	HRRI T1,NDVNOD		;GET ADDRESS OF NODE NAME
	HRLI T1,(POINT 7,)	;FORM POINTER TO NODE NAME
	MOVEM T1,VFYSTR		;SAVE IT FOR LATER USE
	MOVE T3,T2		;GET NUMBER OF CHARS IN NAME (RETURNED FROM PARNDU)
	MOVNI T4,40		;COMPARING 7-BIT TO SIXBIT ASCII
	MOVNI P3,BIGNOD		;MAKE
	HRLZS P3		; AOBJN
	HRRI P3,1		;  WORD
	NOINT			;NO INTERRUPTIONS
	LOCK NMAPLK		; WHILE TABLE LOCKED
NDVFY1:	MOVE T1,VFYSTR		;GET BYTE POINTER TO USER'S NAME
	HRLI T2,440600		;MAKE A BYTE POINTER
	HRRI T2,NODMAP(P3)	; TO MAPPING TABLE
	TLO T3,400000		;SPECIAL CALL TO COMPAR
	CALL COMPAR		;IS THIS IT?
	 JRST [AOBJN P3,NDVFY1	;NO, ANY MORE TO TEST?
	       UNLOCK NMAPLK	;NO, GIVE UP
	       OKINT		; THE LOCK
	       SETZ T1,		;TURN OFF THE "FOUND IT" BIT
	       JRST NDVFY2]	;DONE

;NODE IS IN NODE NAME MAPPING TABLE

	UNLOCK NMAPLK		;DONE WITH THE MAPPING TABLE
	LOCK NODLOK		;NOW LOCK THE REACH TABLE
	MOVE T1,[POINT 2,NODTBL]  ;MAKE BYTE POINTER TO BEGINNING OF REACH TABLE
	HRRZS P3		;GET JUST THE NODE NUMBER
	ADJBP P3,T1		;POINT TO APPROPRIATE ENTRY
	LDB T1,P3		;GET THE INFO
	SKIPN T1		;REACHABLE?
	JRST [UNLOCK NODLOK	;NO, DONE WITH
	      OKINT		; THE LOCK
	      SETZ T1,		;TURN OFF THE "FOUND IT" BIT
	      JRST NDVFY2]	;DONE

;NODE IS REACHABLE

	UNLOCK NODLOK		;DONE WITH
	OKINT			; THE LOCK
	MOVX T1,ND%EXM		;TURN ON THE "FOUND IT" BIT

;RETURN INFO TO THE USER

NDVFY2:	MOVE T2,VFYARG		;RETRIEVE ADDR OF USER'S ARG BLOCK
	UMOVEM T1,.NDFLG(T2)	;RETURN THE NEWS TO THE USER
	RETSKP

	ENDSV.
; NDRNM - GIVEN A NODE NUMBER, RETURN THE NODE NAME

NDRNM:	UMOVE T4,.NDNOD(T2)	;GET NODE @MBER
	CAIL T4,1		;IS IT
	CAILE T4,BIGNOD		; LEGAL?
	RETBAD (NSPX25)		;NO
	NOINT			;LOCK THE
	LOCK NMAPLK		; NODE NAME MAPPING TABLE
	UMOVE T3,.NDCVR(T2)	;GET THE USER'S BP
	HRLI T2,440600		;MAKE A BP
	HRRI T2,NODMAP(T4)	; TO THE NAME
	CALL NTRNAM		;RETURN THE NODE NAME TO THE USER
	UMOVEM T3,.NDCVR(T2)	;RETURN UPDATED BP TO USER
	SETZ T4,		;GIVE HIM
	XCTBU [IDPB T4,T3]	; THE NULL
	UNLOCK NMAPLK		;DONE WITH
	OKINT			; THE LOCK
	RETSKP
	SUBTTL NTMAN% JSYS Functions

;Network Management's interface to the lower layers of DECnet architecture.

;THIS INTERFACE ASSUMES AT ALL TIMES:
;
;Q1/ ADDRESS OF MONITOR'S COPY OF THE USER'S ARGUMENT BLOCK
;Q3/ AMOUNT OF SPACE (IN BYTES) REMAINING IN USER'S RETURN BUFFER

	SWAPCD
.NTMAN::MCENT
	STKVAR <USRARG,ARGSIZ,MONARG>
	MOVE T1,CAPENB		;GET ENABLED CAPABILITIES
	TXNN T1,SC%WHL!SC%OPR	;WHEEL OR OPERATOR ENABLED?
	ITERR (CAPX1)		;NO.  RETURN "NOT ENOUGH CAPABILITIES" ERROR
	UMOVE T2,1		;GET USER'S ARG BLOCK ADDR
	MOVEM T2,USRARG		;SAVE IT
	UMOVE T1,.NTCNT(T2)	;GET USER'S LENGTH OF ARG BLOCK
	CAIE T1,.NTARG		;CORRECT SIZE?
	ITERR (ARGX17)		;NO, ERROR RETURN
	NOINT
	CALL GETBLK		;GET SWAPPABLE FREE SPACE FOR USER'S ARGS
	 JRST [OKINT		;CAN'T
	       HRREI T3,NTXRE	;RESOURCE ERROR
	       MOVE T1,USRARG	;GET USER'S ARG BLOCK ADDRESS
	       UMOVEM T3,.NTERR(T1)  ;UPDATE ERROR RETURN STATUS
	       ITERR (NTMX1)]	;NETWORK MANAGEMENT GENERIC ERROR
	OKINT
	MOVEM T1,MONARG		;SAVE IT
	MOVEI T1,.NTARG		;GET ARG BLOCK LENGTH
	MOVE T2,USRARG		;RETRIEVE USER'S ARG BLOCK ADDR
	MOVE T3,MONARG		;RETRIEVE MONITOR'S ARG BLOCK ADR
	CALL BLTUM1		;MOVE ARG BLOCK TO MONITOR
	MOVE Q1,MONARG		;SET UP ARG BLOCK ADDR
	LDB T1,[POINT 6,.NTBPT(Q1),11]  ;GET THE USER'S BYTE SIZE
	CAIE T1,^D8		;MUST BE 8-BIT BYTES
	IFNSK.			;NOT SO
	   CALL NMXMPE		;NETWORK MANAGEMENT PROGRAM ERROR
	   CALL NTMRET		;CLEAN UP
	   ITERR (ARGX09)	;JSYS ERROR RETURN - INVALID BYTE SIZE
	ENDIF.
	MOVE T1,.NTENT(Q1)	;GET ENTITY
	MOVE Q3,.NTBYT(Q1)	;GET USER'S BUFFER SIZE
	SETZM .NTBYT(Q1)	;INIT THE RETURN COUNT
	CAIL T1,0		;A VALID
	CAIL T1,NTENTL		; ENTITY?
	JRST [CALL NMXII	;INVALID IDENTIFICATION ERROR
	      CALL NTMRET	;CLEAN UP
	      ITERR ( )]	;ERROR RETURN
	MOVE T4,NTMENT(T1)	;YES, GET THE DISPATCH ADDRESS
	CALL (T4)		;GO DO THE WORK
	 JRST [CALL NTMRET	;GO FINISH UP
	       ITERR ( )]	;FAILURE RETURN
	MOVEI T2,NTXGUD		;SUCCESSFUL COMPLETION
	MOVEM T2,.NTERR(Q1)	;PUT STATUS IN ARG BLOCK
	CALL NTMRET		;GO FINISH UP
	MRETNG			;SUCCESS
;NTMAN% JSYS CLEAN UP ROUTINE - FILLS IN USER'S ARGUMENT BLOCK

NTMRET:	SAVEAC <T1>
	MOVEI T1,.NTARG		;GET LENGTH OF ARGUMENT BLOCK
	MOVE T2,Q1		;GET UPDATED ARG BLOCK
	UMOVE T3,T1		;GET USER'S ADDRESS
	CALL BLTMU1		;GIVE IT BACK
	MOVE T1,Q1		;GET ARG BLOCK ADDR
	NOINT
	CALL RELBLK		;RELEASE IT
	OKINT
	RET

	ENDSV.


;NTMAN% "ENTITY" DISPATCH TABLE

NTMENT:	EXP NTNOD		;NODE
	EXP NMXUC		;LINE
	EXP NMXUC		;LOG
	EXP NMXUC		;CIRCUIT
	EXP NMXUC		;MODULE
NTENTL==.-NTMENT
;Network Management Error Status Returns

;ROUTINE TO RETURN ERROR -1 (UNRECOGNIZED FUNCTIONS OR OPTION)

NMXUFO:	HRREI T1,NTXUFO		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -5 (MANAGEMENT PROGRAM ERROR)

NMXMPE:	HRREI T1,NTXMPE		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -6 (UNRECOGNIZED PARAMETER TYPE)

NMXUPT:	HRREI T1,NTXUPT		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -8 (UNRECOGNIZED COMPONENT)

NMXUC:	HRREI T1,NTXUC		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -9 (INVALID IDENTIFICATION)

NMXII:	HRREI T1,NTXII		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -10 (LINE COMMUNICATION ERROR)

NMXLCE:	HRREI T1,NTXLCE		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -11 (COMPONENT IN WRONG STATE)

NMXCWS:	HRREI T1,NTXCWS		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -15 (RESOURCE ERROR)

NMXRE:	HRREI T1,NTXRE		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -16 (INVALID PARAMETER VALUE)

NMXIPV:	HRREI T1,NTXIPV		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -22 (PARAMETER NOT APPLICABLE)

NMXPNA:	HRREI T1,NTXPNA		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -25 (OPERATION FAILURE)

NMXOF:	HRREI T1,NTXOF		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE


;ROUTINE TO RETURN ERROR -29 (PARAMETER MISSING)

NMXPM:	HRREI T1,NTXPM		;GET THE ERROR CODE
	MOVEM T1,.NTERR(Q1)	;PUT IT IN THE ARG BLOCK
	RETBAD (NTMX1)		;RETURN GENERIC ERROR CODE ON JSYS FAILURE
;LIST OF NODE COUNTER TABLE ADDRESSES

NSNODC:	EXP NSBYTR		;BYTES RECEIVED
	EXP NSBYTS		;BYTES SENT
	EXP NSMSGR		;MESSAGES RECEIVED
	EXP NSMSGS		;MESSAGES SENT
	EXP NSCONR		;CONNECTS RECEIVED
	EXP NSCONS		;CONNECTS SENT
	EXP NSTIMO		;RESPONSE TIMEOUTS
	EXP NSRCNE		;RECEIVED CONNECT RESOURCE ERRORS
	EXP NSALNK		;ACTIVE LOGICAL LINKS
NSNODL==.-NSNODC
;NODE COUNTER INFORMATION - PARALLEL TO NSNODC
;LH/ NUMBER OF BITS IN COUNTER DATA
;RH/ COUNTER NUMBER

NSNWID:	.NSW40,,.NSBYR		;BYTES RECEIVED
	.NSW40,,.NSBYS		;BYTES SENT
	.NSW40,,.NSMGR		;MESSAGES RECEIVED
	.NSW40,,.NSMGS		;MESSAGES SENT
	.NSW20,,.NSCNR		;CONNECTS RECEIVED
	.NSW20,,.NSCNS		;CONNECTS SENT
	.NSW20,,.NSRTO		;RESPONSE TIMEOUTS
	.NSW20,,.NSRCE		;RECEIVED CONNECT RESOURCE ERRORS
	.NSW20,,.NSALL		;ACTIVE LOGICAL LINKS
NSNWDL==.-NSNWID



;NODE PARAMETER ITEMS

NSNPAR:	.NDSTT			;NODE STATE
	.NDNID			;IDENTIFICATION
	.NDNNA			;NODE NAME
	.NDCNN			;CIRCUIT FOR NODE NAME
	.NDNNU			;NODE NUMBER
	.NDITM			;INCOMING TIMER
	.NDOTM			;OUTGOING TIMER
	.NDALK			;ACTIVE LINKS
	.NDDLY			;DELAY
	.NDVRS			;VERSION
	.NDLML			;LOCAL MAXIMUM LINKS
	.NDLDF			;LOCAL DELAY FACTOR
	.NDLDW			;LOCAL DELAY WEIGHT
	.NDIAT			;INACTIVITY TIMER
	.NDRTF			;RETRANSMIT FACTOR
	.NDTYP			;TYPE
NSNPRL==.-NSNPAR


;NODE IDENTIFICATION STRING (I-32)

NDIDN:	BYTE (8) ^D10,"T","O","P","S","-","2","0"," ","V","5",0
;ENTITY = NODE
;NOW GET THE FUNCTION
;RETURNS:	+1  FAILED, T1/ ERROR CODE
;		+2  SUCCESS

NTNOD:	MOVE T1,.NTFNC(Q1)	;GET FUNCTION REQUESTED
	MOVNI T2,LOWFNC		;ADJUST THE FUNCTION CODE
	HRRZS T2		;MAKE IT USEFUL
	ADD T1,T2		; FOR DISPATCHING
	CAIL T1,0		;A VALID
	CAIL T1,NTNODL		; FUNCTION?
	JRST NMXII		;NO, ERROR RETURN
	MOVE T4,NTNODF(T1)	;GET DISPATCH ADDRESS
	CALL (T4)		;GO DO THE WORK
	 RETBAD ()		;ERROR
	RETSKP			;SUCCESS

NTNODF:	EXP NTNMAP		;(-2) MAP NODE NUMBER TO NODE NAME
	EXP NTNREX		;(-1) RETURN EXECUTOR NODE ID
	EXP NTNSET		;(0) SET PARAMETER
	EXP NTNCLR		;(1) CLEAR PARAMETER
	EXP NTNZRO		;(2) ZERO ALL COUNTERS
	EXP NTNSHO		;(3) SHOW SELECTED ITMES
	EXP NTNSZC		;(4) SHOW AND ZERO ALL COUNTERS
	EXP NTNRET		;(5) RETURN LIST OF ITEMS
NTNODL==.-NTNODF
;ENTITY = NODE
;FUNCTION = MAP NODE NUMBER TO NODE NAME
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NTNMAP:	STKVAR <BEGIN>
	MOVE T2,.NTBPT(Q1)	;GET USER'S BYTE POINTER
	MOVEM T2,BEGIN		;PRESERVE IT
	MOVEI T1,.NDALN		;GET LENGTH OF NODE NUMBER
	ADJBP T1,.NTBPT(Q1)	;SKIP THE NODE NUMBER
	XCTBU [ILDB T2,T1]	;GET THE NUMBER OF BYTES IN THE NODE NAME
	JUMPN T2,NTNMA1		;IF SOME THERE, MOVE ON
	HRREI T2,-<.NDALN+1>	;BACKUP TO
	ADJBP T2,T1		; NODE NUMBER
	MOVEM T2,.NTBPT(Q1)	;RESET THE BYTE POINTER
	MOVEI T3,.NTBPT(Q1)	;POINT TO THE NEW POINTER
	CALL GETADR		;GET THE NODE NUMBER
	 JRST NMXUC		;FAILED
	CALL FNDNAM		;LOOK UP THE NODE NAME
	CALL RETNAM		;RETURN IT TO USER
	 RETBAD ()		;FAILED
	RETSKP			;DONE

NTNMA1:	SETO T2,		;BACKUP TO
	ADJBP T2,T1		; READ THE NODE NAME
	MOVEM T2,.NTBPT(Q1)	;RESET THE BYTE POINTER
	MOVEI T3,.NTBPT(Q1)	;POINT TO THE NEW POINTER
	CALL GETNAM		;GET THE NODE NAME
	 RETBAD ()		;FAILED
	NOINT
	LOCK NMAPLK		;LOCK THE NODE NAME MAPPING TABLE
	CALL FNDADR		;FIND THE NODE NUMBER
	 JRST [	UNLOCK NMAPLK	;UNLOCK THE TABLE
		OKINT
		JRST NMXUC]	;FAILED
	UNLOCK NMAPLK		;UNLOCK THE TABLE
	OKINT
	MOVE T2,BEGIN		;RESET THE USER'S
	MOVEM T2,.NTBPT(Q1)	; BYTE POINTER
	CALL RETADR		;RETURN THE NODE NUMBER
	 RETBAD ()		;FAILED
	RETSKP

	ENDSV.
;ENTITY = NODE
;FUNCTION = RETURN EXECUTOR NODE ID
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NTNREX:	MOVE T1,OURNUM		;GET OUR NODE NUMBER
	CALL RETADR		;RETURN IT
	 RETBAD ()		;FAILED
	CALL FNDNAM		;LOOK UP NODE NAME
	CALL RETNAM		;RETURN IT
	 RETBAD ()		;FAILED
	RETSKP			;DONE
;ENTITY = NODE
;FUNCTION = SET PARAMETER
;NOW FIND THE PARAMETER
;RETURNS:	+1  FAILURE
;		+2  SUCCESS


NTNSET:	MOVEI T3,.NTBPT(Q1)	;GET USER'S BYTE POINTER
	CALL GETPAR		;GET THE PARAMETER NUMBER
	CALL FNDPAR		;LOOK IT UP
	 RETBAD ( )
	MOVE T4,NTNSTP(T1)	;GET THE DISPATCH ADDRESS
	CALL (T4)		;GO DO THE WORK
	 RETBAD ()		;ERROR
	RETSKP			;SUCCESS

NTNSTP:	EXP NMXUPT		;LOCAL NODE STATE
	EXP NMXUPT		;IDENTIFICATION
	EXP SCNSET		;NODE NAME
	EXP NMXUPT		;CIRCUIT FOR NODE NAME
	EXP NMXUPT		;NODE NUMBER
	EXP NMXUPT		;INCOMING TIMER
	EXP NMXUPT		;OUTGOING TIMER
	EXP NMXUPT		;ACTIVE LINKS
	EXP NMXUPT		;DELAY
	EXP NMXUPT		;VERSION
	EXP NMXUPT		;MAXIMUM LINKS
	EXP NSNLDF		;LOCAL DELAY FACTOR
	EXP NSNLDW		;LOCAL DELAY WEIGHT
	EXP NSNIAT		;INACTIVITY TIMER
	EXP NSNTRY		;RETRANSMIT FACTOR
	EXP NMXUPT		;TYPE
NTNSTL==.-NTNSTP
;ENTITY = NODE
;FUNCTION = SET PARAMETER
;PARAMETER = NAME
;RETURNS:	+1  FAILED
;		+2  SUCCESS

SCNSET:	STKVAR <ADDR>
	MOVEI T3,.NTEID(Q1)	;POINT TO ENTITY ID BYTE POINTER
	CALL GETADR		;GET NODE ADDRESS FROM USER
	 JRST NMXII		;FAILED - "INVALID NODE ADDRESS"
	MOVEM T1,ADDR		;STASH THE NODE ADDRESS
	MOVEI T3,.NTBPT(Q1)	;POINT TO PARAMETER INFO BYTE POINTER
	CALL GETNAM		;GET NODE NAME FROM USER
	 RETBAD ()		;FAILED
	MOVE T2,ADDR		;GET ADDRESS IN GOOD PLACE
	NOINT
	LOCK NMAPLK		;LOCK THE MAPPING TABLE
	HRLZI T3,-<BIGNOD+1>	;MAKE AOBJN WORD
SCNSE1:	HRRZ T4,T3		;GET THE OFFSET ONLY
	ADD T4,[NODMAP]		;MOVE INTO THE TABLE
	CAMN T1,(T4)		;THIS ENTRY MATCH?
	JRST [	HRRZ T4,T3	;YES, GET ITS NUMBER
		CAMN T4,T2	;SAME AS ONE BEING SET?
		JRST SCNSE2	;YES, THAT'S OK
		UNLOCK NMAPLK	;UNLOCK THE TABLE
		OKINT
		JRST NMXCWS]	;FAIL - NAME ALREADY ASSIGNED TO ANOTHER NODE
	AOBJN T3,SCNSE1		;CHECKED THE ENTIRE TABLE?
	ADD T2,[NODMAP]		;MOVE INTO THE TABLE
	MOVEM T1,(T2)		;PUT NODE NAME INTO TABLE
SCNSE2:	UNLOCK NMAPLK		;UNLOCK THE MAPPING TABLE
	OKINT
	RETSKP			;GOOD RETURN

	ENDSV.
;ENTITY = NODE
;FUNCION = SET PARAMETER
;PARAMETER = INACTIVITY TIMER
;RETURNS:	+1 FAILURE
;		+2 SUCCESS

NSNIAT:	MOVEI T3,.NTBPT(Q1)	;GET BP TO USER'S ARG
	MOVEI T4,2		;2 BYTES IN LENGTH
	CALL GETNUM		;GET THE VALUE FROM USER
	CAIL T2,1		;A LEGAL
	CAILE T2,^D65535	; VALUE?
	JRST NMXIPV		;NO, FAIL
	IMULI T2,^D1000		;CONVERT TO MILLISECONDS
	MOVEM T2,NSINAC		;SET THE NEW VALUE
	RETSKP			;DONE


;ENTITY = NODE
;FUNCION = SET PARAMETER
;PARAMETER = LOCAL DELAY WEIGHT
;RETURNS:	+1 FAILURE
;		+2 SUCCESS

NSNLDW:	MOVEI T3,.NTBPT(Q1)	;GET BP TO USER'S ARG
	MOVEI T4,1		;1 BYTES IN LENGTH
	CALL GETNUM		;GET THE VALUE FROM USER
	CAIL T2,1		;A LEGAL
	CAILE T2,^D255		; VALUE?
	JRST NMXIPV		;NO, FAIL
	MOVEM T2,NSLDWS		;SET THE NEW VALUE
	RETSKP			;DONE


;ENTITY = NODE
;FUNCION = SET PARAMETER
;PARAMETER = LOCAL DELAY FACTOR
;RETURNS:	+1 FAILURE
;		+2 SUCCESS

NSNLDF:	MOVEI T3,.NTBPT(Q1)	;GET BP TO USER'S ARG
	MOVEI T4,1		;1 BYTES IN LENGTH
	CALL GETNUM		;GET THE VALUE FROM USER
	CAIL T2,1		;A LEGAL
	CAILE T2,^D63		; VALUE?
	JRST NMXIPV		;NO, FAIL
	MOVEM T2,NSLDFS		;SET THE NEW VALUE
	RETSKP			;DONE


;ENTITY = NODE
;FUNCION = SET PARAMETER
;PARAMETER = RETRANSMIT FACTOR
;RETURNS:	+1 FAILURE
;		+2 SUCCESS

NSNTRY:	MOVEI T3,.NTBPT(Q1)	;GET BP TO USER'S ARG
	MOVEI T4,2		;2 BYTES IN LENGTH
	CALL GETNUM		;GET THE VALUE FROM USER
	CAIL T2,1		;A LEGAL
	CAILE T2,^D20		; VALUE?
	JRST NMXIPV		;NO, FAIL
	MOVEM T2,NSTRYS		;SET THE NEW VALUE
	RETSKP			;DONE
;ENTITY = NODE
;FUNCTION = CLEAR PARAMETER
;NOW FIND THE PARAMETER
;RETURNS:	+1  FAILURE
;		+2  SUCCESS


NTNCLR:	SKIPN Q3		;BYTE COUNT = 0?
	JRST NTNCLA		;YES, THAT MEANS CLEAR ALL PARAMETERS
	MOVEI T3,.NTBPT(Q1)	;GET ADDRESS OF USER'S POINTER
	CALL GETPAR		;GET PARAMETER NUMBER
	CALL FNDPAR		;LOOK IT UP
	 RETBAD ( )
	MOVE T4,NTNCLP(T1)	;GET DISPATCH ADDRESS
	CALL (T4)		;GO DO THE WORK
	 RETBAD ()		;ERROR
	RETSKP			;SUCCESS

NTNCLP:	EXP NMXUPT		;LOCAL NODE STATE
	EXP NMXUPT		;IDENTIFICATION
	EXP SCNCLR		;NODE NAME
	EXP NMXUPT		;CIRCUIT FOR NODE NAME
	EXP NMXUPT		;NODE NUMBER
	EXP NMXUPT		;INCOMING TIMER
	EXP NMXUPT		;OUTGOING TIMER
	EXP NMXUPT		;ACTIVE LINKS
	EXP NMXUPT		;DELAY
	EXP NMXUPT		;VERSION
	EXP NMXUPT		;MAXIMUM LINKS
	EXP NMXUPT		;LOCAL DELAY FACTOR
	EXP NMXUPT		;LOCAL DELAY WEIGHT
	EXP NMXUPT		;INACTIVITY TIMER
	EXP NMXUPT		;RETRANSMIT FACTOR
	EXP NMXUPT		;TYPE
NTNCLL==.-NTNCLP


;ENTITY = NODE
;FUNCTION = CLEAR (ALL)
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NTNCLA:	CALL SCNCLR		;DO SESSION CONTROL'S PART
	 RETBAD ()		;FAILED
	RETSKP			;DONE
;ENTITY = NODE
;FUNCTION = CLEAR PARAMETER
;PARAMETER = NAME
;RETURNS:	+1  FAILED
;		+2  SUCCESS


SCNCLR:	MOVEI T3,.NTEID(Q1)	;POINT TO ENTITY ID BYTE POINTER
	CALL GETADR		;GET USER'S NODE ADDRESS
	 JRST NMXII		;BAD
	NOINT
	LOCK NMAPLK		;LOCK THE MAPPING TABLE
	ADD T1,[NODMAP]		;MOVE INTO THE TABLE
	SETZM (T1)		;NULLIFY CURRENT MAPPING
	UNLOCK NMAPLK		;UNLOCK THE MAPPING TABLE
	OKINT
	RETSKP			;GOOD RETURN


;ENTITY = NODE
;FUNCTION = ZERO COUNTERS
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NTNZRO:	CALL NANUEX		;GET THE NODE NUMBER
	 RETBAD ()		;FAILED
NTNZR2:	MOVEI T4,NSNODL-1	;GET NUMBER OF COUNTERS
NTNZR1:	MOVE T3,NSNODC(T4)	;GET THE TABLE
	ADD T3,T1		;GET THE OFFSET
	SETZM (T3)		;ZERO THE COUNT
	SOJGE T4,NTNZR1		;MORE TO DO?
	RETSKP			;NO, DONE
;ENTITY = NODE
;FUNCTION = SHOW SELECTED ITEMS
;NOW FIND SELECTOR
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NTNSHO:	MOVE T1,.NTSEL(Q1)	;GET THE SELECTOR
	CAIL T1,0		;A VALID
	CAIL T1,NTSHOL		; SELECTOR?
	JRST NMXII		;NO, FAIL
	MOVE T4,NTSHOT(T1)	;GET DISPATCH ADDRESS
	CALL (T4)		;GO DO THE WORK
	 RETBAD ()		;FAILED
	RETSKP			;SUCCESS

NTSHOT:	EXP NTNSUM		;SUMMARY
	EXP NTNSTS		;STATUS
	EXP NTNSCH		;CHARACTERISTICS
	EXP NSNSCO		;COUNTERS
	EXP NMXUFO		;EVENTS
NTSHOL==.-NTSHOT


;ENTITY = NODE
;FUNCTION = SUMMARY
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NTNSUM:	STKVAR <NDNUM>
	CALL NANUEX		;GET THE NODE NUMBER
	 RETBAD ()		;FAILED
	MOVEM T1,NDNUM		;SAVE THE NODE NUMBER
	CALL DOSTA		;DO STATE PARAMETER
	 RETBAD ()		;FAILED
	MOVE T1,NDNUM		;RETRIEVE THE NODE NUMBER
	CALL RETALK		;DO ACTIVE LINK PARAMETER
	 RETBAD ()		;FAILED
	MOVE T1,NDNUM		;RETRIEVE NODE NUMBER
	CAME T1,OURNUM		;IS IT US?
	RETSKP			;NO, DONE
;	CALL RETIDN		;RETURN IDENTIFICATION PARAMETER
;	 RETBAD ()		;FAILED
	RETSKP			;DONE

	ENDSV.
;ENTITY = NODE
;FUNCTION = SHOW SELECTED ITEMS
;SELECTOR = STATUS
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NTNSTS:	STKVAR <NDNUM>
	CALL NANUEX		;GET NODE NUMBER
	 RETBAD ()		;FAILED
	MOVEM T1,NDNUM		;SAVE NODE NUMBER
	CALL SCNSTS		;DO SESSION CONTROL
	 RETBAD ()		;FAILED
	MOVE T1,NDNUM		;RETRIEVE NODE NUMBER
	CALL NSNSTS		;DO NSP
	 RETBAD ()		;FAILED
	RETSKP			;DONE

	ENDSV.


;ROUTINE TO DO SESSION CONTROL'S PART OF SHOW NODE STATUS
;ACCEPTS:	T1/ NODE NUMBER
;RETURNS:	+1  FAILED
;		+2  SUCCESS

SCNSTS:	CALL DOSTA		;DO STATE PARAMETER
	 RETBAD ()		;FAILED
	RETSKP			;DONE


;ROUTINE TO DO NSP'S PART OF SHOW NODE STATUS
;ACCEPTS:	T1/ NODE NUMBER
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NSNSTS:	CALL RETALK		;DO ACTIVE LINK PARAMETER
	 RETBAD ()		;FAILED
	RETSKP
;ROUTINE TO RETURN THE ACTIVE LINK PARAMETER
;ACCEPTS:	T1/ NODE NUMBER
;RETURNS:	+1 FAILED
;		+2 SUCCESS

RETALK:	SAVEAC <P3>
	STKVAR <NDNUM>
	MOVEM T1,NDNUM		;SAVE THE NODE NUMBER
	CALL GTALNK		;GO GET THE NUMBER OF ACTIVE LINKS
	MOVE T1,NDNUM		;RETRIEVE THE NODE NUMBER
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T3,NTPAR		;PARAMETER DATA
	STOR T3,DIDDA,Q2	;PUT IT IN
	MOVEI T3,.NDALK		;PARAMETER IS ACTIVE LINK
	STOR T3,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T1,NTNCD		;NOT CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTBIN		;BINARY NUMBER
	STOR T1,DTYTY,Q2	;PUT IT IN
	MOVEI T1,2		;2 BYTES
	STOR T1,DTYLN,Q2	;PUT IT IN
	MOVEI T1,NTUDN		;UNSIGNED DECIMAL NUMBER
	STOR T1,DTYBF,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,2		;2 BYTES
	MOVE T3,[NSALNK]	;ACTIVE LINKS TABLE
	ADD T3,NDNUM		;OFFSET INTO TABLE
	MOVE P3,(T3)		;GET THE CURRENT VALUE
	LSH P3,^D20		;POSITION IT
	MOVE T2,[441000,,P3]	;MAKE A BYTE POINTER
	CALL RETNUM		;RETURN IT TO USER
	 RETBAD ()		;FAILED
	RETSKP

	ENDSV.
;GET NUMBER OF ACTIVE LINKS FOR ALL NODES
;RETURNS:	+1 WITH NSALNK TABLE FILLED IN

GTALNK:	MOVEI T1,NSALNK		;GET BEGINNING OF TABLE
	SETZM (T1)		;ZERO
	HRL T2,T1		; THE
	HRRI T2,1(T1)		;  ACTIVE LINKS
	BLT T2,BIGNOD(T1)	;   TABLE
	LLLOCK			;LOCK THE LL STRUCTURE
	MOVEI T1,GTALCO		;GET ADDRESS OF COROUTINE
	SETO T2,		;ALL LINKS
	CALL OBJSRC		;GO SEARCH THE LINK STRUCTURE
	 JFCL			;DOESN'T MATTER MUCH
	CALLRET ULOKLL		;UNLOCK THE LL STRUCTURE

GTALCO:	SAVET
	CALL BLKLOK		;LOCK THIS LL BLOCK
	 RET			;CAN'T, GO GET NEXT ONE
	LOAD T2,LLSTA,(T1)	;GET STATE OF LINK
	CAIN T2,LLSLIS		;LISTENING?
	JRST GTALCD		;YES, NOT INTERESTING
	LOAD T2,LLHSN,(T1)	;GET OTHER HOST'S NUMBER
	AOS NSALNK(T2)		;BUMP THE COUNT
GTALCD:	CALLRET BLKULK		;UNLOCK THIS LL BLOCK
;ROUTINE TO ASSIST IN RETURNING THE STATE OF A NODE
;ACCEPTS:	T1/ NODE NUMBER
;RETURNS:	+1/ FAILED
;		+2/ SUCCESS

DOSTA:	CAME T1,OURNUM		;IS IT US?
	JRST DOST1		;NO
	MOVEI T2,.NDON		;YES, SESSION CONTROL IS ON
	JRST DOST2		;MOVE ON
DOST1:	MOVE T3,[440200,,NODTBL]  ;MAKE BP TO REACHABLE NODES TABLE
	ADJBP T1,T3		;OFFSET TO THE NODE IN QUESTION
	LDB T2,T1		;GET ITS STATE
	SKIPE T2		;IS IT REACHABLE?
	JRST [	MOVEI T2,.NDREA  ;YES
		JRST DOST2]	;MOVE ON
	MOVEI T2,.NDUNR		;NO
DOST2:	CALL RETSTA		;RETURN THE STATE
	 RETBAD ()		;FAILED
	RETSKP
;ROUTINE TO RETURN THE STATE PARAMETER
;ACCEPTS:	T2/ STATE
;RETURNS:	+1 FAILED
;		+2 SUCCESS

RETSTA:	SAVEAC <P3>
	STKVAR <STATE>
	MOVEM T2,STATE		;SAVE THE STATE
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T3,NTPAR		;PARAMETER DATA
	STOR T3,DIDDA,Q2	;PUT IT IN
	MOVEI T3,.NDSTT		;PARAMETER IS STATE
	STOR T3,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T1,NTCOD		;CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTSNG		;SINGLE FIELD
	STOR T1,DTYTY,Q2	;PUT IT IN
	MOVEI T1,1		;1 BYTE
	STOR T1,DTYCN,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,1		;1 BYYTE
	MOVE P3,STATE		;GET THE STATE
	LSH P3,^D28		;POSITION IT
	MOVE T2,[441000,,P3]	;MAKE A BP TO IT
	CALL RETNUM		;RETURN IT
	 RETBAD ()		;FAILED
	RETSKP

	ENDSV.
;ENTITY = NODE
;FUNCTION = SHOW SELECTED ITEMS
;SELECTOR = CHARACTERISTICS
;RETURNS:	+1 FAILED, 1/ ERROR CODE
;		+2 SUCCESS

NTNSCH:	CALL NANUEX		;GET NODE NUMBER
	 RETBAD ()		;FAILED
	CAME T1,OURNUM		;IS IT US?
	RETSKP			;NO, NOTHING TO RETURN
	CALL SCNSCH		;DO SESSION CONTROL
	 RETBAD ()		;FAILED
	CALL NSNSCH		;DO NSP
	 RETBAD ()		;FAILED
	CALL XPNSCH		;DO TRANSPORT
	 RETBAD ()		;FAILED
	RETSKP			;DONE


;SESSION CONTROL'S PART OF SHOW CHARACTERISTICS
;RETURNS:	+1 FAILED
;		+2 SUCCESS

SCNSCH:
;	CALL RETIDN		;RETURN THE IDENTIFICATION
;	 RETBAD ()		;FAILED
	RETSKP			;DONE
;NSP'S PART OF SHOW CHARACTERISTICS
;RETURNS:	+1 FAILED
;		+2 SUCCESS

NSNSCH:	SAVEAC <P3>

;DO NSP VERSION

	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T2,NTPAR		;PARAMETER DATA
	STOR T2,DIDDA,Q2	;PUT IT IN
	MOVEI T2,.NDVRS		;PARAMETER IS NSP VERSION
	STOR T2,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T2,NTCOD		;CODED
	STOR T2,DTYCD,Q2	;PUT IT IN
	MOVEI T2,NTMUL		;MULTIPLE FIELDS
	STOR T2,DTYTY,Q2	;PUT IT IN
	MOVEI T2,3		;3 FIELDS
	STOR T2,DTYCN,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,COMVER		;GET THE VERSION OF NSP
	CALL MAKDTY		;DO THE DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,COMECO		;GET THE ECO LEVEL OF NSP
	CALL MAKDTY		;DO THE DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,COMCST		;GET THE CUSTOMER LEVEL OF NSP
	CALL MAKDTY		;DO THE DATA TYPE
	 RETBAD ()		;FAILED

;DO NSP LOCAL DELAY FACTOR

	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T3,NTPAR		;PARAMETER DATA
	STOR T3,DIDDA,Q2	;PUT IT IN
	MOVEI T3,.NDLDF		;PARAMETER IS LOCAL DELAY FACTOR
	STOR T3,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T1,NTNCD		;NOT CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTBIN		;BINARY NUMBER
	STOR T1,DTYTY,Q2	;PUT IT IN
	MOVEI T1,1		;1 BYTE
	STOR T1,DTYLN,Q2	;PUT IT IN
	MOVEI T1,NTUDN		;UNSIGNED DECIMAL NUMBER
	STOR T1,DTYBF,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,1		;1 BYTE
	MOVE P3,NSLDFS		;GET THE CURRENT VALUE
	LSH P3,^D28		;POSITION IT
	MOVE T2,[441000,,P3]	;MAKE A BYTE POINTER
	CALL RETNUM		;RETURN IT TO USER
	 RETBAD ()		;FAILED

;DO NSP LOCAL DELAY WEIGHT

	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T3,NTPAR		;PARAMETER DATA
	STOR T3,DIDDA,Q2	;PUT IT IN
	MOVEI T3,.NDLDW		;PARAMETER IS LOCAL DELAY WEIGHT
	STOR T3,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T1,NTNCD		;NOT CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTBIN		;BINARY NUMBER
	STOR T1,DTYTY,Q2	;PUT IT IN
	MOVEI T1,1		;1 BYTE
	STOR T1,DTYLN,Q2	;PUT IT IN
	MOVEI T1,NTUDN		;UNSIGNED DECIMAL NUMBER
	STOR T1,DTYBF,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,1		;1 BYTE
	MOVE P3,NSLDWS		;GET THE CURRENT VALUE
	LSH P3,^D28		;POSITION IT
	MOVE T2,[441000,,P3]	;MAKE A BYTE POINTER
	CALL RETNUM		;RETURN IT TO USER
	 RETBAD ()		;FAILED

;DO NSP INACTIVITY TIMER

	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T3,NTPAR		;PARAMETER DATA
	STOR T3,DIDDA,Q2	;PUT IT IN
	MOVEI T3,.NDIAT		;PARAMETER IS INACTIVITY TIMER
	STOR T3,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T1,NTNCD		;NOT CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTBIN		;BINARY NUMBER
	STOR T1,DTYTY,Q2	;PUT IT IN
	MOVEI T1,2		;2 BYTES
	STOR T1,DTYLN,Q2	;PUT IT IN
	MOVEI T1,NTUDN		;UNSIGNED DECIMAL NUMBER
	STOR T1,DTYBF,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,2		;2 BYTES
	MOVE P3,NSINAC		;GET THE CURRENT VALUE
	IDIVI P3,^D1000		;CONVERT TO SECONDS
	LSH P3,^D20		;POSITION IT
	MOVE T2,[441000,,P3]	;MAKE A BYTE POINTER
	CALL RETNUM		;RETURN IT TO USER
	 RETBAD ()		;FAILED

;DO NSP RETRANSMIT FACTOR

	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T3,NTPAR		;PARAMETER DATA
	STOR T3,DIDDA,Q2	;PUT IT IN
	MOVEI T3,.NDRTF		;PARAMETER IS LOCAL DELAY WEIGHT
	STOR T3,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;INIT THE ARGUMENT
	MOVEI T1,NTNCD		;NOT CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTBIN		;BINARY NUMBER
	STOR T1,DTYTY,Q2	;PUT IT IN
	MOVEI T1,2		;2 BYTES
	STOR T1,DTYLN,Q2	;PUT IT IN
	MOVEI T1,NTUDN		;UNSIGNED DECIMAL NUMBER
	STOR T1,DTYBF,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,2		;2 BYTES
	MOVE P3,NSTRYS		;GET THE CURRENT VALUE
	LSH P3,^D20		;POSITION IT
	MOVE T2,[441000,,P3]	;MAKE A BYTE POINTER
	CALL RETNUM		;RETURN IT TO USER
	 RETBAD ()		;FAILED
	RETSKP			;DONE
;ROUTINE TO RETURN A DATA TYPE
;ACCEPTS:	1/ VALUE TO BE RETURNED
;RETURNS:	+1 FAILED
;		+2 SUCCESS

MAKDTY:	SAVEAC <P3>
	STKVAR <VALUE>
	MOVEM T1,VALUE		;SAVE THE VALUE
	MOVEI T2,NTNCD		;NOT CODED
	STOR T2,DTYCD,Q2	;PUT IT IN
	MOVEI T2,NTSNG		;SINGLE FIELD
	STOR T2,DTYTY,Q2	;PUT IT IN
	MOVEI T2,1		;1 BYTE
	STOR T2,DTYCN,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE THE DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI T1,1		;1 BYTE
	MOVE P3,VALUE		;RETRIEVE THE VALUE
	MOVE T2,[101000,,P3]	;MAKE A BYTE POINTER TO IT
	CALL RETNUM		;RETURN IT
	 RETBAD ()		;FAILED
	RETSKP

	ENDSV.
;TRANSPORT'S PART OF SHOW CHARACTERISTICS
;RETURNS:	+1 FAILED
;		+2 SUCCESS

XPNSCH:	SAVEAC <P3>
	SETZ Q2,		;ZERO THE ARGUMENT
	MOVEI T2,NTPAR		;PARAMETER DATA
	STOR T2,DIDDA,Q2	;PUT IT IN
	MOVEI T2,.NDTYP		;PARAMETER IS TYPE
	STOR T2,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;ZERO THE ARGUMENT
	MOVEI T2,NTCOD		;CODED
	STOR T2,DTYCD,Q2	;PUT IT IN
	MOVEI T2,NTSNG		;SINGLE FIELD
	STOR T2,DTYTY,Q2	;PUT IT IN
	MOVEI T2,1		;ONE BYTE LONG
	STOR T2,DTYCN,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVEI P3,PHASE2		;WE ARE PHASE II
	LSH P3,^D28		;POSITION IT
	MOVE T2,[441000,,P3]	;MAKE A BYTE POINTER
	MOVEI T1,1		;NUMBER OF BYTES
	CALL RETNUM		;RETURN IT
	 RETBAD ()		;FAILED
	RETSKP
;ROUTINE TO RETURN THE NODE IDENTIFICATION
;RETURNS:	+1 FAILED
;		+2 SUCCESS

RETIDN:	SETZ Q2,		;ZERO THE ARGUMENT
	MOVEI T2,NTPAR		;PARAMETER DATA
	STOR T2,DIDDA,Q2	;PUT IT IN
	MOVEI T2,.NDNID		;PARAMETER IS "IDENTIFICATION"
	STOR T2,DIDNO,Q2	;PUT IT IN
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	SETZ Q2,		;ZERO THE ARGUMENT
	MOVEI T2,NTNCD		;NOT CODED
	STOR T2,DTYCD,Q2	;PUT IT IN
	MOVEI T2,NTASC		;ASCII
	STOR T2,DTYTY,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVE T3,[441000,,NDIDN]  ;MAKE BYTE POINTER TO STRING
	MOVEI T2,.NTBPT(Q1)	;POINT TO USER'S SPACE
RETID1:	ILDB T1,T3		;GET A BYTE
	JUMPE T1,RSKP		;IF NULL, DONE
	CALL NTMBYT		;UPDATE COUNT
	 RETBAD ()		;FAILED
	XCTBU [IDPB T1,(T2)]	;RETURN IT
	JRST RETID1		;GO FOR MORE
;ENTITY = NODE
;FUNCTION = SHOW SELECTED ITEMS
;SELECTOR = COUNTERS
;RETURNS:	+1 FAILED, 1/ ERROR CODE
;		+2 SUCCESS, 1/ NODE ADDRESS

NSNSCO:	SAVEAC <P3>
	STKVAR <ADDR>
	CALL NANUEX		;GET NODE NUMBER
	 RETBAD ()		;FAILED
	MOVEM T1,ADDR		;SAVE THE NODE ADDRESS
	MOVSI P3,-NSNODL	;MAKE AOBJN WORD
NSNSC1:	HRRZ T4,P3		;GET THE OFFSET INTO THE COUNTER TABLES
	ADD T4,[NSNODC]		;POINT TO THIS TABLE'S ADDRESS
	MOVE T3,(T4)		;GET THE TABLE ADDRESS
	ADD T3,ADDR		;GET THE NODE'S OFFSET
	MOVE T2,(T3)		;GET THE CURRENT VALUE OF THIS COUNTER
	MOVE T3,P3		;RETRIEVE OFFSET INTO COUNTER TABLES
	ADD T3,[NSNWID]		;MOVE TO THIS COUNTER'S INFO
	HRRZ T1,(T3)		;GET THE COUNTER NUMBER
	CALL RETCNT		;RETURN THE INFO TO THE USER
	 RETBAD ()		;FAILED
	AOBJN P3,NSNSC1		;ANY MORE TO DO?
	MOVE T1,ADDR		;GET BACK NODE ADDRESS
	RETSKP

	ENDSV.


;ENTITY = NODE
;FUNCTION = SHOW AND ZERO COUNTERS
;RETURNS:	+1 FALIED, 1/ ERROR CODE
;		+2 SUCCESS

NTNSZC:	CALL NSNSCO		;RETURN THE COUNTERS
	 RETBAD ()		;FAILED
	CALL NTNZR2		;ZERO THE COUNTERS
	 RETBAD ()		;FAIELD
	RETSKP
;ENTITY = NODE
;FUNCTION = RETURN LIST OF ITMES
;NOW FIND THE SELECTOR
;RETURNS:	+1 FAILED, 1/  ERROR CODE
;		+2 SUCCESS

NTNRET:	MOVN T1,.NTSEL(Q1)	;GET THE SELECTOR
	SOS T1			;MAKE THE ADJUSTMENT FOR DISPATCHING
	CAIL T1,0		;IS IT
	CAIL T1,NTRETL		; VALID?
	JRST NMXII		;NO, ERROR RETURN
	MOVE T4,NTRETS(T1)	;GET DISPATCH ADDRESS
	CALL (T4)		;GO DO THE WORK
	 RETBAD ()		;FAILED
	RETSKP			;SUCCESS

NTRETS:	EXP NTNRLS		;KNOWN ITEMS
	EXP NTNRAC		;ACTIVE ITEMS
	EXP NMXII		;LOOPED ITEMS
NTRETL==.-NTRETS




;ENTITY = NODE
;FUNCTION = RETURN LIST OF ITEMS
;SELECTOR = KNOWN
;RETURNS::	+1  FAILED, 1/ ERROR CODE
;		+2  SUCCESS

NTNRLS:	CALL SCNRET		;GET SESSION CONTROL INFO
	 RETBAD ()		;FAILED, ERROR RETURN
	RETSKP			;SUCCESS
;ENTITY = NODE
;FUNCTION = RETURN LIST OF ITEMS
;SELECTOR = KNOWN
;SESSION CONTROL'S PART
;RETURNS:	+1  FAILED   1/ ERROR CODE
;		+2  SUCCESS

SCNRET:	SAVEAC <P3>
	NOINT
	LOCK NMAPLK		;LOCK THE MAPPING TABLE
	HRLI P3,-BIGNOD		;MAKE AOBJN
	HRRI P3,1		; WORD
SCNRE1:	MOVE T2,[NODMAP]	;OFFSET INTO
	ADDI T2,(P3)		; THE TABLE
	MOVE T1,(T2)		;GET THE CURRENT NAME
	JUMPE T1,[	MOVE T2,[440200,,NODTBL]  ;POINT TO REACH TABLE
			HRRZ T3,P3		;GET NODE NUMBER
			ADJBP T3,T2		;OFFSET TO NODE
			LDB T2,T3		;GET REACH INFO
			JUMPE T2,SCNRE2		;IF NOT REACHABLE, MOVE ON
			JRST .+1]		;REACHABLE
	HRRZ T1,P3		;GET NODE ADDRESS
	CALL RETADR		;RETURN THE NODE ADDRESS
	 JRST SCNRE3		;FAILED
	CALL FNDNAM		;LOOK UP THE NODE NAME
	CALL RETNAM		;RETURN THE NODE NAME
	 JRST SCNRE3		;FAILED
SCNRE2:	AOBJN P3,SCNRE1		;LOOK AT THE ENTIRE TABLE
	UNLOCK NMAPLK		;UNLOCK THE MAPPING TABLE
	OKINT
	RETSKP			;GOOD RETURN

SCNRE3:	UNLOCK NMAPLK
	OKINT
	RETBAD ()
;ENTITY = NODE
;FUNCTION = RETURN LIST OF ITEMS
;SELECTOR = ACTIVE
;RETURNS:	+1  FAILED  1/ ERROR CODE
;		+2  SUCCESS

NTNRAC:	SAVEAC <P3,P6>
	NOINT
	LOCK NMAPLK
	SETZ P3,		;INIT THE NODE NUMBER
	MOVE P6,[440200,,NODTBL]  ;POINT TO REACH TABLE
NTNRA1:	ILDB T1,P6		;GET THE INFO
	AOS P3			;SET THE NODE NUMBER
	JUMPE T1,NTNRA2
	MOVE T1,P3		;GET THE NODE NUMBER IN A GOOD PLACE
	CALL RETADR		;RETURN THE NODE NUMBER TO USER
	 JRST NTNRA3		;FAILED
	CALL FNDNAM		;LOOK UP THE NODE NAME
	CALL RETNAM		;RETURN THE NODE NAME TO THE USER
	 JRST NTNRA3		;FAILED
NTNRA2:	CAIGE P3,BIGNOD		;MORE NODES TO CHECK?
	JRST NTNRA1		;YES
	UNLOCK NMAPLK
	OKINT
	RETSKP

NTNRA3:	UNLOCK NMAPLK
	OKINT
	RETBAD ()
	SUBTTL NTMAN% JSYS Support Routines

;ROUTINE TO RETURN A NODE NAME TO THE USER
;ACCEPTS:	2/ ADDRESS OF SIXBIT NODE NAME
;		4/ NUMBER OF BYTES IN NODE NAME
;RETURNS:	+1 FAILED    1/ ERROR CODE
;		+2 SUCCESS

RETNAM:	STKVAR <MONPTR,COUNT>
	MOVEM T2,MONPTR		;SAVE
	MOVEM T4,COUNT		;  ARGUMENTS
	MOVE T2,T4		;GET COUNT IN PROPER AC FOR NOUT
	MOVE T1,[POINT 7,T4]	;MAKE BYTE POINTER TO BYTE COUNT
	MOVE T3,[1B17+<12>B35]	;1 BYTE, IN DECIMAL
	NOUT			;CONVERT IT TO ASCII
	 JRST NMXMPE		;INTERNAL NETWORK MANAGEMENT ERROR
	CALL NTMBYT		;UPDATE THE BYTE COUNT
	 RETBAD ()		;DON'T HAVE ROOM
	XCTBU [IDPB T2,.NTBPT(Q1)]	;FILL IN COUNT FIELD
	SKIPN T1,COUNT		;GET THE BYTE COUNT
	RETSKP			;IT'S ZERO, ALL DONE
	MOVE T3,MONPTR		;MAKE BYTE POINTER
	MOVE T2,[POINT 6,(T3)]	; TO THE NODE NAME
RETNA1:	ILDB T4,T2		;GET A BYTE
	ADDI T4,40		;CONVERT TO ASCII
	CALL NTMBYT		;UPDATE BYTE COUNT
	 RETBAD ()		;DON'T HAVE ROOM
	XCTBU [IDPB T4,.NTBPT(Q1)]	;PUT IT IN THE DESTINATION
	SOJG T1,RETNA1		;MORE TO DO?
	RETSKP			;NO

	ENDSV.
;ROUTINE TO LOOK UP A NODE NAME
;ACCEPTS:	1/ NODE ADDRESS
;RETURNS:	+1  WITH  1/ NODE ADDRESS
;			  2/ ADDRESS OF SIXBIT NODE NAME
;		          4/ NUMBER OF BYTES IN NODE NAME

FNDNAM:	SAVEAC <T1>
	STKVAR <ADDR>
	ADD T1,[NODMAP]		;OFFSET INTO TABLE
	MOVEM T1,ADDR		;SAVE IT
	MOVE T2,[POINT 6,(T1)]	;MAKE BYTE POINTER TO IT
	HRLZI T4,-6		;MAXIMUM OF SIX BYTES IN NAME
FNDNA1:	ILDB T3,T2		;GET A BYTE
	SKIPE T3		;IF NULL, ALL DONE
	AOBJN T4,FNDNA1		;MORE BYTES TO CHECK?
FNDNA2:	HRRZS T4		;GET NUMBER OF BYTES INTO PROPER AC
	MOVE T2,ADDR		;RETRIEVE THE NODE NAME ADDRESS
	RET			;ALL DONE

	ENDSV.
;ROUTINE TO GET A NODE NAME FROM THE USER AND VERIFY THAT IT IS MADE
;UP OF ALPHANUMERIC CHARACTERS, ONE OF WHICH MUST BE ALPHA.
;ACCEPTS:	3/ ADDRESS OF USER'S BYTE POINTER
;RETURNS:	+1  -  INVALID, 1/ ERROR CODE
;		+2  -  O.K.  WITH  1/ SIXBIT NODE NAME
;				   2/ NUMBER OF BYTES IN NODE NAME

GETNAM:	SAVEAC <P3,P6>
	STKVAR <COUNT>
	SETZB T1,P6		;ZERO THE DESTINATION WORD AND ALPHA FLAG
	MOVE T4,[POINT 6,T1]	;MAKE BYTE POINTER TO DESTINATION
	XCTBU [ILDB P3,(T3)]	;GET THE "COUNT" BYTE
	CAIL P3,1		;IS IT WITHIN
	CAILE P3,.NDNMX-1	; RANGE?
	JRST NMXII		;NO, INVALID BYTE COUNT FOR NODE NAME
	MOVEM P3,COUNT		;SAVE IT
GETNA1:	XCTBU [ILDB T2,(T3)]	;GET A BYTE
	CALL CHKAL		;IS IT ALPHABETIC?
	 JRST [CALL CHKNUM	;NO, IS IT NUMERIC?
	        JRST NMXII	;NO, INVALID FORMAT
	       JRST .+1]	;YES, MOVE ON
	SUBI T2,40		;MAKE IT SIXBIT
	IDPB T2,T4		;PUT IT IN DESTINATION
	SOJG P3,GETNA1		;MORE TO DO?
	SKIPN P6		;DID WE FIND AN ALPHABETIC CHARACTER?
	JRST NMXII		;NO. INVALID
	MOVE T2,COUNT		;RETRIEVE THE COUNT
	RETSKP

CHKAL:	CAIL T2,"A"
	CAILE T2,"Z"
	RET			;NOT ALPHA
	SETOM P6		;SET THE "FOUND ALPHA" FLAG
	RETSKP			;IS ALPHA

CHKNUM:	CAIL T2,"0"
	CAILE T2,"9"
	RET			;NOT NUMERIC
	RETSKP			;IS NUMERIC

	ENDSV.
;ROUTINE TO FIND A NODE NUMBER BY PARSING THE ENTITY ID FIELD
;RETURNS:	+1  ERROR     1/ ERROR CODE
;		+2  SUCCESS   1/ NODE NUMBER

NANUEX:	MOVEI T1,.NDALN		;GET LENGTH OF NODE NUMBER
	ADJBP T1,.NTEID(Q1)	;SKIP THE NODE NUMBER
	XCTBU [ILDB T2,T1]	;GET THE NUMBER OF BYTES IN THE NODE NAME
	JUMPN T2,NANUE1		;IF SOME THERE, MOVE ON
	HRREI T2,-<.NDALN+1>	;BACKUP TO
	ADJBP T2,T1		; NODE NUMBER
	MOVEM T2,.NTEID(Q1)	;RESET THE BYTE POINTER
	MOVEI T3,.NTEID(Q1)	;POINT TO THE NEW POINTER
	CALL GETADR		;GET THE NODE NUMBER
	 JRST [	SKIPE T1	;WAS IT 0?
		JRST NMXII	;NO, FAIL
		MOVE T1,OURNUM	;YES, THAT MEANS EXECUTOR
		RETSKP]		;DONE
	RETSKP			;DONE

NANUE1:	SETO T2,		;BACKUP TO
	ADJBP T2,T1		; READ THE NODE NAME
	MOVEM T2,.NTEID(Q1)	;RESET THE BYTE POINTER
NANUE2:	MOVEI T3,.NTEID(Q1)	;POINT TO THE NEW POINTER
	CALL GETNAM		;GET THE NODE NAME
	 RETBAD ()		;FAILED
	NOINT
	LOCK NMAPLK		;LOCK THE NODE NAME MAPPING TABLE
	CALL FNDADR		;FIND THE NODE NUMBER
	 JRST [	UNLOCK NMAPLK	;UNLOCK THE TABLE
		OKINT
		JRST NMXUC]	;FAILED
	UNLOCK NMAPLK		;UNLOCK THE TABLE
	OKINT
	RETSKP
;ROUTINE TO LOOK UP A NODE ADDRESS
;
;ACCEPTS:	1/ SIXBIT NODE NAME
;
;RETURNS:	+1  NOT FOUND
;		+2  WITH  1/ NODE ADDRESS

FNDADR:	HRLZI T4,-<BIGNOD+1>	;MAKE AOBJN WORD
FNDAD1:	HRRZ T3,T4		;GET OFFSET ONLY
	ADD T3,[NODMAP]		;MOVE INTO THE TABLE
	CAMN T1,(T3)		;IS THIS A MATCH?
	JRST [HRRZ T1,T4	;YES, GET NODE ADDRESS IN PROPER AC
	      RETSKP]
	AOBJN T4,FNDAD1		;ANY MORE TO CHECK?
	RET			;NO.  FAIL RETURN


;ROUTINE TO UPDATE THE "RETURNED BYTE COUNT" IN THE USER'S ARGUMENT BLOCK
;RETURNS:	+1 FAIL     1/ ERROR CODE
;		+2 SUCCESS

NTMBYT:	SOSGE Q3		;USER HAVE ANY MORE ROOM?
	JRST NMXRE		;NO, FAIL
	AOS .NTBYT(Q1)		;UPDATE THE RETURN COUNT
	RETSKP
;ROUTINE TO RETURN A NODE ADDRESS TO THE USER
;
;ACCEPTS:	1/ NODE ADDRESS
;RETURNS:	+1 FAILED     1/ ERROR CODE
;		+2 SUCCESS
;PRESERVES T1

RETADR:	SAVEAC <T1,P3>
	MOVE P3,T1		;GET ADDRESS IN GOOD PLACE
	LSH P3,4		;POSITION IT
	MOVEI T1,.NDALN		;GET NUMBER OF BYTES IN NODE ADDRESS
	MOVE T2,T1		;PRESERVE IT IN T1
	MOVNS T2		;MAKE BYTE
	MOVE T4,[041000,,P3]	; POINTER
	ADJBP T2,T4		;  TO ADDRESS
	CALL RETNUM		;RETURN NODE ADDRESS TO USER
	 RETBAD ()		;FAILED
	RETSKP


;RETURN A NUMBER TO THE USER
;ACCEPTS:	1/ NUMBER OF BYTES
;		2/ BYTE POINTER TO NUMBER
;RETURNS:	+1 FAILED     1/ ERROR CODE
;		+2 SUCCESS

RETNUM:	SOS T1			;FIX IT FOR BYTE POINTER ADJUSTING AND LOOPING
	MOVE T3,T1		;MAKE A COPY
RETNU1:	ADJBP T1,T2		;POINT TO REMAINING RIGHT-MOST BYTE
	ILDB T4,T1		;GET IT
	CALL NTMBYT		;UPDATE BYTE COUNT
	 RETBAD ()		;FAILED, USER DOESN'T HAVE ROOM
	XCTBU [IDPB T4,.NTBPT(Q1)]  ;GIVE BYTE TO USER
	SOJL T3,RSKP		;MORE TO DO?
	MOVE T1,T3		;YES, GET NEW BYTE POSITION
	JRST RETNU1		;GO BACK FOR MORE


;ROUTINE TO GET A NODE ADDRESS FROM USER
;AND VERIFY THAT IT IS A LEGITIMATE ADDRESS.
;
;ACCEPTS:	3/ ADDRESS OF USER'S BYTE POINTER
;RETURNS:	+1  ERROR 1/ NUMBER FOUND
;		+2  WITH  1/ NUMERIC NODE ADDRESS

GETADR:	MOVEI T4,.NDALN		;GET NUMBER OF BYTES IN A NODE ADDRESS
	CALL GETNUM		;GET THE NUMBER
	MOVE T1,T2		;GET NODE ADDRESS
	CAIL T1,1		;A VALID
	CAILE T1,BIGNOD		; NODE ADDRESS?
	RET
	RETSKP			;GOOD RETURN
;ROUTINE TO GET A PARAMETER NUMBER FROM THE USER
;
;ACCEPTS:	3/ ADDRESS OF USER'S BYTE POINTER
;RETURNS:	2/ PARAMETER NUMBER

GETPAR:	MOVEI T4,.NDPLN		;GET NUMBER OF BYTES IN A PARAMETER NUMBER
	CALLRET GETNUM		;GET THE NUMBER


;ROUTINE TO GET A NUMBER FROM THE USER
;
;ACCEPTS:	3/ ADDRESS OF USER'S BYTE POINTER
;		4/ NUMBER OF BYTES IN NUMBER
;RETURNS:	+1   2/ NUMBER

GETNUM:	SAVEAC <P3>
	MOVE P3,T4		;PRESERVE COUNT FOR LOOPING
	SETZ T2,		;INIT THE DESTINATION WORD
GETNU1:	XCTBU [ILDB T1,(T3)]	;GET BYTE
	IORM T1,T2		;PUT IT IN
	ROT T2,-10		;POSIITON FOR NEXT
	SOJG T4,GETNU1		;MORE TO DO?
	ROT T2,10		;UNWIND
	SOJG P3,.-1		; THE BYTE STRING
	RET			;DONE


;ROUTINE TO LOOK UP A PARAMETER NUMBER
;ACCEPTS:	2/ PARAMETER NUMBER
;RETURNS:	1/ OFFSET INTO PARAMETER TABLE

FNDPAR:	MOVEI T1,NSNPRL		;GET NUMBER OF ENTRIES IN TABLE
	SOS T1			;FIX FOR OFFSETING
FNDPA1:	XMOVEI T3,NSNPAR	;GET TABLE BASE
	ADD T3,T1		;GET OFFSET
	CAMN T2,(T3)		;THIS IT?
	RETSKP			;YES, DONE
	SOJGE T1,FNDPA1		;ANY MORE TO CHECK?
	JRST NMXUPT		;NO, BAD NUMBER
;ROUTINE TO RETURN A NODE ID TO THE USER
;ACCEPTS:	T1/ NODE NUMBER
;		T2/ PARAMETER NUMBER
;RETURNS:	+1 FAILED   1/ ERROR CODE
;		+2 SUCCESS

RETNID:	ASUBR <NDNUM,PARNUM>
	SETZM Q2		;INIT THE ARGUMENT
	MOVEI T1,NTPAR		;PARAMETER DATA
	STOR T1,DIDDA,Q2	;PUT IT IN
	STOR T2,DIDNO,Q2	;PUT IN PARAMETER NUMBER
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILD
	SETZM Q2		;INIT THE ARGUMENT
	MOVEI T1,NTCOD		;CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTMUL		;MULTIPLE FIELDS
	STOR T1,DTYTY,Q2	;PUT IT IN
	MOVEI T1,2		;NUMBER OF FIELDS IN A NODE ID
	STOR T1,DTYCN,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	SETZM Q2		;INIT THE ARGUMENT
	MOVEI T1,NTNCD		;NOT CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTBIN		;BINARY NUMBER
	STOR T1,DTYTY,Q2	;PUT IT IN
	MOVEI T1,NTOCT		;OCTAL NUMBER
	STOR T1,DTYBF,Q2	;PUT IT IN
	MOVEI T1,.NDALN		;BYTES IN A NODE ADDRESS
	STOR T1,DTYLN,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVE T1,NDNUM		;GET NODE NUMBER
	CALL RETADR		;RETURN THE NODE NUMBER TO USER
	 RETBAD ()		;FAIL
	SETZM Q2		;INIT THE ARGUMENT
	MOVEI T1,NTNCD		;NOT CODED
	STOR T1,DTYCD,Q2	;PUT IT IN
	MOVEI T1,NTASC		;ASCII IMAGE
	STOR T1,DTYTY,Q2	;PUT IT IN
	CALL NTMDTY		;MAKE A DATA TYPE
	 RETBAD ()		;FAILED
	MOVE T1,NDNUM		;GET NODE NUMBER
	CALL FNDNAM		;GET THE NODE NAME
	CALL RETNAM		;RETURN THE NODE NAME TO THE USER
	 RETBAD ()		;FAILED
	RETSKP

	ENDAS.
;RETURN A COUNTER TO THE USER
;ACCEPTS:	T1/ COUNTER NUMBER
;		T2/ CURRENT VALUE OF COUNTER
;RETURNS:	+1 FAILED     1/ ERROR CODE
;		+2 SUCCESS

RETCNT:	ASUBR <NUM,VAL,WIDTH>
	SAVEAC <P3>
	SETZM Q2		;INIT THE DESTINATION WORD
	MOVEI T2,NTCOU		;COUNTER DATA
	STOR T2,DIDDA,Q2	;PUT IT IN
	STOR T1,DIDNO,Q2	;PUT IN THE COUNTER NUMBER
	CALL FNDCNT		;FIND THE COUNTER OFFSET
	ADD T2,[NSNWID]		;MOVE TO THIS COUNTER'S INFO
	HLRZ T1,(T2)		;GET THE COUNTER NUMBER
	STOR T1,DIDWD,Q2	;PUT IT IN
	MOVEM T1,WIDTH		;SAVE IT
	CALL NTMDID		;MAKE A DATA ID
	 RETBAD ()		;FAILED
	MOVE T1,WIDTH		;RETRIEVE THE WIDTH
	IDIVI T1,10		;CONVERT TO BYTES
	MOVE T2,T1		;SAVE IT IN T1
	MOVE P3,VAL		;GET THE COUNTER VALUE
	LSH P3,4		;POSITION IT
	MOVNS T2		;MAKE A
	MOVE T3,[041000,,P3]	; BYTE POINTER
	ADJBP T2,T3		;  TO THE NUMBER
	CALL RETNUM		;RETURN THE COUNTER TO USER
	 RETBAD ()		;FAILED
	RETSKP			;DONE

	ENDAS.

;GET A COUNTER'S OFFSET INTO THE COUNTER TABLES
;ACCEPTS:	T1/ COUNTER NUMBER
;RETURNS:	+1  T2/ OFFSET INTO COUNTER TABLES

FNDCNT:	MOVEI T2,NSNWDL		;GET THE NUMBER
	SOS T2			; OF TABLES
FNDCN1:	MOVE T4,T2		;SAVE T2
	ADD T4,[NSNWID]		;OFFSET INTO TABLE
	HRRZ T3,(T4)		;GET THE COUNTER NUMBER
	CAME T3,T1		;A MATCH?
	SOJGE T2,FNDCN1		;NO, MORE TO DO?
	RET			;YES, DONE
;BUILD A DATA ID
;ACCEPTS:	Q2/ DATA ID PARAMETERS
;			DEFSTR (DIDDA,0,0,1)
;			       (DIDWD,0,7,6)
;			       (DIDNO,0,17,11)
;RETURNS:	+1 FAILED    1/ ERROR CODE
;		+2 SUCCESS

NTMDID:	SAVEAC <P3>
	SETZM P3		;INIT THE DESTINATION
	LOAD T2,DIDNO,Q2	;GET THE PARAMETER OR COUNTER NUMBER
	STOR T2,NT%PNM,P3	;PUT IN NUMBER
	LOAD T2,DIDDA,Q2	;GET THE DATA TYPE
	CAIE T2,NTCOU		;COUNTER?
	JRST NTMDI1		;NO, PARAMETER
	SETONE NT%DAT,P3	;SAY COUNTER DATA TYPE
	LOAD T3,DIDWD,Q2	;GET COUNTER WIDTH
	LSH T3,-4		;CONVERT NUMBER OF BYTES
	AOS T3			; INTO PROPER CODE
	STOR T3,NT%CWD,P3	;PUT IN COUNT
NTMDI1:	HRLI T2,441000		;MAKE A BYTE POINTER
	HRRI T2,P3		; TO IT
	MOVEI T1,NTMDIL		;GET LENGTH OF DATA ID
	CALL RETNUM		;GIVE IT TO USER
	 RETBAD ()		;FAILED
	RETSKP
;BUILD A DATA TYPE
;ACCEPTS:	Q2/ DATA TYPE PARAMETERS
;			DEFSTR (DTYCD,0,0,1)
;			       (DTYTY,0,1,1)
;			       (DTYCN,0,7,6)
;			       (DTYBF,0,3,2)
;			       (DTYLN,0,7,4)
;RETURNS:	+1 FAILED    1/ ERROR CODE
;		+2 SUCCESS

NTMDTY:	SETZM T4		;INIT THE DESTINATION
	LOAD T2,DTYCD,Q2	;GET CODE INDICATOR
	CAIE T2,NTCOD		;CODED?
	JRST NTMDT1		;NO
	SETONE NT%COD,T4	;CODED, SAY SO
	LOAD T2,DTYTY,Q2	;GET TYPE
	SKIPE T2		;SINGLE FIELD?
	SETONE NT%TYP,T4	;NO, MULTIPLE FIELDS
	LOAD T2,DTYCN,Q2	;GET NUMBER OF FIELDS OR BYTES
	STOR T2,NT%CNT,T4	;PUT IT IN
	JRST NTMDT2		;MOVE ON

NTMDT1:	LOAD T2,DTYTY,Q2	;NOT CODED, GET TYPE
	SKIPE T2		;BINARY?
	SETONE NT%TYP,T4	;NO, ASCII IMAGE
	LOAD T2,DTYLN,Q2	;GET BYTE COUNT
	STOR T2,NT%LEN,T4	;PUT IT IN
	LOAD T2,DTYBF,Q2	;GET FORMAT
	STOR T2,NT%FMT,T4	;PUT IT IN
NTMDT2:	HRLI T3,441000		;MAKE BP
	HRRI T3,T4		; TO DATA TYPE
	MOVEI T2,NTMDTL		;GET NUMBER OF BYTES IN DATA TYPE
NTMDT3:	ILDB T1,T3		;GET A BYTE
	CALL NTMBYT		;UPDATE BYTE COUNT
	 RETBAD ()		;DON'T HAVE ROOM
	XCTBU [IDPB T1,.NTBPT(Q1)]  ;RETURN IT TO USER
	SOJG T2,NTMDT3		;MORE TO DO?
	RETSKP


	TNXEND
	END