Google
 

Trailing-Edge - PDP-10 Archives - SRI_NIC_PERM_SRC_3_19910112 - mit/monitor/mnetwk.mac
There are no other files named mnetwk.mac in the archive.
;[MIT-XX]PS:<BERLIN.M5>MNETWK.MAC.5, 28-Feb-83 17:12:35, Edit by BERLIN
;3032 ISI merge
;<BERLIN.M5>MNETWK.MAC.4, 30-Aug-82 21:42:46, Edit by BERLIN
;1017 Add NETHST GETAB
;[BBNF]<TAPPAN.NEW>MNETWK.MAC.13, 30-Jul-82 09:18:10, Edit by: TAPPAN
; Fix HSTCK0 to work with Non-NCP network addresses (refuse
; to permit connection)
; bug fix HSTLUK
;REL5:<TAPPAN.NEW>MNETWK.MAC.5 15-Jun-82 13:49:42, Edit by TAPPAN
; Merge ISI NTSIBE code
; REL5 merges
; Changed FLINK -> FNLINK to keep up with DEC
; Call NVTDTT instead of NVTDET
; Change order of searches (IMPPAR before PROLOG)
;<TAPPAN.4>MNETWK.MAC.2, 18-Feb-82 18:49:33, Edit by TAPPAN
; Use host address instead of net number for FNDNCT
;<TAPPAN.4>MNETWK.MAC.2, 22-Oct-81 18:46:01, Edit by TAPPAN
;100 moved .ATNVT to JSYSF, entry point at AATNVT for 
;NCP NVT's
;<BBN-4-MONITOR>MNETWK.MAC.3,  3-Aug-81 11:18:44, Edit by TAPPAN
; rewrote TSTEX0,TSTEX1 so they can be used no matter what original section was
;<TAPPAN.4>MNETWK.MAC.6,  4-Sep-80 12:36:38, Edit by TAPPAN
; Moved Link and socket tables to ANBSEC
;<TAPPAN.4>MNETWK.MAC.1,  2-Jul-80 12:48:41, Edit by TAPPAN
; Remove HSTINI and related stuff to MNETDV.MAC since thats
; really network independent
;[BBNF]<TCP-BBN-4-MONITOR>NETWRK.MAC.4004,  6-May-80 16:33:34, Ed: PLUMMER
;<BBN-4-MONITOR>NETWRK.MAC.6, 24-Jan-80 16:57:36, EDIT BY JBORCHEK
;<BBN-4-MONITOR>NETWRK.MAC.6, 19-Nov-79 21:16:36, EDIT BY JBORCHEK
;FIX TIPS LOSING NETWORK CONNECTIONS
; 
; Many changes betwixt
;
;<4.MONITOR>NETWRK.MAC.2, 29-Jan-78 16:59:49, Edit by BORCHEK
;FIX DIR NET:<*> FROM HANGING JOB. CHECK AT NETSET FOR <*>

	SEARCH IMPPAR,PROLOG,MNTPAR,MACSYM,MONSYM
	TTITLE	MNETWK
;;; Network device stuff for multinet
	ASCIZ	/
	MNETWK
	COPYRIGHT (C) 1980,1981,1982 BOLT BERANEK and NEWMAN INC.
	/
; Macros to turn imp on and off

DEFINE	NCPON<CALL ULKNCP>

DEFINE	NCPOFF<CALL LCKNCP>

; Local accumulators

DEFAC (UNIT,Q1)			;PSEUDO-UNIT NUMBER
DEFAC (IOS,Q2)			;STATUS FLAGS (FROM NETSTS(UNIT))
DEFAC (HN,Q3)
DEFAC (STS,P1)
DEFAC (JFN,P2)
DEFAC (PTR,P3)
DEFAC (DEV,P4)
DEFAC (F1,P5)

;PARAMETERS

NLNKBW==<LLINK+^D35>/^D36	;LENGTH OF LINK BITTABLE

CHKINT==^D30000			; Do a connection hung check this often

; NCP DATA CLUSTER

DEFSTR ANFHS,NETHST,35,36	;FOREIGN HOST
DEFSTR ANLNK,NETAWD,8,9		;LINK
DEFSTR ANCLKS,NETAWD,23,6	;TIME-OUT COUNTDOWN
DEFSTR ANINPI,NETFRK,5,6	;INS/INR PSI CHAN
DEFSTR ANFSPI,NETFRK,17,6	;FSM PSI CHAN
DEFSTR ANFSM,NETSTS,3,4		;FSM STATE
DEFSTR ANBSIZ,NETSTS,17,6	;BIT STREAM BYTE SIZE
DEFSTR ANPVST,NETSTS,35,16	;PREVIOUS 4 STATES

MSGALL==2			;DESIRED MESSAGE ALLOCATION LEVEL

;FLAGS IN NETSTS

FLG(BFSND,L,IOS,020000)		;BUFFERED SEND MODE
FLG(ERRB,L,IOS,010000)		;ERROR HAS OCCURRED
FLG(EOTF,L,IOS,004000)		;END OF TRANSMISSION FLAG
FLG(SVCIF,L,IOS,002000)		;SERVICE INTERRUPTION IN PROGRESS
FLG(CLZF,L,IOS,001000)		;CONNECTION IS BEING CLOSED
FLG(DEDF,L,IOS,000400)		;HOST IS DEAD
FLG(PROGF,L,IOS,000200)		;SET IF PROGRAM IS WATCHING THIS CONNECTION
FLG(ALLFF,L,IOS,000100)		;ALLOCATION RESYNC HAS BEEN DONE

FLG(LINKF,R,IOS,400000)		;LINK TABLE INDEX VALID
; BBN socket numbers description
; A socket number is a 32-bit number which in conjunction with
; A host number specifies one end of a connection
; For bbn sockets, the 32 bit field is divided in 3 parts:
; The high 17 bits is used as follows:
;  if 0:      then this is a system socket
;  if <100000 then the number is a bbn user number and the socket is
;             is called a user socket
;  if >99999  then the number is tss job-number plus 100000, and the
;             socket is called a job socket

; A job socket is analogous to a temporary file and is guaranteed to
; Be unique to that job.  a user socket is analogous to a regular file
; And is guaranteed to be unique to that user.  a system socket is
; For use as agreed upon by members of the network for such purposes
; As inter system communication, memo-distribution etc.

; The next 14 bits are an arbitrary number which may be defaulted
; To the jfn associated with the socket or specified by the name field
; Of the file name string.  the low order bit is determined by
; The gender of the socket.  a socket opened for for writing
; Will have this bit equal to one. a socket opened for reading will
; Have this bit equal to zero.
; Network dispatch table

	SWAPCD

NETDTB::DTBDSP (NETSET)		;DIRECTORY SETUP
	DTBDSP (NETNAM)		;NAME LOOKUP
	DTBDSP (NETEXT)		;EXTENSION LOOKUP
	DTBDSP (NETVER)		;VERSION LOOKUP
	DTBBAD (DESX9)		;PROTECTION INSERT
	DTBBAD (DESX9)		;ACCOUNT INSERT
	DTBBAD (DESX9)		;STATUS INSERT
	DTBDSP (NETOPN)		;OPEN
	DTBDSP (NETSQI)		;BYTE INPUT
	DTBDSP (NETSQO)		;BYTE OUTPUT
	DTBDSP (NETCLZ)		;CLOSE
	DTBBAD (DESX9)		;RENAME
	DTBBAD (DESX9)		;DELETE
	DTBBAD (DESX9)		;DUMP
	DTBBAD (DESX9)	
	DTBBAD (DESX9)		;MOUNT
	DTBBAD (DESX9)		;DISMOUNT
	DTBBAD (DESX9)		;INITIALIZE
	DTBDSP (NETMTP)		;MTOPR
	DTBDSP (NETGST)		;GET STATUS
	DTBDSP (NETSST)		;SET STATUS
	DTBSKP			;RECORD OUT
	DTBDSP (RFTADN)		;READ TAD
	DTBDSP (SFTADN)		;SET TAD
	DTBDSP (BIOINP)		;SET JFN FOR INPUT
	DTBDSP (BIOOUT)		;SET JFN FOR OUTPUT
	DTBBAD (GJFX49)		;CHECK ATTRIBUTE

	DTBLEN==:.-NETDTB	;GLOBAL LENGTH OF DISPATCH TABLE

; Network lock and unlock

LCKNCP::NOINT
	CSKED
	LOCK NCPLCK,<JRST LCKNC1>
LCKNC2:	MOVE CX,0(P)		; Get PC
	HRL CX,FORKX		; And fork
	MOVEM CX,NCPLLK		; Save
	RET

LCKNC1:	ECSKED
	OKINT
	PUSH P,T1
	MOVEI T1,NCPLKT
	MDISMS
	POP P,T1
	JRST LCKNCP

	RESCD

NCPLKT:	SKIPL NCPLCK
	 JRST 0(T4)
	JRST 1(T4)


;;; Convert host number in AC1 to new format

CVNHST::CAMN T1,[-1]		;IF -1 USE LOCAL HOST NUMBER
	 MOVE T1,DEFADR		; Default local host
	AND T1,[HSTMSK]		;CUT DOWN TO SIZE
	TLNE T1,37700
	 RET
	ANDI T1,377
	TRZE T1,100		;SET THE HOST BITS
	 TRO T1,200000
	TRZE T1,200
	 TRO T1,400000
	IOR T1,NETFLD		;Add default network number
	RET

; convert host number in AC1 to old format

CVOHST::CAMN T1,[-1]		;NO HOST?
	 JRST CVOHS1		;RETURN 777
	TDZE T1,[740077,,177700];CHECK TO SEE IF FITS IN OLD FORMAT
	 MOVEI T1,400		;RETURN 400
	TRZE T1,200000		;SET THE HOST BITS
	 TRO T1,100
	TRZE T1,400000
	 TRO T1,200
CVOHS1:	ANDI T1,777
	RET

	SWAPCD

ULKNCP::UNLOCK NCPLCK
	ECSKED
	OKINT
	RET
; Initialize network stuff

NETINI::SE1CAL			;ENTER SECTION 1 FOR THIS ROUTINE
	MOVEI T1,NETSTS		; Point to a table
	SETSEC T1,ANBSEC	; In this section	
	SETZM 0(T1)		; Clear first word
	MOVE T2,[XWD NETSTS,NETSTS+1]
	BLT T2,NSKT-1(T1)	; Clear this far
	SETZM NETCNC
	SETZM FUNNYC
	MOVE T1,[ANBSEC,,NTBUFS]
	MOVEM T1,NETFRE		;INITIAL FREE LIST
	MOVEI T2,NNTBFS		;SIZE OF BUFFER AREA
	IDIV T2,MAXWPM		;CONVERT TO NUMBER OF BUFFERS
	MOVEM T2,NETFRE+2	;FREE SPACE LEFT IN BUFFER AREA
	MOVEM T1,NETFRE+3	;START OF BUFFER AREA
	IMUL T2,MAXWPM		;CONVERT TO WORDS
	ADDI T1,-1(T2)		;END OF BUFFER AREA
	MOVEM T1,NETFRE+4

;INITIALIZE FREE LIST INTO ITEMS OF MAXWPM EACH

	IDIV T2,MAXWPM		;NUMBER OF BUFFERS IN REGION
	MOVE T3,[ANBSEC,,NTBUFS];SET UP C TO POINT TO NET BUFFERS
NETIN2:	MOVE T1,T3		;COPY C INTO A
	ADD T3,MAXWPM		;RH(T3) POINTS TO NEXT BUFFER
	HRLOM T3,0(T1)		;STORE THAT IN LEFT HALF IN CURRENT BUFFER
	SOJG T2,NETIN2		;DO ANOTHER
	HRRZS 0(T1)		;LAST ITEM POINTER IS 0

	SETOM NETFRE+1		;NETWORK BUFFER LOCK
	SETOM NCPLCK
	RET
; Prepare to lookup network names

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

; Name lookup routine

NETNAM:	JUMPE T1,NAMBAD		; *. -- failure
	HRLI T1,(<POINT 7,0,35>); Make lookup pointer into byte pointer
	CALL NAMDEC		; Decode name
	JRST NAMBAD		; Bad syntax
OKRET:	TQNE <UNLKF>
	JRST SK2RET
	OKINT
	JRST SK2RET

NAMBAD:	MOVEI T1,GJFX18
	JRST ERRET		; Error return

ERRET:	OKINT
	RET

; Extension lookup routine

NETEXT:	JUMPE T1,NAMBAD		; .* -- failure
	HRLI T1,(<POINT 7,0,35>); Make lookup pointer into byte pointer
	CALL EXTDEC		; Decode extension to check syntax
	JRST EXTBAD		; Bad syntax
	JRST OKRET		; Success

EXTBAD:	MOVEI T1,GJFX19
	JRST ERRET

; Version lookup

NETVER:	HRRES T1		; Extend sign
	CAIL T1,^D100000	; If geq 100000
	 JRST NETVR1		; Use job related socket
	HLLZ T1,JSBSDN		; Get structure
	LSH T1,-6
	ADD T1,JSBSDN		; Add in directory
	ANDI T1,177777		; Clear junk
NETVR1:	TQNE <UNLKF>
	RETSKP
	OKINT
	RETSKP
; Decode extension string
; Called both at gtjfn and openf to decode extension string into
; Foreign socket number and host number

EXTDEC:	MOVE T4,T1
	ILDB T4,T4
	JUMPE T4,[SETOB T1,T2
		RETSKP]
	MOVE T3,T1			;GET SCRATCH POINTER
	SETZ T4,			;ASSUME NO - FOUND
EXTDE1:	ILDB T2,T3			;GET A BYTE
	CAIN T2,"-"			;SAVE LAST - FOUND
	 MOVE T4,T3
	JUMPN T2,EXTDE1			;DO WHOLE STRING
	JUMPE T4,R			;NO - MEANS ERROR
	DPB T2,T4			;END HOST WITH NUL
	CALL HSTLUK			;LOOKUP HOST
	MOVEI T3,"-"			;RESTORE THE -
	DPB T3,T1
	JUMPG T2,R			;NO HOST FOUND
	MOVEI T3,10			;GET OCTAL SOCKET NUMBER
	NIN
	 RET
	MOVE T1,T4
	RETSKP
HSTLUK::SAVEPQ				;GET SOME ROOM
	MOVE UNIT,T1			;SAVE POINTER
	MOVEI T3,10
	NIN				;TRY TO GET A NUMBER
	 JRST HSTLKI			;TRY A NAME
	MOVE UNIT,T1			;SAVE UPDATED POINTER
	MOVE T1,T2
	CALL CVNHST
	MOVE T4,T1			;RETURN HOST NUMBER
	MOVE T1,UNIT			;AND UPDATED POINTER
	SETZ T2,			;HOST NUMBER FOUND
	RET

HSTLKI:	HRLZ T2,MHOSTS			;SCAN THE TABLE
	PUTSEC STS,MNTSEC		; In this section
HSTLK0:	MOVE T1,UNIT			;DO NAME POINTER
IFNKA	<
	LOAD T4,HSTNMP,(STS)
	ADD T4,[XWD MNTSEC,HSTNAM]	; Point to the table
	MOVE T3,[<POINT 7,0>!1B12]	; Make extended pointer
>
IFKA	<
	LOAD T3,HSTNMP,(STS)
	ADD T3,[POINT 7,HSTNAM]
>
HSTCMP:	ILDB IOS,T1			;COMPARE A STRING
	ILDB HN,T3
	SKIPN IOS
	 JUMPE HN,[LOAD T4,HSTIDX,(STS)
		   SETSEC T4,MNTSEC
		   MOVE T4,HOSTNN(T4)
		   HRR T2,STS		; Save index
		   RET]
	CAIN IOS,(HN)
	 JRST HSTCMP
	AOS STS				; Point to next slot in table
	AOBJN T2,HSTLK0			;STEP TO NEXT HOST
	SETZ T4,			;NO HOST FOUND
	RET
; Decode name string
; Called both at gtjfn and openf to decode name string into
; Local socket number

NAMDEC:	MOVEI T3,10		; Perhaps this should be decimal?
	NIN			; Convert to a number
	JRST NAMDE1		; Failure: no number there
	LDB T3,T1		; Get terminator
	CAIE T3,"#"		; If not number sign
	JRST NAMDE2		; Then ordinary
	MOVE T3,CAPMSK		; Else system socket
	TRNN T3,SC%WHL!SC%OPR!SC%NAS;MUST BE WHEEL, OPR, OR
				; HAVE ABSOLUTE SOCKET CAPABILITY
	RET			; Else fail
	ILDB T3,T1		; Get next ch
	TDZA T1,T1		; Zero for high 17 bits
NAMDE2:	HRRZ T1,FILVER(JFN)	; Use filver for high 17 bits
	JUMPN T3,R		; String too long
	SKIPE T1
	 ANDI T2,77777		; If not system socket, retain 15 bits
	TRZ T2,1		; Clear gender
	ROT T1,^D15
	IOR T1,T2
	RETSKP

NAMDE1:	MOVE T2,JFN		; Default to jfn
	IDIVI T2,MLJFN		; Get the jfn
	LSH T2,1		; Jfn will end up lsh'ed 1
	LDB T3,T1
	JRST NAMDE2

NETDED::MOVE T1,NETSTS(UNIT)	; GET STATUS
	TXNE T1,DEDF+EOTF	; HOST DEAD OR DONE
	 RET
	RETSKP

NETHLK::LOAD T1,ANFHS,(UNIT)	; HOST
	LOAD T2,ANLNK,(UNIT)	; LINK
	RET
; Open network file

NETOPN:	TQNE <XCTF,RNDF>
	JRST ILLACC		; Illegal to access in append or xct
	TQNE <READF>
	TQNN <WRTF>
	TQNN <READF,WRTF>
	JRST ILLACC		; Must be only one of read or write
	LDB T1,PBYTSZ
	CAIN T1,^D8		; Check for 8 32 or 36 bit bytes
	 TRNA
	CAIN T1,^D32
	 TRNA
	CAIN T1,^D36
	 TRNA
	JRST [	MOVEI T1,SFBSX2
		RET]		; Bad byte size
	HLRZ T1,FILNEN(JFN)
	HRLI T1,(<POINT 7,0,35>)
	CALL NAMDEC		; Decode name
	JRST ILLACC		; Can only happen if wheel lost
	TQNE <WRTF>
	TROA T1,1		; If writing set gender bit for local
	TRZ T1,1		; Else clear it
	PUSH P,T1		; Save for later
	HRRZ T1,FILNEN(JFN)
	HRLI T1,(<POINT 7,0,35>)
	CALL EXTDEC		; Decode extension
	 JRST ILLACC		; Fail
	TQNE <READF>
	TROA T2,1		; If reading set gender bit for forskt
	TRZ T2,1		; Else clear
	POP P,T3
	LDB T4,PBYTSZ		; Get file byte size
	JUMPL T1,OPNLSN		; No foreign socket, do a listen
	CALL CONNECT		; Connect
	 RET
	TQZ <WNDF>
NETOP1:	HRLM UNIT,FILSKT(JFN)	;REMEMBER UNIT NUMBER
	SETZ IOS,		; Clear status bits
	LDB T1,[POINT 4,STS,35]
	CAIE T1,5		; In modes 5
	CAIN T1,7		; Or 7
	TQO <BFSND>		; DO BUFFERED TRANSMISSION
	IORB IOS,NETSTS(UNIT)	; Set it in status word
	MOVEI T1,^D36
	LDB T2,PBYTSZ
	IDIV T1,T2		; Get bytes per WORD
	XCTBU [LDB T3,[POINT 6,2,17]];GET DESIRED SIZE OF BUFFER
	IMUL T1,T3		; DESIRED BYTES
	HRLM T1,NETBUF(UNIT)	; Gives bytes per buffer
	SETZM FILBYN(JFN)	; About to reference byte 0 of buffer
	SETZM FILOFN(JFN)	; NEXT BYTE TO XMIT = 0
	TQO <SIZF>		; CANNOT CHANGE BYTE SIZE
	TQOE <WNDF>		; NO BUFFER YET. ALSO IF LISTEN
	RETSKP			; Return immediately
	LDB T1,[POINT 4,STS,35]
	CAIE T1,6		; Also in modes 6
	CAIN T1,7		; And 7
	RETSKP			; Return immediately
	LOAD T1,ANFSM,(UNIT)	; No. get current state
	CAIN T1,RFCS		; Will usually be rfcs
	CALL WATNOT		; If so, wait for it to not be
	LOAD T1,ANFSM,(UNIT)	; Get state
	MOVE IOS,NETSTS(UNIT)
	TQNN <EOTF>		; IF LEFT OPND
	CAIN T1,OPND		; OR STILL OPENED
	 RETSKP			; THEN SUCCEED
	MOVX T2,PROGF
	ANDCAM T2,NETSTS(UNIT)	; Program not watching
	CALL NETCLD		; FSM close
	TQNE <ERRB>		; ERRB REMEMBERS BAD BYTE SIZE
	SKIPA T1,[OPNX22]	; MAKE THAT THE ERROR CODE
	MOVEI T1,OPNX21		; ELSE IT WAS REJECTED
	RET			; And give bad return

OPNLSN:	CALL LISTEN
	 RET			; Can't listen
	TQO <WNDF>		; TO REMEMBER THAT THIS WAS A LISTEN
	JRST NETOP1		; First bin/out is accept

ILLACC:	MOVEI T1,OPNX14
	RET
; Wait for fsm to leave state given in a

WATNOT:	HRLI T1,NOTTST		; TEST ROUTINE ADDRESS
WATNO1:	HRRZ T2,UNIT		; COMPUTE SCHEDULER TEST ARGUMENT
	ROT T2,-9
	MOVSS T1
	IOR T1,T2
	MDISMS
	RET

; Wait for fsm to enter a particular state

WATFOR:	HRLI T1,WATTST
	JRST WATNO1

	RESCD

NOTTST:	SE1ENT			; Enter section 1
	LDB T2,[POINT 9,T1,26]	; EXTRACT UNIT
	SETSEC T2,ANBSEC	; Point into proper section
	ANDI T1,777		; AND STATE TO TEST AGAINST
	LOAD T3,ANFSM,(T2)	; GET CURRENT STA(E
	CAMN T1,T3		; IS IT THE SAME
	 JRST WATTS1		; YES, MAKE OTHER TESTS
;;; TSTEX1 - exit multisection test, with skip return
TSTEX1::
	AOS T4			; increment return address
TSTEX0::			; Exit with non-skip return
	TLZ T4,-40		; clear any program flags
	JRST @T4		; and back from the test

;;; SCHEDULER TEST WAITING FOR CONNECTION TO GET TO A STATE

WATTST:	SE1ENT			; Enter section 1
	LDB T2,[POINT 9,T1,26]	; EXTRACT UNIT
	SETSEC T2,ANBSEC	; Point to proper section
	ANDI T1,777		; AND STATE
	LOAD T3,ANFSM,(T2)	; GET CURRENT STATE
	CAMN T3,T1		; SAME?
	 JRST TSTEX1		; return good

WATTS1:	MOVE T3,FKINT(HN)	; Look for deferred interrupts
	TLNN T3,(1B1)
	 JRST TSTEX0		; bad
	SETZ T3,
	STOR T3,ANCLKS,(T2)	; Set clock to zero to hasten time-out
	JRST TSTEX0		; return

;;; SCHEDULER TEST FOR BIT ALLOCATION

;;; CONNECTION NUMBER IN T1

BALTST:	SE1ENT			; Enter section 1
	SETSEC T1,ANBSEC	; Right section
	LOAD T2,ANBSIZ,(T1)	;GET BIT STREAM BYTE SIZE
	LOAD T3,LTIDX,(T1)	;GET LINK TABLE INDEX
	SETSEC T3,ANBSEC	; In the right section
	SKIPN IMPLT4(T3)	;SKIP IF NEITHER MSG ALLOC OR BUFFER
	 JRST BALTS1
	CAMG T2,NETBAL(T1)	;MSG OK, HOW ABOUT BITS?
	 JRST TSTEX1		; Exit good

BALTS1:	MOVE T3,NETSTS(T1)	;GET STATUS INFO
	TXNE T3,DEDF+EOTF	;ALLOC BAD. BUT IF DEAD..STILL OK
	 JRST TSTEX1		; Exit good
	JRST TSTEX0		; Flunk
	SWAPCD

; Close network file

NETCLZ:	HLRZ UNIT,FILSKT(JFN)
	SETSEC UNIT,ANBSEC	; Place in proper section
	TQNN <WNDF>		; IF NO BUFFER EVER ASSIGNED
	TQNN <WRTF>		; OR IF READING
	JRST NETCL1		; Then skip the following
	CALL DMPBUF		; Dump last buffer
	 JRST NETCLW		; NOT ALL SENT. GO WAIT.
NETCL1:
   REPEAT 0,<
	TQNE <ERRF>		; ANY FINAL ERRORS
	 JRST [	MOVEI T1,IOX5
		RET]		; DON'T CLOSE IF ANY UN-HANDLED ERRORS
   >
	HRROS FILSKT(JFN)	; IN CASE JFN RE-OPENED, SET UNIT TO -1
	SETOM NETFRK(UNIT)
	HRRZ T2,NETBUF(UNIT)	;GET BUFFER ADDRESS
	JUMPE T2,NETCL3		;IS THERE A BUFFER
	MOVEI T1,JSBFRE		;THIS IS ALSO THE BLOCK TO FREE
	CALL RELFRE		;YES. RELEASE IT
NETCL3:	CALL NETCLD		; FSM close
	UMOVE T1,1
	TDNN T1,[1,,400000]
	TLNN T1,(1B1)
	 JRST NETCL2		; Return immediately if no bit 1
	LOAD T2,ANFSM,(UNIT)
	MOVEI T1,FREE
	CAIE T2,FREE
	CALL WATFOR
NETCL2:	MOVX T1,PROGF
	ANDCAM T1,NETSTS(UNIT)	; No program wants this any more
	RETSKP

NETCLD:	TQNN <WRTF>		; IF NOT SENDING
	SKIPA T1,[CLZR]		; THEN DO CLZR
	MOVEI T1,CLZS		; ELSE do clzs
	CALLRET DOFSM

NETCLW:	MOVEI T2,<^D5*^D60*^D1000>/CHKINT	; 5 MINUTES OF TICKS
	STOR T2,ANCLKS,(UNIT)
	MOVX IOS,CLZF
	IORB IOS,NETSTS(UNIT)
	MDISMS
	JRST NETCLZ		; AND GO TRY AGAIN

; Close nvt

NVTCLZ::MOVE T1,LSKT(UNIT)
	TRNN T1,1
	SKIPA T1,[CLZR]
	MOVEI T1,CLZS
	CALLRET DOFSM
; Network mtopr routines

NETMTP:	TQNN <OPNF>		;CHECK TO SEE IF OPENED
	RETBAD (CLSX1)		;NOT OPENED
	HLRZ UNIT,FILSKT(JFN)
	SETSEC UNIT,ANBSEC	; In proper section
	MOVE IOS,NETSTS(UNIT)
	CAIG T2,26
	CAIGE T2,20
	 RETSKP			; ANYTHING ELSE IS A NOP
	JRST .+1-20(T2)
	JRST NETACP
	JRST NETDMP
	JRST SNDINT
	JRST ABTCON
	JRST NETINT
	JRST NETRDY
	JRST NETFAL

NETACP:	LOAD T2,ANFSM,(UNIT)
	MOVEI T1,ACPT
	CAIN T2,RFCR
	 CALL DOFSM
	RETSKP

NETDMP:	TQNE <BFSND>		;SENDING BY BUFFER?
	TQNN <WRTF>		;AND A SEND CONNECTION?
	 RETSKP			;NO, A NOP
	TQNE <WNDF>		;YES. BUFFER SET UP?
	 RETSKP			;NO, NOTHING TO SEND
	CALL DMPBUF
	 JRST WATXXX
	RETSKP

SNDINT:	LOAD T1,ANFHS,(UNIT)
	LOAD T2,ANLNK,(UNIT)
	MOVE T4,LSKT(UNIT)
	TRNE T4,1
	SKIPA T4,[IMPINS]
	MOVEI T4,IMPINR
	NCPOFF
	LOAD T3,ANFSM,(UNIT)
	CAIN T3,OPND
	CALL (T4)
	NCPON
	RETSKP
; WAIT FOR READY TO SEND AT LEAST ONE BYTE

ABTCON:	MOVE T1,CAPENB
	TXNN T1,SC%NWZ
	 JRST [	MOVEI T1,NTWZX1	; NOT A NET WIZARD. FAIL.
		RET]
	CALL SKTDWN
	RETSKP

NETRDY:	TQNN <WRTF>		; RECEIVE OR SEND?
	 JRST NETRD1		; RECEIVE. SEND ALLOCATES OUT
	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	CALL PKCHK		; GET BYTES THAT CAN BE SENT
	JUMPE T2,[CALL WATBAL	; COMPUTE ACTIVATION TEST
		JRST WATXXX]	; AND WAIT
	CALL PKULCK
	RETSKP

NETFAL:	TQNN <WRTF>		; (ISI) Check for read
NETRD1:	TQNN <WNDF>		;HAS ALLOCATION ALREADY BEEN SENT?
	RETSKP
	CALL FIRSTI		;NO. SEND IT OUT.
	RET			;PASS ON DOWN BLOCK
	RETSKP

NETINT:	UMOVE T2,3
	HRR T2,FORKX		; REMEMBER THIS FORK, AND USER'S
	MOVEM T2,NETFRK(UNIT)	;  REQUESTED PI CHANNELS
	RETSKP


; HERE WHEN A FORK IS KILLED, TO FORGET THE PSI INFO

NETKFK::SE1CAL			; Place us in section 1
	SAVEQ
	PUTSEC UNIT,ANBSEC	; Put UNIT in right section for tables
	MOVEI HN,NSKT		; Counter
NETKF1:	HRRE IOS,NETFRK(UNIT)
	CAMN IOS,FORKX
	 SETOM NETFRK(UNIT)
	AOS UNIT		; Increment pointer
	SOJG HN,NETKF1
	RET			; And return
; HERE FROM LOGOUT CODE TO RELEASE JOB-WIDE NET RESOURCES

NETLGO::SETO T1,0		;RELEASE ALL SPECIAL QUEUES
	RELSQ
	RET			; THAT'S ALL

; SKIP IF NET INPUT BUFFER EMPTY
; Called ONLY when DEV = NETDTB
NTSIBE::
	MOVEI T1,^D60		; Try for file lock upto 60 times..
	NOINT			; 
	AOSE FILLCK(JFN)	; 
	 SOJGE T1,[OKINT	; 
		PUSH P,T1	; 
		MOVEI T1,^D1000	; 
		DISMS		; 
		POP P,T1	; 
		JRST .-2]	; 
	JUMPL T1,[OKINT		; 
		SETZ T1,	; No input
		RETSKP]		; 
	HLRZ UNIT,FILSKT(JFN)
	SETSEC UNIT,ANBSEC
	TQNE <WNDF>		; Are buffers established?
	 JRST NTSIBA		;  no, try to do so, no input until then!
	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	MOVSI T2,777777
	TDNN T2,IMPLT4(T1)
	TDNE T2,IMPLT3(T1)
	 JRST NTSIBB		; Raw input available
NTSIB2:	SETZ T1,		; Say no input available
	AOS 0(P)		; 
NTSIB1:	TQZ <BLKF>		; Don't leave with this set!
	MOVEM STS,FILSTS(JFN)	; Remember any status change!
	SETOM FILLCK(JFN)	; Free lock!
	OKINT			; 
	RET			; Return count to user

NTSIBA:	CALL FIRSTI		; Try to initialize our buffers, send allocate
	 JRST NTSIB2		;  can't, don't block, return immediately!
NTSIBB:	SKIPLE T1,FILCNT(JFN)	; If our file buffer contains any input,
	 JRST NTSIB1		;  return how much
	CALL LODBUF		; Check with IMPDV for recent arrivals
	 JRST NTSIB2		;  nothing, don't block, return immediately
	TQNE <EOFF>		; If end-of-file,
	 JRST NTSIB2		;  say no input
	AOS T1,FILCNT(JFN)	; Since we are not taking a byte (LODBUF
	JRST NTSIB1		;  thought we would), increment the count
; Network file sequential byte input

NETSQI:	HLRZ UNIT,FILSKT(JFN)
	SETSEC UNIT,ANBSEC
	MOVE IOS,NETSTS(UNIT)
	TQNN <WNDF>
	JRST NTSQI1
	CALL FIRSTI		; Wait for listen set up buffers etc.
	RET			;PASS ON DOWN BLOCK
NTSQI1:	SOSL FILCNT(JFN)
	JRST NTSQI2
	CALL LODBUF		; Get another bufferful
	RET			;PASS ON DOWN BLOCK
NTSQI2:	TQNE <EOFF>
	RET
	ILDB T1,FILBYT(JFN)
	AOS FILBYN(JFN)
	RET

LODBUF:	MOVX IOS,ERRB
	TDNE IOS,NETSTS(UNIT)
	TQO <ERRF>
	ANDCAB IOS,NETSTS(UNIT)
	MOVE T3,NETBUF(UNIT)	;GET ADDRESS OF BUFFER
	HLL T3,FILBYT(JFN)	;GET THE BYTE SIZE
	TLZ T3,770000		;SET AT END OF FIRST WORD
	TLNN T3,700		;36 BIT MODE?
	 TLO T3,40000		;NO GET BYTE OFFSET RIGHT
	MOVEM T3,FILBYT(JFN)	;SAVE BYTE POINTER
	HLRZ T4,NETBUF(UNIT)	;GET BUFFER SIZE
	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	CALL UPMSG		;UNPACK MESSAGE(S) INTO BUFFER
	 JRST [MOVX IOS,EOTF	;GET END OF FILE FLAG
		TDNE IOS,NETSTS(UNIT) ;IS IT SET FOR THIS CONNECTION
		 JRST [ TQO <EOFF> ;YES SET FOR THIS JFN
			RETSKP]	;AND RETURN
		JRST WATXXX]	;BACK OUT AND WAIT THEN START OVER
	HLRZ T2,NETBUF(UNIT)	;GET BUFFER SIZE IN BYTES
	SUB T2,T4		;BYTES LOADED
	MOVEM T2,FILCNT(JFN)	;SET BYTES IN BUFFER FOR THIS JFN
	ADDM T2,FILLEN(JFN)	;UPDATE NUMBER OF BYTES ON THIS CONN.
	LOAD T4,ANBSIZ,(UNIT)	;GET BYTE SIZE
	IMUL T4,T2		;BITS RECEIVED
	ADDM T4,NETBTC(UNIT)	;KEEP COUNT OF BITS RECEIVED
	MOVN T2,T4		;GET NEGATIVE OF BITS RECIEVED
	ADDM T2,NETBAL(UNIT)	;DEBIT ALLOCATION FOR MESSAGE RECEIVED
	CALL NETRAL		;RE-ALLOCATE IF NEEDED
	SOSGE FILCNT(JFN)	;DID WE GET ANYTHING?
	JRST LODBUF		;NO BYTES GO TRY AGAIN
	RETSKP

NETRAL::NCPOFF			; PREVENT CONFUSION
	MOVE IOS,NETSTS(UNIT)
	TQNE <EOTF,DEDF>
	 JRST NETRAX		; DON'T BOTHER IF DEAD OR DONE
	STKVAR<NETRBA,NETRMA>
	MOVE T4,NETDAL(UNIT)	; GET DESIRED BIT ALLOCATION
	MOVE T2,T4
	ASH T2,-1		; HALVE
	MOVEM T2,NETRBA
	MOVEI T3,MSGALL		; DESIRED LEVEL OF MSG ALLOC
	MOVE T2,T3
	ASH T2,-1		; HALVE
	MOVEM T2,NETRMA
	LOAD T2,LTIDX,(UNIT)	; GET LINK TABLE INDEX
	SETSEC T2,ANBSEC
	HRRZ T2,IMPLT4(T2)	; OUTSTANDING MSG ALLOC
	SUB T3,T2		; NEEDED INCREMENT
	SUB T4,NETBAL(UNIT)	; NEEDED INCREMENT
	LOAD T1,ANFHS,(UNIT)
	LOAD T2,ANLNK,(UNIT)
	CAMGE T4,NETRBA		; IF GREATER THAN HALF
	CAML T3,NETRMA		; FOR EITHER ONE
	 CALL IMPALL		; THEN SEND AN ALLOCATE
NETRAX:	NCPON
	RET

FIRSTI:	CALL FRSTIO		; SET UP BUFFER
	RET			;PASS ON DOWN BLOCK
	JUMPG T2,FRSTI1		; BUFFER SPECIFIED. USE FOR ALLOCATION
	PUSH P,T1
	MOVE T1,MAXBPM		; MAXIMUM BITS IN A MESSAGE
	LOAD T2,ANBSIZ,(UNIT)	; CONNECTION BYTE SIZE
	IDIV T1,T2		; BYTES
	IMULI T1,MSGALL		; TIMES MESSAGE ALLOCATION
	POP P,T2		; THAT PLUS FILE BUFFER BYTES
	ADD T2,T1		; IS WHAT TO USE
FRSTI1:	LOAD T4,ANBSIZ,(UNIT)	; GET BYTES SIZE
	IMUL T4,T2		; BITS IN BUFFERS
	MOVEM T4,NETDAL(UNIT)	; SAVE DESIRED LEVEL
	CALL NETRAL		; SEND ALLOCATE AS NEEDED
	RETSKP
WATLSN:	LOAD T1,ANFSM,(UNIT)	; Get state of this connection
	CAIN T1,OPND
	 RETSKP
	CAIN T1,RFCR
	 JRST [	MOVEI T1,ACPT
		CALL DOFSM
		RETSKP]
	CAIN T1,RFCS		; If still waiting for rfc
	 JRST WATLS1		; Continue waiting
	CAIE T1,LSNG
	 JRST [	MOVX IOS,EOTF
		TDNE IOS,NETSTS(UNIT)
		 RETSKP		; Null file sent
		MOVX IOS,ERRB!EOTF ; Connection never actually opened
		IORB IOS,NETSTS(UNIT)
		RETSKP]


WATLS1:	HRRZ T2,UNIT		;GET UNIT
	ROT T2,-9		;PUT IN BITS 0-8
	HRLI T1,NOTTST		;TEST ROUTINE ADDRESS,,STATE 
	MOVSS T1		;STATE TO WAIT FOR,,TEST ROUTINE ADDRESS
	IOR T1,T2		;UNIT/STATE,,TEST ROUTINE
	TQO <BLKF>		;BLOCK FOR STATE CHANGE
	RET



WATXXX:	TQO <BLKF>		;TELL LOWER LEVEL TO BLOCK
	RET
; Network file sequential byte output

NETSQO:	HLRZ UNIT,FILSKT(JFN)
	SETSEC UNIT,ANBSEC
	MOVE IOS,NETSTS(UNIT)
	TQNE <DEDF,ERRB>
	 TQO <ERRF>
	TQNE <DEDF,EOTF>
	 RET
	PUSH P,T1
	TQNN <WNDF>
	JRST NTSQO4
	CALL FIRSTO
	 JRST [POP P,0(P)	;CLEAN UP STACK
		RET]		;PASS ON DOWN BLOCK
NTSQO4:	TQNE <BFSND>		; IMMEDIATE SEND?
	 JRST NTSQO1		; No
	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	CALL PKCHK		; HOW MANY BYTES CAN WE SEND?
	POP P,T3
	JUMPE T2,NTSQO3		; NOT ENOUGH
	CALL PKBYT
	 TRN
	LOAD T1,ANBSIZ,(UNIT)
	ADDM T1,NETBTC(UNIT)
	MOVNS T1
	ADDM T1,NETBAL(UNIT)
	MOVEI T1,<^D2*^D60*^D1000>/CHKINT
	STOR T1,ANCLKS,(UNIT)	; RESET CLOCK TO TWO MINUTES
	RET

NTSQO1:	SOSL FILCNT(JFN)
	 JRST NTSQO2
	CALL DMPBUF
	 JRST [POP P,T3		;CLEAN UP STACK
		JRST WATXXX]	; Can't dump now, wait
NTSQO2:	AOS FILBYN(JFN)
	POP P,T1
	IDPB T1,FILBYT(JFN)
	RET

NTSQO3:	CALL WATBAL		;WAIT FOR BITS AND A MSG TO BE ALLOCATED
	JRST WATXXX		; ..
DMPBUF:	MOVX IOS,ERRB		;GET ERROR HAS OCCURED FLAG
	TDNE IOS,NETSTS(UNIT)	;HAS ERROR OCCURED?
	 TQO <ERRF>		;YES.  INDICATE IT FOR THE JFN
	ANDCAB IOS,NETSTS(UNIT)	;CLEAR ERROR FLAG FOR CONNECTION
	MOVE T4,FILOFN(JFN)	;GET CURRENT OUTPUT POINT
	CAML T4,FILBYN(JFN)	;DONE?
	 JRST DMPDUN		;YES
	TQNE <EOTF,DEDF>	;END OF FILE OR DEAD HOST
	 JRST [ TQO <ERRF>	;YES.  SET ERROR FOR JFN
		SETZM FILBYT(JFN) ;ZERO BYTE POINTER
		SETZM FILBYN(JFN) ;BYTE COUNT
		SETZM FILOFN(JFN) ;AND CURRENT POSITION IN FILE
		HRLOI T1,377777	;AND SET NUMBER OF BYTES TO INFINITY
		MOVEM T1,FILCNT(JFN)
		RETSKP]
	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	CALL PKCHK		;HOW MANY BYTES CAN WE SEND?
	JUMPE T2,WATBAL		;NONE, WAIT
	MOVE T4,FILBYN(JFN)	;GET BYTE COUNT
	SUB T4,FILOFN(JFN)	;GET NUMBER OF BYTES IN BUFFER
	CAML T4,T2
	MOVE T4,T2		;TAKE MIN OF THE TWO
	MOVE T3,NETBUF(UNIT)	;GET BUFFER ADR
	HLL T3,FILBYT(JFN)	;GET BYTE SIZE
	TLZ T3,770000		;END OF FIRST WORD
	TLNN T3,700		;36 BIT MODE?
	 TLO T3,40000		;NO GET BYTE OFFSET RIGHT
	MOVE T1,FILOFN(JFN)	;GET BYTE OFFSET
	TLNE T3,6700		;8 BIT?
	 JRST DMPBF1		;NO
	IDIVI T1,4		;GET WORDS TO ADJUST IN T1
	HRRZS T3		;WE WILL ADD IN THE PROPER LH
	ADD T3,[041000,,0	;CASE 0. POINT TO PREVIOUS WORD
		341000,,1	;SO PKMSG WILL DO A BLT
		241000,,1	;OTHERS CASES USE STD. PTR
		141000,,1](T2)
DMPBF1:	ADDI T3,(T1)		;DO WORD OFFSET
	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	PUSH P,T4		;SAVE COUNT WE ARE ASKING FOR
	CALL PKMSG		;GO PACK MESSAGE AND SEND IT
	POP P,T4		;GET BYTE COUNT BACK
	ADDM T4,FILOFN(JFN)	;UPDATE BYTE COUNT OF BUFFER
	LOAD T3,ANBSIZ,(UNIT)	;GET BYTE SIZE
	IMUL T4,T3		;GIVES BITS JUST SENT
	ADDM T4,NETBTC(UNIT)	;KEEP COUNT OF BITS SENT
	MOVNS T4		;GET NEGATIVE OF BITS SENT
	ADDM T4,NETBAL(UNIT)	;UPDATE BIT ALLOCATION
	MOVEI T1,<2*^D60*^D1000>/CHKINT
	STOR T1,ANCLKS,(UNIT)	;RESET CLOCK FOR THIS CONNECTION
	JRST DMPBUF		;GO CHECK FOR ERRORS
DMPDUN:	SETZM FILBYN(JFN)	;ZERO BYTE COUNT FOR BUFFER
	SETZM FILOFN(JFN)	;ZERO CURRENT OUTPUT POINT
	MOVE T1,NETBUF(UNIT)	;GET ADDRESS OF BUFFER
	HLL T1,FILBYT(JFN)	;GET THE BYTE SIZE
	TLZ T1,770000		;SET AT END OF FIRST WORD
	TLNN T1,700		;36 BIT MODE?
	 TLO T1,40000		;NO GET BYTE OFFSET RIGHT
	MOVEM T1,FILBYT(JFN)	;SAVE BYTE POINTER
	HLRZ T1,NETBUF(UNIT)	;GET BUFFER SIZE
	SUBI T1,1		;DECREMENT IT BY ONE
	MOVEM T1,FILCNT(JFN)	;AND SAVE IT AS BYTES IN BUFFER
	RETSKP

WATBAL:	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	CALL PKULCK		;UNLOCK CONNECTION TOO
	MOVEI T1,BALTST		;GET ADDRESS OF TEST ROUTINE
	HRL T1,UNIT		;AND UNIT TO WAIT ON
	RET
FIRSTO:	TQNN <BFSND>		; BUFFERED?
	 JRST [	CALL WATLSN	; NO, WAIT FOR CONNECTION TO OPEN
		RET		;PASS ON DOWN BLOCK
		TQZ <WNDF>
		RETSKP]
	CALL FRSTIO		; YES, SET UP BUFFER ETC
	RET			;PASS ON DOWN BLOCK
	RETSKP

;FRSTIO -  SET UP BUFFER IN JSB FREE SPACE

;ACCEPTS  UNIT/   NETWORK PSEUDO UNIT NUMBER

;RETURNS +1  FAILURE
;	 +2  SUCCESS   
;		RH NETBUF(UNIT)  HAS BUFFER ADDRESS

FRSTIO:	CALL WATLSN		; Wait for connection complete
	 RET			; Pass on down block
	STKVAR <FRSTBY,FRSTBF>
	MOVEI T1,^D36		; Bits per word
	LOAD T3,ANBSIZ,(UNIT)	; Connection byte size
	IDIV T1,T3		; Connection bytes per word
	IMUL T3,T1		; Used bits per word
	MOVE T2,MAXBPM		; Max bits per net message
	IDIVM T2,T3		; Max words per net message
	MOVEI T1,^D36		; Bits per machine word
	LDB T2,PBYTSZ		; File byte size
	IDIVM T1,T2		; File bytes per word
	MOVEM T2,FRSTBY		; Save file bytes per word
	HLRZ T1,NETBUF(UNIT)	; Desired bytes per buffer
	IDIV T1,T2		; Number of words needed
	SKIPE T1		; If zero
	CAML T1,T3		; Or bigger than max
	 MOVE T1,T3		; Use max
	MOVEM T1,FRSTBF		; Save bytes per buffer
	AOS T2,T1		; Plus header
	CALL ASGJFR		;ASSIGN A PAGE IN JOB AREA
	 JRST [TQO <ERRF>	;INDICATE AN ERROR
		RETBAD]		;RETURN
	HRRM T1,NETBUF(UNIT)	;SAVE BUFFER ADDRESS
	MOVE T3,FRSTBF		;GET SIZE AVAILABLE FOR BUFFER
	MOVE T1,FRSTBY		;GET BYTES/WORD BACK
	IMUL T1,T3		;CALCULATE BYTES BUFFER WILL HOLD
	HLRZ T2,NETBUF(UNIT)	;RETURN AS VALUE
	HRLM T1,NETBUF(UNIT)	;REAL BYTES PER BUFFER
	TQZ <WNDF>
	RETSKP
;100 Begin modification
; Attach sockets to pty
; Call:	1 (u)	; Receive jfn of opened network connection
;	2 (u)	; Send jfn of opened network connection
;	CHKJFN done on (1)
;	JRST AATNVT from .ATNVT
; Returns
;	+1	; Cannot attach
;	+2	; Ok.  the jfns are released, ac 1 has line number of
;		; Attached pty.

AATNVT::STKVAR <ATUNTS,ATRCJF,ATNDAD>
;100 End modification
	MOVEI T1,ATNX2		; Error code if test skips
	TQNE <READF>		; MUST BE OPENED FOR READING
	CALL CHKATP		; Check for dev=net, open, no buffer
	 JRST ATPER1		; Failed one of the above
	HLRZ UNIT,FILSKT(JFN)
	SETSEC UNIT,ANBSEC
	MOVEM UNIT,ATUNTS	;SAVE DEV AND JFN
	MOVEM JFN,ATRCJF
	UMOVE JFN,2		; Get send jfn
	CALL CHKJFN		; Check it
	JRST ATPER2		; Must also be a real jfn
	JRST ATPER2
	JRST ATPER2
	MOVEI T1,ATNX2		; Becomes atNx8 at atper3
	TQNE <WRTF>		; THIS ONE MUST BE FOR WRITING
	CALL CHKATP		; And dev=net, open, no buffer
	 JRST ATPER3		; Failed above tests
	HLRZ UNIT,FILSKT(JFN)
	SETSEC UNIT,ANBSEC
	LOAD T1,ANFSM,(UNIT)
	CAIN T1,RFCS
	CALL WATNOT		; Wait for response from foreign host
	MOVEI T1,ATNX12		; Error code for refused send
	LOAD T2,ANFSM,(UNIT)	; Now get state
	CAIE T2,OPND		; If not opnd
	JRST ATPER4		; Then fail
	HRLM UNIT,ATUNTS	;SAVE SEND JFN IN LEFT HALF
	HRRZ UNIT,ATUNTS	;SWITCH TO RECEIVE CONNECTION
	SETSEC UNIT,ANBSEC
	LOAD T1,ANFSM,(UNIT)	; Get its state
	CAIN T1,RFCS
	CALL WATNOT		; Wait for response from foreign host
	MOVEI T1,ATNX6		; Error code for refused receive
	LOAD T2,ANFSM,(UNIT)
	CAIE T2,OPND		; If not opnd
	JRST ATPER4		; Then fail
	NCPOFF
	LOAD T1,ANFSM,(UNIT)
	CAIE T1,OPND
	 JRST [	MOVEI T1,ATNX6
		JRST ATPERZ]
	HLRZ UNIT,ATUNTS	;GET SEND UNIT
	SETSEC UNIT,ANBSEC
	LOAD T1,ANFSM,(UNIT)
	CAIE T1,OPND
	 JRST [	MOVEI T1,ATNX12
		JRST ATPERZ]
	UMOVE 1,1		; GET OPTION FLAGS
	HRR T1,ATUNTS		;SET UP ARGS, RECEIVE UNIT IN 1
	HLRZ T2,ATUNTS		;SEND UNIT IN 2
	CALL ASNNVT		; Assign NVT to these units
	 JRST [	MOVEI T1,ATNX13	; Can't, no pty's
		JRST ATPERZ]
	MOVEM T2,ATNDAD		;SAVE ADDRESS OF DYNAMIC DATA
	HRRZ UNIT,ATUNTS	;RECIEVE UNIT
	SETSEC UNIT,ANBSEC
	MOVX T3,PROGF
	ANDCAM T3,NETSTS(UNIT)	; PROGRAM NO LONGER LOOKING
	HRRM T1,NETBUF(UNIT)	; Store pty number here
	HLRZ UNIT,ATUNTS	;SEND UNIT
	SETSEC UNIT,ANBSEC
	ANDCAM T3,NETSTS(UNIT)	; NOT HERE EITHER
	HRRM T1,NETBUF(UNIT)	; Also here
	NCPON
	IORI T1,400000		; Convert pty to tty designator
	UMOVEM T1,1		; Return to user
	CALL RELJFN		; Release send jfn
	MOVE JFN,ATRCJF
	CALL RELJFN		; And receive jfn
	HRRZ UNIT,ATUNTS	;GET RECIEVE UNIT
	SETSEC UNIT,ANBSEC
	MOVE T2,ATNDAD		;GET ADDRESS OF DYNAMIC DATA
	CALL NVTRAL		;GO REALLOCATE
	MOVE T2,ATNDAD		;GET ADDRESS OF DYNAMIC DATA
	CALL ULKTTY		;UNLOCK DATA BASE
	SMRETN			;RETURN SKIPPING
; Check validity of jfn for atpty

CHKATP:	MOVEI T1,ATNX3		; Receive not open
	TQNN <OPNF>		; IS IT OPEN?
	RET			; NO
	HRRZ T2,DEV
	MOVEI T1,ATNX4
	CAIE T2,NETDTB
	RET
	MOVEI T1,ATNX5
	TQNN <WNDF>
	RET
	RETSKP

ATPERZ:	NCPON
	JRST ATPER4

ATPER2:	MOVEI T1,ATNX7		; Bad send jfn
	JRST ATPER5

ATPER3:	ADDI T1,ATNX7-ATNX1	; Convert receive errors to send errors
ATPER4:	CALL UNLCKF
ATPER5:	MOVE JFN,ATRCJF		;GET RECIEV JFN
	MOVE STS,FILSTS(JFN)
ATPER1:	CALL UNLCKF
	JRST MRETNE		; Save error return in ac1

ATPER0:	MOVEI T1,ATNX1		; Bad receive jfn
	JRST MRETNE
; Convert jfn to absolute network socket number
; Call:	1	; Jfn
;	CVSKT
; Returns
;	+1	; Error
;	+2	; Ok, in 2 the absolute socket number

.CVSKT::MCENT
	MOVE JFN,T1
	CALL CHKJFN
	 RETERR (CVSKX1)
	 RETERR (CVSKX1)
	 RETERR (CVSKX1)
	CAIE PTR,NETDTB
	 RETERR (CVSKX1,<CALL UNLCKF>)
	HLRZ T1,FILNEN(JFN)
	HRLI T1,(<POINT 7,0,35>)
	CALL NAMDEC
	 RETERR (CVSKX2,<CALL UNLCKF>)
	CALL UNLCKF
	UMOVEM T1,2
	JRST SKMRTN

;ROUTINE TO PRODUCE THE OLD HOSTN TABLE

GHOSTN::SETSEC T2,MNTSEC		; Point into right section
	LOAD T4,HSTIDX,(T2)		;GET INDEX
	SETSEC T4,MNTSEC
	MOVE T1,HOSTNN(T4)		;GET THE HOST NUMBER
	CALL CVOHST			;CONVERT TO OLD FORMAT
	MOVE T3,HSTSTS(T4)		;GET HOST STATUS
	ANDI T3,777000			;GET THE RIGHT BITS
	IORI T1,(T3)			;BUILD LH
	SKIPGE HOSTN(T2)		;NICKNAME?
	 TXO T1,HS%NCK
	MOVSI T1,(T1)
	LOAD T3,HSTNMP,(T2)		;GET THE NAME POINTER
	HRRI T1,(T3)
	RET
;ROUTINE TO PRODUCE THE OLD NETAWD TABLE

GNTAWD::SETSEC T2,ANBSEC
	LOAD T1,ANFHS,(T2)		;GET THE HOST NUMBER
	CALL CVOHST			;CONVERT TO OLD FORMAT
	MOVSI T1,(T1)			;HOST NUMBER TO LH
	MOVE T3,NETAWD(T2)		;GET REST OF WORD
	TLZ T3,777			;CLEAR OUT SLOT FOR HOST
	IOR T1,T3			;PUT IT TOGETHER
	RET

;ROUTINE TO PRODUCE OLD IMPHRT GETAB TABLE.

GTBHRT::SAVEQ			;NEED SOME ACS
	HRRZ UNIT,T2		;GET INDEX
	IMULI UNIT,^D36		;CONVERT TO 1ST HOST NUMBER
	HRLI UNIT,-^D36		;LOOP COUNTER
	SETO IOS,		;SET TO ALL UP

GTBHR1:	ROT IOS,1		;MAKE ROOM FOR NEXT BIT
	HRRZ T1,UNIT		;GET NEXT HOST NUMBER
	CAIL T1,400		;OUT OF RANGE
	 JRST GTBHR2
	CALL CVNHST		;CONVERT TO NEW FORMAT
	CALL HSTHSH		;LOOKUP HOST INDEX
	 TRNA			;NOT THERE SO NOT UP
	SKIPL HSTSTS(T2)	;UP?
GTBHR2:	 TXZ IOS,1		;NO, CLEAR BIT
	AOBJN UNIT,GTBHR1	;LOOP FOR ALL 36 HOSTS IN THIS WORD
	MOVE T1,IOS		;RETURN WORD FOR GETAB
	RET

;ROUTINE TO PRODUCE OLD HSTSTS GETAB TABLE.

GTBHSS::SAVEQ			;NEED WORK SPACE
	HRRZ IOS,T2		;GET INDEX
	LSH IOS,1		;TURN INTO HOST NUMBER
	MOVE T1,IOS		;HOST N
	CALL GTBHSH		;GET RIGHT STATUS
	HLLZ UNIT,T1		;RESULT FOR HOST N IN LEFT HALF
	AOS T1,IOS		;HOST N+1
	CALL GTBHSH		;GET RIGHT STATUS
	HLR UNIT,T1		;RESULT FOR HOST N+1 IN RIGHT HALF
	MOVE T1,UNIT		;RETURN WORD FOR GETAB
	RET

GTBHSH:	CALL CVNHST		;CONVERT TO NEW FORMAT
	CALL HSTHSH		;LOOKUP HOST INDEX
	 JRST RFALSE		;NO SUCH HOST, RETURN 0
	SKIPL T1,HSTSTS(T2)	;UP?
	 TXOA T1,<1B0+1B1>	;SET VALID AND DEAD BITS
	MOVX T1,<1B0>		;OTHERWISE JUST SET VALID
	RET
;GTNCP RETURNS A TABLE OF DATA FOR AN NCP CONNECTION

.GTNCP::MCENT
	SKIPL T1			;CHECK RANGE OF FUNCTION
	 CAIL T1,GTNMAX
	  RETERR (ARGX02)		;BAD FUNCTION NUMBER
	XCT GTNDSP(T1)			;DO FUNCTION
GTNCPX:	SETSEC UNIT,ANBSEC		; Point it to right section
	SKIPL UNIT			;GET THE INDEX
	 CAML UNIT,[XWD ANBSEC,NSKT]	; value to large?
	  RETERR (GTJIX1)		;BAD INDEX
	UMOVE T3,3			;GET AC3 AND AC4 FROM USER
	UMOVE T4,4
GTNCPL:	HRRZ T1,T4			;OUT OF THINGS?
	CAIL T1,NCPLEN
	 JRST GTNCLX			;YES
	XCT NCPTAB(T1)			;LOAD DATA WORD
	UMOVEM T1,(T3)			;RETURN TO USER
	AOJ T3,
	AOBJN T4,GTNCPL			;LOOP
GTNCLX:	UMOVEM T4,4			;UPDATE COUNTER
	JRST SKMRTN

NCPTAB:	HRRZ T1,UNIT			;(00)NCP UNIT
	LOAD T1,ANFHS,(UNIT)		;(01)FOREIGN HOST
	MOVE T1,LSKT(UNIT)		;(02)LOCAL SOCKET
	MOVE T1,FSKT(UNIT)		;(03)FOREIGN SOCKET
	LOAD T1,ANFSM,(UNIT)		;(04)FINITE STATE
	LOAD T1,ANLNK,(UNIT)		;(05)LINK
	CALL [	HRRZ T1,NETBUF(UNIT)	;(06)RETURN NVT IF
		CAIGE T1,1000		;THERE IS ONE
		 JUMPN T1,R
		JRST RTRUE]
	LOAD T1,ANBSIZ,(UNIT)		;(07)BYTE SIZE OF CONNECTION
	CALL [	LOAD T1,LTIDX,(UNIT)	;(10)MSG ALLOC
		SETSEC T1,ANBSEC
		HRRZ T1,IMPLT4(T1)
		RET]
	MOVE T1,NETBAL(UNIT)		;(11)BIT ALLOC
	MOVE T1,NETDAL(UNIT)		;(12)DESIRED ALLOC
	MOVE T1,NETBTC(UNIT)		;(13)BITS XFERRED
	HLRZ T1,NETBUF(UNIT)		;(14)BYTES/BUFFER
	LOAD T1,ANCLKS,(UNIT)		;(15)TIMEOUT
	MOVE T1,NETSTS(UNIT)		;(16)STATUS OF CONN
NCPLEN==.-NCPTAB
GTNDSP:	JRST GTNSIZ			;(00)GET TABLE SIZE
	HRRZ UNIT,T2			;(01)INDEX GIVEN
	JRST GTNNVI			;(02)INPUT NVT
	JRST GTNNVO			;(03)OUTPUT NVT
	JRST GTNJFN			;(04)JFN
GTNMAX==.-GTNDSP			;NUMBER OF FUNCTIONS

GTNSIZ:	MOVSI T2,-NSKT			;-LENGTH,,1ST INDEX
	UMOVEM T2,2			;RETURN TO USER
	MOVE T3,NVTPTR			;-# NVTS,,1ST NVT
	UMOVEM T3,3
	JRST SKMRTN			;DONE

GTNJFN:	MOVE JFN,T2			;CHECK THE JFN
	CALL CHKJFN
	 RETERR (GTNCX1)
	 RETERR (GTNCX1)
	 RETERR (GTNCX1)
	HLRZ UNIT,FILSKT(JFN)		;GET THE UNIT
	CALL UNLCKF
	CAIE PTR,NETDTB			;MAKE SURE IS NET:
	 RETERR (GTNCX1)
	JRST GTNCPX			;REJOIN MAIN CODE

GTNNVI:	SKIPA UNIT,[NVTIPU]		;GET INPUT UNIT
GTNNVO:	MOVEI UNIT,NVTOPU		;USE OUTPUT UNIT
	CAIN T2,.CTTRM			;WANT CONTROLLING TTY?
	 MOVE T2,CTRLTT			;YES
	ANDI T2,377777			;CLEAR 400000
	CALL NVTCHK
	 RETERR (GTNCX2)		;BAD NVT
	CALL (UNIT)			;CALL ROUTINE
	 SETO UNIT,			;CATCH ERROR AS BAD UNIT
	CALL ULKTTY			;UNLOCK TTY DATA BASE
	JRST GTNCPX			;REJOIN MAIN CODE
; Flush host

.FLHST::MCENT
	MOVEI T2,SC%WHL!SC%OPR
	TDNN T2,CAPENB
	 ITERR (WHELX1)
	CALL CVNHST		;CONVERT HOST NUMBER
	CALL HSTDED
	CALL IMSRST
	JRST MRETN


; Set local host number routine. Takes old or new style number.
; Sets to new style, and puts it in NLHOST.

STHSTJ:: ITERR()			; No longer a valid function, no-one should be using this

; Get net status

NETGST:	HLRZ UNIT,FILSKT(JFN)
	SETSEC UNIT,ANBSEC
	LOAD T1,ANFHS,(UNIT)
	CALL CVOHST		; Convert to old host format
	UMOVEM T1,3
	HLLZ T1,NETSTS(UNIT)
	MOVE T2,FSKT(UNIT)
	UMOVEM T2,4

; Set net status

NETSST:	RET
; The following code and tables PROVIDE a finite state machine
; Implementation of the transitions and actions produced by various
; Events associated with a connection
; Assumed are that unit indexes the proper local socket

; Events are numbered as follows

RRFC==0		; Received an rfc
CLSR==1		; Cls for a receive socket
CLSS==2		; Cls for a send socket
CLZR==3		; Close done on a receive socket
CLZS==4		; Close done on a send socket
ACPT==5		; Program issued an accept
CONN==6		; Program issued a connect
LISN==7		; Program issued a listen
RRFN==10	; Received a rfnm with no more data outstanding
HUNG==11	; Time out event (happens 2 minutes after last dofsm)
RRFB==12	; RECEIVED RFC WITH NON-MATCHING BYTE SIZE

; Actions are numbered as follows

ANOP==0		; No operation
AFNY==1		; No operation (unexpected event)
ACLS==2		; Send cls
ARFC==3		; Send rfc
AOPB==4		; Send rfc and open link
AOPL==5		; Open link
ACLL==6		; Close link
ACLO==7		; Close link and send cls
AEOR==10	; END OF RECEIVE
AEOS==11	; END OF SEND
AES1==12	; END OF SEND WHEN ABORTED BY FOREIGN HOST
AABT==13	; CONNECTION ABORTED BY FAR END
ACKA==14	; CHECK ALLOCATION

; States are numbered as follows

DEAD==0		; Never used
CLZD==1		; Closed
PNDG==2		; Pending. rfc received while closed
LSNG==3		; Listening. listen issued while closed
RFCR==4		; Rfc received while listening
CLW1==5		; Close wait alternate. clzr from opnd
RFCS==6		; Rfc sent
OPND==7		; Opened
CLSW==10	; Waiting for a cls
DATW==11	; Waiting for all data to be sent
RFN1==12	; Waiting for last rfnm
CLZW==13	; Waiting for program close
RFN2==14	; Waiting for rfnm after clss
NUSE==15	; THIS STATE NO LONGER USED
FREE==16	; Not in use
; The following table of byte pointers is used to get to the next state
; Given the current state and the event
; This table is indexed by event, the table addressed by this table
; Is indexed by old state

RADIX ^D10

QQ==3

CBPFSM:	REPEAT 9,<
	POINT 4,NXTSTT(T2),QQ
QQ==QQ+4>
QQ==3
	REPEAT 9,<
	POINT 4,NXTSTT+1(T2),QQ
QQ==QQ+4>

; Following table of pointers is used to get the action to be taken
; Given the current state and the event
; This table is indexed by event, the table addressed by this table
; Is indexed by old state

QQ==3
CBAFSM:	REPEAT 9,<
	POINT 4,ACTION(T2),QQ
QQ==QQ+4>
QQ==3

	REPEAT 9,<
	POINT 4,ACTION+1(T2),QQ
QQ==QQ+4
>

; This is the transition table
; Each word contains the new state for a given old state
; Successive bytes are used for different events

; Event rrfc clsr clss clzr clzs acpt conn lisn rrfe hung rrfb old state

NXTSTT:
BYTE (4)DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD,DEAD	; Dead
BYTE (4)PNDG,CLZD,CLZD,CLZD,CLZD,CLZD,RFCS,LSNG,CLZD,CLZD,CLZD	; Clzd
BYTE (4)PNDG,FREE,FREE,PNDG,PNDG,PNDG,OPND,RFCR,PNDG,CLW1,PNDG	; Pndg
BYTE (4)RFCR,LSNG,LSNG,FREE,FREE,LSNG,LSNG,LSNG,LSNG,LSNG,CLSW	; Lsng
BYTE (4)RFCR,CLZW,CLZW,CLW1,CLW1,OPND,RFCR,RFCR,RFCR,RFCR,RFCR	; Rfcr
BYTE (4)CLW1,FREE,FREE,CLW1,CLW1,CLW1,CLW1,CLW1,CLW1,FREE,CLW1	; Clw1
BYTE (4)OPND,CLZW,CLZW,CLW1,CLW1,RFCS,RFCS,RFCS,RFCS,CLSW,CLSW	; Rfcs
BYTE (4)OPND,CLZW,RFN2,CLW1,DATW,OPND,OPND,OPND,OPND,OPND,OPND	; Opnd
BYTE (4)CLSW,CLZW,CLZW,CLW1,CLW1,CLSW,CLSW,CLSW,CLSW,CLZW,CLSW	; Clsw
BYTE (4)DATW,DATW,RFN1,DATW,DATW,DATW,DATW,DATW,CLW1,CLW1,DATW	; Datw
BYTE (4)RFN1,RFN1,RFN1,RFN1,RFN1,RFN1,RFN1,RFN1,FREE,FREE,RFN1	; Rfn1
BYTE (4)CLZW,CLZW,CLZW,FREE,FREE,CLZW,CLZW,CLZW,CLZW,CLZW,CLZW	; Clzw
BYTE (4)RFN2,RFN2,RFN2,RFN1,RFN1,RFN2,RFN2,RFN2,CLZW,CLZW,RFN2	; Rfn2
BYTE (4)NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE,NUSE	; Nuse
BYTE (4)FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE,FREE	; Free
; This is the action table
; It is referenced the same as the transition table

; Event rrfc clsr clss clzr clzs acpt conn lisn rrfe hung rrfb old state

ACTION:
BYTE (4)AFNY,AFNY,AFNY,AFNY,AFNY,ANOP,AFNY,AFNY,AFNY,ANOP,AFNY	; Dead
BYTE (4)ANOP,AFNY,AFNY,AFNY,AFNY,ANOP,ARFC,ANOP,AFNY,ANOP,AFNY	; Clzd
BYTE (4)AFNY,ACLS,ACLS,AFNY,AFNY,ANOP,AOPB,ANOP,AFNY,ACLS,AFNY	; Pndg
BYTE (4)ANOP,AFNY,AFNY,ANOP,ANOP,ANOP,AFNY,AFNY,AFNY,ANOP,ACLS	; Lsng
BYTE (4)AFNY,ACLS,ACLS,ACLS,ACLS,AOPB,AFNY,AFNY,AFNY,ANOP,AFNY	; Rfcr
BYTE (4)AFNY,ACLL,ACLL,AFNY,AFNY,ANOP,AFNY,AFNY,AFNY,ACLL,AFNY	; Clw1
BYTE (4)AOPL,ACLS,ACLS,ACLS,ACLS,ANOP,AFNY,AFNY,AFNY,ACLS,ACLS	; Rfcs
BYTE (4)AFNY,AEOR,AES1,ACLS,AEOS,ANOP,AFNY,AFNY,AFNY,ACKA,AFNY	; Opnd
BYTE (4)ANOP,ANOP,ANOP,ANOP,ANOP,ANOP,AFNY,AFNY,AFNY,ANOP,AFNY	; Clsw
BYTE (4)AFNY,AFNY,AES1,AFNY,AFNY,ANOP,AFNY,AFNY,ACLS,ACLS,AFNY	; Datw
BYTE (4)AFNY,AFNY,AFNY,AFNY,AFNY,ANOP,AFNY,AFNY,ACLO,ACLO,AFNY	; Rfn1
BYTE (4)AFNY,AFNY,AFNY,ACLL,ANOP,ANOP,AFNY,AFNY,AFNY,ANOP,AFNY	; Clzw
BYTE (4)AFNY,AFNY,AFNY,ANOP,ANOP,ANOP,AFNY,AFNY,ACLO,ACLO,AFNY	; Rfn2
BYTE (4)AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY,AFNY	; Nuse
BYTE (4)AFNY,AFNY,AFNY,ANOP,ANOP,AABT,AFNY,AFNY,AFNY,ANOP,AFNY	; Free

;DISPATCH TABLE FOR ACTIONS
;ROUTINES ARE CALLED EFFECTIVELY BY CALL @ACTAB(ACTION#)

ACTAB:	IFIW!R			;NOP
	IFIW!FUNNY		;UNEXPECTED EVENT
	IFIW!SNDCLS		;SEND CLS
	IFIW!SNDRFC		;SEND STR OR RTS
	IFIW!NETOPB		;SNED RFC AND OPEN LINK
	IFIW!NETOPL		;OPEN LINK
	IFIW!NETCLL		;CLOSE LINK
	IFIW!NETCLB		;CLOSE LINK AND SEND CLS
	IFIW!DOEOR		;FINISH UP INPUT
	IFIW!DOEOS		;FINISH UP OUTPUT
	IFIW!DOES1		;END OF SEND IF TRANSMISSION ABORTED
	IFIW!DOABT		;ACCEPT ON ABORTED CONNECTION
	IFIW!CKALL		;ALLOCATIN CHECK FOR OPENED CONN

RADIX 8
;UNEXPECTED EVENT

;	T1/   EVENT 
;	UNIT/ UNIT INDEX

FUNNY:	HLL T1,NETSTS(UNIT)	;GET STATUS
	LOAD T2,ANFHS,(UNIT)	;GET FOREIGN HOST
	MNTBUG(INF,NCPFUN,<NCP FSM RECEIVED FUNNY INPUT>,<<T1,D>,<T2,D>,<UNIT,D>>)
	AOS FUNNYC		;COUNT THEM
	MOVE T1,T2
	SETZ T2,
	JRST NCPERR		;AND SEND TYPE 0 ERR

; ACCEPTED AN ABORTED REQUEST

DOABT:	MOVX IOS,EOTF		; SET FLAG TO CAUSE ERROR
	IORB IOS,NETSTS(UNIT)	; IN STATUS WORD
	RET

; CHECK ALLOCATION

CKALL:	MOVE T1,LSKT(UNIT)
	TRNN T1,1		; SEND SOCKET?
	 RET			; NO. DO NOTHING
	TQNE <ALLFF>		; Allocation failure??
	TQNN <CLZF>		; BEING CLOSED?
	 JRST CKALL1		; NO, IGNORE
	TQO <ERRB,EOTF>		; SIGNAL ERROR, AND STOP TRANSMISSION
	HLLM IOS,NETSTS(UNIT)
	RET

CKALL1:	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	LOAD T2,ANBSIZ,(UNIT)
	CAMG T2,NETBAL(UNIT)	; SUFFICIENT BIT ALLOCATION?
	SKIPN IMPLT4(T1)	; AND MESSAGE SPACE?
	 JRST CKALL2		; NO
	TQZ <ALLFF>
	HLLM IOS,NETSTS(UNIT)
	RET

CKALL2:	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	CALL IMPSYN		; RESYNC ALLOCATION
	MOVX IOS,ALLFF
	IORB IOS,NETSTS(UNIT)	; REMEMBER WE DID THIS ONCE
	RET
; END OF SEND

DOES1:	CALL DOEOS
	CALLRET IMPABL		; FLUSH QUEUED MESSAGES

DOEOS:	MOVX IOS,EOTF
	IORB IOS,NETSTS(UNIT)
	LOAD T1,LTIDX,(UNIT)	;GET LINK TABLE INDEX
	SETSEC T1,ANBSEC
	CALLRET IMPSDB		; SET DONE BIT IN LINK TABLE

; End of receive

DOEOR:	CALL SNDCLS
	HRRZ T2,NETBUF(UNIT)
	JUMPE T2,DOEOS
	CAIL T2,1000
	JRST DOEOS
	CALL DOEOS		; DO SAME AS END OF SEND
	NCPON			; NCP BACK ON SO NVTDET CAN USE IT
EORNV0:	HRRZ T2,NETBUF(UNIT)	; PICK UP LINE NUMBER
	JUMPE T2,EORNV1		;ALREADY GONE
	PUSH P,UNIT
	CALL LCKDVL		;LOCK DEVICE LOCK, GO NOINT
	CALL NVTDTT
	 JRST EORNV2		;FAILURE
EORNV3:	UNLOKK DEVLKK		;UNLOCK THE DEVICE LOCK
	OKINT			;DEVLKK WENT NOINT
	POP P,UNIT
EORNV1:	NCPOFF			; BACK OFF SO CALLER IS NOT CONFUSED
	RET

EORNV2:	TXZN T1,1B0		;WAIT OR ERROR?
	JRST [	MNTBUG (INF,NETDET,<NVTDET: COULD NOT CLOSE NVT>,<<T1,D>>)
		JRST EORNV3]	;GO CLEAN UP
	UNLOKK DEVLKK		;UNLOCK THE DEVICE LOCK
	OKINT			;DEVLKK WENT NOINT
	POP P,UNIT
	HRL T1,NETBUF(UNIT)	;GET TTY NUMBER
	MDISMS			;WAIT UNTIL DEALLOCATE IS POSSIBLE
	JRST EORNV0		;GO TRY AGAIN

; Close link

NETCLL:	LOAD T1,LTIDX,(UNIT)	; Get link table index
	SETSEC T1,ANBSEC
	TQZE <LINKF>		; Link setup?
	 CALL IMPCLL
	MOVEM IOS,NETSTS(UNIT)	; Store status
	RET

NETCLB:	CALL NETCLL
SNDCLS:	LOAD T1,ANFHS,(UNIT)	; Get foreign host
	MOVE T2,LSKT(UNIT)	; And local socket
	MOVE T3,FSKT(UNIT)	; And foreign socket
	TQNN <DEDF>
	 CALL IMPCLS		; Send the control message
	RET
; OPEN LINK

NETOPL:	LOAD T1,ANFHS,(UNIT)
	LOAD T2,ANLNK,(UNIT)
	LOAD T3,ANBSIZ,(UNIT)
	MOVE T4,LSKT(UNIT)
	TRNE T4,1		; Send socket?
	 JRST NETOPS		; Yes, open send link
	CALL IMPOPL		; No, open a receive link
	SKIPA
NETOPS:	CALL IMPOPS		; Open a send link
	STOR T1,LTIDX,(UNIT)	; Keep the link index
	MOVX IOS,LINKF		; Mark valid link table index
	IORB IOS,NETSTS(UNIT)
	RET

; Send rfc and open link

NETOPB:	CALL NETOPL

; Send rfc

SNDRFC:	TQNE <DEDF>
	 RET
	LOAD T1,ANFHS,(UNIT)	; Get foreign host
	MOVE T2,LSKT(UNIT)	; And local socket
	MOVE T3,FSKT(UNIT)
	LOAD T4,ANBSIZ,(UNIT)	; Byte size
	TRNE T2,1
	JRST IMPSTR
	LOAD T4,ANLNK,(UNIT)
	JRST IMPRTS		; Send control message
; This here is the main fsm routine

DOFSM:	MOVE IOS,NETSTS(UNIT)
	TQNN <DEDF>
	 JRST DOFSMA
	CALL DOFSMA
	LOAD T1,ANFSM,(UNIT)
DOFSMB:	PUSH P,T1
	MOVEI T1,HUNG
	CALL DOFSMA
	LOAD T1,ANFSM,(UNIT)
	POP P,T2
	CAME T1,T2
	 JRST DOFSMB
	RET

DOFSMA:	NCPOFF			; Allow no control messages while here
	MOVEI T2,<2*^D60*^D1000>/CHKINT	; Time out in 2 minutes
	STOR T2,ANCLKS,(UNIT)
	LOAD T2,ANFSM,(UNIT)	; Get old state
	MOVE T4,T2		; Save old state
	LSH T2,1		; Two words per old state
	LDB T3,CBPFSM(T1)	; Get new state
	STOR T3,ANFSM,(UNIT)
	LDB T2,CBAFSM(T1)	; Get action
	CAME T3,T4		; State changed?
	 CALL STCPSI		; GENERATE STATE CHANGE PSI
	MOVE IOS,NETSTS(UNIT)	; Get current status
	CALL @ACTAB(T2)		; Call action routine
	NCPON
	RET

; Generate state change PSI

STCPSI:	SAVET
	LOAD T1,ANPVST,(UNIT)	; Save previous 4 states
	LSH T1,4
	IOR T1,T4
	STOR T1,ANPVST,(UNIT)	; Save previous state
	HRRE T1,NETFRK(UNIT)
	JUMPL T1,R		; No fork for interrupts
	LOAD T2,ANFSPI,(UNIT)	; Get psi channel
	CAIL T2,^D36
	 RET
	EXCH T1,T2
	CALLRET PSIRQ
; Make a socket or find existing one

GETSKT:	TDZA T4,T4
MAKSKT:	SETO T4,
	PUSH P,T4
	PUSH P,T1		; Save foreign host
	PUSH P,T2		; Save foreign socket
	PUSH P,T3		; Save local socket
	MOVE UNIT,T3
	XOR UNIT,T2
	TRNN UNIT,1		; Homosexual?
	JRST MAKSKX		; Yes, go tell Anita
	ROT T3,-4
	MOVS UNIT,T3
	IMULI T3,123431
	XOR UNIT,T3		; Randomize from local socket
	LSH UNIT,-1
	MULI UNIT,NSKT		; Initial probe
	MOVEI T4,NSKT
	SETO T3,
	NCPOFF
	SETSEC UNIT,ANBSEC
MAKSKL:	LOAD T1,ANFSM,(UNIT)	; Get state of this socket
	CAIE T1,FREE
	CAIN T1,DEAD
	JRST MAKSK1
	CAIN T1,CLZW		; WAITING FOR USER TO CLOSE?
	JRST MAKSKN		; YES. DON'T PICK THIS ONE
	MOVE T2,LSKT(UNIT)	; What local socket is this for?
	CAME T2,(P)
	JRST MAKSKN		; Not the one we're after, try next
	SKIPGE -2(P)
	JRST MAKSK6
	LOAD T2,ANFHS,(UNIT)
	MOVE T1,FSKT(UNIT)
	JUMPL T2,[SKIPN -3(P)	; Was getskt called?
		JRST MAKSKN	; Yes, getskt called
		POP P,T3	; Makskt...suceed
		JRST MAKSKF]
	CAMN T2,-2(P)
	CAME T1,-1(P)
	 JRST MAKSKN		; Foreign host or socket doesn't match
	AOS -4(P)		; EVERYTHING MATCHES. SKIP RETURN
	NCPON
	JRST MAKSKV		; NCPON, POP STACK


MAKSK6:	POP P,T3
	SUB P,BHC+3
	MOVE T2,FSKT(UNIT)
	LOAD T1,ANFHS,(UNIT)
	NCPON
	RETSKP

MAKSKN:	SOJLE T4,MAKSKE		; Full, error
	SOS UNIT		; Loop back for next slot
	TRNN UNIT,100000	; Past start of table?
	 JRST MAKSKL		; No, loop some more
	ADDI UNIT,NSKT		; Point to end of table
	JRST MAKSKL
MAKSK1:	SKIPGE T3
	MOVE T3,UNIT		; Save where it's at
	CAIE T1,DEAD
	JRST MAKSKN		; Space keeper, test next
MAKSK5:	SKIPN -3(P)
	JRST MAKSKR
	MOVE UNIT,T3
	SETZM NETHST(UNIT)
	SETZM NETSTS(UNIT)
	SETZM NETBUF(UNIT)
	SETZM NETAWD(UNIT)
	SETZM NETBAL(UNIT)
	SETZM NETBTC(UNIT)
	SETOM NETFRK(UNIT)
	MOVEI T1,CLZD
	STOR T1,ANFSM,(UNIT)	; Set its state to be closed
	POP P,T3
	MOVEM T3,LSKT(UNIT)
MAKSKF:	MOVE T1,-1(P)		; Foreign host
	MOVE T2,LSKT(UNIT)
	TRNE T2,1		; Receive?
	 JRST MAKSKQ
	CALL ASNLNK		; Assign link for that host
	 JRST [	LOAD T1,ANFSM,(UNIT)
		MOVEI T2,FREE
		CAIN T1,CLZD	; Just created?
		STOR T2,ANFSM,(UNIT) ; Yes, delete it
		PUSH P,LSKT(UNIT)
		JRST MAKSKR]	; And fail
MAKSKQ:	POP P,T2		; Common for old and new
	MOVEM T2,FSKT(UNIT)
	POP P,T1
	STOR T1,ANFHS,(UNIT)
	SUB P,BHC+1
	NCPON
	RETSKP

MAKSKE:	JUMPGE T3,MAKSK5
	TDZA T1,T1		; FULL
MAKSKR:	MOVEI T1,4		; NON-EXISTENT
	NCPON
	SKIPA			; RETURN 0 OR FOUR ERROR CODE
MAKSKX:	MOVEI T1,3		; BAD PARAMETERS
	MOVEM T1,-1(P)		; STORE ERROR CODE
MAKSKV:	POP P,T3
	POP P,T2
	POP P,T1
	SUB P,BHC+1
	RET
; Assign link number for this connection

ASNLNK:	SAVET
	MOVEI T4,1(P)		; Where bits will be
	PUSH P,[<1B<FNLINK>-1>_1+1]
	REPEAT NLNKBW-2,<PUSH P,[-1]>
	PUSH P,[-<1B<LLINK-<^D36*<NLNKBW-1>>>>]
	PUSH P,UNIT		; Preserve unit
	PUSH P,T1
	PUTSEC UNIT,ANBSEC
	MOVEI HN,NSKT
ASNLNL:	LOAD T1,ANFSM,(UNIT)
	CAIE T1,FREE
	CAIN T1,DEAD
	 JRST ASNLNN
	LOAD T1,ANFHS,(UNIT)
	CAME T1,0(P)		; Check all connection to this host
	 JRST ASNLNN		; Get next
	MOVE T1,LSKT(UNIT)
	TRNE T1,1		; Only receive connections
	 JRST ASNLNN
	LOAD T1,ANLNK,(UNIT)	; Get link assigned
	IDIVI T1,^D36		; Separate word and bit
	MOVE T2,BITS(T2)	; Get the bit
	ADD T1,T4
	ANDCAM T2,0(T1)		; Clear bits for links in use
ASNLNN:	AOS UNIT
	SOJG HN,ASNLNL		; Loop thru all connections
	HRLI T4,-NLNKBW		; Prepare to look at all bits
	SETZ T3,
ASNLNC:	MOVE T1,0(T4)
	JFFO T1,ASNLNF
	ADDI T3,^D36
	AOBJN T4,ASNLNC
	POP P,T1		; Failed.  Must clean stack before returning
	POP P,UNIT
	SUB P,BHC+NLNKBW
	RET

ASNLNF:	ADD T2,T3
	POP P,T1
	POP P,UNIT
	STOR T2,ANLNK,(UNIT)
	SUB P,BHC+NLNKBW
	RETSKP
; Do a listen (openf for file with no foreign host/socket)

LISTEN:	CALL HSTCHK
	RET
	PUSH P,T4		; Save byte size
	CALL MAKSKT		; Make a socket
	 JRST [	POP P,T4
		MOVEI T1,OPNX10
		RET]		; No room
	MOVEI T1,LISN
	JRST CONNE1

; Do a connect (openf for file with foreign host/socket specified)

CONNEC:	CALL HSTCHK
	RET
	PUSH P,T4		; Save byte size
	CALL MAKSKT		; Make a socket or find existing one
	 JRST [	POP P,T4
		MOVEI T1,OPNX10
		RET]		; No room
	MOVEI T1,CONN
CONNE1:	NCPOFF
	LOAD T2,ANFSM,(UNIT)
	CAIN T2,CLZD		; Received any rfc here?
	 JRST CONNE2		; No
	CAIN T2,PNDG		; Same question
	 JRST CONNE3		; Yes
	MOVEI T1,OPNX9		; Already in use
	POP P,T4
	NCPON
	RET

CONNE2:	MOVX T4,PROGF
	IORM T4,NETSTS(UNIT)	; Mark as attached to program
	NCPON
	POP P,T4		; My choice of byte size
	STOR T4,ANBSIZ,(UNIT)	; Set byte size
	CALL DOFSM		; Send rfc etc
	RETSKP

CONNE3:	TRNE T3,1		; Are we sender?
	 JRST CONNE2		; Also our choice
	LOAD T4,ANBSIZ,(UNIT)	; Get his byte size
	CAMN T4,0(P)		; Does byte size agree?
	 JRST CONNE2		; Yes, same as if my choice
	NCPON
	MOVEI T1,HUNG		; Flush his connection attempt
	CALL DOFSM
	POP P,T4
	MOVEI T1,OPNX22		; Bad byte size error
	RET
;;; HSTCHK - Check if host is available
;;; Called with T1 - 32 bit host number
;;; Returns+1 if host cannot be reached, error number in T1
;;; +2 if successful
;;;

HSTCHK::
	JUMPL T1,RSKP		; ALWAYS OK IF LISTEN
	CALL HSTCK0		; CHECK THE HOST
	 JRST [	MOVE T1,0	; Get error number
		RET]		; AND ERROR RETURN
	JRST RSKP		; UP AND READY

;;; 
;;; HSTCK0 - Work routine for above, returns +2 if host is up,
;;; else +1 with error number in 0
;;;
HSTCK0:	SAVET
	SAVP1			; (STS)
	MOVE T2,T1		; Save host number here

	CALL	FNDNCT		; Check if that net is up
	 JRST	[ MOVEI 0,OPNX19	; Down, can't do anything
		  RET]		; Return

	LOAD T1,NTTYP,(STS)	; Get network type
	CAIE T1,NT.NCP		; NCP traffic work?
	 JRST	[ MOVEI 0,OPNX19 	; No
		  RET]
REPEAT 0,<
	MOVE T1,NTNET(P1)	; Get network number for this interface
	CAIN T1,^D10		; ARPANET?
	 JRST [	MOVE T1,CAPMSK	; Get possible capabilities
		TXNE T1,SC%WHL+SC%OPR+SC%ANA ; WHEEL, OPER, or ARPA
		 JRST .+1
		MOVEI 0,WHELX1	; Insufficent capabilities
		RET]
>

	MOVE T1,T2		; Get back to normal AC
	LDB T2,[POINT 8,T1,19]
	CAIL T2,FKHOST
	 JRST HSTCKX		; Fake hosts are down
	CALL HSTHSH		; Get the host index
	 JRST RSKP		; No room, try anyway
	SKIPGE HSTSTS(T2)	; Up?
	 RETSKP			; Yes
	PUSH P,T2
	CALL IMSRST		; Reset him
	POP P,T2
	MOVEI T3,^D10		; Wait 5 sec
HSTCK1:	MOVEI T1,^D500		; Wait
	DISMS
	SKIPGE HSTSTS(T2)	; Up?
	 RETSKP
	SOJG T3,HSTCK1
HSTCKX:	MOVEI 0,OPNX20		; Host is down
	RET

; Routines to call when control messages are received

; Receive cls
; Reccls(fhost,fskt,lskt)--nil

RECCLS::CALL GETSKT		; Get the socket entry
	 JRST NCPERR
RECCL1:	MOVE T2,LSKT(UNIT)
	TRNN T2,1
	SKIPA T1,[CLSR]
	MOVEI T1,CLSS
	CALLRET DOFSM

; RECEIVED INCORRECT MESSAGE
; REPLY WITH ERR

NCPERR:	SAVET
	SAVEQ
	MOVE T3,I8COP		; GET LAST OP CODE
	MOVE HN,[I8CAL,,T4]	; COMPLAIN ABOUT LAST CONTROL MESSAGE
	BLT HN,HN
	CALLRET IMPERR

; Receive str
; Recstr(fhost,fskt,lskt)--nil

RECSTR::PUSH P,T4		; Save byte size
RCSTR0:	CALL MAKSKT
	 JRST [	POP P,T4
		JRST NCPERR]
	MOVE T4,0(P)
	CALL CHKSKT		; MAKE SURE THIS SOCKET NOT IN USE
	 JRST RCSTR0		; IT WAS. DELETED. NOW TRY AGAIN.
	LOAD T1,ANFSM,(UNIT)	; What is state of this connection
	CAIE T1,CLZD		; If not clzd
	 JRST [	LOAD T4,ANBSIZ,(UNIT) ; Then get user's byte size
		CAMN T4,0(P)	; If not the same
		JRST .+1
		MOVEI T1,RRFB	; RECEIVED BAD BYTE SIZE
		CALL DOFSM
		MOVX T1,ERRB
		IORM T1,NETSTS(UNIT)
		POP P,T4
		RET]
	POP P,T4
	STOR T4,ANBSIZ,(UNIT)
	MOVEI T1,RRFC
	CALL DOFSM
	MOVE T1,UNIT
	LOAD T2,ANLNK,(UNIT)
	RET

CHKSKT:	SAVET
	LOAD T1,ANFSM,(UNIT)	; GET STATE
	CAIE T1,RFCS		; STATES WHERE RFC IS EXPECTED
	CAIN T1,CLZD
	 RETSKP
	CAIN T1,LSNG
	 RETSKP
	CALLRET SK2DWN		; KILL THE OLD ONE

CHKLNK:	SAVET
	STKVAR<CHKLLK,CHKLHS>
	MOVEM T1,CHKLHS
	MOVEM T4,CHKLLK
	PUTSEC UNIT,ANBSEC
	MOVEI HN,NSKT
CHKLK1:	LOAD T2,ANLNK,(UNIT)	; GET THE LINK
	LOAD T3,ANFHS,(UNIT)	; AND HOST
	CAMN T2,CHKLLK
	CAME T3,CHKLHS
	 JRST CHKLK2
	MOVE T2,LSKT(UNIT)
	TRNN T2,1
	 JRST CHKLK2		; SKIP SEND CONNECTIONS
	LOAD T2,ANFSM,(UNIT)	; LINK-HOST MATCHES. GET STATE
	CAIE T2,DEAD
	CAIN T2,FREE
	 JRST CHKLK2
	CAIE T2,CLZD
	CAIN T2,RFCS
	 JRST CHKLK2
	CAIE T2,LSNG
	CAIN T2,CLZW
	 JRST CHKLK2
	CALL SK2DWN
CHKLK2:	AOS UNIT		; Increment socket pointer
	SOJG HN,CHKLK1
	RET
; Receive rts
; Recrts(fhost,fskt,lskt,link)

RECRTS::CALL CHKLNK		; CHECK AND DELETE ANY MATCHING LINKS
	PUSH P,T4		; SAVE LINK
	CALL MAKSKT		; MAKE SOCKET TABLE ENTRY
	 JRST [	POP P,T4	; FAILED, SEND ERR
		JRST NCPERR]
	POP P,T4		; RESTORE LINK
	CALL CHKSKT		; MAKE SURE NO DUPLICATES
	 JRST RECRTS		; PREVIOUS CONNECTION CLOSED. TRY AGAIN
	STOR T4,ANLNK,(UNIT)
	MOVEI T1,RRFC
	CALLRET DOFSM

; Receive rfnm

RCFRFN::MOVEI T1,RRFN
	CALLRET DOFSM

; Receive ins/inr

RECINR::
RECINS::LOAD T2,ANINPI,(UNIT)
	LOAD T1,ANFSM,(UNIT)
	CAIGE T2,^D36		; RETURN IF CHANNEL IS 77 OCTAL
	CAIE T1,OPND
	 RET
	HRRZ T1,NETBUF(UNIT)
	SKIPE T1
	CAIL T1,1000
	TRNA
	 RET
	HRRE T1,NETFRK(UNIT)
	JUMPL T1,R
	EXCH T1,T2
	CALLRET PSIRQ

; INITIATE SERVICE INTERRUPTION (HOST DEAD)

SVCINT::MOVX IOS,SVCIF
	IORB IOS,NETSTS(UNIT)
	CALLRET STCPSI		; GENERATE STATE CHANGE PSI

; TERMINATE SERVICE INTERRUPTION

SVCRST::MOVX IOS,SVCIF
	ANDCAB IOS,NETSTS(UNIT)
	CALLRET STCPSI
;;; Receive reset message

RECRST::CALL NETHDN
	JRST IMPRRP

;;; Kill all connection -- net is down
;;; P1 -- NCT for the network
NETDWN::MOVEI HN,NSKT
	PUTSEC UNIT,ANBSEC	; Place pointer to right section
NETDWL:	MOVE T1,NETHST(UNIT)	; Get the host for this one
	CALL NETCMP		; Same net?
	 SKIPA			; No
	CALL SKTDWN
	AOS UNIT		; Point to next
	SOJG HN,NETDWL		; Loop
	RET			; And return

;;; Periodic check of all connections for time-out

CONNCK::PUTSEC UNIT,ANBSEC
	MOVEI HN,NSKT
CONCKL:	LOAD T1,ANFSM,(UNIT)	;Get connection state
	CAIE T1,DEAD		; Is this an active connection?
	CAIN T1,FREE		; ?
	 JRST CONCKN		; No, try next
	MOVX T1,DEDF		; is it alive?
	TDNE T1,NETSTS(UNIT)	; ?
	 JRST CONCK1		; No, hang it
	LOAD T2,ANCLKS,(UNIT)	; else count down clock
	SOS T2			; ..
	STOR T2,ANCLKS,(UNIT)	; ..
	JUMPG T2,CONCKN		; and on to next if it hasn't counted down

CONCK1:	MOVEI T1,HUNG
	CALL DOFSM
CONCKN:	AOS UNIT		; INCREMENT POINTER
	SOJG HN,CONCKL
	MOVEI T1,CHKINT		; Get check interval
	ADD T1,TODCLK
	MOVEM T1,NETTIM
;3032	RET
	callret ntdset		;3032 fix up IMPTIM and return with todclk
; Host has died

NETHDN::PUTSEC UNIT,ANBSEC
	PUSH P,T2
	MOVEI T2,NSKT
	PUSH P,T1
NETHDL:	LOAD T1,ANFSM,(UNIT)
	CAIE T1,FREE
	CAIN T1,DEAD
	JRST NETHDX
	LOAD T1,ANFHS,(UNIT)
	CAMN T1,(P)
	CALL SKTDWN
NETHDX:	AOS UNIT		; Increment pointer
	SOJG T2,NETHDL		; And loop through all
	POP P,T1
	POP P,T2
	RET

SK2DWN::HRRZ T2,NETBUF(UNIT)
	CALL NVTCHK		; AN NVT?
	 JRST SKTDWN		; NO, TREAT NORMALLY
	PUSH P,UNIT
	PUSH P,T2
	CALL SKTDWN
	MOVE T2,0(P)
	CALL NVTIPU		;GET INPUT UNIT
	 TRNA			;NO UNITS FOR THIS LINE
	CALL SKTDWN		; CLOSE THE OTHER HALF
	POP P,T2		;GET ADDRESS OF DYNAMIC DATA FOR TTY
	CALL ULKTTY		;UNLOCK DATA BASE
	POP P,UNIT
	RET

SKTDWN:	LOAD T1,ANFSM,(UNIT)	; GET STATE
	CAIN T1,LSNG		; IF LSNG
	 RET			; IGNORE
	MOVX T2,ERRB!DEDF
	IORM T2,NETSTS(UNIT)
	CAIE T1,CLSW		; IF WAITING FOR CLOSE,
	CAIN T1,CLW1
	CALL SKTDW2		; PRETEND ONE HAPPENED.
	CAIE T1,RFCR
	CAIN T1,OPND		; If opnd
SKTDW2:	CALL RECCL1		; Simulate receipt of cls
	MOVEI T1,HUNG
	CALLRET DOFSM
;;;
;;; The following routines simulate various NCP Getab tables
;;; (since the data is now in ANBSEC they can't be accesed directly
;;;

;;; GNTRDY - Get the NETRDY table
;;; attempts to find the data from the NCT for the primary network
;;;
GNTRDY::
	MOVE T1,DEFADR		; get primary address
	CALL NETNCT		; Find an NCT for it
	 RETERR()		; Error
	MOVE T1,@GNTAB(T2)	; get an entry
	RET			; And return

;;; Indirect table for deriving the data
GNTAB:	IFIW!<STS>B17+NTRDY	; NETRDY From the NCT
	IFIW!<STS>B17+NETON	; As NETON
	IFIW+NETENT		; NETENT has its own cell
	IFIW+BHC		; NCPUPT (wrong data but)
	IFIW+IGDMSG		; Last Imp going down message
	IFIW!<STS>B17+NTXDNT	; Last ready line drop
	IFIW!<STS>B17+NTXUPT	; last ready line up time
	IFIW+IGDTIM		; Last imp going down message time

;;; GHTSNM - get a word form the HSTNAM Table
;;;
GHSTNM::
	SETSEC T2,MNTSEC	; Point to right sction
	MOVE T1,HSTNAM(T2)	; get entry
	RET

;;; GNTLSK,GNTFSK,GNTBAL,GNTSTS,GNTBUF,GNTBTC
;;; Get entries from various NCP tables
GNTLSK::
	SETSEC T2,ANBSEC
	MOVE T1,LSKT(T2)
	RET

;1017 Begin addition
GNTHST::
	SETSEC T2,ANBSEC
	MOVE T1,NETHST(T2)
	RET
;1017 End addition

GNTFSK::
	SETSEC T1,ANBSEC
	MOVE T1,FSKT(T2)
	RET

GNTBAL::
	SETSEC T2,ANBSEC
	MOVE T1,NETBAL(T2)
	RET

GNTSTS::
	SETSEC T2,ANBSEC
	MOVE T1,NETSTS(T2)
	RET

GNTBUF::
	SETSEC T2,ANBSEC
	MOVE T1,NETBUF(T2)
	RET

GNTBTC::
	SETSEC T2,ANBSEC
	MOVE T1,NETBTC(T2)
	RET

;;; GIMLT1-4, Get from the link tables IMPLT1-4
GIMLT1::
	SETSEC T2,ANBSEC
	MOVE T1,IMPLT1(T2)
	RET

GIMLT2::
	SETSEC T2,ANBSEC
	MOVE T1,IMPLT2(T2)
	RET

GIMLT3::
	SETSEC T2,ANBSEC
	MOVE T1,IMPLT3(T2)
	RET

GIMLT4::
	SETSEC T2,ANBSEC
	MOVE T1,IMPLT4(T2)
	RET


	TNXEND
	END