Trailing-Edge
-
PDP-10 Archives
-
BB-4170G-SM
-
sources/nspsrv.mac
There are 31 other files named nspsrv.mac in the archive. Click here to see a list.
;<3A.MONITOR>NSPSRV.MAC.65, 22-Aug-78 18:08:01, EDIT BY OPERATOR
;FIX NTMVOP TO CHECK FOR NEG COUNT
;<3A.MONITOR>NSPSRV.MAC.64, 22-Aug-78 10:48:51, EDIT BY MILLER
;CHECK FOR BAD OPTDATA FIELD IN CC MESSAGE
;<3A.MONITOR>NSPSRV.MAC.63, 18-Aug-78 09:18:45, EDIT BY MILLER
;FIX TYPEO
;<3A.MONITOR>NSPSRV.MAC.62, 18-Aug-78 09:06:55, EDIT BY MILLER
;FIX SKPFLD TO PASS NUMBER TO GTASCI
;<3A.MONITOR>NSPSRV.MAC.61, 18-Aug-78 08:43:26, EDIT BY MILLER
;MAKE GTASCI AND GTBNRY CHECK LIMITS OF STRINGS
;<3A.MONITOR>NSPSRV.MAC.60, 21-Jul-78 11:15:49, EDIT BY HALL
;CHANGE LLNAM TO LLFNM IN DCNOPN
;<3A.MONITOR>NSPSRV.MAC.59, 26-Jun-78 09:45:19, Edit by KIRSCHEN
;TEST CORRECT AC AT SQISN2 WHEN CHECKING NEED FOR LS MSG
;<3A.MONITOR>NSPSRV.MAC.58, 22-Jun-78 09:12:06, Edit by KIRSCHEN
;DEFER SENDING VERIFICATION MSG UNTIL LINE DEFINITELY UP
;<3A.MONITOR>NSPSRV.MAC.57, 21-Jun-78 17:11:57, EDIT BY MILLER
;GET LARGER BLOCK FOR TASK NAME AT GETTSK
;<3A.MONITOR>NSPSRV.MAC.56, 7-Jun-78 07:59:40, EDIT BY MILLER
;MAKE NSPTSK STAY IN BALSET FOR A LONG TIME
;<3A.MONITOR>NSPSRV.MAC.55, 26-May-78 16:31:55, EDIT BY MILLER
;MORE FIXES TO MTOPR CLOSE FUNCTION
;<3A.MONITOR>NSPSRV.MAC.54, 26-May-78 15:43:20, EDIT BY MILLER
;FIX UP NTMTCZ TO WAIT FOR ACKS
;<3A.MONITOR>NSPSRV.MAC.53, 23-May-78 17:16:04, Edit by MCCLURE
; Add port number to NSPRTH
;<3A.MONITOR>NSPSRV.MAC.52, 22-May-78 08:09:38, EDIT BY MILLER
;ALWAYS REQUEST POSTING OF "NUMBERED SEGMENTS" FROM DEVICE DRIVER.
; DON'T "FLUSH" SEGEMENT STILL AWAITING POSTING
;<3A.MONITOR>NSPSRV.MAC.51, 19-May-78 14:03:01, EDIT BY OPERATOR
;FIX STRMSG NOT TO USE ACVAR
;<3A.MONITOR>NSPSRV.MAC.50, 18-May-78 09:47:30, Edit by MCCLURE
;<3A.MONITOR>NSPSRV.MAC.49, 28-Apr-78 15:31:31, EDIT BY MILLER
;CHECK FOR DATA IN FILE SYSTEM BUFFER AT CHKRAW
;<3A.MONITOR>NSPSRV.MAC.48, 28-Apr-78 12:21:04, Edit by MCCLURE
; ADD ERROR CODES IN NDSLP
;<3A.MONITOR>NSPSRV.MAC.47, 26-Apr-78 09:54:42, EDIT BY MILLER
;CHANGE .DCX40 TO .DCX39 IN DEDMCB
;<3A.MONITOR>NSPSRV.MAC.46, 20-Apr-78 12:00:32, Edit by KIRSCHEN
;<3A.MONITOR>NSPSRV.MAC.45, 16-Apr-78 14:42:57, EDIT BY MILLER
;ADD GJFX50 ERROR RETURNS FOR BAD ATTRIBUTE ARGS
;<3A.MONITOR>NSPSRV.MAC.44, 13-Apr-78 16:28:52, EDIT BY MILLER
;ADD DECR LLDMT IF VERSEG FAILS
;<3A.MONITOR>NSPSRV.MAC.43, 10-Apr-78 14:46:05, EDIT BY MILLER
;CLEAR LINK WORD AT LSINT1
;<3A.MONITOR>NSPSRV.MAC.42, 5-Apr-78 12:28:26, EDIT BY MILLER
;FIX ANOTHER TYPEO IN NTRCOB
;<3A.MONITOR>NSPSRV.MAC.41, 5-Apr-78 12:02:37, EDIT BY KIRSCHEN
;FIX NTRCOB TO USE PROPER FIEDL
;<3A.MONITOR>NSPSRV.MAC.40, 5-Apr-78 08:15:24, Edit by KIRSCHEN
;CHANGE FAL TO BE OBJECT 21
;<3A.MONITOR>NSPSRV.MAC.39, 4-Apr-78 16:06:36, EDIT BY MILLER
;MORE FIXES TO NTMVOP
;<3A.MONITOR>NSPSRV.MAC.38, 4-Apr-78 12:19:47, Edit by KIRSCHEN
;<3A.MONITOR>NSPSRV.MAC.37, 4-Apr-78 10:19:10, Edit by KIRSCHEN
;<3A.MONITOR>NSPSRV.MAC.36, 4-Apr-78 09:42:31, Edit by KIRSCHEN
;<3A.MONITOR>NSPSRV.MAC.35, 3-Apr-78 14:35:32, Edit by KIRSCHEN
;<3A.MONITOR>NSPSRV.MAC.34, 3-Apr-78 12:47:04, EDIT BY MILLER
;CHANGE RETBAD TO "JRST SQOBAD"
;<3A.MONITOR>NSPSRV.MAC.33, 3-Apr-78 12:42:57, EDIT BY MILLER
;CHECK FOR OPTDATA LENGTH IN NTMVOP
;<3A.MONITOR>NSPSRV.MAC.32, 30-Mar-78 11:48:09, EDIT BY MILLER
;ALLOW DEST OBJECT TYPE OF TWO. IF SO, IGNORE GROUP,USER
;<3A.MONITOR>NSPSRV.MAC.31, 15-Mar-78 13:50:16, Edit by MCCLURE
; ADD LOOPBACK SUPPORT FOR KS10
;<3A.MONITOR>NSPSRV.MAC.30, 13-Mar-78 09:24:52, EDIT BY MILLER
;FIX UP VERSION NUMBERS IN NODE INIT MESSAGE
;<3A.MONITOR>NSPSRV.MAC.29, 1-Mar-78 14:31:06, EDIT BY MILLER
;CHANGE RANGE CHECK ON NODE NUMBER IN NODE JSYS
;<3A.MONITOR>NSPSRV.MAC.28, 24-Feb-78 09:40:23, EDIT BY MILLER
;FIX SETTING OF NODE NUMBER IN NSPINI
;<3A.MONITOR>NSPSRV.MAC.27, 24-Feb-78 08:58:48, EDIT BY MILLER
;ADD EXTNS
;<3A.MONITOR>NSPSRV.MAC.26, 24-Feb-78 08:56:48, EDIT BY MILLER
;DEFINE OURNUM. DEFINE NODE FUNCITON TO SET AND READ IT
;<3A.MONITOR>NSPSRV.MAC.25, 13-Feb-78 12:42:37, Edit by MCCLURE
;DON'T SET OURCNT IF DON'T SET OURNAM AT NSPINI
;<3.SM10-RELEASE-3>NSPSRV.MAC.24, 12-Jan-78 15:31:08, EDIT BY KIRSCHEN
;CLEAN UP FILBFI ON OPEN FAILURE
;<3.SM10-RELEASE-3>NSPSRV.MAC.23, 8-Jan-78 13:14:02, EDIT BY MILLER
;SET UP FOR INPUT AT NTMTOP
;<3.SM10-RELEASE-3>NSPSRV.MAC.22, 3-Jan-78 13:15:52, EDIT BY MILLER
;<3.SM10-RELEASE-3>NSPSRV.MAC.21, 30-Dec-77 16:45:21, EDIT BY MILLER
;FIX CREATION OF ACCESS FIELDS
;<3.SM10-RELEASE-3>NSPSRV.MAC.20, 23-Dec-77 01:46:06, EDIT BY MCCLURE
;DON'T SET OURNAM IF SETSPD ALREADY SET IT
;<3-MONITOR>NSPSRV.MAC.207, 10-Nov-77 16:00:27, EDIT BY HURLEY
;BE SURE TO DECREMENT DCCUR WHENEVER NECESSARY
;<3-MONITOR>NSPSRV.MAC.206, 10-Nov-77 15:27:10, EDIT BY HALL
;EDIT BY MILLER- FIX FAILURE CASE IN NTRCN
;<3-MONITOR>NSPSRV.MAC.205, 9-Nov-77 12:03:55, EDIT BY MILLER
;CHANGE "NCU" OBJECT TO BE # 23
;<3-MONITOR>NSPSRV.MAC.204, 9-Nov-77 09:55:31, EDIT BY KIRSCHEN
;MORE COPYRIGHT UPDATING...
;<3.SM10-RELEASE-3>NSPSRV.MAC.18, 14-Dec-77 13:08:07, EDIT BY MILLER
;FIX NCU'S NUMBER
;<3.SM10-RELEASE-3>NSPSRV.MAC.17, 14-Dec-77 11:43:47, EDIT BY MILLER
;REPLACE ALL .DCX11 CODES WITH .DCX9
;<3.SM10-RELEASE-3>NSPSRV.MAC.16, 13-Dec-77 18:34:00, EDIT BY MILLER
;FIX TYPEO IN LAST EDIT
;<3.SM10-RELEASE-3>NSPSRV.MAC.15, 13-Dec-77 18:31:11, EDIT BY MILLER
;FIX DEDMCB TO CLOSE "ALL" LINKS
;<3.SM10-RELEASE-3>NSPSRV.MAC.14, 9-Dec-77 12:03:06, EDIT BY MILLER
;IMPROVE SEARCH CODE IN DCNOPN
;<3.SM10-RELEASE-3>NSPSRV.MAC.13, 8-Dec-77 12:52:31, EDIT BY MILLER
;USE OURCNT IN DCNOPN
;<3.SM10-RELEASE-3>NSPSRV.MAC.12, 8-Dec-77 09:39:56, EDIT BY MILLER
;ADD PROPER EXTN'S
;<3.SM10-RELEASE-3>NSPSRV.MAC.11, 8-Dec-77 09:34:46, EDIT BY MILLER
;SET UP "OURCNT" WHEN "OURNAM" IS DEFINED
;<3.SM10-RELEASE-3>NSPSRV.MAC.10, 8-Dec-77 09:04:40, EDIT BY MILLER
;SAVE COUNTS OF NODE NAMES IN MCBDTE
;<3.SM10-RELEASE-3>NSPSRV.MAC.9, 7-Dec-77 16:47:35, EDIT BY MILLER
;<3.SM10-RELEASE-3>NSPSRV.MAC.8, 7-Dec-77 16:23:34, EDIT BY MILLER
;BUG FIXES
;<3.SM10-RELEASE-3>NSPSRV.MAC.7, 7-Dec-77 14:22:06, EDIT BY MILLER
;MORE FIXES TO STRMSG
;<3.SM10-RELEASE-3>NSPSRV.MAC.6, 7-Dec-77 13:40:04, EDIT BY MILLER
;MAKE NSPMAX AN ARRAY AND FIX UP STRMSG CODE
;<3.SM10-RELEASE-3>NSPSRV.MAC.5, 6-Dec-77 21:53:21, EDIT BY MCCLURE
;<3.SM10-RELEASE-3>NSPSRV.MAC.4, 1-Dec-77 12:48:22, EDIT BY MILLER
;FIX NTRJCT TO SEND OPT DATA IF DESIRED.
;<3.SM10-RELEASE-3>NSPSRV.MAC.3, 30-Nov-77 14:46:39, EDIT BY MILLER
;TELL DRIVER IF SEGEMENT HAS BEEN SENT BEFORE
;<3.SM10-RELEASE-3>NSPSRV.MAC.2, 1-Nov-77 00:52:39, Edit by MCLEAN
;SEARCH PROKL
;<3-MONITOR>NSPSRV.MAC.203, 12-Oct-77 14:02:41, EDIT BY KIRSCHEN
;UPDATE COPYRIGHT FOR RELEASE 3
;<3-MONITOR>NSPSRV.MAC.202, 8-Oct-77 10:37:15, EDIT BY MILLER
;FIX UP CLOSE CODE WHEN SNDDI FAILS
;<3-MONITOR>NSPSRV.MAC.201, 5-Oct-77 10:14:16, EDIT BY MILLER
;CHANGE ALL USES OF .DCX21 TO .DCX41
;<3-MONITOR>NSPSRV.MAC.200, 30-Sep-77 09:06:09, EDIT BY MILLER
;CHANGE OBJECT # OF NCU TO 17
;<3-MONITOR>NSPSRV.MAC.199, 23-Sep-77 08:28:53, EDIT BY MILLER
;WAKE UP PROCESS WHEN LS MESSAGE IS RECEIVED
;<3-MONITOR>NSPSRV.MAC.198, 21-Sep-77 16:04:25, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.197, 21-Sep-77 08:48:51, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.196, 20-Sep-77 14:24:47, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.195, 20-Sep-77 11:21:41, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.194, 20-Sep-77 11:13:23, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.193, 12-Sep-77 14:35:10, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.192, 9-Sep-77 15:10:34, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.191, 8-Sep-77 13:30:41, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.190, 7-Sep-77 16:38:44, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.189, 6-Sep-77 17:33:38, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.188, 6-Sep-77 17:05:24, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.187, 31-Aug-77 17:39:22, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.186, 31-Aug-77 12:39:22, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.185, 29-Aug-77 09:32:59, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.184, 29-Aug-77 09:30:14, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.183, 29-Aug-77 08:32:04, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.182, 27-Aug-77 10:57:12, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.181, 24-Aug-77 16:25:02, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.180, 24-Aug-77 15:26:36, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.179, 24-Aug-77 08:32:04, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.178, 19-Aug-77 12:01:06, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.177, 18-Aug-77 17:13:08, EDIT BY MILLER
;FIX SNDDI FOR OPTDATA
;<3-MONITOR>NSPSRV.MAC.176, 18-Aug-77 16:52:23, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.175, 18-Aug-77 10:33:01, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.174, 17-Aug-77 13:53:26, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.173, 17-Aug-77 11:49:24, EDIT BY MILLER
;<3-MONITOR>NSPSRV.MAC.172, 17-Aug-77 11:17:06, EDIT BY MILLER
;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 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
SEARCH PROLOG,PROKL
TTITLE NSPSRV
EXTN <BLKASG,ITSID,ITSNAM,ITSNUM,LASTSK,LLBIT,LLBITS>
EXTN <LLHEAD,LLLLCK,MAXBLK,MAXEXP,MAXLNK,MCBDTE,MSGQ>
EXTN <NAKCNT,NODNUM,NSPLPB,NSPMAX,OBJMAX,OBJTBL,OURCNT>
EXTN <OURNAM,OURNUM,RMSGQ,SMSGQ>
;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.
;A PROCESS OWNS ONE END OF A LOGICAL LINK BY VIRTUE OF ITS HAVING
;A JFN ON THE LINK. THIS JFN IS THE PROCESS' TOOL FOR SENDING
;DATA TO ITS COMPANION PROCESS ON THE OTHER SIDE OF THE LINK OR
;FOR RECEIVING DATA SENT TO IT. THE FOLLOWING JFN FIELDS ARE RELEVANT
;TO NETWORK CONNECTIONS ONLY:
;FILLLB CONTAINS THE ADDRESS OF THE LOGICAL LINK ENTRY
;FILBFO CONTAINS A BYTE POINTER FOR THE CURRENT OUTPUT BUFFER
; LH OF FILBCT CONTAINS COUNT OF BYTES REMAINING IN OUTPUT BUFFER
;FILBFI CONTAINS BYTE POINTER TO CURRENT INPUT BUFFER
; RH OF FILBCT CONTAINS COUNT ON INPUT BYTES REMAINING
; RH OF FILWND CONTAINS WINDOW PAGE ADDRESS FOR INPUT
; LH OF FILWND CONTAINS WINDOW PAGE ADDRESS FOR OUTPUT
; THE FIELDS: FILCNT, FILBYN, FILLEN, AND FILBYT ARE SET UP
; BY NSPSRV FOR THE PROPER DIRECTION OF I/O. THAT IS, WHEN
; THE PROCESS WANTS TO DO OUTPUT, THESE LOCATIONS ARE SET UP
; TO THE VALUES RELEVANT FOR OUTPUT; AND WHEN THE PROCESS
; WANT TO DO INPUT, THESE VALUES ARE SET UP FOR INPUT.
;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
;DEFINE LOCAL MACROS
DEFINE LLLOCK
< CALL LOKLL ;;GO LOCK UP THE TREE
> ;;END OF LLLOCK MACRO
DEFINE LLLULK
< CALL ULOKLL ;;GO UNLOCK THE TREE
> ;;DONE
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)
;DEFINE DATA BASES
;FIELD DEFINITIONS FOR LINK TABLE
LKSIZE==22 ;SIZE OF A STANDARD ENTRY
LKOBJS==6 ;EXTRA ENTRIES NEEDED FOR OBJECT
DEFSTR (LLUPL,0,35,36) ;UP POINTER
DEFSTR (LLDWN,1,35,36) ;DOWN POINTER
DEFSTR (LLLOK,2,0,1) ;BLOCK LOCK
DEFSTR (LLSTA,2,5,5) ;STATE OF THIS LINK
LLSTRN==0 ;LINK IN TRANSITION. NON-EXISTANT
LLSLIS==1 ;OBJECT IS LISTENING
LLSCIS==2 ;CONNECT-INITIATE SENT
LLSCIR==3 ;CONNECT-INITIATE RECEIVED
LLSRUN==4 ;LINK IS ACTIVE.
LLSDIS==5 ;DI SENT
LLSDIQ==6 ;DI IS QUEUED
LLSDIR==7 ;DI RECIEVED
LLSABT==10 ;CONNECTION ABORTED/REFUSED BY LOCAL NSP
;DEFSTR (LLFLG,2,17,12) ;LINK FLAGS
DEFSTR (LLFOB,2,17,1) ;THIS IS AN OBJECT
DEFSTR (LLFEM,2,16,1) ;EOM
DEFSTR (LLFII,2,15,1) ;INPUT INTERRUPT NEEDED
DEFSTR (LLFDI,2,14,1) ;DI WAS AN ABORT
DEFSTR (LLTRN,2,13,1) ;NEED INTIAL LS MESSAGE
DEFSTR (LLFIM,2,12,1) ;EOM IN INPUT BUFFER
DEFSTR (LLFNA,2,11,1) ;IF SET, BLOCK WAITING FOR ACK TO GO
DEFSTR (LLOPW,2,10,1) ;LINK IS OPEN FOR WRITE
DEFSTR (LLOPI,2,9,1) ;LINK IS OPEN FOR READ
DEFSTR (LLFNN,2,8,1) ;IF ON, DATA MESSAGE WAS THROWN AWAY
DEFSTR (LLSDE,2,7,1) ;IF ON, LL BLOCK DISASSOCIATED FROM PROCESS
DEFSTR (LLLWC,2,6,1) ;LINK WAS CONNECTED (I.E. CC RECEIVED)
DEFSTR (LLLNK,2,35,18) ;LINK I.D. OF THIS LINK
DEFSTR (LLFRK,3,17,18) ;OWNING FORK
DEFSTR (LLDRC,3,23,6) ;PI FOR DATA RECEIVED
DEFSTR (LLPII,3,29,6) ;PI CHANNEL FOR INTERRUPT MESSAGES
DEFSTR (LLPIC,3,35,6) ;PI FOR CONNECT-INITITATE
DEFSTR (LLIIN,4,11,12) ;SEGMENT NUMBER FOR INCOMING LS/INT
DEFSTR (LLFNM,4,19,8) ;REMOTE OBJECT NUMBER
DEFSTR (LLHLK,4,35,16) ;LINK I.D. ON FOREIGN HOST
LLMSG==5 ;POINTER TO CHAIN OF RAW MESSAGES
LLMSI==6 ;POINTER TO INTERRUPT MESSAGE
DEFSTR (LLBRP,7,0,1) ;BACK-PRESSURE BIT FOR TRANSMIT
DEFSTR (LLBRL,7,1,1) ;BACK-PRESSURE FOR RECEIVE
DEFSTR (LLMFC,7,3,2) ;0=NO FLOW CONTROL
;1=SEGMENT FLOW CONTROL
;2=MESSAGE FLOW CONTROL
DEFSTR (LLSWG,7,19,16) ;MAX SEGMENT SIZE FOR MESSAGE
DEFSTR (LLMSM,7,27,8) ;MAX SEGMENTS THIS LINK CAN HAVE
DEFSTR (LLQUN,7,31,4) ;# SEGS IN QUEUER TO RESEND
DEFSTR (LLQOU,7,35,4) ;# OF SEGS IN QUEUER
DEFSTR (LLBOM,10,0,1) ;AT BEGINNING OF MESSAGE
DEFSTR (LLPRT,10,2,2) ;DTE # FOR THIS CONNECTION
DEFSTR (LLFLI,10,3,1) ;INPUT DIRECTION
DEFSTR (LLFLO,10,4,1) ;OUTPUT DIRECTION
DEFSTR (LLIMS,10,5,1) ;INPUT IS MESSAGE-TYPE
DEFSTR (LLOPT,10,35,30) ;OPTIONAL DATA STORAGE
DEFSTR (LLDSN,11,11,12) ;SEG # FOR NEXT DATA TRANSMIT
DEFSTR (LLISN,11,23,12) ;SEG # FOR NEXT LS/INT TRANSMIT
DEFSTR (LLIDN,11,35,12) ;SEG # FOR NEXT DATA RECEIVE
LLOMSG==12 ;ORDERED DATA QUEUE
DEFSTR (LLUCT,13,5,6) ;# OF BYTES IN OPTDATA FIELD
DEFSTR (LLTSK,13,35,30) ;POINTER TO TASK NAME
DEFSTR (LLHST,14,35,36) ;POINTER TO REMOTE HOST NAME
DEFSTR (LLMIC,15,5,6) ;COUNT OF INT SEGMENTS ALLOWED TO SEND
DEFSTR (LLFDS,15,35,30) ;REMOTE DESCRIPTOR BLOCK
LLBPTR==16 ;WORK CELL CONTAINING BYTE POINTER
LLBPCT==17 ;CURRENT BYTE COUNT
DEFSTR (LLBSZ,20,5,6) ;BYTE SIZE OF OPENING
DEFSTR (LLDRW,20,9,4) ;COUNT OF RAW DATA MESSAGES
DEFSTR (LLDMT,20,14,5) ;COUNT OF TOTAL DATA MESSAGES ON QUEUES
DEFSTR (LLLSA,20,15,1) ;SPECIAL FLAG USED TO CONTROL DATA INTS
; FROM SCHED WHILE DOING LS MESSAGES
DEFSTR (LLLSC,20,19,4) ;COUNT OF LS BUFFERS TO REQUEST
DEFSTR (LLRSN,20,35,16) ;DISCONNECT REASON
LLSEGQ==21 ;HEADER FOR SENT QUEUE
;DEFINITIONS FOR OBJECT PART OF TABLE
DEFSTR (LLSOB,LKSIZE,35,18) ;OBJECT USED IN CI BY REMOTE
DEFSTR (LLNAM,LKSIZE,17,18) ;NUMBER OF THIS OBJECT
DEFSTR (LLDSC,LKSIZE+1,35,36) ;POINTER TO DESCRIPTOR BLOCK
DEFSTR (LLUSR,LKSIZE+2,35,36) ;POINTER TO USER NAME BLOCK
DEFSTR (LLACT,LKSIZE+3,35,36) ;POINTER TO ACCOUTN STRING BLOCK
DEFSTR (LLPCT,LKSIZE+4,5,6) ;COUNT OF BYTES IN PASSWORD
DEFSTR (LLPSW,LKSIZE+4,35,30) ;POINTER TO PASSWORD BLOCK
LLUSGP==LKSIZE+5 ;SAVE USER,GROUP FROM CI
;MORE DEFINITIONS
;DEFINITIONS FOR OUTGOING MESSAGES
MSHDR==4 ;SIZE OF MESSAGE HEADER
DEFSTR (MSRLS,0,0,1) ;IF POSTER SHOULD RELEASE MESSAGE
DEFSTR (MSPST,0,1,1) ;IF MESSAGE NEEDS POSTING
DEFSTR (MSLNK,0,35,18) ;LINK WORD
DEFSTR (MSPRT,1,2,2) ;DTE # OR ALL ONES FOR LOCAL CONNECITON
DEFSTR (MSLCL,1,3,1) ;IF A LOCAL DATA MESSAGE
DEFSTR (MSNAK,1,4,1) ;MESSAGE HAS BEEN NAK'ED
DEFSTR (MSMS1,1,5,1) ;MESSAGE ALREADY SENT IF 1
DEFSTR (MSSEG,1,17,12) ;SEG # OF MESSAGE
DEFSTR (MSLLA,1,33,16) ;LL ADDRESS
DEFSTR (MSTOM,1,35,2) ;TYPE OF THIS MESSAGE
MSCTL==0 ;CONTROL MESSAGE
MSLSI==1 ;LS/INT MESSAGE
MSDAT==2 ;DATA MESSAGE
DEFSTR (MSCNT,2,35,12) ;# OF BYTES IN MESSAGE
DEFSTR (MSDTC,2,23,12) ;# OF BYTES EXCLUDING NSP OVERHEAD BYTES
DEFSTR (MSMFL,2,11,12) ;MESSAGE FLAGS
MSBPTR==3 ;BYTE POINTER TO DATA PART OF MESSAGE
DEFAC (STS,P1)
DEFAC (JFN,P2)
DEFAC (DEV,P4)
DEFAC (F1,P5)
;DEFINITIONS FOR FILE SPECS
MAXDSC==^D16 ;MAX CHARACTERS IN DESCRIPTOR
TSKMAX==^D16 ;MAX CHARACTERS IN A TASK NAME
MAXHST==6 ;MAX SIZE OF A HOST STRING
;GENERAL NSP PARAMETERS
NSPEXT==200 ;EXTENSIBLE BIT IN FIELD DEFINITIONS
NSPLCH==53 ;STANDARD LINK CHARACTERISTICS
NSPSEG==^D181 ;MAXIMUM USER DATA SEGMENT
MAXSEG==5 ;MAX SEGS TO RECEIVE ON RONLY LINK
MAXSG1==3 ;MAX SEGS TO RECIEVE ON READ/WRITE LINK
MAXSGQ==3 ;MAX SEGMENTS IN QUEUER
;MESSAGE AND ROUTING FLAGS
RTFLG==106 ;ROUTING FLAGS
VERTYP==2 ;VERIFICATION MESSAGE TYPE
CNMRFL==10 ;BASIC CONTROL MESSAGE TYPE
NDIFLG==5B31 ;NODE INIT MESSAGE
CNMCI==20 ;CI
CNMCF==40 ;CONNECT-CONFIRM
CNMDI==60 ;DI
CNMDC==100 ;DC
CIMMFL==30 ;CI MESSAGE FLAGS
DATMFL==0 ;BASIC DATA MESSAGE FLAGS
DATFLI==20 ;INT/LS FLAGS
DATINT==40 ;INTERRUPT MESSAGE FLAG
DATBOM==40 ;BEGINNING OF MESSAGE SEGMENT
DATEOM==100 ;END OF MESSAGE SEGEMENT
; ..
;MORE NSP DEFINITIONS
CISRVS==1 ;CI BASIC SERVICES
CIMCNT==10 ;MESSAGE COUNTS
CIMSCT==4 ;SEGEMENT COUNTS
LNKPRI==2 ;DEFAULT LINK PRIORITY
SEGSIZ==400 ;MAX SEGMENT SIZE
MAXRSZ==300 ;MAX SEG SIZE TO SEND IN A NODE INIT
OBJZRO==0 ;OBJECT TYPE 0 (NO DESCRIPTOR)
OBJONE==1 ;OBJECT TYPE 1 (WITH DESCRIPTOR)
OBJTWO==2
OBJTSK==0 ;OBJECT # FOR TASK
RTHLEN==4 ;# OF WORDS NEEDED FOR ROUTING HEADER
DTMLEN==2 ;# OF WORDS NEEDED FOR DATA MESSAGE HEADER
CCLEN==13 ;# OF WORDS NEEDED FOR CC MESSAGE
LSLEN==3 ;# OF WORDS FOR LS MESSAGE
WSEGSZ==<SEGSIZ/11>*11 ;SEG SIZE IF OPEN IN WORD MODE
OPTSIZ==5 ;# OF WORDS FOR OPTDATA BLOCK
MAXDIF==^D30 ;MAX # OF OUTSTANDING SEGEMENTS
ACKBIT==10000 ;BIT TO SAY IF ACK OR NACK
ACKIND==100000 ;FIELD IS ACK BIT
ACKFLM==4 ;MESSAGE FLAG FOR ACK MESSAGE
ACKLSI==20 ;SUB-TYPE FOR LS/INT ACK
DILEN==^D10
CONLEN==^D27 ;SIZE OF CI BLOCK
ACKLEN==6 ;LENGTH OF AN ACK MESSAGE
INTLEN==6
NSPHDR==7 ;# OF BYTES IN HEADER OF DATA MESSAGE
;COMM VERSION DEFINITIONS
COMVER==3 ;VERSION OF NSP
COMECO==0 ;ECO LEVEL
COMCST==0 ;CUSTOMER LEVEL
ROUVER==0 ;ROUTING VERSION
ROUECO==0 ;ECO LEVEL
ROUCST==0 ;CUSTOMER LEVEL
NDISIZ==7 ;SIZE OF A NODE INIT MESSAGE
STRTYP==1 ;INIT MESSAGE TYPE
OURCAP==0 ;OUR CAPABILITIES
OURREQ==6 ;REQUIRED CAPS
OURNED==6 ;WE NEED THESE FROM MCB
VERIF==1 ;VERIFY MESSAGE NEEDED BIT
CNTFLD==77B5 ;COUNT FIELD IN ARG TO SNDDI
;TEMPORARY DEFINITIONS
FRKRUN==1B1 ;FLAG IN MCBDTE TO SAY NETWORK IS INITED
INIRCV==1B0 ;NODE INIT RECEIVED
NTSHUT==1B2 ;IF SET, NSP IS IN "SHUTDOWN" STATE
NOTMCB==1B3 ;NEIGHBOR IS NOT AN MCB
INISNT==1B4 ;NODE INIT SENT
REQVER==1B5 ;VERIFICATION MSG NEEDED ON THIS LINE
DEFSTR (NAMCN,,17,3) ;COUNT OF BYTES IN NODE NAME
;ROUTINE TO INIT NETWORK DATA BASES,ETC.
SWAPCD ;SWAPPABLE
NSPINI::UNLOCK LLLLCK ;UNLOCK LOCK
DMOVE T1,[ASCIZ /TOPS20/] ;GET OUR NAME
SKIPE OURNAM ;DID SETSPD SET OUR NODE NAME ?
JRST NSPIN1 ;DON'T SET NAME BECAUSE SETSPD BEAT US
DMOVEM T1,OURNAM ;NO SO DEFAULT IT
MOVEI T1,6 ;COUNT OF CHARS IN "OURNAM"
MOVEM T1,OURCNT ;STORE IT
NSPIN1: MOVEI T1,NODNUM ;GET DEFAULT NODE NUMBER
SKIPN OURNUM ;NUMBER ALREADY SET?
MOVEM T1,OURNUM ;NO. SET IT TO THE DEFAULT THEN
CALL OBJINI ;INIT OBJECT TABLE
CALL LLINIT ;AND INIT LL ADDRESS BIT TABLE
MOVX T1,1B1 ;MAKE FORK HAVE ALL CAPS
SETZ T2,
CFORK ;GET A FORK
BUG (HLT,NSPFRK,<NSPINI-CFORK FAILED>)
MOVEI T2,TSKINI ;THE STARTING ADDRESS
MSFRK ;START IT
MOVX T2,FRKRUN ;SAY FORK IS RUNNING
IORM T2,MCBDTE ;SET FLAG
RET ;AND DONE
SWAPCD ;CALLED ONLY IN PROCESS CONTEXT
;ROUTINES USED TO LOCK AND UNLOCK LL TREE
LOKLL: NOINT ;PREVENT INTS
LOCK LLLLCK,<CALL LCKTST> ;LOCK UP THE TREE
RET ;DONE
ULOKLL: UNLOCK LLLLCK ;UNLOCK THE TREE
OKINT ;ALLOW INTS
RET ;AND DONE
;ROUTINES TO LOCK AND UNLOCK INDIVIDUAL LL BLOCKS
;LOCK A BLOCK.
; T1/ BLOCK ADDRESS
;RETURNS: +1 FAILED. BLOCK ROUTINE IN T1
; +2 SUCCESS
BLKLOK: NOSKED ;PREVENT RACES
JE LLLOK,(T1),[ SETONE LLLOK,(T1) ;IF NO AVAILABLE, GET IT
NOINT ;PREVENT INTS
OKSKED ;ALLOW SCHEDULING AGAIN
RETSKP] ;AND DONE
OKSKED ;NOT AVAILABLE
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: SETZRO LLLOK,(T1) ;FREE THE LOCK
OKINT ;AND ALLOW INTS AGAIN
RET ;AND DONE
;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
;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
;LLLKUH MUST NOT BE CALLED FROM SCHED CONTEXT.
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?
RET ;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
RET ;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 /FAL/],,21
[ASCIZ /NCU/],,23
[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
;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 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 IR 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: DMOVE T3,T1 ;SAVE ARGS
SKIPN T1,LLHEAD ;ANY LINKS?
RET ;NO. CAN'T FIND IT THEN
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
JUMPN T4,[LOAD T2,LLSTA,(T1) ;IF MUST BE LISTENING, GET STATE
CAIE T2,LLSLIS ;IS IT LISTENING?
JRST OBJSNO ;NO. NOT INTERESTED THEN
JRST .+1] ;YES
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,R ;IF BACK TO FENCE, NO SUCH OBJECT
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: 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
TSKLO1: 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
;COMPARE TWO STRING STORED IN EXTENDED BLOCKS
;ACCEPTS: T1/ BLOCK 1
; T2/ BLOCK 2
; T3/ COUNT
;RETURNS: +1 NO MATCH
; +2 MATCH
CMPSTR: MOVSI T3,1 ;GET HUGE COUNT
CMPST1: ACVAR <W1,W2,W3> ;GET SOME REGS
MOVE W3,T3 ;SAV COUNT
SKIPN T1 ;HAVE A POINTER HERE?
MOVEI T1,[0] ;NO. INVENT A NULL STRING THEN
SKIPN T2 ;HAVE A POINTER HERE?
MOVEI T2,[0] ;NO. INVENT ONE HERE TOO
MOVE W1,[POINT 7,0(T1)]
MOVE W2,[POINT 7,0(T2)]
CMPLOP: ILDB T3,W1 ;GET NEXT BYTE
ILDB T4,W2 ;GET THIS ONE'S NEXT
CAME T3,T4 ;MATCH?
RET ;NO. NO MATCH THEN
SOSLE W3 ;ANY MORE BYTES?
JUMPN T3,CMPLOP ;DO ENTIRE STRING
RETSKP ;A MATCH!!!!
;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
;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 (MONX01) ;NO. INSUFFICIENT RESOURCES
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
GETRES: HRLI T1,.RESP3 ;IN PROCESS CONTEXT
MOVE T2,[RS%SE0!.RESNP] ;FROM THE NETWORK
CALL ASGRES ;GET SOME SPACE
RETBAD() ;COULDN'T
RETSKP ;GOT IT
;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: ACVAR <W1> ;GET A WORK REG
MOVE W1,[POINT 7,0(T1)] ;FORM STRING POINTER
MOVST2: ILDB T4,T2 ;GET A BYTE
IDPB T4,W1 ;STORE IT
SOJG T3,MOVST2 ;DO ALL BYTES
RET ;DONE
;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 T1,T1 ;NO ADDITIONAL WORDS
OPNSRC: MOVEI T1,LKOBJS ;ADDITIONAL WORDS FOR OBJECT
MOVX T2,FRKRUN ;SEE IF NETWORK IS INTIALIZED
TDNN T2,MCBDTE ;IS IT?
RETBAD (DCNX11) ;NO. ILLEGAL TO USE IT THEN
ADDI T1,LKSIZE ;BASIC SIZE OF A LL BLOCK
TRVAR <SAVBLK,SAVERR> ;TO REMEMBER LL BLOCK ADDRESS
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: 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
NOSKED ;MUST MAKE THIS CHECK RACE FREE
OPSTRM <AOS T2,>,DCCUR ;GET AND INCREMENT COUNT
MOVE T3,CAPENB ;GET CURRENT CAPABILITIES
LOAD T4,DCMAX ;GET MAX COUNT ALLOWED
TXNN T3,SC%WHL!SC%OPR ;IS THIS A PRIVILEGED FORK?
CAIG T2,0(T4) ;NO. ALLOWED TO MAKE ANOTHER LINK?
SKIPA ;YES
JRST [ MOVEI T1,DCNX5 ;NO. GIVE ERROR
OKSKED ;ALLOW SCHEDULING AGAIN
JRST OPNFAI] ;AND GO FAIL
OKSKED ;AND ALLOW SCHEDULING AGAIN
MOVEI T1,2 ;SIZE OF HOST NAME BLOCK
CALL GETBLK ;GET ONE
JRST OPNFAI ;COULDN'T
MOVE T2,SAVBLK ;GET LL BLOCK ADDRESS
STOR T1,LLHST,(T2) ;SAVE 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
HRRZ T1,FILNEN(JFN) ;GET POINTER TO EXTENSION BLOCK
JUMPE T1,OPNDFT ;NONE. GO DEFAULT TASK NAME
LDB T2,[POINT 7,1(T1),6] ;GET FIRST BYTE
JUMPE T2,OPNDFT ;IF NULL EXTENSION. GO DEFAULT TASK NAME
; ..
;USER SPECIFIED EXTENSION. CHECK FOR DUPLICATE
HRRZ T1,0(T1) ;GET SIZE OF EXTENSION
SOS T1 ;DISCOUNT THE HEADER
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
HRRZ T2,FILNEN(JFN) ;GET STRING BLOCK
AOS T2 ;POINT TO TEXT
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
LDB T3,PBYTSZ ;GET BYTE SIZE OF OPENING
STOR T3,LLBSZ,(T1) ;SAVE BYTE SIZE
CAIE T3,44 ;WORD MODE?
JRST OPENX1 ;NO. GO ON
SETONE LLFDI,(T1) ;YES. REMEMBER THIS
OPENX1: MOVEM T1,FILLLB(JFN) ;SAVE BLOCK ADDRESS
TQNE <READF> ;WANT BI-DIRECTIONAL LINK?
CALL [ SETONE LLOPI,(T1) ;YES.
RET]
TQNE <WRTF> ;WANT WRITE?
CALL [ SETONE LLOPW,(T1) ;YES.
RET]
RETSKP ;AND DONE
;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,DCNX4 ;?
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
CAMN T2,FORKX ;IS IT?
RET ;YES. NO NEED TO CHECK ANYMORE
JRST TSKLO1 ;NO. DO NORMAL TASK CHECKING
;DELETE NODE FROM LL TREE
; T1/ BLOCK ADDRESS
DELNOD: ASUBR <SAVBLK> ;SAVE BLOCK ADDRESS
LOAD T1,LLLNK,(T1) ;GET ITS ADDRESS
SETOM T2 ;ANY MATCH
CALL LLLKUP ;GO LOOK IT UP
BUG (HLT,DELNDF,<DELNOD-LLLKUP FAILED>)
JUMPE T2,[SETZM LLHEAD ;IF THE HEAD. CLEAR HEADER
JRST DELNO1] ;AND PROCEED
LOAD T3,LLUPL,(T2) ;SEE IF THIS IS UP OR DOWN
NOSKED
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
OKSKED
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,>,LLHST,(T1) ;HAVE A HOST NAME STRING?
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: CALLRET RELRES ;FREE BLOCK AND RETURN
DELREL: SAVET
MOVE T1,T2 ;GET BLOCK ADDRESS
CALLRET RELBLK ;FREE BLOCK
;ROUTINE TO RESET AN LL BLOCK SO THAT IT CAN REVERT TO
;THE LISTENING STATE. USED WHEN A SERVER REJECTS A CONNECTION.
CLRBLK: 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
LOAD T2,LLFDS,(T1)
SETZM 0(T2) ;NO REMOTE DESCRIPTOR
SETZRO LLRSN,(T1) ;NO DISCONNECT REASON
JE LLFOB,(T1),R ;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
RET ;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 (HLT,ADDONF,<ADDOBJ-LLLKUP FAILED>)
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
;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
;THE ATTRIBUTE TABLE
ATTRTB: ATTENT (.PFUDT,0,^D16,0)
ATTENT (.PFPWD,0,^D8,.PFBPW)
ATTENT (.PFBPW,1,^D8,.PFPWD)
ATTENT (.PFACN,0,^D16,0)
ATTENT (.PFOPT,0,^D16,.PFBOP)
ATTENT (.PFBOP,1,^D16,.PFOPT)
MAXNTA==.-ATTRTB
;DEFINE DTB'S
;FOR DEVICE SRV
SRVDTB::IFIW!NETDIR ;DIRECTORY SET
IFIW!SRNSET ;NAME LOOKUP
IFIW!EXTSET ;EXTENSION LOOKUP
IFIW!VERSET ;VERSION LOOKUP
DTBBAD (DESX9) ;NO PROTECTION
DTBBAD (DESX9) ;NO ACCOUNT
DTBBAD (DESX9) ;NO STATUS
IFIW!SRCOPN ;OPEN
IFIW!NETSQI ;INPUT
IFIW!NETSQO ;OUTPUT
IFIW!NETCLZ ;CLOSE
REPEAT 7,<
DTBBAD (DESX9)> ;ILLEGAL FUNCTIONS
IFIW!NTMTOP ;MTOPR
REPEAT 2,<DTBBAD (DESX9)> ;ILLEGAL FUNCTIONS
IFIW!NETSQR ;SOUTR
IFIW!RFTADN ;NO TIME AND DATE
IFIW!RFTADN ;NO TIME AND DATE
IFIW!NETINP ;SET FOR INPUT
IFIW!NETOUP ;SET FOR OUTPUT
DTBBAD (GJFX49) ;NO ATTRIBUTES
;FOR THE DCN DEVICE
DCNDTB::IFIW!NETDIR ;DIR SET
IFIW!DCNSET ;NAME LOOKUP
IFIW!EXTSET ;EXTENSION LOOKUP
IFIW!VERSET ;VERSION LOOKUP
REPEAT 3,<
DTBBAD (DESX9)> ;ILLEGAL FUNCTIONS
IFIW!DCNOPN ;OPEN
IFIW!NETSQI ;INPUT
IFIW!NETSQO ;OUTPUT
IFIW!NETCLZ ;CLOSE
REPEAT 7,<
DTBBAD (DESX9)> ;ILLEGAL FUNCTIONS
IFIW!NTMTOP ;MTOPR
REPEAT 2,<DTBBAD (DESX9)> ;ILLEGAL FUNCITONS
IFIW!NETSQR ;SOUTR
IFIW!RFTADN ;NO TIME AND DATE
IFIW!SFTADN ;NO TIME AND DATE
IFIW!NETINP ;SET FOR INPUT
IFIW!NETOUP ;SET FOR OUTPUT
IFIW!NETATR ;PARSE ATTRIBUTES
;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 ;FAILED
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: SETZM FILBFI(JFN) ;CLEAN UP JFN BLOCK
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.
GTSBLK: MOVEI T1,OPTSIZ ;THE PROPER SIZE
CALL GETBLK ;GET ONE
RET ;FAILED
RETSKP ;GOT IT
;ROUTINE CALLED FROM THE OPENF JSYS TO OPEN A DCN NETWORK CONNECTION
DCNOPN: ACVAR <W1,W2,W3> ;GET A WORK REGISTER
TRVAR <NTCNT,NTPNT,NTOBJ,NTDSC,NTDSS,NTHST,NTHSC,NTCIB>
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
MOVE W1,T1 ;SAVE LL BLOCK ADDRESS
MOVE T1,NTOBJ ;GET OBJECT
STOR T1,LLFNM,(W1) ;SAVE IT
SKIPG T3,NTHSC ;HAVE A HOST NAME?
JRST [ SKIPL W2,NSPLPB ;DOING LOOPBACK ?
JRST HSTLCL ;NO SO USUAL LOCAL PROCEDURE
MOVE T2,[POINT 7,OURNAM] ;POINT TO OUR NAME
MOVE T3,OURCNT ;AND SIZE OF OUR NAME
JRST DCNOP8 ]
CAME T3,OURCNT ;SAME COUNT AS OUR NAME?
JRST DCNOP0 ;NO. CAN'T BE US THEN
HRRZ T1,NTHST ;GET BLOCK POINTER
AOS T1 ;PUT TO START OF NAME
MOVEI T2,OURNAM ;GET OUR NAME
CALL CMPST1 ;SEE IF THE SAME
JRST DCNOP0 ;NO. SAVE IT THEN
SKIPL W2,NSPLPB ;IS THERE A LOOPBACK PORT ?
JRST HSTLCL ;NO. DO SAME AS LOCAL THEN
JRST DCNOP7 ;USE LOOPBACK PORT FOR MESSAGES
DCNOP0: MOVSI W2,-DCN ;MAKE PORT NUMBER COUNTER
SETOM W3 ;WHERE TO REMEMBER INT. NODE
DCNOP2: SKIPGE T2,MCBDTE(W2) ;IS PORT ACTIVE ?
TXNE T2,NTSHUT ;IS PORT SHUTTING DOWN ?
JRST DCNOP3 ;CAN'T USE THIS ONE
TXNN T2,NOTMCB ;IS THIS AN MCB?
HRRZ W3,W2 ;YES. REMEMBER PORT THEN
MOVE T3,NTHSC ;GET COUNT OF CHARS IN NAME
OPSTR <CAME T3,>,NAMCN,MCBDTE(W2) ;SAME COUNT AS NODE NAME?
JRST DCNOP3 ;NO. THIS CAN'T BE IT THEN
MOVEI T2,ITSNAM(W2) ;ALMOST ADR OF NEIGHBOR'S NAME
ADDI T2,(W2) ;MAKE NEIGHBORS NAME
HRRZ T1,NTHST ;GET BLOCK POINTER AGAIN
AOS T1 ;PUT TO START OF NAME
CALL CMPST1 ;SEE IF THIS MATCHES
DCNOP3: AOBJN W2,DCNOP2 ;LOOP BACK FOR REST OF PORTS
JUMPL W2,DCNOP7 ;IF FOUND MATCH
SKIPGE W2,W3 ;FOUND AN MCB?
JRST [ MOVEI T1,DCNX13 ;NODE NOT ACCESSIBLE
JRST SRCFAL] ;AND BOMB
DCNOP7: MOVE T2,NTHST ;GET POINTER TO STRING TO BE MOVED
MOVE T3,NTHSC ;GET COUNT
DCNOP8: STOR W2,LLPRT,(W1) ;SAVE PORT #
LOAD T1,LLHST,(W1) ;GET ADDRESS OF HOST STRING
CALL MOVST1 ;AND MOVE IT
HSTLCL: SKIPG T3,NTDSC ;HAVE A DESCRIPTOR?
JRST DSCNUL ;NO.
LOAD T1,LLFDS,(W1) ;GET DESCRIPTOR BLOCK
MOVE T2,NTDSS ;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
JRST SRCFAL ;FAILED. GIVE UP
MOVEM T1,NTCIB ;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
CALL ASGWDW ;NOW SET UP WINDOWS
JRST [ EXCH T1,NTCIB ;SAVE ERROR. GET BLOCK
CALL RELRES ;RELEASE IT
MOVE T1,NTCIB ;GET BACK ERROR CODE
JRST SRCFAL] ;AND GIVE UP
MOVE T1,W1 ;LL BLOCK ADDRESS
MOVEI T2,CNMRFL+CNMCI ;MESSAGE FLAGS
CALL RTHDCI ;GO PUT ON CI ROUTING HEADER
CALL DOSRVS ;DO COMMON SERVICES
; ..
;DCNOPN CONTINUED...
;NOW BUILD OBJECT ADDRESSING FIELDS
SKIPG NTDSC ;HAVE A COUNT FOR DESCRIPTOR
JRST [ MOVEI T2,OBJZRO ;GET OBJECT TYPE ZERO INDICATOR
CALL ONEBYT
MOVE T2,NTOBJ ;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,NTOBJ ;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
SETZ T2, ;DEFAULT MENU BYTE
CALL ONEBYT ;PUT IT IN
MOVE T3,LLBPTR(T1) ;GET POINTER TO MENU
MOVEM T3,NTPNT ;SAVE IT
MOVEI T2,1 ;ASSUME WILL BE PRESENT
MOVEM T2,NTCNT ;ASSUME WILL BE PRESENT
MOVEI T2,.PFUDT ;SEE IF USER I.D. GIVEN
CALL FNDATR ;IS IT?
JRST [ SETZM T2 ;NOT THERE.
CALL ONEBYT ;STORE A NULL COUNT
JRST DOPSW1] ;AND GO TO THE PASSWORD
CALL ASCIIZ ;PUT IN THE DATA
DOPSW1: MOVEI T2,.PFPWD ;SEE IF A PASSWORD IS GIVEN
CALL FNDATR ;IS IT?
JRST [ MOVEI T2,.PFBPW ;NO. SEE ABOUT ALTERNATE FORM
CALL FNDATR
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
CALL FNDATR ;HAVE ONE?
MOVEI T3,[0] ;NO. PUT IN NULL STRING
CALL ASCIIZ ;YES. PUT IT IN
NOUSED: MOVEI T2,.PFOPT ;HAVE OPTIONAL USER DATA?
CALL FNDATR ;?
JRST [ MOVEI T2,.PFBOP ;NO. TRY OTHER FORM
CALL FNDATR
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,NTCNT ;TO THE MENU
CALL 0(T4) ;INSERT IT
INMENU: MOVE T2,NTCNT ;GET FINAL MENU
DPB T2,NTPNT ;PUT IT IN THE MESSAGE
MOVEI T2,LLSCIS ;GET NEW STATE
STOR T2,LLSTA,(T1) ;STORE NEW STATE
LLLULK ;RELEASE TREE NOW
MOVE T2,NTCIB ;GET BLOCK ADDRESS
CALL SNDCTL ;SEND MESSAGE TO THE NETWORK
RETSKP ;AND DONE FOR NOW
;ROUTINE TO INSERT THE LL ADDRESSES IN A MESSAGE.
;ACCEPTS: T1/ LL BLOCK ADDRESS
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
;ROUTINE TO INSERT CI/CC COMMON FIELDS
; T1/ LL BLOCK
DOSRVS: CALL PUTLLA ;PUT IN LL ADDRESSES
MOVEI T2,CISRVS+CIMSCT ;ASSUME SEG COUNTS
OPSTR <SKIPE>,LLIMS,(T1) ;WANT MESSAGE COUNTS?
TXC T2,CIMSCT+CIMCNT ;YES
CALL ONEBYT ;PUT IN SERVICES BYTE
MOVEI T2,LNKPRI ;GET DEFAULT PRIORITY
CALL ONEBYT
MOVEI T2,SEGSIZ ;GET SEGMENT SIZE
OPSTR <SKIPE>,LLFDI,(T1) ;OPEN IN WORD MODE?
MOVEI T2,WSEGSZ ;YES. GET PROPER SEG SIZE
SETZRO LLFDI,(T1) ;INIT THIS FLAG
CALLRET TWOBYT
;ROUTINE TO BUILD A ROUTING HEADER. CALLED FOR CONTROL MESSAGES
;ACCEPTS: T1/ LL BLOCK ADDRESS
; T2/ PROPER MESSAGE FLAGS
RTHDCI: STKVAR <MSGFLG> ;TO SAVE MESSAGE FLAGS
MOVEM T2,MSGFLG ;SAVE FLAGS
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 TSTLCL ;SEE IF A LOCAL CONNECTION
MOVEI T3,[0] ;IT IS
CALL ASCIIZ ;PUT IT IN
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
;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
;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
;ROUTINES TO INSERT BYTES IN MESSAGE AND ACCOUNT FOR THEM
;INSERT ONE BYTE. ACCEPTS: T2/ THE BYTE
; T1/ LL BLOCK ADDRESS
;PRESERVES ALL REGISTERS
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
;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
FNDAT1: 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 FNDAT1] ;AND LOOK AT IT
MOVEI T3,1(T3) ;GET POINTER TO BLCOK
RETSKP ;AND SAY WE FOUND IT
;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 FILBFI(JFN) ;CLEAN UP JFN BLOCK
RETBAD (MONX02)] ;AND FAIL
HRLM T1,FILWND(JFN) ;STORE WINDOW
RETSKP ;AND DONE
;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
;MTOPR ROUTINES
NTMTOP: CALL NETINP ;SET UP FOR INPUT...
MOVE T1,FILLLB(JFN) ;MUST LOCK UP BLOCK
CALL BLKLOK ;DO IT
JRST WATBLK ;MUST WAIT FOR THE LOCK
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
MOVEI T1,MTOX1 ;NOT FOUND
JRST SQOBAD ;GIVE ERROR
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
NTMTCT==.-NTMTTB ;LENGTH OF TABLE
;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 SQOBAD ;BAD
LOAD T2,MO%INA,W1 ;GET INT CHANNEL
CALL MTSETI ;GO DO INT CHANNEL
JRST SQOBAD ;BAD
LOAD T2,MO%DAV,W1 ;GET DATA CHANNEL
CALL MTSETD ;SET IT
JRST SQOBAD ;BAD
CALL BLKULK ;FREE BLOCK
RETSKP ;AND DONE
;MTOPR FUNCTIONS CONTINUED...
;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
LOAD T2,LLHST,(T1) ;YES. GET HOST STRING
CALL TSTLCL ;IS THIS A LOCAL CONNECTION?
MOVEI T2,OURNAM ;YES. USE LOCAL NAME THEN
CALLRET NTCPY ;AND GO COPY TO USER
;WORKER ROUTINE TO COPY AN ASCII STRING TO THE USER.
; T2/ ADDRESS OF STRING BLOCK
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
;MTOPR FUNCTIONS CONTINUED...
;READ LINK STATUS
NTSTS: LOAD T3,LLRSN,(T1) ;GET REASON IN CASE NOW DISCONNECTED
OPSTR <SKIPE>,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
CAIE T2,LLSLIS ;LISTENING?
CAIN T2,LLSCIS ;OR CI SENT?
TXO T3,MO%WFC ;YES. WAITING FOR CONNECT THEN
CAIN T2,LLSCIR ;CI RECEIVED?
TXO T3,MO%WCC ;YES. WAITING FOR US TO CONFIRM
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
OPSTR <SKIPE>,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 ;NOTE LINK WAS CONNECTED IF CC RECEIVED
JRST .+1] ;CONTINUE
UMOVEM T3,3 ;RETURN RESULT
CALL BLKULK ;FREE BLOCK
RETSKP ;AND DONE
;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
CAIN T2,LLSCIR ;IN CIR STATE?
RETSKP ;YES. IS GOOD THEN
MTRNCK: LOAD T2,LLSTA,(T1) ;GET STATE
CAIN T2,LLSRUN ;RUNNING?
RETSKP ;YES.
MTOBJ1: RETBAD (DCNX11) ;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
;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
OPSTR <SKIPN>,LLDRW,(T1) ;HAVE ANY MESSAGES ON RAW Q?
SKIPE LLOMSG(T1) ;NO. ANY ORDERED 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
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
;MORE MTORP FUNCTIONS...
;RECEIVE INTERRUPT MESSAGE
MTRDIN: CALL MTRNCK ;CHECK STATE
JRST SQOBAD ;ERROR
ACVAR <W1> ;GET A REG
SKIPN T2,LLMSI(T1) ;HAVE AN INT MESSAGE?
JRST [ MOVEI T1,DCNX11 ;NO.
CALLRET SQOBAD] ;GIVE ERROR
LOAD T3,MSSEG,(T2) ;GET SEG NUMBER
STOR T3,LLIIN,(T1) ;IT IS NOW LAST ACKED SEG
CALL ACKLI ;GO ACK IT
JRST SQOBAD ;GO BLOCK
MOVEI T2,1 ;ASK FOR ONE MORE
MOVEI T3,MSLSI ; INTERRUPT MESSAGE
CALL SNDLS ;SEND MESSAGE
JRST SQOBAD ;NEED TO BLOCK
MOVE T2,LLMSI(T1) ;GET BACK MESSAGE
SETZM LLMSI(T1) ;NONE NOW
LOAD T4,MSDTC,(T2) ;GET COUNT
UMOVEM T4,4 ;RETURN COUNT TO USER
UMOVE T3,3 ;GET USER;S BYTE POINTER
TLC T3,-1
TLCN T3,-1
HRLI T3,(<POINT 7,>) ;GET DEFAULT
UMOVEM T3,3 ;RETURN BYTE POINTER
MOVE T3,MSBPTR(T2) ;GET POINTER TO MESSAGE DATA
JRST MTRDI2 ;GO MOVE DATA
MTRDI1: ILDB W1,T3 ;GET NEXT BYTE
XCTBUU [IDPB W1,3] ;STORE IT
MTRDI2: SOJGE T4,MTRDI1 ;DO THEM ALL
CALL BLKULK ;DONE WITH BLOCK
MOVE T1,T2 ;GET FREE SPACE ADDRESS
CALL RELRES ;RELEASE MESSAGE
RETSKP ;AND DONE
;MORE MTOPR'S.... SEND INTERRUPT MESSAGE
MTSNIN: CALL MTRNCK ;MAKE SURE IS RUNNING
JRST SQOBAD ;NOT. ERROR
UMOVE T4,4 ;GET COUNT
CAILE T4,MAXDSC ;WITHIN RANGE?
JRST [ MOVEI T1,DCNX12 ;ARG TOO LARGE
JRST SQOBAD] ;GIVE ERROR
JE LLMIC,(T1),[ MOVEI T1,DCNX14 ;ANY QUOTA?
JRST SQOBAD] ;NO
ACVAR <W1> ;CAN SEND IT
MOVEI T1,INTLEN+MSHDR ;LENGTH
CALL GETRES ;GET SOME SPACE
JRST SQOBAD ;NONE AVAIABLE. TRY LATER
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 ONEBYT ;INTO THE MESSAGE
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
UMOVE T4,4 ;GET COUNT
UMOVE T3,3 ;GET BP
TLC T3,-1
TLCN T3,-1
HRLI T3,(<POINT 7,>) ;FORM DEFAULT
UMOVEM T3,3 ;STORE IT BACK
JRST MSTSN2 ;GO SEND THEM
MSTSN1: XCTBUU [ILDB T2,3] ;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 T1,FILLLB(JFN) ;GET BACK BLOCK ADDRESS
JRST MTDON ;AND DONE
;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
;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
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,LLSRUN ;NOW CONNECTED?
JRST NTRCB1 ;NO. CAN;T DISCONNECT THEN
UMOVE T2,2 ;GET DISCONNECT REASON
SKIPE T2 ;NORMAL CLOSE?
CAIN T2,.DCX11 ;OR THIS WAY?
SKIPA ;YES. GO ON
JRST [ CALL FLUSH ;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
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 DOEN
;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
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
RETBAD ;MUST WAIT AWHILE
CALL SNDCTL ;SEND THE MESSAGE
RETSKP ;AND DONE
;ROUTINE TO COPY OPTDATA TO A BUFFER AND RETURN PROPER OPTDATA
;ARG
; T3/ BUFFER ADDRESS
;RETURNS: +1 TOO LONG
; +2 DONE
NTMVOP: ACVAR <W1,W2,W3>
MOVE W3,T3 ;SAVE BUFFER ADDRESS
SETZM T3 ;ASSUME NO DATA
UMOVE T4,4 ;GET COUNT
JUMPE T4,RSKP ;IF NONE, NO ARG
SKIPL T4 ;COUNT MUST BE POSITIVE
CAILE T4,MAXDSC ;WITHIN LIMITS?
RETBAD (DCNX12) ;NO. TOO LONG
STOR T4,CNTFLD,W3 ;BUILD RETURN ARG
MOVE W2,[POINT 8,0(W3)] ;GET POINTER TO SOURCE
UMOVE T3,3 ;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
;CODE TO DO CLOSF
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 BLKLOK ;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
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
OPSTR <SKIPE>,LLFLO,(T1); FLOW NOW TO F/S?
SKIPE T2 ;YES. ANY BYTES?
SKIPA ;HAVE DATA TO SEND
JRST CLZCMS ;ALL DATA SENT. WAIT FOR ACKS
SETONE LLFEM,(T1) ;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
MOVEI T2,LLSDIQ ;DI IS NOW QUEUED
STOR T2,LLSTA,(T1) ;MARK STATE CHANGE
CLZDIQ: SETZM T3 ;NO USER DATA
LOAD T2,LLRSN,(T1) ;GET OUR REASON
MOVEI T4,CNMRFL+CNMDI ;IS A DI
CALL SNDDI ;GO SEND DI
JRST [ TXNN W2,CZ%ABT ;ABORT?
JRST SQOBAD ;NO. CONVENTIONAL WAIT
BUG (INF,CLZDIN,<NETCLZ-COULD NOT SEND DI>)
CALL MOVUNL ;TURN OFF BLOCK. RESTORE LL POINTER
JRST CLZDQ1] ;AND PROCEED
CALL SNDCTL ;SEND THE MESSAGE
CLZDQ1: MOVEI T2,LLSDIS ;SAY DI IS SENT
STOR T2,LLSTA,(T1)
CLZWDC: TXNE W2,CZ%ABT ;ABORT CLOSE?
JRST [ SETONE LLSDE,(T1) ;YES. DISSOCIATE PROCESS AND LINK
CALL FLUSH ;KILL OF QUEUES
CALL BLKULK ;FREE THE BLOCK
JRST CLZDN1] ;AND GO FINISH UP
MOVEI T2,CHKDCR ;WAIT FOR DC TO COME BACK
JRST OUTWAT
;MORE CLOSE ROUTINES
;DC HAS ARRIVED. FIND OUT IF IT WHAT WE WANTED
CLZDIR: ;CLOSE IN DI RECEIVED STATE
CLZABT: 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
;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>
MOVEI T1,DILEN+MSHDR ;GET A BLOCK FOR THE DI
CALL GETRES ;GET IT
JRST GENWAT ;FAILED
MOVEM T1,LLMSGB ;SAVE BLOCK ADDRESS
MOVEI T2,MSHDR(T1) ;GET TO START OF DATA PORTION
HRLI T2,(<POINT 8,>)
MOVE T1,LLBLK ;GET BACK LL BLOCK ADDRESS
MOVEM T2,LLBPTR(T1) ;SAVE POINTER
SETZM LLBPCT(T1) ;INIT COUNT
MOVE T2,DIFLGS ;GET FLAGS
CALL RTHDCI ;PUT ON ROUTING HEADER
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 BLKLOK ;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
OPSTR <SKIPE>,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
OPSTR <SKIPE>,LLFLI,(T3) ;IS INPUT FLOW TO THE F/S?
SKIPE LLMSI(T3) ;YES. FREE OF INT MESSAGES
SETZM T1 ;NO. USE ZERO COUNT THEN
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
OPSTR <SKIPN>,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
OPSTR <SKIPN>,LLFLO,(T3) ;IS OUTPUT FLOW FROM THE F/S?
SETZM T1 ;NO.
JRST NETSCM ;AND DONE
;SET UP ROUTINES CONTINUED...
;UNDO OUTPUT
NETUOU: TQZN <FILOUP> ;NOW DOING OUTPUT?
RET ;NO. ALL DONE
MOVE T1,FILLLB(JFN) ;GET LL BLOCK
OPSTR <SKIPN>,LLFLO,(T1) ;FLOW FROM THE F/S?
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
OPSTR <SKIPN>,LLFLI,(T1) ;FLOW TO THE F/S?
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
;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
SWAPCD ;IS SWAPPABLE
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
MOVEM T3,NTCNT ;STARTING COUNT
HRLI T1,(<POINT 7,0,35>) ;GET STRING POINTER TO THE BLOCK
MOVEM T1,NTPNT ;AND SAVE THE STARTING POINTER
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,NTCNT ;FOUND A NULL THEN. GET CHARACTERS SKIPPED
MOVNS T3 ;GET COUNT
MOVEM T3,NTCNT ;AND SAVE CORRECT 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
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 (DCNX12) ;NO. STRING TOO LONG
MOVEM T1,NTHST ;SAVE POINTER TO HOST
MOVEM T3,NTHSC ;AND SAVE COUNT
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
;SEQUENTIAL I/O JSYSS.
;SEQUENTIAL OUTPUT.
NETSQO: ASUBR <NETCHR> ;SAVE THE CHARACTER
MOVE T1,FILLLB(JFN) ;GET LL BLOCK ADDRESS
CALL BLKLOK ;LOCK IT UP
JRST WATBLK ;GO WAIT FOR THE LOCK
LOAD T2,LLSTA,(T1) ;GET CURRENT 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 BLKLOK ;LOCK IT
JRST WATBLK ;GO WAIT FOR THE LOCK
LOAD T2,LLSTA,(T1) ;GET STATE
JRST @SQOOTR-1(T2) ;DO WORK
NETSR1: SETONE LLFEM,(T1) ;SAY SHOULD GET EOM ON OUTPUT
CALL OUTRR ;DO THE WORK
RETBAD() ;FAILED
MOVE T1,FILLLB(JFN) ;GET BACK LL BLOCK
CALL BLKULK ;UNLOCK BLOCK
RETSKP ;AND RETURN GOOD
;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
OPSTR <SKIPN>,LLFLO,(T1) ;IS FLOW FROM THE F/S?
JRST OUTRR1 ;NO. ALL SET TO GO THEN
;FLOW IS FROM THE FILE SYSTEM. COMPUTE BYTES NOW IN OUTPUT BUFFER
;AND SWITCH FLOW TO THE NETWORK
SETZRO LLFLO,(T1) ;SWITCH FLOW
LOAD T3,LLBSZ,(T1) ;GET BYTE SIZE
HLRZ T1,FILWND(JFN) ;GET WINDOW ADDRESS
CALL MAKPTR ;GET MAX BYTES IN BUFFER
HLRZ T3,FILBCT(JFN) ;GET REMAINING COUNT
SUBI T2,0(T3) ;COMPUTE BYTES IN THE BUFFER
MOVE T4,FILLLB(JFN)
LOAD T3,LLBSZ,(T4) ;GET BYTE SIZE
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
JUMPE T2,RSKP ;IS NONE LEFT, ALL DONE
MOVEM T1,FILBFO(JFN) ;PUT IN STARTING BYTE POINTER
HRLM T2,FILBCT(JFN) ;STORE COUNT TO SEND
; ..
;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,[SETONE LLFLO,(T1) ;NO. SWITCH FLOW TO F/S
LOAD T3,LLBSZ,(T1) ;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
JN LLBRP,(T1),[ MOVEI T2,CHKBRP ;IF FLOW CONTROL OFF, WAIT
JRST OUTWAT]
JN LLQUN,(T1),[MOVEI T2,CHKSWD ;IF ANY NAK'ED SEGS
JRST OUTWAT] ;WAIT
LOAD T2,LLQOU,(T1) ;GET SEGS NOW IN THE QUEUER
CAILE T2,MAXSGQ ;CAN WE PUT ANOTHER ONE IN?
OUTRR8: JRST [ MOVEI T2,CHKQTA ;WAIT FOR QUEUER COUNT TO COME DOWN
JRST OUTWAT] ;AND GO SET UP WAIT
LOAD T3,LLMFC,(T1) ;GET TYPE OF FLOW CONTROL
JUMPE T3,OUTRR2 ;IF NO FLOW CONTROL, ALL SET
LOAD T4,LLMSM,(T1) ;GET CURRENT FLOW COUNT
JUMPE T4,[MOVEI T2,CHKSCT ;WAIT FOR SOME COUNT TO APPEAR
JRST OUTWAT] ;AND GO SET UP BLOCK
CAIE T3,2 ;MESSAGE FLOW CONTROL?
TRNN T4,200 ;NO. SEGMENT. IS COUNT POSITIVE?
JRST OUTRR2 ;YES. CAN SEND A SEGMENT
MOVEI T2,CHKSCP ;WAIT FOR COUNT TO GO POSITIVE
OUTWAT: TQNE <ERRF> ;ERROR?
JRST SQOBAD ;YES. GO AWAY
CALL MAKTST ;MAKE A STANDARD TEST WORD
OUTWA1: TQO <BLKF> ;REQUEST BLOCK
CALLRET SQOBAD ;AND FINISH UP
;CAN SEND SOME DATA
OUTRR2: HLRZ T3,FILBCT(JFN) ;GET # OF BYTES REMAINING
LOAD T4,LLSWG,(T1) ;GET MAX SEG 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
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) ;YES. IS THIS START OF MESSAGE?
TXO T4,DATBOM ;YES. SET BOM THEN
JRST OUTRR4] ;YES. KEEP BOM
OUTRR4: OPSTR <SKIPE>,LLFEM,(T1) ;WANT EOM?
SKIPE T2 ;IS THIS LAST SEGMENT OF MESSAGE?
JRST [ CAIN T3,2 ;MESSAGE FLOW CONTROL?
JRST OUTRR6 ;YES. SKIP FLOW ADJUSTMENT
JRST OUTRR3] ;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
; ..
;OUTRR CONTINUED...
OUTRR3: JUMPE T3,OUTRR6 ;IF NO FLOW CONTROL, SKIP ADJUSTMENT
NOSKED ;PREVENT RACES
CALL DECMSM ;ADJUST FLOW CONTROL
OKSKED ;AND ALLOW SCHEDULING AGAIN
OUTRR6: MOVE T2,T4 ;GET COMPUTED FLAGS
MOVE T4,MBLOCK ;GET MESSAGE BLOCK ADDRESS
STOR T2,MSMFL,(T4) ;SAVE MESSAGE FLAGS
CALL ONEBYT ;STASH IT
CALL PUTLLA ;PUT IN LL ADDRESSES
MOVE T2,LLBPTR(T1) ;GET CURRENT POINTER
MOVEM T2,MSBPTR(T4) ;SAVE IN MESSAGE BLOCK
LOAD T2,LLDSN,(T1) ;GET SEG NUMBER
AOS T2 ;NEXT ONE
STOR T2,LLDSN,(T1) ;PUT IT BACK
ANDI T2,7777 ;ONLY 12 BITS
STOR T2,MSSEG,(T4) ;SAVE SEG # IN DATA BLOCK
CALL TWOBYT ;PUT IN SEGNUM
MOVE T4,MSIZE ;GET COUNT
ADDM T4,LLBPCT(T1) ;AND COUNT UP MESSAGE SIZE
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 T3,LLBPCT(T1) ;GET COUNT OF BYTES IN MESSAGE
SUBI T3,5 ;DISCOUNT NSP OVERHEAD
STOR T3,MSDTC,(T2) ;AND SAVE IN MESSAGE
CALL SNDSEG ;GO SEND A SEGMENT. ROUTINE
;PLUGS IN LL ADDRESS AND MESSAGE SIZE
JRST OUTR00 ;AND TRY FOR ANOTHER SEGMENT
;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
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
;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
;ROUTINE TO MAKE A STANDARD TEST WORD
MAKTST: LOAD T1,LLLNK,(T1) ;GET LL BLOCK ADDRESS
HRLS T1 ;TO THE LH
HRRI T1,0(T2) ;TEST ROUTINE
RET ;DONE
;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
MOVEI T2,MSHDR(T1) ;GET START OF DATA
HRLI T2,(<POINT 8,>)
MOVE T1,SAVLL ;GET BACK LL BLOCK
MOVEM T2,LLBPTR(T1)
SETZM LLBPCT(T1)
MOVEI T2,CNMRFL+CNMCF ;GET CC FLAGS
CALL RTHDCI ;PUT IN ROUTE HEADER
CALL DOSRVS ;PUT IN STANDARD CI/CC 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
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: 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 CONTROL MESSAGE
SQOCN1: CALL TURNON ;TRY TO SEND IT
JRST [ SETONE LLTRN,(T1) ;SAY STILL NEED LS
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
CAIE T2,LLSLIS ;LISTENING?
CAIN T2,LLSCIS ;OR CI SENT?
JRST 0(4) ;YES. NOT CONNECTED THEN
JRST 1(4) ;NO. CONNECTED
;WAIT UNTIL BLOCK LOCK IS FREE
CHKLOK: SETOM T2 ;ANY MATCH
CALL LLLKUP ;FIND LL BLOCK
JRST 1(4) ;CAN'T HAPPEN
JN LLLOK,(T1),0(4) ;IF STILL SET, 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
CAILE T2,MAXSGQ ;CAN TAKE SOME MORE?
JRST 0(4) ;NO. WAIT SOME MORE
JRST 1(4) ;YES.
;WAIT UNTIL SOME ACKS COME IN
CHKSCT: CALL CHKSET ;VERIFY LINK STATE
JRST 1(4) ;LINK CHANGED STATED
JN LLMSM,(T1),1(4) ;IF SOME ACKS, WAKE UP
JRST 0(4) ;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.
OPSTR <SKIPN>,LLFLI,(T1) ;ANYTHING IN FILE BUFFER PAGE?
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 IT 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 LLMSG(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)
LOAD T2,LLSTA,(T1) ;GET STATE
CAIE T2,LLSABT ;DC RECEIVED?
JRST 0(4) ;NO. KEEP WAITING
JRST 1(4) ;YES. AWAKE
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
;TEST ROUTINE FOR NSPTSK
NSPTST:
SKIPE KDPFLG ;DOES KMC11 WANT SERVICE
JRST 1(4) ;YES
; SKIPN RMSGQ ;ANY BLOCKS TO RELEASE?
SKIPE MSGQ ;NO. ANY MESSAGES TO DO?
JRST 1(4) ;YES.
JRST 0(4) ;NO.
;ROUTINES FOR SEQUENTIAL INPUT
;ROUTINE TO TAKE SEGMENTS OFF OF THE RAW DATA QUEUE AND
;PUT THEM ON THE ORDERED DATA QUEUE
SWAPCD
MOVSEG: ACVAR <W1,W2>
OPSTR <SKIPE>,LLFNN,(T1) ;NEED A NACK?
CALL MOVNAK ;YES. SEND NACK
MOVSE1: SKIPN T2,LLMSG(T1) ;HAVE ANY?
RETSKP ;NO. MUST BE DONE THEN
NOSKED ;PREVENT SCHEDULING
LOAD T3,MSLNK,(T2) ;GET LINK
MOVEM T3,LLMSG(T1) ;NEW LINK
OKSKED ;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 MESSAGE
MOVE T1,T2 ;GET SEGMENT ADDRESS
CALL RELRES ;FREE IT UP
MOVE T1,FILLLB(JFN) ;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
CALL MOVUNL ;FAILED. FORGE AHEAD ANYWAY
JRST MOVSE1] ;AND DONE
;MESSAGE IS GOOD. PUT IT ON THE ORDERED QUEUE
CAILE T3,MAXSEG ;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,FILLLB(JFN) ;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,FILLLB(JFN) ;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
;SNDACK WANTED TO BLOCK. IGNORE IT AND CONTINUE THE SCAN
MOVUNL: MOVE T1,FILLLB(JFN) ;GET BACK LL BLOCK ADDRESS
TQZ <BLKF> ;CON'T WANT TO BLOCK ANYMORE
RET ;AND DONE
;ROUTINE TO SEND A NACK FOR THE LINK
MOVNAK: 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 [ CALL MOVUNL ;IGNORE FAILURE
CALLRET DATINR] ;BUT MAKE IT RETRY SOON
SETZRO <LLFNN,LLFNA>,(T1) ;CLEAR FLAGS
RET ;AND DONE
;LOCAL ROUTINE TO HANDLE AN ACK FOUND ON LLMSG 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
;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
;ROUTINE TO VERIFY A SEGMENT
;ACCEPTS: T1/ LL BLOCK ADDRESS
; T2/ SEGMENT ADDRESS
; T3/ SEGMENT TYPE
;RETURNS: +1 BAD SEGMENT.
; T3=0 MEANS BADLY FORMED (PROTOCOL ERROR)
; T3=/0 MEANS OLD SEGMENT. NEEDS TO BE IGNORED
; +2 GOOD. T3/ "AGE"
VERSEG: TRVAR <MSGCNT,MSGBYP,MSGBLK,MSGSGT>
MOVEM T3,MSGSGT ;SAVE SEGMENT TYPE
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
MOVE T3,MSGSGT ;GET TYPE
CALL ACKCHN ;AND GO HANDLE THE ACK
CALL GETTWO ;GET SEGNUM
JRST VERBDY ;BAD
GOTSEG: SKIPG MSGCNT ;HAVE ANY BYTES LEFT?
JRST VERBDY ;NO. BADLY FORMED MESSAGE THEN
MOVE T3,T2 ;SAVE SEGMENT #
MOVE T2,MSGSGT ;GET TYPE
XCT [ LOAD T4,LLIIN,(T1)
LOAD T4,LLIDN,(T1)]-1(T2)
MOVE T2,MSGBLK ;GET BLOCK
STOR T3,MSSEG,(T2) ;SAVE SEGMENT #
SUBI T3,0(T4) ;COMPUTE "AGE"
ANDI T3,7777 ;MOD 4096
SKIPE T3 ;IS IT CURRENT ONE?
CAILE T3,MAXDIF ;NO. IS IT NEW?
AOJA T3,R ;NO. IS OLD
RETSKP ;YES. RETURN AGE IN T3
VERBDY: MOVE T2,MSGBLK ;GET BACK BLOCK ADDRESS
SETZM T3 ;SAY PROTOCOL ERROR
RET ;AND DONE
;ROUTINE TO DO SEQUENTIAL INPUT.
NETSQI: MOVE T1,FILLLB(JFN) ;GET LL BLOCK ADDRESS
CALL BLKLOK ;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
CALL BLKULK ;FREE THE BLOCK
MOVE T1,T2
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 OUTWA1 ;GO BLOCK
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: TRVAR <MSGCNT,MSGBYP,SQICNT,<MDPTR,2>>
SETZM SQICNT ;NONE YET
OPSTR <SKIPN>,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
SQI23: MOVE T1,FILLLB(JFN) ;RESTORE LL BLOCK
SQI22: CALL MOVSEG ;FIRST, PICK UP ACKS
RETBAD() ;OOPS. AN ERROR
JN LLFNA,(T1),SQISNA ;IF NEED ACK ONLY, GO DO IT
JN LLLSC,(T1),SQISN2 ;NEED AN LS MESSAGE?
SQI2: CALL MOVSEG ;NO INPUT. GET ANY SEGS
RETBAD() ;ERROR
SKIPN T2,LLOMSG(T1) ;GET TOPMOST SEGMENT
JRST SQIEMP ;NO. ALL DONE THEN
LOAD T3,MSSEG,(T2) ;GET SEGMENT NUMBER
LOAD T4,LLIDN,(T1) ;GET LAST ACKED DATA SEGMENT
AOS T4 ;THE ONE WE EXPECT
ANDI T4,7777 ;MOD 12
CAIE T3,0(T4) ;IS THIS IT?
JRST SQIEMP ;NO. CAN'T DO INPUT THEN
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
TRNE T2,100000 ;IS THIS ACKNUM?
CALL GETTWO ;YES. SO SKIP SEGNUM NOW
JFCL
; ..
;NOW POSITIONED TO DATA PORTION OF SEGMENT. MOVE DATA INTO
;JFN WINDOW PAGE
MOVE T4,MSGCNT ;GET REMAINING COUNT
ADD T4,SQICNT ;COMPUTE BYTES TO BE IN BUFFER
CAILE T4,4000 ;WILL THEY FIT?
JRST SQIEMP ;NO. DON'T MOVE IT THEN
MOVEM T4,SQICNT ;YES. UPDATE COUNT
MOVE 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: OPSTR <SKIPE>,LLIMS,(T1) ;MESSAGE INTERFACE?
JRST [ JE LLFIM,(T1),SQI4 ;YES. HAVE EOM IN BUFFER?
JRST .+1] ;YES
INCR LLLSC,(T1) ;NEED ANOTHER BUFFER SENT
SQI4: MOVE T4,MSGCNT ;GET BACK THE COUNT
LOAD T2,LLBSZ,(T1) ;GET BYTE SIZE
CAIN T2,44 ;WORD MODE?
JRST SQIWRD ;YES. MOVE WORDS THEN
SQIMOV: MOVE T3,T4 ;GET COUNT
MOVE T1,MSGBYP ;GET SOURCE POINTER
MOVE T2,FILBFI(JFN) ;GET DESTINATION
CALL NETMOV ;MOVE THE BYTES
MOVEM T2,FILBFI(JFN) ;UPDATE DESTINATION POINTER
MOVE T1,FILLLB(JFN) ;RESTORE LL BLOCK POINTER
SQIMV1: MOVE T2,LLOMSG(T1) ;GET EXPENDED MESSAGE
LOAD T3,MSSEG,(T2) ;GET SEG #
STOR T3,LLIDN,(T1) ;AND UPDATE LL BLOCK
LOAD T3,MSLNK,(T2) ;GET NEXT
MOVEM T3,LLOMSG(T1) ;NEW HEAD
MOVE T1,T2 ;MESSAGE BLOCK
CALL RELRES ;FREE IT
MOVE T1,FILLLB(JFN) ;GET BACK LL ADDRESS
DECR LLDMT,(T1) ;ONE LESS DATA MESSAGE
OPSTR <SKIPN>,LLFIM,(T1) ;HAVE EOM?
JRST SQI2 ;AND TRY AGAIN
; ..
;NETSQI CONTINUED....
;GOT ALL MESSAGES MOVED.
SQIEMP: SKIPG SQICNT ;GET ANY BYTES?
JRST SQINOB ;NO. NOTHING TO DO
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
SQISNA: MOVE T1,FILLLB(JFN) ;GET BACK LL BLOCK
LOAD T2,LLIDN,(T1) ;GET SEG # TO ACK
MOVEI T3,MSDAT ;ON THE DATA CHANNEL
OPSTR <SKIPE>,LLFNN,(T1) ;NEED A NACK?
TXO T2,ACKBIT ;YES.
CALL SNDACK ;SEND IT
JRST [ MOVE T2,FILLLB(JFN)
SETONE LLFNA,(T2) ;SAY NEED TO DO IT AGAIN
JRST CHKFRE] ;GO CHECK ON TYPE OF FAILURE
SETZRO <LLFNA,LLFNN>,(T1) ;CLEAR ACK FLAGS
SQISN2: LOAD T2,LLLSC,(T1) ;GET SEGS TO REQUEST
JUMPE T2,SQISN3 ;IF NONE, JUMP OFF
MOVEI T3,MSDAT ;ON THE DATA CHANNEL
SETONE LLLSA,(T1) ;TELL SCHED TRYING FOR LS SEND
CALL SNDLS ;SEND MESSAGE
JRST [ MOVE T2,FILLLB(JFN) ;GET BACK LL BLOCK
SKIPN LLMSG(T2) ;HAVE A MESSAGE NOW?
JRST CHKFRE ;NO. MUST BLOCK THEN
TQZ <BLKF> ;YES. NO LONGER WANT TO BLOCK
JRST SQI23] ;AND GO TRY AGAIN
SETZRO <LLLSC,LLLSA>,(T1) ;CLEAR ALL LS INDICATORS
SQISN3: SETONE LLFLI,(T1) ;FLOW IS NOW TO F/S
RETSKP ;ALL DONE. WITH GOOD DATA
;COULDN'T FIND ANY BYTES
SQINOB: SKIPE LLMSG(T1) ;HAVE ANY NOW?
JRST SQI2 ;AND TRY AGAIN
MOVEI T2,CHKRAW ;THE BLOCK ROUTINE
CALLRET MAKTST ;GO ARRANGE FOR THE BLOCK
;ROUTINE TO MOVE WORDS FROM THE NETWORK TO AN INPUT BUFFER
SQIWRD: 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
JRST SQIMV1 ;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: 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
EXCH T1,FILLLB(JFN) ;RESTORE TEST ROUTINE
RET ;AND DONE
;ROUTINES TO ADJUST FLOW CONTROL COUNTS FOR A LL
;INCREMENT COUNT
INCMSM: ACVAR <W1> ;USE A PRESERVED REG
LOAD W1,LLMSM,(T1) ;GET CURRENT COUNT
AOS W1 ;INCREMENT IT
INCMS1: STOR W1,LLMSM,(T1) ;NEW COUNT
RET ;DONE
;DECREMENT COUNT
DECMSM: ACVAR <W1> ;USE A PRESERVED REG
LOAD W1,LLMSM,(T1) ;GET COUNT
SOS W1 ;DECREMENT IT
JRST INCMS1 ;AND FINISH UP IN COMMON CODE
;NOW DEFINE STATE TRANSITION TABLES
;FOR SEQUENTIAL OUTPUT
SWAPCD ;ALL OF THESE ARE SWAPPABLE
SQOSTA: IFIW!SQOLIS ;BLOCK UNTIL CONNECTED
IFIW!SQOLIS ;SAME HERE
IFIW!SQOCNF ;GO CONFIRM CIR
IFIW!NETSQ1 ;ALL SET TO GO
IFIW!SQODIS ;LINK IS CLOSED. GIVE ERROR
IFIW!SQODIS ;SAME HERE
IFIW!SQODIR ;DI RECEIVED. SEE IF ABORT OR CLOSE
IFIW!SQOABT
;FOR SOUTR CALL
SQOOTR: IFIW!SQOLIS ;BLOCK UNTIL CONNECTED
IFIW!SQOLIS ;BLOCK UNTIL CONNECTED
IFIW!SQOCN2 ;GO CONFIRM
IFIW!NETSR1 ;NORMAL STUFF
IFIW!SQODIS ;LINK IS CLOSED
IFIW!SQODIS ;""
IFIW!SQODIR ;DI RECIEVED
IFIW!SQOABT ;LINK ABORTED
;FOR SEQUENTIAL INPUT
SQISTA: IFIW!SQOLIS ;WAIT FOR CONNECT
IFIW!SQOLIS ;WAIT FOR CONNECT
IFIW!SQICNF ;CONFIRM CONNECTION
IFIW!SQI1 ;ALL SET
IFIW!SQODIS ;GIVE ERROR
IFIW!SQODIS ;GIVE ERROR
IFIW!SQIDIR ;DI RECEIVED
IFIW!SQOABT ;ERROR
;TABLE FOR CC RECEIVED
CCREC: IFIW!CCJECT ;CAN'T CONFIRM A LISTENER
IFIW!CCGUD ;GOOD CC
IFIW!CCDON ;IGNORE IT
IFIW!CCDON ;IGNORE IT
IFIW!CCDON ;IGNORE IT
IFIW!CCDON ;IGNORE IT
IFIW!CCDON ;IGNORE IT
IFIW!CCJECT ;ERROR
;TABLE FOR DI RECEIVED
DIREC: IFIW!CCJECT ;ILLEGAL ADDRESS
IFIW!CONREJ ;CONNECT BEING REJECTED
IFIW!CCDON ;IGNORE
IFIW!DIMSG2 ;CLOSING DOWN THE LINK
IFIW!DIABT ;ABORT IT
IFIW!DIABT ;ABORT IT
IFIW!DIABT ;ABORT IT
IFIW!DCDCS ;SEND DC AND IGNORE IT
;TABLE FOR DC RECEIVED
DCREC: IFIW!CCDON ;IGNORE FOR LISTENER
IFIW!CHKIDL ;CHECK FOR VALID DC
IFIW!CCDON ;IGNORE
IFIW!DCRUN ;SHUTTING DOWN
IFIW!DCABT ;VALID REPLY TO DI SENT
IFIW!DCABT ;ABORT THE LINK
IFIW!DCABT ;ABORT THE LINK
IFIW!CCDON ;IGNORE IT
;CLOSF
CLZSTA: IFIW!CLZDON ;JUST GET RID OF A LISTENER
IFIW!CLZDON ;SAME FOR CIS
IFIW!CLZDI ;NEED TO REFUSE CONNECTION
IFIW!CLZRUN ;NORMAL STATE
IFIW!CLZWDC ;WAIT FOR DC
IFIW!CLZDIQ ;Q STATE
IFIW!CLZDIR
IFIW!CLZABT
;ACK RECEIVED
ACKSTA: IFIW!CCJECT
IFIW!ACKCIS
IFIW!CCDON
IFIW!ACKRUN
IFIW!CCDON
IFIW!CCDON
IFIW!CCDON
IFIW!CCDON
;DATA,INT OR LS MESSAGE
DATSTA: IFIW!CCJECT ;ERROR
IFIW!CCDON ;IGNORE
IFIW!CCDON ;IGNORE
IFIW!DATRUN ;GOOD MESSAGE
REPEAT 4,<
IFIW!CCDON> ;IGNORE
;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: MCENTR ;GET INTO MONITOR CONTEXT
SE1ENT ;MAKE IT RUN IN PROPER SECTION
TRVAR <MSGCNT,MSGBYP,MSGSRC,MSGDST,MSGBLK,MSGLLB,MSGOBJ,<MSGDDC,5>,<MSGHSN,2>,MSGW1,MSGW2,MSGSOB,<MSGSDC,5>,<MSGDML,LKSIZE>,MSGLCL>
MOVEI T1,MAXQ ;DON'T ALLOW THIS FORK TO BE "COMPUTE-BOUND"
MOVEM T1,JOBBIT ;BY PREVENTING MAXQ SCHEDULING BEHAVIOR
NSPTSK:
REPEAT 0,< ;RMSGQ NOT USED PRESENTLY
SKIPN T1,RMSGQ ;ANYTHING ON EXPENDED QUEUE?
JRST NSPTS1 ;NO. GO ON
HRRZS T1 ;GET HEAD OF QUEUE
NOSKED ;NO SCHEDULING
CHNOFF DLSCHN ;TURN OFF CHANNEL
LOAD T2,MSLNK,(T1) ;GET NEXT
MOVEM T2,RMSGQ ;NEW HEAD
CHNON DLSCHN ;TURN ON CHANNEL
OKSKED ;AND THE SCHEDULER
CALL RELRES ;FREE THE BLOCK
JRST NSPTSK ;AND DO THEM ALL
> ;END OF REPEAT 0
NSPTS1: SKIPN MSGQ ;ANYTHING ON THE QUEUE?
JRST [ SKIPE KDPFLG ;DOES KMC11 WANT SERVICE
CALL KDPTSK ;YES SO CHECK IT
MOVEI T1,NSPTST ;REST UNTIL WORK TO DO
HDISMS (^D1500) ;WAIT, BUT STAY IN BALSET
JRST NSPTSK] ;AND TRY AGAIN
NOSKED ;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
OKSKED ;AND ALLOW SCHEDULING
SETZM MSGLCL ;ASSUME NOT LOCAL
OPSTR <SKIPE>,MSLCL,(T1) ;IS IT LOCAL?
SETOM MSGLCL ;YES. REMEMBER THIS
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
CALL GETBYT ;GET A BYTE
JRST BADMSG ;BADLY FORMED. REJECT IT
TRNE T2,201 ;IS THIS A COUNT?
JRST INVHDR ;HAS A COUNT. INVALID THEN
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
MOVEI T4,MAXHST
CALL GTASCI ;AND GET ASCII FIELD
JRST BADMSG ;BADLY FORMED MESSAGE
CALL GETBYT ;GET MESSAGE FLAGS
JRST 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!CIDON ;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 (CHK,NSPRTH,<NSPTSK- INVALID ROUTING HEADER>,<T1,T2>)
;OPTIONAL DATA IS PORT NUMBER, OFFENDING CHARACTER
CALL PROOFF ;TURN OFF THE INT THAT DID IT
JRST CIDON ;AND GIVE UP
;GOT A STARTUP MESSAGE
STRMSG: 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
CALL GETBYT ;GET STARUP TYPE
JRST BADSTR ;BADLY FORMED
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,ITSNAM(Q1) ;ITSNAM IS 2 WORDS/PORT
ADDI T3,(Q1) ;POINT WHERE TO PUT NAME
MOVEI T4,MAXHST
CALL GTASCI ;GET IT
JRST BADSTR ;BAD
STOR T2,NAMCN,MCBDTE(Q1) ;STORE COUNT OF BYTES IN NAME
CALL GETBYT ;GET SUPPORTED FUNCTIONS
JRST BADSTR ;BAD
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
CALL GETBYT ;GET ITS REQUIRED FUNCS
JRST BADSTR ;BAD
TXNE T2,VERIF ;WANT SECURITY MESSAGE?
SETOM Q2 ;NOTE VERIFICATION WANTED
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
MOVEM T2,NSPMAX(Q1) ;YES. SET UP NSPMAX THEN
MOVEI T4,10 ;BYTES TO IGNORE
STRMS1: CALL GETBYT ;GET A BYTE
JRST BADSTR
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 ;MAX SIZE OF ITSID
CALL GTASCI ;GET IT
JRST BADSTR
HRRM Q1,MCBDTE(Q1) ;SAVE PORT WE INITED ON
MOVEI T1,ITSNAM(Q1) ;ITSNAM IS 2 WORDS/PORT
ADDI T1,(Q1) ;POINT WHERE TO PUT 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 SCHEDULED FOR LOOPBACK
CAIE Q1,(T1) ;IS THIS PORT SCHEDULED FOR LOOPBACK ?
JRST BADSTR ;NO SO FLUSH INIT
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
JRST CIDON ;AND GO TO IT
BADSTR: CALL PROOFF ;TURN OFF FE
BUG (INF,ILLSTR,<NSPTSK-ILLEGAL INIT MESSAGE>,<Q1>)
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
;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
CALLRET SNDSG0 ;SEND IT
;ROUTINE USED TO SHUT ALL LINKS TO AN MCB THAT HAS DIED.
;ACCEPTS: T1/ PORT NUMBER
DEDMCB::TRVAR <WAITER,DEDPRT,<DEDDUM,14>,MSGW1>
SKIPL MCBDTE(T1) ;WAS THAT OURS
RET ;NO
SETZRO <INISNT,INIRCV,REQVER>,MCBDTE(T1) ;YES. NO LONGER INITED
MOVEI T2,.DCX39 ;GET ERROR
MOVEM T2,MSGW1 ;SAVE REASON
MOVEM T1,DEDPRT ;SAVE PORT
HRRZ T2,NSPLPB ;GET LOOPBACK PORT
CAMN T1,T2 ;WAS THAT ONE WHICH DIED ?
SETZM NSPLPB ;NO LONGER LOOPED BACK
DEDMC1: LLLOCK ;LOCK TREE
MOVE T1,[DEDCOR] ;COROUTINE
SETOM T2 ;ALL LINKS
CALL OBJSRC
JRST [ LLLULK ;FREE TREE
RET] ;AND DONE
LLLULK
MOVE T1,WAITER ;GET WAIT TEST
MDISMS ;WAIT FOR LINK
JRST DEDMC1 ;AND PROCEED
RET ;DONE
;COROUTINE TO DO THE WORK
DEDCOR: SAVET
LOAD T2,LLPRT,(T1) ;GET PORT
CAME T2,DEDPRT ;THIS ON THIS MCB?
RET ;NO
CALL BLKLOK ;YES. LOCK IT
JRST [ MOVEM T1,WAITER ;CAN'T. STORE WAIT
RETSKP] ;AND STOP NOW
CALL TSTLCL ;IS IT LOCAL?
JRST DEDMC2 ;YES. NOT INTERESTED
LOAD T2,LLSTA,(T1) ;GET STATE
CAIG T2,LLSDIR ;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]-2(T2) ;AND, FINALLY, FOR DI REC
JN LLSDE,(T1),[ OKINT ;IF DISASSOCIATED
CALLRET DELNOD] ;RELEASE NDOE
DEDMC2: CALLRET BLKULK ;RELEASE BLOCK AND RETURN
;ROUTINES TO HANDLE CONTROL MESSAGES
;PROCESS A CONNECT-INITIATE
CIMSG: 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
CALL GETBYT ;GET FORMAT OF DEST OBJECT
INVPRC: JRST [ MOVEI T2,.DCX5
JRST CIDC] ;AND ERROR
CAILE T2,OBJTWO ;IS IT A FORMAT WE UNDERSTAND?
JRST INVPRC
MOVE T4,T2 ;SAVE OBJECT TYPE
CALL GETBYT ;GET OBJECT NUMBER
JRST INVPRC
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 ;MAX SIZE
CALL GTASCI ;MOVE DESCRIPTOR STRING
JRST INVPRC
DSCNO: CALL GETBYT ;GET SOURCE OBJECT TYPE
JRST INVPRC
CAILE T2,OBJTWO ;VALID?
JRST INVPRC
MOVE T4,T2 ;SAVE IT
CALL GETBYT ;GET OBJECT #
JRST INVPRC
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 ;MAX SIZE
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
OPSTR <SKIPE>,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: MOVEI T1,CICOR ;COROUTINE ADDRESS
MOVEI T2,1 ;LOOK FOR LISTENING OBJECT ONLY
LLLOCK ;LOCK THE TREE
CALL OBJSRC ;GO LOOK FOR IT
JRST [ LLLULK ;RELEASE TREE
MOVEI T2,.DCX4 ;NO SUCH OBJECT
JRST CIDC]
CALL BLKLOK ;LOCK THE BLOCK
JRST [ LLLULK ;COULDN'T.
MDISMS ;WAIT HERE
JRST DSCNO2] ;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
SKIPE MSGLCL ;LOCAL CONNECTION?
JRST HOSTNL ;YES. LEAVE NULL HOST NAME
MOVEI T2,MSGHSN ;GET POINTER TO HOST NAME
LOAD T1,LLHST,(T1) ;GET OUT HOST STRING
SETOM T3 ;NO COUNT
CALL MOVSTR ;MOVE THE STRING
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
HOSTNL: 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: CALL GETBYT ;GET MENU BYTE
JRST NODATA ;NONE. NO OPTIONAL DATA THEN
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,MAXDSC ;MAX SIZE
CALL GTASCI ;GET IT
JRST BADUDT ;BADLY FORMED
LOAD T3,LLPSW,(T1) ;WHERE TO PUT PASSWORD
MOVEI T4,^D8 ;MAX PASSWORD SIZE
CALL GTBNRY ;GET OCTETS
JRST BADUDT ;BADLY FORMED
STOR T2,LLPCT,(T1) ;SAVE COUNT
LOAD T3,LLACT,(T1) ;GET ACCOUNT DATA
MOVEI T4,MAXDSC ;MAX SIZE
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,MAXDSC ;MAX SIZE OF OPTDATA
CALL GTBNRY ;GET OCTETS
JRST BADUDT ;BADLY FORMED
STOR T2,LLUCT,(T1) ;SAVE COUNT
NODATA: CALL BLKULK ;RELEASE THE BLOCK
DSCMV1: CALL CONINT ;GIVE INTERRUPT
BADMSG: ;IGNORE THE MESSAGE
CIDON: MOVE T1,MSGBLK ;GET BACK MESSAGE BLOCK
CALL RELRES ;FREE THE BLOCK
JRST NSPTSK ;AND TRY AGAIN
;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,MSGW1 ;GET FC OPTION
STOR T2,LLMFC,(T1) ;STORE IT
MOVE T2,MSGW2 ;GET SEGSIZE
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
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
;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
MOVEI T3,MSGHSN ;COMPARE HOST NAMES
LLLOCK ;LOCK THE TREE
CALL LLLKUH ;AND LOOK UP THE BLOCK
JRST [ LLLULK ;FREE THE TREE
MOVEI T2,.DCX41 ;NO MATCH
JRST CIDC] ;GO DC THE LINK
CALL BLKLOK ;LOCK BLOCK LOCK
JRST [ LLLULK ;FREE TREE LOCK
MDISMS ;WAIT HERE A WHILE
JRST CCMSG1] ;AND TRY AGAIN
LLLULK ;FREE THE TREE
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 [ CALL BLKULK ;FREE THIS BLOCK
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 LINK WAS CONNECTED
LOAD T3,LLOPT,(T1) ;SEE IF ANY OPTDATA
MOVEI T4,MAXDSC ;MAX SIZE OF OPTDATA
CALL GTBNRY
JRST [ JUMPE T2,CCGUD2 ;IF NO OPTDATA, OKAY
JRST BADUDT] ;OTHERWISE, BAD MESSAGE
STOR T2,LLUCT,(T1) ;YES. SAVE COUNT
CCGUD2: MOVEI T2,1 ;INITIAL COUNT FOR LS/INT
STOR T2,LLMIC,(T1) ;STASH IT
CALL BLKULK ;DONE WITH THE BLOCK
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 CIDON ;IGNORE THE MESSAGE
;ROUTINES TO SEND DC'S FOR CONNECT ERRORS
CIDC: SKIPE MSGLCL ;IS IT LOCAL?
JRST CIDCLC ;YES. GO DO IT
SKIPN MSGHSN ;HAVE A HOST NAME FOR THE RETURN?
JRST [ BUG (CHK,NOMHDR,<ILLEGAL MESSAGE WITH NO HEADER>)
JRST CIDON] ;AND GIVE UP
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 CIDON ;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: MOVEI T4,MSGHSN ;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
CALLRET SNDDI ;BUILD THE MESSAGE
;RECEIVED AN ACK
ACKMSG: 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
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
JRST CONREJ ;AND FAKE A CI REJECT
;IN RUN STATE
ACKRUN: MOVE T2,MSGBLK ;GET MESSAGE
LOAD T2,MSMFL,(T2) ;GET FLAGS
CALL ACKDO ;GO DO THE ACTUAL ACK
JRST ABTMSG ;BADLY FORMED MESSAGE
OPSTR <SKIPE>,LLLSA,(T1) ;WANT TO RETRY A LS SEND?
CALL DATINR ;YES. MAKE PROCESS WAKE NOW THEN
JRST CCDON ;AND DONE
;RECEIVED A DI MESSAGE
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 LLLKUH ;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
LOAD T3,LLOPT,(T1) ;GET OPTDATA, IF ANY
MOVEI T4,MAXDSC
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 DIMSG3 ;SEND DC
;HERE FOR DI RECEIVED WHEN IN NON-RUN STATE
DIABT: CALL CHKFRN ;SOURCE ADDR MUST MATCH
JRST CCJECT ;DOESN'T
JN LLSDE,(T1),[ CALL RELLNK ;IF DISASSOCIATED
MOVEI T2,.DCX9 ;SAY A USER ABORT
JRST CIDC] ;AND SEND DC
CALL RJECT1 ;GO CHANGE LINK STATE
JRST DIMSG3 ;SEND DC
;DI OR DC RECIEVED IN RUN STATE
DIMSG2: CALL CHKFRN ;SOURCE ADDR MUST MATCH
JRST CCJECT ;DOESN'T
CALL SHUTLK ;SHUT DOWN LINK
DIMSG3: SKIPN T2,MSGW1 ;HAVE A BAD REASON?
;COMMON POINT FOR DI OR DC IN RUN STATE OR DC IN ABT STATE
DCDCS: MOVEI T2,.DCX42 ;NO. SAY REPLY TO DI THEN
JRST CCJEC1 ;AND GO SEND DC
;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
CALLRET FLUSH ;CLEAR OUT LINK'S QUEUES
;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
CALLRET FLUSH] ;AND CLEAN UP LINK
SETONE LLFDI,(T1) ;YES. SAY SO
RET ;AND DONE
;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
;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
MOVEI T3,MSGHSN ;HOST NAME STRING
LLLOCK ;LOCK THE TREE
CALL LLLKUH ;FIND THE LINK
JRST [ LLLULK ;FREE THE TREE
JRST CIDON] ;IGNORE THE MESSAGE
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 ;REJECTING A CONNECTION?
CALL RJECT ; YES, GO SET PROPER LINK STATE
JRST CCDON ;AND DONE
;RECEIVED DC IN NON-RUN STATE
DCABT: JN LLSDE,(T1),[ CALL RELLNK ;IF DISASSOCIATED
JRST CIDON] ;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 LOCK
CALLRET DELNOD ;FREE NODE AND RETURN
;DATA MESSAGE RECEIVED
DATMSG: 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
LOAD T2,LLSTA,(T1) ;GET STATE
JRST @DATSTA-1(T2) ;GO DO IT
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: CALL BLKULK ;FREE BLOCK
JRST NSPTSK ;AND DONE
INTLS: CALL GETTWO ;GET ACK NUMBER
JRST ABTMSG ;GO KILL LINK
TXZE T2,ACKIND ;AN ACK?
JRST [ MOVEI T3,MSLSI ;GET PROPER CHANNEL
CALL ACKCHN ;DO ACK
CALL GETTWO ;GET SEGNUM
JRST ABTMSG ;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 ;HAVE IT
CAILE T3,MAXDIF ;OLD OR NEW?
JRST LSIDON ;TOO NEW. IGNORE IT FOR NOW
INTLS1: CALL ACKLI ;OLD SEG. GO REACK SUBCHANNEL
JRST [ MDISMS ;NO FREE SPACE. WAIT AWHILE
MOVE T1,MSGLLB ;RESTORE BLOCK ADDRESS
JRST INTLS1] ;AND TRY AGAIN
JRST LSIDON ;AND DONE
;HAVE A GOOD INT OR LS MESSAGE
LSINT1: STOR T2,LLIIN,(T1) ;STORE SEG #
MOVE T4,MSGW1 ;GET BACK SUBTYPE
TRNN T4,2 ;INT OR LS MESSAGE?
JRST LSMSG ;LS
SKIPE LLMSI(T1) ;NOW HAVE AN INTERRUPT MESSAGE?
JRST ABTMSG ;KILL LINK
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
CALL ACKLI ;GO ACK IT
SKIPA T1,MSGLLB ;GET BACK LL BLOCK
JRST DATDON ;AND DONE
TQZ <BLKF> ;IGNORE BLOCK REQUEST
JRST DATDON ;AND DONE
;HAVE A LS MESSAGE
LSMSG: CALL ACKLI ;ACK THE LS MESSAGE NOW
JRST [ MDISMS ;WAIT HERE UNTIL CAN DO IT
MOVE T1,MSGLLB ;GET BACK LL BLOCK
JRST LSMSG] ;AND TRY AGAIN
CALL GETBYT ;GET LSFLAGS BYTE
JRST ABTMSG ;BADLY FORMED
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
CALL GETBYT ;GET NEXT
JRST ABTMSG ;BADLY FORMED
TXNE T3,4 ;DATA COUNTS?
JRST [ OPSTR <ADD T2,>,LLMIC,(T1) ;NO. COMPUTE NEW VALUE
TXNE T2,200 ;WITHIN RANGE?
JRST ABTMSG ;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 ABTMSG ;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 BLKULK ;FREE THE BLOCK
JRST CIDON ;AND DONE
;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 [ 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
; +2 SUCCESS. MESSAGES SENT
TURNON: JE LLOPI,(T1),RSKP ;IF NOT OPEN FOR READ, DON'T SEND LS
MOVEI T3,MSDAT ;ON THE DATA SUBCHANNEL
MOVEI T2,MAXSEG ;ASSUME SEG FLOW CONTROL
OPSTR <SKIPE>,LLOPW,(T1) ;OPEN FOR WRITE AS WELL?
MOVEI T2,MAXSG1 ;YES. USE A SMALLER NUMBER
OPSTR <SKIPE>,LLIMS,(T1) ;MESSAGE?
MOVEI T2,1 ;YES. ONE MESSAGE THEN
CALLRET SNDLS ;SEND IT OFF
;ROUTINE TO CHECK IF A CONNECTION IS TO ANOTHER TASK
;ON THE SAME NODE.
; T1/ LL BLOCK ADDRESS
;RETURNS: +1 IS TO A LOCAL
; +2 TO ANOTHER NODE
TSTLCL: SAVEAC <T2>
LOAD T2,LLHST,(T1) ;GET REMOTE HOST NAME
SKIPE T2 ;IF NO BLOCK
SKIPN 0(T2) ;OR IF NO STRING
RET ;IS LOCAL
RETSKP ;OTHERWISE, IS TO A REMOTE
;COLLECTION OF ROUTINES TO GET FIELDS FROM A MESSAGE
;MOST ARE RESIDENT BECAUSE THEY ARE USED BY THE CHANNEL 7 CODE
;GET A BYTE
RESCD ;CALLED FROM SCHEDULER
GETBYT: SOSGE MSGCNT ;HAVE ANOTHER BYTE?
RET ;NO. PROBABLY ERROR
ILDB T2,MSGBYP ;GET A BYTE
RETSKP ;AND DONE
;GET TWO BYTE FIELD
;PRESERVES T4
GETTWO: CALL GETBYT ;GET A BYTE
RET ;FAILED
LSHC T2,-10 ;SAVE LOW ORDER BYTE
CALL GETBYT ;GET NEXT ONE
RET ;FAILED
LSHC T2,10 ;COMBINE BYTES
RETSKP ;AND DONE
;COPY ASCII STRING
; T3/ POINTER TO COPY TO
; T4/ MAX SIZE 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
CALL GETBYT ;GET COUNT FIELD
JRST [ SETZM T2 ;NO STRING
RET] ;DONE
CAMLE T2,T4 ;COUNT WITHIN RANGE?
RET ;NO. BAD MESSAGE THEN
MOVE W2,T2 ;SAVE COUNT
SKIPN T4,T2 ;SAVE COUNT
JRST GTASCD ;NO COUNT
GTASC1: CALL GETBYT ;GET A BYTE
RET ;FAILED
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
;MORE BYTE MANIPULATION ROUTINES
;SKIP AN IMAGE FIELD
SKPFLD: MOVE T2,[POINT 0,0,2] ;GET DUMMY FIELD
MOVEI T4,-1 ;BIG NUMBER
CALLRET GTASC0 ;MOVE ASCII FIELD TO NULL AREA
;GET AN EXTENSIBLE FIELD
SWAPCD ;ONLY FROM PROCESS CONTEXT
GETEXT: SETZB T3,T4 ;INIT ACCUMULATOR AND COUNTER
GETEX1: CALL GETBYT ;GET NEXT BYTE
RET ;BAD
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
;ROUTINE USED BY CI AND CC TO PROCESS COMMON FIELDS
SWAPCD ;SWAPPABLE
CIPSRV: CALL GETBYT ;GET SERVICES
RET ;BAD
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
CALL GETBYT ;GET LINK PRI
RET ;ASSUME IT IS GOOD
CALL GETTWO ;GET SEGSIZE
RET ;BAD
SKIPN MSGLCL ;LOCAL LINK?
CALL [ SAVEAC <T3>
MOVE T3,MSGBLK ;GET MESSAGE ADDRESS
LOAD T3,MSPRT,(T3) ;GET PORT OF MESSAGE
CAMLE T2,NSPMAX(T3) ;NO. SEE IF CAN SEND ONE THIS BIG
MOVE T2,NSPMAX(T3) ;NO. USE INTERCEPT'S NUMBER
SUBI T2,NSPHDR ;ADJUST FOR THE HEADER
RET] ;AND DONE
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
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
CALL TSTLCL ;SEE IF TO A LOCAL
JRST CTLLCL ;YES. GO HANDLE IT
MOVE T2,SAVMSG ;GET BLOCK ADDRESS
SNDSG0: LOAD T1,LLPRT,(T1) ;GET PORT I.D.
; HRLI T1,MSGPST ;POSTING ADDRESS
HRLI T1,RELRES ;MAKE DTESRV RELEASE THE BLOCK
SNDMSG: STKVAR <SAVPST,SAVFF> ;TEMP SAVE LOCATIONS
MOVEM F,SAVFF ;SAVE F
MOVE F,T2 ;UNIQUE CODE FOR POST
OPSTR <SKIPE>,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
;CONNECTION IS TO A TASK ON THIS NODE
CTLLCL: SETONE MSLCL,(T2) ;REMEMBER IS LOCAL
CALLRET ONMSQ ;AND GO DO IT
;VARIOUS QUEUENING ROUTINES USED BY INT, SCHED, AND PROCESS LEVELS
;ROUTINE TO PUT A MESSGE ON NSPTSK'S QUEUE
RESCD
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
MOVEI T3,SMSGQ ;GET QUEUE HEAD
CALLRET PUTONQ ;AND DO IT
;ROUTINE TO SEND A DATA,LS, OR INT MESSAGE
;ACCEPTS: T1/ LL BLOCK
; T2/ MESSAGE BLOCK
SWAPCD ;IS SWAPPABLE
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
CALL TSTLCL ;LOCAL CONNECTION?
JRST SNDLCL ;YES.
CALL ONSEGQ ;PUT IT ON THE SEG QUEUE
SNDSE2: 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
;ROUTINE TO PUT A DATA,LS, OR INT SEGEMENT ON THE SEND Q
;ACCEPTS: T1/ LL BLOCK ADDRESS
; T2/ MESSAGE BLOCK
ONSEGQ: INCR LLQOU,(T1) ;ONE MORE ON Q
ONSGQ0: MOVEI T3,LLSEGQ(T1) ;GET HEADER
CALLRET PUTONQ ;PUT SEG ON THE Q
;LOCAL ROUTINE TO PUT MESSAGE ON INPUT QUEUE
ONMSQ: NOSKED ;NO SCHEDULING
CALL ONMSGQ ;PUT MESSAGE ON THE QUEUE
OKSKED ;AND SCHEDULING
RET ;AND DONE
;ENTRY USED TO RESEND A NACKED MESSAGE
SNDSE0: ASUBR <SNLBLK,SNMSG>
CALLRET SNDSE2 ;SEND IT
;SNDSEG CONTINUED...
;ROUTINE TO SEND SEGMENT TO A LOCAL CONNECTION
SNDLCL: SETONE MSLCL,(T2) ;SAY IS LOCAL
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 SNDBAD ;NOT THERE
LLLULK ;RELEASE THE TREE
MOVE T2,SNMSG ;GET MESSAGE BLOCK
NOSKED ;PROTECT LINK STATE
LOAD T3,LLSTA,(T1) ;GET STATE OF THE LINK
CAIE T3,LLSRUN ;RUNNING?
JRST SNDBA1 ;NO.
CALL ONRAWQ ;GO PUT ON THE QUEUE
OKSKED ;ALL DONE
JRST SNDSE1 ;GO Q IT UP ON SEG Q
;ERROR ROUTINES
SNDBA1: OKSKED
SNDBAD: MOVE T2,SNMSG ;GET MESSAGE ADDRESS
CALL ONMSQ ;PUT DATA MESSAGE ON NSPTSK'S Q
JRST SNDSE1 ;AND DONE FOR NOW
;ROUTINES USED BY INTERRUPT LEVEL TO QUEUE UP PACKETS
;PUT A DATA MESSAGE ON THE LINK'S QUEUE
; T1/ LL BLOCK ADDRESS
; T2/ MESSAGE BLOCK
RESCD ;MUST BE RESIDENT
ONRAWQ: NOSKD1 ;HOLD OFF SCHEDULER
LOAD T3,MSMFL,(T2) ;GET MESSAGE FLAGS
TXNE T3,ACKFLM ;IS IT AN ACK?
JRST [ JN LLLSA,(T1),ONRAW2 ;IN LS SEND WAIT?
JRST ONRAW1] ;NO. GO ON
OPSTR <AOS T3,>,LLDMT,(T1) ;ACCOUNT FOR ONE MORE DATA MESSAGE
CAILE T3,MAXSEG ;TOO MANY ON Q?
JRST [ SETONE LLFNN,(T1) ;YES.
PUSH P,T1 ;SAVE LL BLOCK
MOVE T1,T2 ;GET DATA BLOCK ADDRESS
CALL RELRES ;GET RID OF IT
POP P,T1
CALL DATINR ;REQUEST INT
JRST ONRAW3] ;AND GO WRAP UP
STOR T3,LLDMT,(T1) ;NO. SAVE NEW COUNT
OPSTRM <AOS T3,>,LLDRW,(T1) ;INCREMENT DATA MESSAGE COUNT
CAIN T3,1 ;NO. IS THIS NOT THE FIRST ONE?
ONRAW2: CALL DATINR ;GIVE INT
ONRAW1: MOVE T3,LLMSG(T1) ;GET HEAD OF QUEUE
MOVEM T2,LLMSG(T1) ;STORE NEW HEAD
STOR T3,MSLNK,(T2) ;COMPLETE LINK
ONRAW3: OKSKD1
RET ;AND DONE
;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
;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
SWAPCD
ACKCHN: CALL TSTLCL ;LOCAL?
RET ;YES. NOTHING TO DO
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
TRZE T2,ACKBIT ;IS IT A NACK?
JRST [ CALL ACKCHN ;DO IT
JRST DONACK] ;AND GO DO THE NACK
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 SUBCHANNEL?
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.
MOVEI T4,LLSEGQ(T1) ;THE Q ADDRESS
CALL UNQSEG ;REMOVE SEGEMENT
DECR LLQOU,(T1) ;ONE LESS SEG IN QUEUER
EXCH T1,W1 ;GET BLOCK
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: RET ;AND DONE
;LOCAL ROUTINE TO TAKE A SEGMENT OFF OF A SEGMENT Q
UNQSEG: JUMPE W2,[LOAD T3,MSLNK,(W1) ;IS HEAD
HRRM T3,0(T4) ;MAKE NEW HEAD
SKIPN T3 ;NOW EMPTY?
SETZM 0(T4) ;YES
RET] ;AND DONE
LOAD T3,MSLNK,(W1) ;GET LINK
STOR T3,MSLNK,(W2) ;REMOVE FROM Q
SKIPN T3 ;REMOVING THE TAIL?
HRLM W2,0(T4) ;YES. MAKE NEW TAIL THEN
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?
JRST ACKDON ;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 [ CALL INCMSM ;YES. ACCOUNT FOR THE NACK
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
TXNE T3,DATEOM ;IS THIS THE EOM?
CALL INCMSM ;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.
CALL DECMSM ;YES. COUNT DOWN
DONRES: MOVE T2,W1 ;GET SEG
CALL SNDSE0 ;RESEND IT NOW
DONNXT: MOVE W2,W1 ;NEW HEAD
LOAD W1,MSLNK,(W2) ;GET NEXT
JUMPN W1,DONAC1 ;IF MORE, DO IT
JRST ACKDON ;DONE
DONRQ: SETONE MSNAK,(W1) ;REMEMBER IS NAKED
INCR LLQUN,(T1) ;AND ACCOUNT FOR IT
JRST DONNXT ;AND CONTINUE DOWN Q
;ROUTINE TO PUT A DATA MESSAGE ON A SEGMENT Q
; T2/ THE MESSAGE
; T3/ THE QUEUE ADDRESS
;CLOBBERS T4
RESCD
PUTONQ: 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: OPSTR <SKIPN>,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
TXNE T3,DATEOM ;IS THIS EOM?
RSEND2: CALL DECMSM ;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,LLMSG,LLOMSG
; T1/ LL BLOCK LL TREE MUST BE LOCKED
;RETURNS +1 ALWAYS
SWAPCD
FLUSH: SETZRO <LLQUN,LLQOU>,(T1) ;CLEAR COUNTS
MOVEI T2,LLOMSG(T1) ;GET ORDERED QUEUE
CALL PRUNE ;KILL IT
MOVEI T2,LLMSG(T1) ;GET ORDERED Q
CALL PRUNE ;KILL IT
MOVEI T2,LLMSI(T1) ;INT MESSAGES
CALL PRUNE ;KILL THIS AS WELL
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,(T2),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.
RESCD
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
SWAPCD ;BACK TO SWAPPABLE MONITOR
;ROUTINE TO SEND AN ACK MESSAGE.
; T1/ LL BLOCK
; T2/ SEGMENT # TO ACK
; T3/ SUBCHANNEL TO ACK
;RETURNS +1 ALL REGS PRESERVED
SNDACK: ASUBR <LLBLK,ACKNO,ACKTYP>
CALL TSTLCL ;SEE IF A LOCAL CONNECTION
RETSKP ;YES IT IS. NOTHING TO DO THEN
JRST ACKRMT ;NO. NEED TO SEND A MESSAGE
;HANDLE LOCAL ACK
;THIS CODE HAS BEEN REMOVED AS IT IS NO LONGER NECESSARY.
;NOTE, THERE IS A BUG IN IT ANYWAY,AS A FAILURE TO LOCK THE
;OTHER BLOCK WILL CAUSE CONFUSION IN NETSET. IF THIS CODE
;IS EVER TURNED ON AGAIN, THEN CHKFRE MUST INCLUDE A CHECK
;FOR LOCK FAILURE AS WELL AS FREE SPACE FAILURE. ASM
REPEAT 0,<
LOAD T2,LLLNK,(T1)
LOAD T1,LLHLK,(T1) ;GET OTHER ONE'S ADDRESS
LLLOCK ;LOCK THE TREE
CALL LLLKUP ;GO LOOK UP MATCHER
JRST ACKLO2 ;NOT THERE. THIS WILL GET FIXED
LOAD T2,LLSTA,(T1) ;GET CURRENT STATE?
CAIE T2,LLSRUN ;RUNNING
CAIN T2,LLSDIQ ;OR DI QUEUED?
JRST ACKLO1 ;IS GOOD
ACKLO2: LLLULK ;FREE TREE
ACKLO3: MOVE T1,LLBLK ;RETURN LL BLOCK ADDRESS
RETSKP ;AND RETURN
ACKLO1: CALL BLKLOK ;LOCK THE BLOCK
JRST [ LLLULK ;FAILED
RET] ;TRY AGAIN LATER
LLLULK ;FREE TREE
MOVE T2,ACKNO ;GET NUMBER
MOVE T3,ACKTYP ;AND THE TYPE
CALL ACKCHN ;GO DO THE ACK
CALL BLKULK ;UNLOCK THE BLOCK
JRST ACKLO3 ;AND GO WRAP UP
> ;END OF REPEAT 0
;ROUTINE TO ACK THE LS/INT CHANNEL
ACKLI: LOAD T2,LLIIN,(T1) ;GET SEG TO ACK
MOVEI T3,MSLSI ;THE CHANNEL I.D.
CALLRET SNDACK ;SEND ACK
;SNDACK CONTINUED.....
;SEND ACK TO REMOTE NODE.
ACKRMT: STKVAR <MSGBL> ;PLACE TO SAVE MESSAGE BLOCK
MOVEI T1,ACKLEN+MSHDR ;LENGTH REQUIRED
CALL GETRES ;GET IT
CALLRET GENWAT ;FAILED
MOVEM T1,MSGBL ;SAVE BLOCK ADDRESS
MOVE T2,T1
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.
CALL RTHDCI ;PUT ON ROUTING HEADER
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
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 T2,OURNUM ;GET OUR NUMBER
CALL ONEBYT ;STASH IT
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,MAXRSZ ;OUR SEG SIZE
CALL TWOBYT
MOVEI T2,MAXRSZ ;OUR NSP 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
CALL SNDSG0 ;SEND IT
MOVE T1,NODPRT ;GET PORT NUMBER
SETONE INISNT,MCBDTE(T1) ;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
;ROUTINE TO SEND AN LS MESSAGE
; T1/ LL BLOCK ADDRESS
; T2/ COUNT OF SEGS TO REQUEST
; T3/ SUBCHANNEL
SNDLS: ASUBR <SNDLBL,SNDLCT,SNDLTP,SNDLMS>
CALL TSTLCL ;LOCAL?
JRST SNDLSL ;YES
LOAD T2,LLQOU,(T1) ;GET SEGS IN QUEUER
CAILE T2,MAXSGQ+1 ;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 GENWAT ;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 ONEBYT ;PUT IT IN THE MESSAGE
CALL PUTLLA ;PUT IN ADDRESSES
LOAD T2,LLISN,(T1) ;GET SEG #
AOS T2 ;NEXT ONE
ANDI T2,7777
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) ;""
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
;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
NOSKED
CAIE T3,MSDAT ;DATA
JRST [ OPSTRM <ADDM T2,>,LLMIC,(T1) ;NO
JRST SNDLS1] ;GO WRAP UP
OPSTRM <ADDM T2,>,LLMSM,(T1) ;YES
SNDLS1: OKSKED
LLLULK ;FREE TREE
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.
RESCD
NSPSPC::ASUBR <PRTNO,PRTCNT>
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
;SCHEDULER AND INT INTERFACES
;ROUTINE TO QUEUE UP A RECEIVED MESSAGE.
; T1/ BLOCK ADDRESS
NSPMSG::TRVAR <MSGCNT,MSGBYP,MSGSRC,MSGDST,MSGBLK,NAKFLG>
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
CALL GETBYT ;GET FIRST BYTE
JRST NSPMSE ;ERROR
TRNE T2,201 ;A ROUTINE 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
CALL GETBYT ;GET FLAGS
JRST NSPMSE ;BAD MESSAGE
NSPMS1: MOVE T1,MSGBLK ;GET BLOCK
STOR T2,MSMFL,(T1) ;SAVE FLAGS
SETZM NAKFLG ;ASSUME NOT AN ACK OR NACK
TRNN T2,ACKFLM!CNMRFL!ACKLSI ;IS IT A DATA SEGMENT?
JRST NSPMS2 ;YES. KEEP IT THEN
TRNN T2,ACKFLM ;NO. IS IT AN ACK OR NACK?
JRST NSPMSE ;NO. IS CONTROL, LS, OR INT MESSAGE
AOS NAKFLG ;YES. NOTE THAT
NSPMS2: CALL GETLLA ;YES. GET LINK NUMBERS
JRST NSPMSE ;BAD MESSAGE
MOVE T1,MSGDST ;GET OUR NAME
MOVE T2,MSGSRC ;GET ITS NAME
CALL LLLKUP ;FIND THE LINK
JRST NSPMSE ;COULDN'T.
LOAD T2,LLSTA,(T1) ;GOT IT. GET STATE
CAIE T2,LLSRUN ;RUNNING?
JRST NSPMSE ;NO
MOVE T2,MSGBLK ;YES.
MOVE T3,MSGCNT ;GET REMAINING COUNT
STOR T3,MSDTC,(T2) ;SAVE RESIDUAL COUNT
MOVE T3,MSGBYP
MOVEM T3,MSBPTR(T2) ;SAVE RESIDUAL BYTE POINTER
SKIPE NAKFLG ;IS THIS AN ACK OR NACK?
JRST [ CALL GETTWO ;YES. GET ACKNUM FIELD
JRST NSPMSE ;BAD MESSAGE
TRNE T2,ACKBIT ;A NACK?
JRST NSPMSE ;YES. GIVE IT TO NSPTSK
MOVE T2,MSGBLK ;NO, MUST RESTORE MESSAGE BLOCK ADDRESS
JRST .+1] ;GO ON
CALLRET ONRAWQ ;AND PUT IT ON LINK'S Q
NSPMSE: MOVE T2,MSGBLK ;GET BLOCK ADDRESS
CALLRET ONMSGQ ;PUT IN ON THE TASK'S Q
;ROUTINE CALLED BY THE SCHEDULER EVERY 20 MS TO PROCESS MESSAGES
;ARRIVED FROM THE NETWORK
NSPCH7::ACVAR <W1> ;GET A WORK REG
MOVEI W1,12 ;DO A LIMITED # PER PASS
NSPCH0: SKIPN T1,SMSGQ ;ANY MESSAGE TO DO?
RET ;NO. ALL DONE
CHNOFF DLSCHN ;TURN OFF NETWORK
HRRZS T1 ;GET HEAD POINTER
LOAD T2,MSLNK,(T1) ;GET POINTER
HRRM T2,SMSGQ ;NEW HEAD
SKIPN T2 ;ANY MORE IN THE Q?
SETZM SMSGQ ;NO
CHNON DLSCHN ;TURN ON NET
CALL NSPMSG ;GO PROCESS THE MESSAGE
SOJGE W1,NSPCH0 ;GO DO MORE
RET ;ALL DONE
SUBTTL 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,NODMAX ; 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 SETNAM ;(0) SET LOCAL NODE NAME
EXP GETNAM ;(1) GET LOCAL NODE NAME
EXP SETNUM ;(2) SET LOCAL NODE NUMBER
EXP GETNUM ;(3) GET LOCAL NODE NUMBER
EXP NDSLP ;(4) SET LOOPBACK PORT
EXP NDCLP ;(5) CLEAR LOOPBACK PORT
EXP NDFLP ;(6) FIND LOOPBACK PORT
NODMAX==.-NODTAB
;SETNAM - ROUTINE TO SET THE LOCAL NODE NAME
SETNAM: STKVAR <<NODNAM,2>,BLKADR,ERRFLG>
SETZM ERRFLG ;INITIALIZE ERROR FLAG
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
CALL CPYFUS ;COPY STRING FROM USER
RETBAD () ;FAILED
MOVEM T1,BLKADR ;SAVE ADDRESS OF FREE BLOCK
; CHECK NUMBER OF CHARACTERS IN THE STRING
HRRI T4,1(T1) ;GET ADDRESS OF STRING
HRLI T4,(POINT 7,) ;FORM POINTER TO STRING
MOVEI T3,0 ;INITIALIZE CHARACTER COUNT
MOVE T1,[POINT 7,NODNAM] ;GET POINTER TO WHERE NAME IS BEING ASSEMBLED
STNAM1: ILDB T2,T4 ;GET NEXT CHARACTER FROM USER STRING
IDPB T2,T1 ;ADD CHARACTER TO DESTINATION STRING
JUMPE T2,STNAM2 ;IF END OF STRING, PUT IT INTO NSP DATABASE
CAIL T3,6 ;TOO MANY CHARACTERS IN NAME ?
JRST [ MOVEI T4,NODX01 ;YES, GET ERROR CODE
MOVEM T4,ERRFLG ;NOTE ERROR
JRST STNAM3 ] ;GO RELEASE FREE BLOCK AND RETURN
AOJA T3,STNAM1 ;LOOP OVER EACH CHARACTER
; HERE TO ADD STRING TO NSP DATABASE
STNAM2: DMOVE T1,NODNAM ;GET NODE NAME
DMOVEM T1,OURNAM ;STORE FOR NSP
MOVEM T3,OURCNT ;STORE CHARACTER COUNT AS WELL
; HERE TO RELEASE FREE BLOCK AND RETURN
STNAM3: MOVEI T1,JSBFRE ;GET ADDRESS OF FREE HEADER
MOVE T2,BLKADR ;GET ADDRESS OF FREE BLOCK
CALL RELFRE ;RELEASE SPACE
SKIPE T1,ERRFLG ;ANY ERRORS ?
RETBAD () ;YES, RETURN ERROR CODE
RETSKP ;NO, SUCCESS RETURN
;GETNAM - RETURN LOCAL NODE NAME
GETNAM: UMOVE T2,2 ;GET ADDRESS OF USER'S ARGUMENT BLOCK
UMOVE T1,.NDNOD(T2) ;GET POINTER TO WHERE NODE NAME IS TO GO
MOVEI T3,.NDNOD(T2) ;GET ADDRESS TO RETURN UPDATED POINTER
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
SETNUM: UMOVE T2,2 ;GET WORD WHERE NODE NUMBER IS
UMOVE T2,0(T2) ;GET USER'S NODE NUMBER
CAIL T2,2
CAILE T2,177 ;WITHIN RANGE?
RETBAD() ;NO. CAN'T
MOVEM T2,OURNUM ;YES. SET IT
RETSKP ;AND DONE
;GET LOCAL NODE NUMBER
GETNUM: UMOVE T2,2
MOVE T3,OURNUM
UMOVEM T3,0(T2) ;RETURN IT
RETSKP ;AND 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
TNXEND
END