;-*-MIDAS-*-

TITLE	BOJ JOB MLDEV, Uses MLSLV on other system

VERSIO==.FNAM2

ICPSOC==123			;This is the Postel-approved number

A=1
B=2
C=3
D=4
E=5
T=6
TT=7
INT=10	;FLAG FOR INTERRUPT, -1 INT HAPPENED
H=11
J=12
Q=13
W=14
P=15
IOP=16	;AOBJN POINTER FOR I/O ROUTINES
U=17	;CLOBBERED AT INTERRUPT LEVEL

CH==,,-1	;BIT TYPEOUT MODE MASK FOR I/O CHANNEL NAMES.

CHBOJ==1
CHFILE==3
CHNETI==4
CHNETO==5

IOCEOF==8	;IOCERROR CODE FOR EOF.

DEFINE SYSCAL NAME,ARGS
	.CALL [ SETZ ? SIXBIT/NAME/ ? ARGS ((SETZ))]
TERMIN

LOC	42
	JSR TSINT
LOC	77
SIXBIT /MLDEV/
RDEVN:	BLOCK 4
ACCP:	0
DIRECTN:0
CRUNAM:	0
CRJNAM:	0
FILLEN:	0	;FILE LENGTH, IN BYTES OF SIZE NOW OPEN IN,
		;OR -1 => FILLEN, FILBLN AND FILBSZ NOT KNOWN.
BYTSIZ:	0	;BYTE SIZE OPEN IN.  IF WE CAN'T GET THIS FROM
		;A FILLEN, WE GUESS AT IT FROM OPEN MODE.
FILBLN:	0	;FILE LENGTH, IN BYTES OF SIZE WRITTEN IN.
FILBSZ:	0	;BYTE SIZE FILE WRITTEN IN.
FILDTP:	0	;-1 => WE KNOW THE CREATION DATE OF THIS FILE.
FILDAT:	0	;FILE CREATION DATE (IF KNOWN).


PAT:
PATCH:	BLOCK 100
PATCHE:	-1
DEBUG:	0

;START HERE.
GO:	MOVE P,[-LPDLL-1,,PDL-1]
	.SUSET [.SMASK,,[%PIIOC+%PIILO+%PIMPV+%PIPDL]]
	.OPEN CHBOJ,[27,,'BOJ]
	 .VALUE
	SYSCAL RFNAME,[
		1000,,CHBOJ
		2000,,0
		2000,,CRUNAM
		2000,,CRJNAM]
	 JFCL
	.CALL JBGT	;GET INFO FOR ICP
	 .VALUE
	MOVE A,JBCOP
	TLNE A,60000	;IF HE ALREADY PCLSR'D, GIVE UP, SINCE HE WILL GIVE UP ON US
	 JRST DIE	;SINCE WE DID A JOBGET AND SAW THAT FACT.
	ANDI A,-1	;NOW .VALUE IF OPCODE IS .IOT - SHOULDN'T HAPPEN, 
	CAIN A,1	;BUT DID DUE TO A BUG.
	 .VALUE
	MOVEI A,HSTPAG
	MOVEI B,CHFILE
	PUSHJ P,NETWRK"HSTMAP
	 .VALUE
	MOVE A,JBCDEV	;GET "DEVICE"
	MOVEM A,RDEVN	;REMEMBER IT TO RETURN FOR .RCHST'S.
IRPS Y,,AI ML DM MC MX MD KL KS DB
	CAMN A,[SIXBIT /X!Y/]
	 MOVE A,[SIXBIT /Y/]	;ALLOW "XAI", ETC., FOR EXPERIMENTAL VERSIONS OF "AI", ETC.
	CAMN A,[SIXBIT /DIR!Y/]
	 MOVE A,[SIXBIT /Y!DIR/]
TERMIN			;DEVICES SUCH AS "DIRML" ARE REALLY HANDLED AS "MLDIR".
			;THAT'S BECAUSE IT'S FASTER THAT WAY.  DIR DEVICE MUST READ BOTH
			;IMAGE AND ASCII DIRECTORIES.
	MOVEM A,JBCDEV
	LDB A,[301400,,JBCDEV]	;MIGHT BE DMAR1, ETC.
IRP X,,[DM,AI,ML,MC,MX,MD,KL,KS,DB]
	CAIN A,(SIXBIT / X/)	;**** IF ANY NON 2-CHAR HOST NAME EVER EXISTS,
	 JRST GOTHST		;THIS BARFUCIOUS KLUDGE WILL HAVE TO BE FIXED UP.
TERMIN
	MOVS A,JBCDEV
	CAIN A,'XGP	;XGP THROUGH THE NET TO AI FROM ML/MC/DM
	 JRST [	MOVS A,[SIXBIT/AIXGP/]
		MOVSM A,JBCDEV
		MOVEI A,'AI
		JRST GOTHST]
	CAIN A,'GLP		;GOULD THROUGH THE NET TO MX
	 JRST [	MOVS A,[SIXBIT/MXGLP/]
		MOVSM A,JBCDEV
		MOVEI A,'MX
		JRST GOTHST]
	CAIN A,'DVR	;DVR THROUGH THE NET TO MC FROM AI/ML/DM
	 JRST [	MOVS A,[SIXBIT/MCDVR/]
		MOVSM A,JBCDEV
		MOVEI A,'MC
		JRST GOTHST]
	CAIN A,'DVS	;DVS THROUGH THE NET TO MC FROM ML/DM
	 JRST [	MOVS A,[SIXBIT/MCDVS/]
		MOVSM A,JBCDEV
		MOVEI A,'MC
		JRST GOTHST]
	CAIN A,'TPL	;TPL THROUGH THE NETWORK FOR MC
	 JRST [	MOVS A,[SIXBIT/MLTPL/]
		MOVSM A,JBCDEV
		LDB B,[000400,,JBCOP]
		CAIN B,2
		 JRST TPLLK	;TRYING TO LINK ON TPL: LOSES
		LDB B,[410100,,JBCOP]	;0 => INPUT  1 => OUTPUT
		CAIN B,1		;SKIP IF E.G. READING DIRECTORY
		 JSP A,[MOVSI B,(SIXBIT/>/)	;ALSO SKIP IF DELETING
			MOVEM B,JBCFN1
			.SUSET [.RUNAME,,JBCFN2]
			JRST (A) ]
		MOVEI A,'ML		;USE THE MATHLAB LINE PRINTER
		JRST GOTHST ]
;HOST NOT RECOGNIZED
NSD:	MOVSI A,%ENSDV
	JRST NOGO2

;A CONTAINS SIXBIT HOST, RIGHT-JUSTIFIED
GOTHST:	MOVE B,[440700,,BUF]		;Make ASCIZ host name
GOTHS1:	LDB T,[360600,,A]
	JUMPE T,GOTHS2
	ADDI T,40
	IDPB T,B
GOTHS2:	LSH A,6
	JUMPN A,GOTHS1
	IDPB A,B
	MOVEI A,BUF
	PUSHJ P,NETWRK"HSTLOOK
	 .VALUE				;Host not in host table?
	MOVEM A,HOSTN'			;Host number
	MOVEM TT,NETWRK'		;Network number
	PUSHJ P,NETWRK"HSTUNMAP		;Don't need host table any more
	 .VALUE
	LDB A,[3000,,JBCDEV]		;Right-hand four characters
	JUMPN A,.+2
	 MOVE A,[SIXBIT /  DSK/]
	LSH A,14
	MOVEM A,JBCDEV
	MOVEM A,FDEVN
	SETOM JBGTN'	;FLAG INITIAL JOBGET DONE
	MOVE A,NETWRK
	CAMN A,[NW%CHS]
	 JRST CHAICP
	CAMN A,[NW%ARP]
	 JRST TCPICP
	.VALUE		;How did we get an unknown network?

CHAICP:	MOVEI A,CHNETI
	MOVE B,HOSTN
	MOVEI C,[ASCIZ/MLDEV/]
	MOVEI D,8
	PUSHJ P,NETWRK"CHACON
	 JRST NOGO			;Can't connect
	JRST ICP1

TCPICP:	MOVEI A,CHNETI	
	MOVE B,HOSTN
	MOVEI C,ICPSOC
	PUSHJ P,NETWRK"TCPCON
	 JRST NOGO		;Can't connect
	JRST ICP1

;HERE FOR VARIOUS ERRORS THAT WE DETECT BEFORE FINISHING THE CONNECTION.
TPLLK:	SKIPA A,[%ELCDV,,]
NOGO:	MOVSI A,%ENADV	;DEVICE NOT AVAILABLE.
NOGO2:	MOVEM A,ERRCOD
	MOVEI C,20.
NOGO1:	.CALL JBGT
	 .VALUE		;JOBGET ON INITIAL IS NOT SUPPOSED TO FAIL.
	MOVE A,JBCOP
	TLNE A,60000	;HE CLOSED US => WE CAN STOP NOW.
	 JRST REUSE
	.CALL JBRT3	;KEEP TRYING TO RETURN THIS ERROR, IN CASE HE PCLSR'S AND COMES BACK.
	 SOJG C,[MOVEI B,1 ? .SLEEP B, ? JRST NOGO1]
	JRST REUSE

ICP1:	SETZM INT
	SETZM NTICIN
	.SUSET [.SMSK2,,[1_CHBOJ+1_CHNETI]]
;COME HERE WHEN REUSED BY A SECOND CREATOR.
REUSE1:	SETZM CALING	;WE'RE NOT AWAITING A REPLY FOR A .CALL
	SETZM CALACK
	SETZM RNMWOS	;OR A RENMWO
	SETZM MLINKS	;OR A MLINK.
	SETZM ACCACK	;OR A .ACCESS
	SETZM ACCP	;WE ARE AT THE BEGINNING OF THE FILE.
	SETZM RETOOU	;WE AREN'T INSIDE AN IOT
	SETZM RETOIN
	SETZM FILOPN	;NO FILE OPEN.
	SETOM JBINT	;DO ONE JOBGET NOW IN CASE ALREADY CLEARED THE INTERRUPT.
	JRST GOLOOP

;ANY CHANGES IN THIS SHOULD BE REPORTED TO INFO-MLDEV@AI AND 
;UPDATED IN MLSLV ALSO.  NEW VERSION MUST THEN BE UPDATED
;SIMULTANEOUSLY ON ALL ITS'S AND ON MULTICS.

;[This comment inoperative since NCP has been terminated]
;ICP IS TO SOCKET 197. IF DOING MOSTLY INPUT, 199. IF MOSTLY OUTPUT

;COMMAND FORMAT:	TO SLAVE
;AOBJN POINTER (RH = COMMAND CODE)
;BLOCK OF ARGUMENTS

;COMMAND CODES:
COPENI==1	;OPEN FOR INPUT
		;ARG1:	DEVICE
		;ARG2:	FN1
		;ARG3:	FN2
		;ARG4:	SNAME
		;ARG5:	OPEN MODE

COPENO==2	;OPEN FOR OUTPUT
		;ARG1:	DEVICE
		;ARG2:	FN1
		;ARG3:	FN2
		;ARG4:	SNAME
		;ARG5:	OPEN MODE

CDATA==3	;WRITE DATA (WD COUNT INCLUDES DATA WDS AND BYTE COUNT WD).
		;# OF BYTES OF DATA
		;DATA, PACKED ILDB-STYLE INTO AT MOST 200 WORDS.

CALLOC==4	;READ ALLOCATE
		;ARG:	ALLOCATION IN BYTES

CICLOS==5	;INPUT CLOSE
		;ARG:	IGNORED

COCLOS==6	;OUTPUT CLOSE
		;ARG:	IGNORED

CFDELE==7	;.FDELE (DELETE OR RENAME)
		;ARG1:  DEV
		;ARG2:	FN1
		;ARG3:	FN2
		;ARG4:	0 OR NEW FN1
		;ARG5:	0 OR NEW FN2
		;ARG6:	SNAME

CRNMWO==10	;.FDELE (RENAME WHILE OPEN)
		;ARG1:	NEW FN1
		;ARG2:	NEW FN2

CNOOP=11	;NOOP
		;ARG:	ECHOED BY THE NOOP REPLY

CACCES==12	;ACCESS
		;ARG1: TRANSACTION NUMBER.
		;ARG2: ACCESS POINTER
		;ARG3: NEW ALLOCATION

CSYSCL==13	;RANDOM SYSTEM CALL. 11 (DECIMAL) ARGUMENTS.
		;ARG1: SYSTEM CALL NAME IN SIXBIT
		;ARG2: FLAGS (CONTROL-BIT ARGUMENT)
		;ARG3: NUMBER OF FOLLOWING ARGS THAT HAVE SIGNIFICANCE
		;ARG4: 1ST ARG TO SYSTEM CALL
		;...
		;ARG11: 8TH ARG TO SYSTEM CALL

CREUSE==14	;REINITIALIZE YOURSELF, BECAUSE WE ARE ABOUT TO BE REUSED
		;BY A NEW CREATOR FOR A NEW FILE.

CLOGIN==15	;LOGIN USER (RECORD XUNAME FOR SYS: DELETION PURPOSES, ETC.)
		;ARG1: XUNAME (USED AS "TERMINAL NAME" IN LOGIN CALL)

CMAX==16	;LARGEST COMMAND NUMBER, PLUS ONE.

;REPLIES FROM SLAVE START WITH AN AOBJN POINTER (RH = REPLY CODE)
;FOLLOWED BY A BLOCK OF ARGUMENTS

R==,,-1		;REPLY CODES:

RDATA==1	;INPUT DATA (WD COUNT INCLUDES DATA WDS AND BYTE COUNT WD).
		;# OF BYTES OF DATA
		;DATA, PACKED ILDB-STYLE INTO WORDS.
		;NOTE:  SLAVE MUST ALWAYS SEND FULLY POPULATED WORDS
		;EXCEPT WHEN EOF IS REACHED.

ROPENI==2	;INPUT OPEN STATUS. 1 OR 11 ARGUMENTS.
		;ARG1: -1 => SUCCEEDED; >0 => OPEN LOSS NUMBER
		;ARG2-ARG11 PRESENT ONLY IF ARG1 IS -1.
		 ;ARG2: REAL DEVICE NAME (USUALLY SIXBIT/DSK/)
		 ;ARG3: REAL FN1
		 ;ARG4: REAL FN2
		 ;ARG5: REAL SNAME
		 ;ARG6: FILE LENGTH
		 ;ARG7: BYTE SIZE OPEN IN
		 ;ARG8: FILE LENGTH IN BYTE SIZE WRITTEN IN
		 ;ARG9: BYTE SIZE WRITTEN IN
		 ;ARG10: FILDTP - -1 IF "RFDATE" WINS ON THIS FILE
		 ;ARG11: CREATION DATE (IF "RFDATE" WINS).

ROPENO==3	;OUTPUT OPEN STATUS. 1 OR 11 ARGUMENTS.
		;ARG1: -1 => SUCCEEDED; >0 => OPEN LOSS NUMBER
		;ARG2-ARG11 PRESENT ONLY IF ARG1 IS -1.
		 ;ARG2: REAL DEVICE NAME
		 ;ARG3: REAL FN1
		 ;ARG4: REAL FN2
		 ;ARG5: REAL SNAME
		 ;ARG6: FILE LENGTH (-1 => FILLEN FAILS ON THIS DEVICE)
		 ;ARG7: BYTE SIZE OPEN IN
		 ;ARG8: FILE LENGTH IN BYTE SIZE WRITTEN IN
		 ;ARG9: BYTE SIZE WRITTEN IN
		 ;ARG10: FILDTP - -1 IF "RFDATE" WINS ON THIS FILE
		 ;ARG11: CREATION DATE (IF "RFDATE" WINS).

REOF==4		;EOF ON INPUT
		;ARG:	IGNORED

RFDELE==5	;.FDELE STATUS. 1ST ARGUMENT:
		;RH:	-1 => SUCCEEDED
		;	 >=0 => FAILURE CODE
		;LH:	-1 => DELETE OR RENAME
		;	 0 => RENAME WHILE OPEN
		;IF RENAME WHILE OPEN CALL SUCCEEDED, THERE ARE 4 MORE ARGS:
		 ;ARG2: REAL DEVICE NAME
		 ;ARG3: REAL FN1 (AS RENAMED)
		 ;ARG4: REAL FN2
		 ;ARG5: REAL SNAME

RNOOP==6	;NOOP REPLY
		;ARG:	ECHO ARG SENT BY NOOP COMMAND

RACCES==7	;ACKNOWLEDGE ACCESS
		;ARG: TRANSACTION NUMBER FROM CACCES.

RSYSCL==10	;RESPOND TO SYSTEM CALL. 9 ARGUMENTS.
		;ARG1: <ERROR CODE OR 0>,,<# OF TIMES CALL SKIPPED>
		;ARG2: 1ST VALUE FROM SYSTEM CALL.
		;...
		;ARG9: 8TH VALUE FROM SYSTEM CALL.

RICLOS==11	;RESPOND TO INPUT-CLOSE.

ROCLOS==12	;RESPOND TO OUTPUT CLOSE.

RIOC==13	;REFLECT AN IOC ERROR
		;ARG:	IOC ERROR CODE, RIGHT-JUSTIFIED IN WORD.

RREUSE==14	;ACKNOWLEDGE A CREUSE.  ARG IS MEANINGLESS (NONE RETURNED).

RLOGIN==15	;ACKNOWLEDGE A LOGIN.  ARG IS MEANINGLESS (NONE RETURNED).

RMAX==16	;LAST REPLY CODE + 1.

GOL:	SKIPL INT	;THERE ARE NO INTERRUPTS => WAIT QUIETLY.
	 .HANG
GOLOOP:	SETZM INT	;HERE TO SERVICE ANY INTERRUPTS THERE ARE.
	SKIPGE NTICIN	;NET INTS HAVE PRIORITY.
	 JRST NTINT
	AOSN RETOOU	;NO REPLIES => IF WE ARE INSIDE AN OUTPUT IOT,
	 JRST JIOT	;XFER ANOTHER BATCH OF STUFF TO THE NET.
	SKIPL JBINT
	 JRST GOL
	SETZM JBINT
TRYOV:	SETZM RETOIN
	AOSG JBGTN	;-1 IF INITIAL, DONT DO AGAIN
	 JRST TRYOV1
	.CALL JBGT
	 JRST GOLOOP
TRYOV1:	MOVE B,JBCOP
	TLNE B,60000
	 JRST JCLS
	LDB A,[000400,,JBCOP]
	TLNE B,200	;IF THIS IS A RETRY OF A CALL THAT PCLSR'ED,
	 JRST RETRY	;GIVE IT THE SAME JOBRET WE TRIED TO GIVE LAST TIME.
RETRYR:	SETZM CALING	;NO LONGER WAITING FOR STATUS OF .CALL OR RENMWO SINCE WE
	SETZM MLINKS
	SETZM RNMWOS	;INTERRUPTED OUT OF IT AND DID SOMETHING ELSE.  TOO BAD.
	SETZM PCLSRD	;WE CAN'T MANAGE TO NHANDLE A RETRY AFTER ANYTHING ELSE HAPPENS.
	CAILE A,7
	 JRST JSYSCL	; HANDLE A .CALL
	JRST @DISP(A)

DISP:	JOPEN
	JIOT
	JMLINK
	JRESET
	JRCH
	JACC
	JFDEL1
	JRNMWO

;HERE WHEN CREATOR GIVES US A SYSTEM CALL AND SAYS IT'S A RETRY.
RETRY:	SKIPL CALING	;IF HE'S RETRYING THE SAME SYSTEM CALL WHOSE REPLY WE ARE
	 JRST RETRY1	;NOW WAITING FOR, KEEP WAITING.
	CAIE A,10
	 JRST RETRY1
	SKIPE CALACK	;IF ALREADY ACK'D, SEND CALL AGAIN SO WE GET THE ACK AGAIN
	 JRST GOLOOP	;SO THAT WE CAN RETURN THE CALL'S VALUES.
RETRY1:	SKIPL RNMWOS
	 JRST RETRY2
	CAIN A,7
	 JRST GOLOOP
RETRY2:	AOSE PCLSRD	;IF WE HADN'T SEEN THE SYSTEM CALL THE FIRST TIME,
	 JRST RETRYR	;TREAT IT AS NEW.
	MOVE B,LJBRTA	;IF WE FINISHED HANDLING IT AND OUR JOBRET FAILED,
	JRST -2(B)	;GIVE HIM THE SAME JOBRET AGAIN.

PCLSR:	POP P,LJBRTA	;FOLLOW EVERY JOBRET WITH A PUSHJ P,PCLSR.
PCLSR1:	SETOM PCLSRD	;A FAILING JOBRET INDICATES THAT CREATOR WAS PCLSRD AND WE SHOULD
	SETOM JBINT	;EXPECT HIM TO RETRY HIS SYSTEM CALL.  WE MUST SET JBINT NOW
	JRST GOLOOP	;BECAUSE COMING BACK IN MIGHT NOT SET THE INTERRUPT BIT.

PCL==PUSHJ P,PCLSR

LJBRTA:	0		;2 PLUS ADDRESS OF LAST FAILING JOBRET.
PCLSRD:	0		;-1 => OUR LAST JOBRET FAILED, SO EXPECT A RESTARTED SYSTEM CALL.

JRESET:
JSTS:	.CALL JBRTL
	 PCL
	JRST GOLOOP

JCLS:	HRROI B,CICLOS
	MOVE IOP,[-2,,B]
	PUSHJ P,NETOFR
	SETOM SNTCLS	;WE MUSTN'T DIE TILL WE RECEIVE A REPLY FOR THE CICLOS.
	JRST REUSE

JSACC:	MOVE A,JBCA2	;ACCESS POINTER FOR SYMBOLIC CALL ACCESS
	MOVEM A,JBCWD1
	PUSHJ P,JACC1
	.CALL JBRT1
	 PCL
	JRST GOLOOP

JACC:	PUSHJ P,JACC1
	JRST JSTS

JACC1:	HRROI IOP,[-3,,CACCES]	;HANDLE .ACCESS
	PUSHJ P,NETOUT
	AOS B,TRANS	;GENERATE A TRANSACTION NUMBER
	MOVEM B,ACCNUM	;REMEMBER IT
	HRROI IOP,B
	PUSHJ P,NETOUT	;AND SEND IT TO SLAVE, WHICH WILL IDENTIFY REPLY WITH IT.
	HRROI IOP,JBCWD1
	PUSHJ P,NETOUT	;INFORM THE SLAVE OF NEW ACCESS POINTER
	MOVE A,JBCWD1
	MOVEM A,ACCP
	PUSHJ P,BUFINI	;FLUSH BUFFERED INPUT FROM SLAVE
	HRROI IOP,INPALL
	PUSHJ P,NETOFR
	SETZM INREAL
	SETOM ACCACK	;AND ACCEPT NO MORE UNTIL ACCESS IS ACKNOWLEDGED.
	POPJ P,		;(THOSE ACTIONS IRRELEVANT ON OUTPUT).

JRCH:	SYSCAL JOBRET,[
		1000,,CHBOJ
		1000,,0
		[-5,,RDEVN]]
	 JRST TRYOV	;NO NEED FOR "PCL" SINCE WE HAVEN'T ALTERED ANYTHING.
	JRST GOLOOP

JOPEN:	LDB W,[410100,,JBCOP]	;0 => INPUT  1 => OUTPUT
	MOVEM W,DIRECTN
JOPNC1:	MOVE B,JBCWD6		;SAVE OPEN-MODE.
	MOVEM B,OPMODE
	ANDI B,7		;GET JUST LOW 3 BITS.
	TRC B,1			;FLIP DIRECTION (CREATOR READING =>
				  ;WE MUST WRITE TO HIM).
	TRO B,20		;UNHANG OUR IOTS IF HE PCLSRS.
	SYSCAL OPEN,[ 1000,,CHBOJ ? 4000,,B ? ['BOJ,,]]
	 .VALUE
	PUSHJ P,LOGIN
	MOVE A,FDEVN
	MOVE B,JBCFN1
	MOVE C,JBCFN2
	MOVE D,JBCSNM
	HRRZ E,JBCWD6	;GET FULL OPEN-MODE.
	MOVE IOP,[-6,,0]
	MOVE 0,[-5,,COPENI ? -5,,COPENO](W)
	PUSHJ P,NETOUT
	PUSHJ P,REPLY	;READ REPLY INTO B, RH IN A.
	CAIE A,ROPENI	;IT MUST BE AN OPEN-REPLY, OR THERE'S A BUG.
	 CAIN A,ROPENO
	  JRST JOPEN1
	 .VALUE

JOPEN1:	HRROI IOP,B
	PUSHJ P,NTIIOT	;READ THE SUCCESS/FAILURE CODE.
	MOVE A,B
	JUMPGE A,OPNIL	;-1 => SUCCESS.
	PUSHJ P,OPNSN	;READ THE REAL FILE NAMES
	MOVE IOP,[-6,,FILLEN]	;AND THE FILE LENGTHS, BYTE SIZES, DATE.
	PUSHJ P,NTIIOT
	PUSHJ P,NTIFRC
JOPJRT:	.CALL JBRT1	;NOW TELL THE CREATOR THAT THE OPEN SUCCEEDED.
	 PUSHJ P,IJBRTF
	SETOM FILOPN	;ONCE HE KNOWS THAT, WE ARE ATTACHED UNTIL HE CLOSES.
	PUSHJ P,BUFINI	;NOW THAT WE KNOW BYTE SIZE, WE CAN SET UP BUFFER PTRS.
	JUMPG W,GOLOOP
	MOVE B,INPALL
	HRROI A,CALLOC	;READ ALLOCATE
	MOVE IOP,[-2,,A]
	PUSHJ P,NETOFR
	JRST GOLOOP

OPNSN:	PUSH P,RDEVN	;DON'T REPLACE "DM", "ML", OR "AI" WITH "DSK"
	MOVE IOP,[-4,,RDEVN]
	PUSHJ P,NTIIOT	;READ IN REAL FILE NAMES.
	POP P,RDEVN
	.CALL JBST	;GIVE NAMES TO SYSTEM FOR RCHST/RFNAME
	 .VALUE
	POPJ P,

OPNIL:	PUSHJ P,NTIFRC
	HRLZM A,ERRCOD	;HERE FOR FAILURE REPLY TO OPEN, ERROR CODE IN A.
	.CALL JBRT3
	 PUSHJ P,IJBRTF
	JRST REUSE	;IF WE SUCCEED IN TELLING CREATOR, WE ARE FINISHED.

IJBRTF:	MOVEI A,30.	;IF INITIAL JOBRET FAILS, WAIT A WHILE BEFORE JOBGETING,
	.SLEEP A,	;SINCE IF WE JOBGET BEFORE HE RETRIES WE WILL READ A CLOSE
	JRST PCLSR	;AND GIVE UP, AND HE WILL DO WHATEVER IT IS TWICE.

;SET UP BUFFER POINTERS FROM BYTSIZ (WHICH WE GET IN THE ROPENI/ROPENO).
BUFINI:	MOVEI B,36.
	IDIV B,BYTSIZ
	MOVEM B,BYTSWD
	IMULI B,BUFL
	MOVEM B,BUFSIZ
	MOVE B,OPMODE
	MOVEI C,BUF
	MOVEM C,BUFI		;BUFI IS ALWAYS AN ADDR
	MOVE A,BYTSIZ		; SINCE SLAVE SENDS PACKED BYTES.
	LSH A,6
	IORI A,440000		;IN UNIT MODE, BUFO SHOULD BE 44NN00,,ADDR.
	TRNN B,.BAI		;IN BLOCK MODE, IT SHOULD BE JUST AN ADDR.
	 TLO C,(A)
	MOVEM C,BUFO
	SETZM EOFI		;EOF NOT DETECTED YET.
	SETZM INREAL		;SAY THAT ALL THE BUFFER SPACE IS ALLOCATED.
	MOVE C,BUFSIZ		;(IT'S CALLER'S RESPONSIBILITY TO DO THAT.
	MOVEM C,INPALL		;OF COURSE, FOR OUTPUT, THIS IS IGNORED.)
	SETZM BUFONM		;SINCE WE RESET THE ADDR FORMS OF PNTRS,
	POPJ P,			;RESET THE BYTE-NUMBER FORM TOO.

LOGIN:	SKIPN LOGGED		;LOGIN DONE ?
	 SKIPE LOGINS		;OR EVEN STARTED ?
	  POPJ P,
	MOVE IOP,[-2,,B]	;HERE TO LOGIN AT FOREIGN HOST
	HRROI B,CLOGIN
	.SUSET [.RXUNAM,,C]
	PUSHJ P,NETOFR
	SETOM LOGINS		;SAY SENT
	POPJ P,

JIOT:	SKIPN FILOPN
	 .VALUE
	MOVE A,JBCOP
	TLNN A,100000	;SKIP IF OUTPUT IOT
	 JRST JIOTI
	TLNN A,200000	;SKIP IF BLOCK IOT
	 JRST JIOTO1
	HLRE D,JBCWD1	;USER'S BLOCK IOT POINTER - GET WD COUNT.
	MOVNS D
JIOTO5:	SKIPN RETOOU	;IF RESUMING PROCESSING OF AN IOT AFTER WE LOOKED AT NET FOR A WHILE,
	 MOVE D,RETOCT	;GET # BYTES NOT SENT YET.  JBCWD1 HAS TOTAL INCLUDING THOSE SENT.
JIOTO2:	MOVE C,BYTSWD
	IMULI C,200	;GET # BYTES THAT 200 WORDS WILL HOLD.
	CAMLE C,D	;SLAVE CAN'T BE EXPECTED TO HANDLE MORE.
	 MOVE C,D	;C HAS # BYTES WE WILL SEND NOW.
	SUB D,C		;# BYTES OF USER'S IOT THAT WILL BE LEFT.
	MOVE A,JBCOP
	TLNE A,200000	;NOW READ THE BYTES FROM THE USER.
	 JRST JIOTO4	;USING SIOT OR BLOCK IOT, WHICHEVER WE CAN.
	MOVE B,[440000,,BUF]
	MOVE A,BYTSIZ
	DPB A,[300600,,B] ;FOR SIOT, MAKE BP. WITH APPRO BYTE SIZE.
	MOVE A,C
	SYSCAL SIOT,[ 1000,,CHBOJ ? B ? C]
	 .VALUE
	SUB A,C		;A GETS # BYTES WE GOT, C # WE WANTED BUT DIDN'T GET.
;HERE SIOT AND BLOCK IOT LINES RECOMBINE.
;A HAS NUMBER OF BYTES GOTTEN FROM CREATOR.
;RH(B) POINTS TO LAST FILLED WORD IN BUF.
;C HAS # BYTES WE TRIED TO READ BUT DIDN'T GET (WILL BE 0 UNLESS
  ;THE CREATOR WAS PCLSR'ED).
;D HAS # OF EXTRA BYTES CREATOR WAS TRYING TO SEND, THAT WE HAVEN'T
  ;EVEN TRIED TO READ YET.
;HDR1 HAS # BYTES WE GOT THIS TIME.
JIOTO3:	MOVEM A,HDR1
	PUSHJ P,UPDACP	;UPDATE ACCP AND MAYBE FILLEN, FILBLN.
	MOVNI IOP,-HDR0(B) ;RH(IOP) GETS MINUS # OF WORDS IN CDATA COMMAND.
	HRLZS IOP
	HRRI IOP,CDATA
	MOVEM IOP,HDR0	;PUT CDATA COMMAND IN BEFORE BYTE COUNT WORD.
	ADD IOP,[-1,,HDR0-CDATA] ;MAKE COMMAND (NOTE NO CARRY FROM RH SINCE HDR0 > CDATA)
	SKIPE HDR1	;NOW SEND THE COMMAND (BUT IF 0 BYTES, DON'T BOTHER).
	 PUSHJ P,[PUSHJ P,NETOUT	;TRANSMIT TO SYSTEM, BUT LET SYSTEM
		  JRST BUFFRC]		;CHOOSE PACKET SIZE
	JUMPN C,GOLOOP	;NOW, IF THIS IOT WAS PCLSR'ED, DON'T TRY TO DO
		;ANY MORE FOR IT.  IF IT COMES BACK IN WE WILL FIND OUT.
	JUMPE D,GOLOOP	;IF THERE IS MORE STUFF TO OUTPUT,
	SKIPL NTICIN	;LOOP BACK, UNLESS THERE ARE REPLIES COMING BACK.
	 JRST JIOTO2
	SETOM RETOOU	;IN THAT CASE, SET FLAG SO WE WILL COME BACK TO IOT'ING,
	MOVEM D,RETOCT	;REMEMBER HOW MANY BYTES LEFT TO SEND WHEN WE COME BACK,
	JRST GOLOOP	;AND CHECK OUT THE REPLIES.

;HERE TO XFER FROM CREATOR IN BLOCK MODE.
JIOTO4:	MOVN B,C
	HRLZS B
	HRRI B,BUF	;AOBJN PTR TO # WDS WE WANT TO READ.
	.IOT CHBOJ,B
	MOVEI A,-BUF(B)	;A GETS # BYTES WE READ.
	SUB C,A		;C GETS # THAT WE EXPECTED BUT DIDN'T GET.
	SOJA B,JIOTO3	;MAKE B POINT AT LAST WORD FILLED.

;HERE TO DECODE A UNIT MODE IOT OR SIOT.
JIOTO1:	TLNE A,1000	;SKIP IF UNIT IOT
	 SKIPA D,JBCWD1	;SIOT, GET BYTE COUNT
	  MOVEI D,1	;IOT, TRANSFER ONE BYTE
	JRST JIOTO5

;UPDATE OUR ACCESS POINTER WHEN WE WRITE C(A) BYTES.
UPDACP:	ADDB A,ACCP
	SKIPL FILLEN	;IF FILE LENGTH KNOWN,
	 CAMG A,FILLEN	;AND WRITING PAST END OF FILE
	  POPJ P,
	MOVEM A,FILLEN	;THEN UPDATE THE FILE LENGTH
	MOVEM A,FILBLN	;SINCE WE'RE WRITING, BYTE SIZE WRITTEN AND CURRENT BYTE SIZE MUST BE SAME
	POPJ P,

JIOTI:	TLNN A,200000	;SKIP IF BLOCK IOT
	 JRST JIOTI3
	HLRE C,JBCWD1	;USER'S BLOCK IOT POINTER - GET WD COUNT.
	MOVNS C
;C HAS # BYTES THE USER WANTS IN THIS IOT OR SIOT.
;A HAS JBCOP, EVERYWHERE ON THIS PAGE.  DON'T CLOBBER IT!
JIOTI1:	MOVE D,BUFSIZ
	SUB D,INPALL
	SUB D,INREAL	;D HAS # BYTES OF INPUT WE HAVE IN BUFFER.
	JUMPE D,JIOTIS	;NONE => EITHER IT'S EOF OR WE MUST WAIT.
	CAMLE D,C
	 MOVE D,C	;ELSE GIVE USER AT MOST WHAT WE'VE GOT.
	MOVE E,BUFSIZ	;NOW, WE CAN'T DO ONE IOT THAT WRAPS AROUND,
	SUB E,BUFONM	;SO SEE HOW FAR IT IS TO WRAP AROUND FROM HERE.
	CAMLE D,E
	 MOVE D,E	;THAT'S THE MOST WE CAN GIVE IN ONE SHOT.
	JUMPE D,LOSE5
	SUB C,D		;C <=  # BYTES THAT WILL REMAIN.
	TLNN A,200000
	 JRST JIOTI4	;NOW IN UNIT MODE GO XFER THEM WITH SIOT.
	MOVNS D
	HRLZS D
	HRR D,BUFO	;IN BLOCK MODE, MAKE AOBJN TO WHAT WE WILL GIVE
	.IOT CHBOJ,D	;GIVE
	SKIPGE D	;IF CREATOR DIDN'T TAKE ALL WE OFFERED, HE WAS
	 SETZ C,	;PCLSRED, SO DON'T TRY TO OFFER ANY MORE.
	MOVEI E,(D)
	SUB E,BUFO	;NUMBER OF WORDS GIVEN TO CREATOR
	HRRZS D		;WHAT IS 1ST BUFFER WORD WE HAVEN'T JUST SENT?
	CAIN D,EBUF
	 MOVEI D,BUF
	MOVEM D,BUFO	;THAT WILL BE NEXT TO SEND
;HERE E HAS # BYTES WE JUST GAVE THE USER.  BUFO HAS BEEN UPDATED,
;BUT NOT BUFONM.
JIOTI5:	ADDM E,ACCP
	MOVE D,E
	ADDB D,BUFONM
	CAMN D,BUFSIZ
	 SETZM BUFONM
	ADDB E,INREAL	;WHAT WE SENT IS NOW EMPTY.
	JUMPL E,LOSE6
	LSH E,1
	CAMGE E,BUFSIZ	;MAYBE THERE'S A LOT EMPTY AND WE SHOULD REALLOCATE.
	 JRST JIOTI2
	MOVE E,INREAL
	SETZM INREAL
	ADDM E,INPALL	;MARK THIS SPACE AS PART OF ALLOCATION
	SKIPGE B,INPALL
	 .VALUE
	CAMLE B,BUFSIZ
	 .VALUE
	HRROI D,CALLOC	;AND TELL THE SLAVE.
	MOVE IOP,[-2,,D]
	PUSHJ P,NETOFR	;REALLOCATE
JIOTI2:	JUMPN C,JIOTI1	;NOW, IF CREATOR'S IOT NOT ALL FILLED, GIVE HIM MORE.
	JRST GOLOOP

;HERE TO GIVE THE CREATOR SOME DATA IN UNIT MODE.
JIOTI4:	MOVE E,D
	SYSCAL SIOT,[1000,,CHBOJ ? BUFO ? D]
	 .VALUE
	SUB E,D		;E GETS # BYTES HE TOOK.
	SKIPE D		;IF HE DIDN'T TAKE ALL WE OFFERED, HE WAS PCLSRED,
	 SETZ C,	;SO DON'T TRY TO GIVE HIM ANY MORE.
	MOVNI B,BUFL
	MOVE D,BUFO	;NOW, IF BUFO IS POINTING AT END OF BUFFER,
	IBP D
	ANDI D,-1
	CAIN D,EBUF
	 ADDM B,BUFO	;MAKE IT POINT AT BEGINNING.
	JRST JIOTI5

;HERE IF CREATOR WANTS STUFF BUT OUR BUFFER IS EMPTY.
JIOTIS:	SKIPGE EOFI
	 JRST JIOTIE	;MAYBE IT'S EMPTY BECAUSE WE'RE AT EOF.
	MOVEM C,RETOIN	;OTHERWISE, WAIT FOR DATA FROM SLAVE
	JRST GOLOOP	;AND SAY TO GIVE IT TO CREATOR WHEN IT COMES.

;HANDLE EOF RETURNED BY SLAVE
JIOTIE:	MOVE A,JBCOP
	TLNN A,201000	;SKIP IF BLOCK OR SIOT BIT ON
	 JRST JIOTI6	;FOR UNIT-MODE IOTS, RETURN SOMETHING.
	.CALL JBRTL	;JUST UNHANG A BLOCK IOT OR SIOT.
	 PCL
	JRST GOLOOP

JIOTI6:	TLNE A,400000	;EOF, AND USER'S CHANNEL IS UNIT MODE.
	 JRST JIOTI8
	.IOT CHBOJ,[-1,,^C]	;IF ASCII, INDICATE EOF (CHBOJ IS UNIT MODE)
	JRST GOLOOP

JIOTI8:	SYSCAL JOBIOC,[MOVEI CHBOJ ? MOVEI 2]	;IOCERR FOR EOF
	 JRST TRYOV
	JRST GOLOOP	;ON UNIT IMAGE CHANNEL

JIOTI3:	TLNE A,1000	;SKIP IF UNIT IOT
	 SKIPA C,JBCWD1	;SIOT, GET BYTE COUNT
	  MOVEI C,1	;IOT, TRANSFER ONE BYTE
	JRST JIOTI1

JFDEL1:	PUSHJ P,LOGIN
	MOVE A,[-6,,CFDELE]	;5 ARGS, AND THIS IS A DELETE/RENAME.
	MOVEM A,JBCOP
	MOVE A,FDEVN
	EXCH A,JBCWD1	;DEV GOES IN WD1, FOLLOWED BY FN1 AND FN2 IN NEXT 2 WDS.
	EXCH A,JBCWD4	;FOLLOWED BY NEW FN1; GET SNAME
	EXCH A,JBCWD6	;AND PUT AFTER WHERE NEW FN2 GOES;
	MOVEM A,JBCWD5	;PUT NEW FN2 IN RIGHT PLACE.
	MOVE IOP,[-7,,JBCOP]
	PUSHJ P,NETOUT
	PUSHJ P,REPLY	;SEND COMAND, WAIT FOR REPLY.
	CAIE A,RFDELE	;IT HAD BETTER BE THE RIGHT KIND OF REPLY.
	 .VALUE
	HRROI IOP,B	;GET REPLY CODE
	PUSHJ P,NTIIOT
	PUSHJ P,NTIFRC
	TRNN B,400000
	 JRST JFDEL3	;THE RENAME FAILED.
	.CALL JBRT1
	 PUSHJ P,IJBRTF
	JRST REUSE	;AFTER JOBRETTING ON A DELETE/RENAME WE ARE FINISHED.

JFDEL3:	HRLZM B,ERRCOD
	.CALL JBRT3
	 PUSHJ P,IJBRTF
	JRST REUSE

JRNMWO:	MOVE A,[-2,,CRNMWO]	; RENAME WHILE OPEN
	MOVEM A,JBCWD4	;ARRANGE CODE FOR RENMWO,
	MOVE A,JBCWD1
	MOVEM A,JBCWD5	;FOLLOWED BY NEW FN1 (NEW FN2 ALREADY IN WD 6).
	MOVE IOP,[-3,,JBCWD4]
	PUSHJ P,NETOFR
	SETOM RNMWOS	;SAY WE ARE AWAITING A REPLY FOR A RENMWO.
	JRST GOLOOP

JSYSCL:	MOVE A,JBCWD1	;HANDLE A .CALL.  WHAT IS ITS NAME?
	CAMN A,['FILLEN]
	 JRST JFILLEN	;FILLEN WE CAN HANDLE WITHOUT GOING OVER THE NET.
	CAMN A,['SFDATE]
	 JRST JSFDAT	;SFDATE WE PASS OVER BUT MUST UPDATE OUR DATE FIRST.
	CAMN A,['SAUTH]
	 JRST JSAUTH
	CAMN A,['RFDATE]
	 JRST JRFDAT	;RFDATE WE CAN ANSWER DIRECTLY.
	CAMN A,['ACCESS]
	 JRST JSACC	;ACCESS WE HAVE TO KNOW ABOUT

;THE FOLLOWING IS COMMENTED OUT SINCE THERE IS NO SUCH CALL IN ITS, AND
;IF IT IS EVER PUT IN IT IS UNLIKELY TO BE WITH THIS NAME AND THESE ARGS.
;	CAMN A,[SIXBIT/TRUNC/]
;	 JRST [	SKIPGE JOUOP	;TRUNC ALLOWED ONLY ON OUTPUT FILES;
;		 JRST .+1	;ON AN INPUT FILE DON'T DO ANYTHING, IT WILL FAIL.
;		MOVE A,JBCWD3	;IF IT'S AN OUTPUT FILE, AND FILLEN IS KNOWN,
;		SKIPGE FILLEN
;		 JRST .+1
;		MOVEM A,FILLEN	;WE MUST TAKE NOTE OF THE CHANGES TO LENGTH AND POINTER.
;		CAMGE A,ACCP
;		 MOVEM A,ACCP
;		JRST .+1]
	AOS CALACK	;COUNT # OF SYSTEM CALL REQUESTS NOT REPLIED TO.
	SETOM CALING	;SAY WAITING FOR RSYSCL REPLY TO WHAT WE ARE ABOUT TO SEND.
	PUSHJ P,JSYSC1	;SEND IT - A COMMAND TO DO THE SYSTEM CALL.
	JRST GOLOOP

JSYSC1:	PUSHJ P,LOGIN
	MOVE A,[-11.,,CSYSCL]	;SEND A CSYSCL COMMAND WITH ITS ARGS.
	MOVEM A,JBCOP
	MOVE IOP,[-12.,,JBCOP]
	PUSHJ P,NETOFR
	POPJ P,

;TELL THE SLAVE TO DO AN MLINK SYSTEM CALL
JMLINK:	PUSHJ P,LOGIN
	MOVEI A,7	;NUMBER OF .CALL ARGS
	MOVEM A,JBCOP
	MOVE A,JBCWD1	;PUT THE ARGS IN THE RIGHT ORDER: DEV, FN1, FN2, SNAME, TO-FN1, FN2, SNAME
	MOVEM A,JBCDEV
	MOVE A,FDEVN
	MOVEM A,JBCWD1
	SETOM MLINKS
	AOS CALACK	;NO NEED TO TURN OFF INTERRUPTS FOR THIS, SINCE
	SETOM CALING	;MLINK HAS TO BE THE FIRST REAL OPERATION DONE.
	MOVE IOP,[-12.,,MLINKP]
	PUSHJ P,NETOUT
	PUSHJ P,REPLY	;NOW WAIT FOR A REPLY.
	CAIE A,RSYSCL	;IT HAD BETTER BE THE RIGHT KIND FOR AN MLINK.
	 .VALUE
	JRST XCALL	;NOW GO HANDLE IT AND JOBRET (IT'S A SYSTEM-CALL REPLY).

JFILLEN:		;HANDLE .CALL FILLEN
	SKIPL FILLEN	;IF FILE'S LENGTH IS UNKNOWABLE,
	 JRST JFILL1
WTDERR:	MOVSI A,%EBDDV	;RETURN "WRONG TYPE DEVICE" ERROR.
	MOVEM A,ERRCOD
	.CALL JBRT3
	 PCL
	JRST GOLOOP

JRFDAT:	SKIPN FILDTP	;.CALL RFDATE.
	 JRST WTDERR	;BARF "WRONG TYPE DEVICE" IF DATE NOT DEFINED.
	SKIPA A,[-1,,FILDAT]
JFILL1:  MOVE A,[-4,,FILLEN]
	MOVEM A,JRFDAP	;ALL ARGS OF RFDATE MUST STAY AROUND IN CASE
	SYSCAL JOBRET,[ 1000,,CHBOJ ? 1000,,1 ? JRFDAP]
	 PCL		;THE SYSTEM CALL WAS PCLSR'ED AND COMES IN AGAIN.
	JRST GOLOOP

JRFDAP:	0

JSAUTH:	SKIPN FILDTP	;SAUTH: ASSUME IT WORKS IF THE DEVICE HAS FILE DATES,
	 JRST WTDERR
	JRST JSAUT1	;AND DON'T WAIT FOR ACKNOWLEDGEMENT.

JSFDAT:	SKIPN FILDTP
	 JRST WTDERR
	MOVE B,JBCA2	;.CALL SFDATE - TAKE NOTE OF THE DATE
	MOVEM B,FILDAT	;BEING SENT TO THE SLAVE.
JSAUT1:	AOS CALACK	;COUNT # OF SYSTEM CALL REQUESTS NOT REPLIED TO.
	PUSHJ P,JSYSC1	;SEND IT.  BUT DON'T WAIT FOR ACKNOWLDGEMENT;
	.CALL JBRT1	;WE CAN REPORT SUCCESS RIGHT AWAY.
	 PCL
	JRST GOLOOP

NTINT:	PUSHJ P,NTCHK
	 JRST GOLOOP
	PUSHJ P,REPLY1
	CAIL A,RMAX
	 .VALUE
	MOVEM B,LREPLY'
	JRST @CMDTB(A)

;SLAVE REPLY ROUTINES DISPATCHED TO WITH LH(B) = - # ARGS MUST BE READ FROM NET
CMDTB:	LOSE1
	NTDI
	OPNSI
	OPNSO
	EOF
	FDELST
	XNOOP
	XACC
	XCALL
	XICLOS
	XOCLOS
	XIOC

REPLY:	PUSHJ P,NETFRC	;HERE TO WAIT FOR A REPLY FROM THE SERVER.
REPLY1:	HRROI IOP,B	;WE DON'T CHECK FOR JOB DEVICE INTERRUPTS.
	PUSHJ P,NTIIOT	;THAT IS DELIBERATE;  IN THE INITIAL OPEN, WE DON'T WANT
	HRRZ A,B	;TO DO A JOBGET AND GIVE UP IF HE PCLSRS.
	CAIE A,RLOGIN	;LOGIN MIGHT BE "IN THE MIDDLE", SO SKIP IT SO CALLER
	 POPJ P,	;WILL NOT BE CONFUSED
	PUSHJ P,NTIFRC
	SKIPE LOGINS	;CONSISTENCY CHECK
	 SKIPE LOGGED
	  .VALUE
	SETZM LOGINS
	SETOM LOGGED
	JRST REPLY1

;NETWORK 36-BIT OUTPUT ROUTINES

NETOFR:	PUSHJ P,NETOUT		;Output then force
NETFRC:	PUSHJ P,BUFFRC		;Force our buffer and system's too
SYSFRC:	.CALL [ SETZ ? SIXBIT/FORCE/ ? SETZI CHNETO ]	;Send it
	 .LOSE %LSSYS
	POPJ P,

BUFFRC:	PUSH P,H		;Force our buffer into system
	PUSH P,J
	PUSH P,Q
	AOSE NBFOXF
	 JRST NETFR1
	MOVE H,NBFOXW		;Send extra word
	MOVEI J,0		;Padded with zeros
	PUSHJ P,NETOU2
NETFR1:	PUSHJ P,NETBFO		;Code-convert buffer
POPQJH:	POP P,Q
	POP P,J
	POP P,H
	POPJ P,

;Send words, IOP is aobjn pointer
NETOUT:	PUSH P,H
	PUSH P,J
	PUSH P,Q
	AOSE NBFOXF
	 JRST NETOU1
	MOVE H,NBFOXW		;Send saved word from last time
	MOVE J,(IOP)		;Followed by first new word
	PUSHJ P,NETOU2
	AOBJP IOP,POPQJH
NETOU1:	MOVE H,(IOP)		;Send two words
	AOBJP IOP,NETOU3	;No more
	MOVE J,(IOP)
	PUSHJ P,NETOU2
	AOBJN IOP,NETOU1
	JRST POPQJH

NETOU3:	MOVEM H,NBFOXW		;Send this word next time
	SETOM NBFOXF
	JRST POPQJH

;Send pair of 36-bit words in H,J
NETOU2:	MOVE Q,NBUFOC		;Space in buffer?
	CAIGE Q,9
	 PUSHJ P,NETBFO		;Make some
	MOVNI Q,9
	ADDM Q,NBUFOC
REPEAT 9,[
	ROTC H,8
	IDPB J,NBUFOP
]
	POPJ P,

;Send and refresh the buffer -- clobbers Q only
NETBFO:	MOVEI Q,NBUFL
	SUB Q,NBUFOC		;Number of 8-bit bytes in buffer
	JUMPE Q,CPOPJ		;Empty
	PUSH P,J
	MOVE J,[440800,,NBUFO]
	MOVEM J,NBUFOP
	ADDM Q,NBUFOC
	.CALL [ SETZ ? SIXBIT/SIOT/ ? MOVEI CHNETO ? J ? SETZ Q ]
	 .LOSE %LSSYS
	POP P,J
	POPJ P,

;Read 36-bit words from network into aobjn pointer in IOP
;If an odd number of words, NTIFRC will clean up the extra word
;(Calls to NTIFRC must match calls to NETFRC at other end).
NTIFRC:	SETZM NBFIXF		;Swallow extra word, if any
	POPJ P,

NTIIOT:	PUSH P,H
	PUSH P,J
	PUSH P,Q
	AOSE NBFIXF		;If have extra word, recieve it first
	 JRST NTIIO1
	MOVE H,NBFIXW
	MOVEM H,(IOP)
	AOBJP IOP,POPQJH
NTIIO1:	HLRO H,IOP		;Compute how much input we need
	ASH H,-1		;Rounded-up negative number of word pairs
	IMUL H,[-9]		;Number of bytes
	CAILE H,NBUFL		;Take at most one buffer full
	 MOVEI H,NBUFL
	PUSH P,H
	IDIVI H,9		;Store number of word pairs
	MOVEM H,NBUFIC
	POP P,H
	MOVE J,[440800,,NBUFI]
	MOVEM J,NBUFIP
	.CALL [ SETZ ? SIXBIT/SIOT/ ? MOVEI CHNETI ? J ? SETZ H ]
	 .LOSE %LSSYS
	JUMPN H,DIE		;Failed to transfer, could be TCP conn closed
NTIIO2:	MOVEI J,0		;Receive two words into H,J
REPEAT 9,[
IFN .RPCNT, LSHC H,8
	ILDB Q,NBUFIP
	IOR J,Q
]
	MOVEM H,(IOP)
	AOBJP IOP,NTIIO3
	MOVEM J,(IOP)
	AOBJP IOP,POPQJH
	SOSLE NBUFIC
	 JRST NTIIO2
	JRST NTIIO1		;Need another buffer full

NTIIO3:	MOVEM J,NBFIXW		;Save this word for next time
	SETOM NBFIXF
	JRST POPQJH

;TEST THE INPUT NETWORK CHANNEL STATUS.
;IF IT HAS INPUT, SKIP.
;IF IT HAS NONE, BUT IS HAPPY, DON'T SKIP.
;IF IT IS IN AN ERROR STATE, SUICIDE AFTER GIVING USER AN IOC ERROR.
NTCHK:	SETZM NTICIN	;TENTATIVELY CLEAR INTERRUPT, BEFORE READING STATUS
	.CALL [ SETZ ? 'WHYINT ? MOVEI CHNETI
		MOVEM A ? MOVEM B ? SETZM C ]
	 .LOSE %LSSYS
	CAIN A,%WYCHA
	 JRST [	CAIE B,%CSOPN
		 JRST NTIOC
		TLNE C,-1
		 JRST NTCHK1
		POPJ P, ]	;No input available
	CAIN A,%WYTCP
	 JRST [	MOVEI A,1
		LSH A,(B)
		TRNN A,1_%NSOPN+1_%NSRFN+1_%NSINP
		 JRST NTIOC	;I guess this means not open?
		JUMPN C,NTCHK1
		POPJ P, ]	;No input available
	.VALUE
NTIOC:	.CALL JBIOC	;GIVE USER IO CHANNEL ERROR
	 JFCL
	JRST DIE	;COMMIT SUICIDE.  CAN'T TRY TO BE REUSED SINCE NO LONGER HAVE SLAVE.

NTCHK1:	SETOM NTICIN	;DATA PRESENT, SET INT AGAIN IN CASE WE DON'T READ IT ALL
POPJ1:	AOS (P)
CPOPJ:	POPJ P,

;HANDLE "RDATA", DATA FOR ML: DEVICE INPUT.
NTDI:	HLRO A,B	;A => - # WORDS TO BE READ
	MOVN C,A	;C => NUMBER OF WORDS TO BE READ IN
	JUMPGE A,LOSE8
	SKIPE ACCACK	;IF INPUT IS INVALID BECAUSE USER DID A .ACCESS,
	 JRST NTDI3	;GO READ IT AND DISCARD IT.
	HRROI IOP,B
	PUSHJ P,NTIIOT	;READ THE BYTE COUNT
	SUBI C,1	;C GETS # WDS LEFT.
	MOVEI D,-1(B)
	ADD D,BYTSWD
	IDIV D,BYTSWD	;NUMBER OF WORDS IT OUGHT TO TAKE
	CAME C,D
	 .VALUE		;MLSLV IS TRYING TO ROUGH US OVER
	MOVN A,B
	ADDB A,INPALL	;DECREASE ALLOCATION
	JUMPL A,LOSE2
	CAMLE A,BUFSIZ
	 .VALUE
NTDI2:	MOVEI A,EBUF
	SUB A,BUFI	;A => ROOM TILL END OF BUFFER
	CAMLE A,C
	 MOVE A,C	;TRANSFER MIN OF A AND C
	SUB C,A		;C => REMAINING # WORDS TO READ
	MOVN IOP,A
	HRLZS IOP
	HRR IOP,BUFI
	PUSHJ P,NTIIOT
	CAIN IOP,EBUF
	 MOVEI IOP,BUF
	MOVEM IOP,BUFI
	JUMPG C,NTDI2
	JUMPL C,LOSE7
	PUSHJ P,NTIFRC
	SKIPN C,RETOIN	;IS CREATOR HANGING IN AN IOT WAITING FOR THIS DATA?
	 JRST GOLOOP
	SETZM RETOIN	;IF SO, RETURN TO IOT CODE AND GIVE IT TO HIM.
	MOVE A,JBCOP
	JRST JIOTI1

;HERE IF WE MUST IGNORE SOME DATA, BECAUSE WE HAVE GOT A .ACCESS
;THAT THE SLAVE HASN'T ACKNOWLEDGED YET.
NTDI3:	MOVEI A,200
	CAIGE C,200
	 MOVE A,C
	SUB C,A
	MOVN IOP,A
	HRLZS IOP
	HRRI IOP,BUF
	PUSHJ P,NTIIOT
	JUMPG C,NTDI3
	PUSHJ P,NTIFRC
	JRST GOLOOP

OPNSO:
OPNSI:	HRRI B,RCH	;FLUSH UNDESIRED OPEN REPLY
	PUSHJ P,NTIIOB	;OPEN REPLIES THAT ARE EXPECTED ARE SNARFED UP BY JOPEN.
	JRST GOLOOP	;AN OPEN REPLY MAKING IT THRU THE MAIN DISPATCH MUST BE UNEXPECTED.

NTIIOB:	MOVE IOP,B
	PUSHJ P,NTIIOT
	JRST NTIFRC

EOF:	HRRI B,C
	PUSHJ P,NTIIOB
	SKIPE ACCACK
	 JRST GOLOOP
	SETOM EOFI
	SKIPN RETOIN	;SKIP IF CREATOR WAITING FOR MORE DATA
	 JRST GOLOOP
	SETZM RETOIN	;GIVE EOF INSTEAD
	JRST JIOTIE

FDELST:	HRROI IOP,B	;GET REPLY CODE AND NAMES
	PUSHJ P,NTIIOT
	JUMPL B,FDLST2	;IF A RENAME/DELETE REPLY, IT MUST BE UNEXPECTED SINCE
			;THEY ARE READ IN BY JFDEL1.  SO IGNORE IT.
	SKIPL RNMWOS	;WERE WE EXPECTING THIS REPLY?
	 JRST FDELS2	; NO => IGNORE IT.
	SETZM RNMWOS
	TRNN B,400000
	 JRST FDLST1	;THE RENAME FAILED.
	PUSHJ P,OPNSN	;IT WON.  READ IN THE NEW REAL FILE NAMES.
	.CALL JBRT1
	 PCL
FDLST2:	PUSHJ P,NTIFRC
	JRST GOLOOP

FDLST1:	HRLZM B,ERRCOD
	.CALL JBRT3
	 PCL
	JRST FDLST2

;IGNORE THE REST OF A RENMWO REPLY THAT WAS NOT AWAITED.
FDELS2:	MOVE IOP,[-4,,RCH]
	TRNE B,400000
	 PUSHJ P,NTIIOT
	JRST FDLST2

XNOOP:	HRROI B,C
	PUSHJ P,NTIIOB
	JRST GOLOOP

XACC:	HRRI B,B	;HANDLE ACCESS ACKNOWLEDGEMENT.
	PUSHJ P,NTIIOB	;WHAT TRANSACTION NUMBER IS THIS?
	CAMN B,ACCNUM	;IF THIS IS RESPONSE TO MOST RECENT ACCESS,
	 SETZM ACCACK	;ALLOW INPUT TO BE READ AGAIN.
	JRST GOLOOP	;AND RESUME PROGRAM, DATA WILL SOON ARRIVE

XCALL:	HRRI B,XCALLB
	PUSHJ P,NTIIOB	;READ THE NINE VALUES (FIRST IS ERROR CODE AND SKIPPAGE)
	SOSG CALACK	; NOTE THE ACKNOWLEDGE AND SKIP IF NOT CURRENT YET
	 SKIPN CALING	 ; CURRENT; SKIP IF USER IS WAITING
	  JRST GOLOOP	; NOT CURRENT YET, KEEP WAITING; OR DON'T WANT IT
	SETZM CALING	;WE ARE NO LONGER WAITING FOR A .CALL REPLY.
	SYSCAL JOBRET,[	;GIVE VALUES TO USER.
		1000,,CHBOJ
		XCALLB
		[-8,,XCALLB+1]]
	 PCL
	SKIPL MLINKS	;IF THIS .CALL WAS AN MLINK, WE SHOULD EXIT NOW.
	 JRST GOLOOP
	JRST REUSE

XOCLOS::
XICLOS::
	JRST DIE

XIOC:	HRROI B,B	;HANDLE "RIOC" (MLSLV GOT AN IOC ERROR FROM DISK)
	PUSHJ P,NTIIOB	;READ IN THE IOC ERROR CODE
	SYSCAL JOBIOC,[1000,,CHBOJ ? B]
	 JFCL		;PASS IT TO CREATOR.
;AT THE MOMENT, SINCE DATA IS LOST WHEN AN IOC ERROR IS PASSED BACK,
;THERE IS NO USE IN LEAVING THE FILE OPEN.
JRST DIE
	SETZM RETOIN	;THIS FLUSHES ANY .IOT THAT WAS IN PROGRESS.
	SETZM CALING
	SETZM CALACK
	JRST GOLOOP

TSINT:	0
	0
	SKIPL U,TSINT
	 JRST TSFW
	TRNN U,1_CHBOJ+1_CHNETI
	 .VALUE
	SETOM INT
	TRZE U,1_CHBOJ
	 SETOM JBINT
	TRZE U,1_CHNETI
	 SETOM NTICIN
	CAME U,[SETZ]
	 .VALUE
	.DISMISS TSINT+1

TSFW:	TRNN U,%PIIOC
	 .VALUE [ASCIZ /:UNHANDLED RANDOM INTERRUPT/]
	.SUSET [.RBCHN,,U]	   ;Read erring channel number.
	CAIE U,CHNETI
	 CAIN U,CHNETO
	  CAIA
	   .VALUE
	SKIPN FILOPN
	 .DISMISS [NOGO]	;ERROR CONNECTING => DEV NOT AVAIL
	.DISMISS [NTIOC]	;ERROR TRANSFERRING => IOC ERROR

LOSE1:	.VALUE
LOSE2:	.VALUE
LOSE3:	.VALUE
LOSE4:	.VALUE
LOSE5:	.VALUE
LOSE6:	.VALUE
LOSE7:	.VALUE
LOSE8:	.VALUE

;COME HERE WHEN WE HAVE BEEN FINISHED WITH BY ONE CREATOR, TO OFFER OURSELVES TO OTHERS.
REUSE:	MOVEI A,30.*5		;WAIT FIVE SECONDS FOR SOMEONE TO TRY TO REUSE US.
	.SUSET [.SAMSK2,,[1_CHBOJ]]
	SYSCAL JOBREU,[
		RDEVN		;DEVICE NAME WE ARE HANDLING.
		['JOBDEV]	;FILENAMES WE WERE LOADED FROM.
		RDEVN
		['DEVICE]
		A]		;AMOUNT OF TIME TO WAIT (UPDATED, AS IN .SLEEP).
	 JRST REUSL
	.SUSET [.SIMSK2,,[1_CHBOJ]]
	SYSCAL RFNAME,[		;SOMEBODY GOBBLED US.  FIND OUT WHO, FOR PEEK.
		1000,,CHBOJ
		2000,,0
		2000,,CRUNAM
		2000,,CRJNAM]
	 JFCL
	MOVE IOP,[-2,,[-1,,CREUSE ? 0]]
	PUSHJ P,NETOUT
REUSE2:	PUSHJ P,REPLY	;NOW SNARF REPLIES TILL WE GET TO THE RREUSE.
	CAIE A,RREUSE
	 JRST [	HRRI B,BUF	;IGNORE ANY OTHER REPLIES.
		PUSHJ P,NTIIOB
		JRST REUSE2]
	HRRI B,RCH
	PUSHJ P,NTIIOB
	SETZM SNTCLS	;WE ARE NO LONGER WAITING FOR A CICLOS (WE IGNORED IT)
	JRST REUSE1

;HERE IF WE SEE WE ARE NOT GOING TO BE REUSED.
REUSL:	SKIPE SNTCLS	;IF WE SENT A CICLOS, WE MUST WAIT FOR THE RICLOS, WHICH WILL
	 JRST GOLOOP	;COME BACK TO DIE.
;COME HERE TO REALLY GIVE UP THE GHOST.
DIE:	SKIPN DEBUG
	 .LOGOUT
	.VALUE
	JRST DIE

JBGT:	SETZ
	'JOBCAL
	[CHBOJ]
	2000,,JBCOP
	SETZ [-11.,,JBCWD1]

JBST:	SETZ
	'JOBSTS
	MOVEI CHBOJ
	MOVEI 43	;SNDSK
	RDEVN
	RDEVN+1
	RDEVN+2
	SETZ RDEVN+3

JBRT1:	SETZ
	SIXBIT /JOBRET/
	[CHBOJ]
	SETZ [1]

JBRTL:	SETZ
	SIXBIT /JOBRET/
	[CHBOJ]
	SETZ [0]

JBRT3:	SETZ		;JOBRET AN ERROR CODE.
	SIXBIT /JOBRET/
	[CHBOJ]
	SETZ ERRCOD

ERRCOD:	0		;ERROR CODE PUT IN HL OF THIS WORD.

JBIOC:	SETZ
	SIXBIT /JOBIOC/
	1000,,CHBOJ
	401000,,1

$$HSTMAP==1
$$HOSTNM==1
$$SYMLOOK==1
$$CHAOS==1
$$ARPA==1
$$HST3==1
$$TCP==1
$$CONNECT==1

.SCALAR USENCP,USETCP		;Bullshit

.INSRT SYSTEM;CHSDEF
.INSRT SYSENG;NETWRK

NW%CHS==NETWRK"NW%CHS
NW%ARP==NETWRK"NW%ARP

IFNDEF %WYTCP,%WYTCP==7	; Until defined in sys

VARIABLES
CONSTANTS


MLINKP:	-11.,,CSYSCL	;THESE ARE BEGINNING OF THE BLOCK SENT TO SLAVE
	SIXBIT/MLINK/	;TO HANDLE AN "MLINK" OPERATION. FORMAT OF BLOCK IS SAME
	0		;AS THE BLOCK FOR RANDOM SYSTEM CALL.
;JBCOP MUST BE NEXT LOCATION!

;DATA RETURNED BY JOBCAL.
JBCOP:	0	;OPCODE: 0-8 MEANING OPEN, IOT, MLINK, RESET, RCHST, ACCESS, DELETE/RENAME, RENMWO, .CALL.
JBCWD1:	0	;BLOCK IOT PTR / ACCESS PTR / NEW FN1 IN RENAME&MLINK / 0 IN DELETE. / SYSTEM CALL NAME.
JBCFN1:
JBCWD2:: 0	;FN1
JBCFN2:
JBCWD3:: 0	;FN2

JBCSNM:		;SNAME
JBCA1::		;AND 1ST ARGUMENT OF .CALLS.
JBCWD4:: 0
JBCDEV:		;DEVICE NAME
JBCA2::		;AND 2ND ARGUMENT OF .CALLS.
JBCWD5:: 0
JBCWD6:	0	;NEW FN2 IN RENAME&MLINK / OPEN MODE IN OPEN.
JBCWD7:	0	;NEW SNAME IN MLINK.
JBCWD8:	0
JBCWD9:	0
JBCW10:	0
JBCW11:	0

FDEVN:	0	;FORIGN DEVICE NAME (DSK, FOR ML.  DIR, FOR MLDIR.  ETC.)
ACCNUM:	0	;TRANSACTION NUMBER OF LAST CACCES COMMAND.
ACCACK:	0	;-1 => WE ARE WAITING FOR A RACCES.

RNMWOS:	0		;-1 => WAITING FOR REPLY FOR RENAME WHILE OPEN.
CALING:	0		;-1 => MOST RECENT THING USER DID WAS A .CALL.
CALACK:	0		;NUMBER OF CSYSCL COMMANDS SENT AND NOT YET REPLIED TO.
MLINKS:	0		;-1 => THE .CALL WE ARE IN IS AN MLINK, SO DIE WHEN IT FINISHES.
TRANS:	0	;NUMBER OF LAST TRANSACTION (RIGHT NOW, ONLY CACCES USES A
		;TRANSACTION NUMBER).

XCALLB:	BLOCK 9. ;ARGS TO RSYSCL COMMAND READ IN HERE.

RCH:	BLOCK 12.	;BETTER BE AT LEAST AS LONG AS OPEN REPLY ARGS
INPALL:	0	;INPUT ALLOCATION KNOW TO SLAVE, IN BYTES.
INREAL:	0	;# BYTES EMPTY IN BUFFER BUT NOT REALLOCATED.
OPMODE:	0	;MODE CREATOR OPENED US IN.
EOFI:	0	;-1 => HAVE REACHED EOF ON INPUT
RETOIN:	0	;NONZERO => CREATOR HUNG IN INPUT IOT, THIS IS # BYTES WANTED.
RETOOU:	0	;-1 => CREATOR HUNG IN AN OUTPUT IOT WHILE WE EXAMINE REPLIES FROM SERVER.
RETOCT:	0	;WHEN RETOOU IS -1, THIS HAS # BYTES LEFT TO XFER IN THAT IOT.
FILOPN:	0	;-1 => OUR CREATOR "HAS A FILE OPEN".  WE AREN'T FREE OF HIM TILL HE CLOSES.
LOGGED:	0	;-1 => HAVE LOGGED IN AT FOREIGN HOST
LOGINS:	0	;- => LOGIN REQUEST SENT, BUT NOT YET ANSWERED
SNTCLS:	0	;-1 WE HAVE SENT A CICLOS, SO MUST NOT SUICIDE TILL THE RICLOS.
JBINT:	0	;-1 => CHBOJ INT
NTICIN:	0	;-1 => CHNETI INT
LPDLL==100
PDL:	BLOCK LPDLL+4

CONSTANTS
VARIABLES

NBUFL==360.			;Number of 8-bit bytes of network buffer
NBUFO:	BLOCK NBUFL/4		;NBUFL must be multiple of 4 and 9
NBUFOP:	440800,,NBUFO		;Fill pointer for network buffer
NBUFOC:	NBUFL			;Bytes remaining
NBFOXF:	0			;-1 => extra word in NBFOXW
NBFOXW:	0			;extra word not sent yet

NBUFI:	BLOCK NBUFL/4
NBUFIP:	440800,,NBUFI		;Take pointer for network buffer
NBUFIC:	0
NBFIXF:	0			;-1 => extra word in EXTRAW
NBFIXW:	0			;extra word not sent yet

BUFI:	BUF	;POINTER FOR LOADING BUF FROM RDATA'S
BUFO:	BUF	;POINTER FOR TAKING FROM BUF TO GIVE TO CREATOR.
BUFSIZ:	0	;BUFFER SIZE IN BYTES OF SIZE WE'RE USING.
BYTSWD:	0	;# BYTES IN A WORD.
BUFONM:	0	;BUFO, IN FORM OF # BYTES FROM BEGINNING OF BFR.

HDR0:	0	;MUST BE BUF-2.  FOR OUTPUT TO NETWORK, THE CDATA COMMAND IS
		;PUT HERE, SO ONE .IOT CAN SEND IT AND THE DATA IN BUF.
HDR1:	0	;BYTE COUNT OF CDATA PUT HERE.
BUFL==6000-.	;TRY TO FIT IN 3K
IFL BUFL-1000,BUFL==BUFL+2000	;OH, WELL
BUF:	BLOCK BUFL
EBUF==.
	LOC EBUF-1
	-1	;ENSURE CORE EXISTENCE
	LOC EBUF

DEFINE INFORM A,B
PRINTX/A=B
/TERMIN
IF1 INFORM BUFFER SIZE,\BUFL
IF1 INFORM HIGHEST USED,\.

HSTPAG==<.+1777>/2000

END	GO
