diff --git a/README.md b/README.md index 876773bb..87627fcd 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,7 @@ from scratch. - FTPU, FTP Client - NAME, Shows logged in users and locations, aka FINGER - TALK/WHO/WHOJ/WHOM/USERS, list users. + - MLDEV, MLSLV, Allows access to remote systems as devices (e.g. DB:) 6. A brand new host table is built from the host table source and installed into SYSBIN; HOSTS3 > using H3MAKE. diff --git a/build/build.tcl b/build/build.tcl index ad839852..1aead6ce 100644 --- a/build/build.tcl +++ b/build/build.tcl @@ -394,6 +394,16 @@ respond "*" ":link sys;ts f,sys;ts name\r" respond "*" ":link sys2;ts n,sys;ts name\r" respond "*" ":link device;tcp syn117,sys;ts name\r" +respond "*" ":midas device;atsign mldev_sysen2;mldev\r" +expect ":KILL" + +respond "*" ":link device;jobdev db,device;atsign mldev\r" + +respond "*" ":midas device;atsign mlslv_sysen2;mlslv\r" +expect ":KILL" + +respond "*" ":link device;tcp syn123,device;atsign mlslv\r" + respond "*" ":link kshack;good ram,.;ram ram\r" respond "*" ":link kshack;ddt bin,.;@ ddt\r" respond "*" $emulator_escape diff --git a/doc/sysdoc/mldev.protoc b/doc/sysdoc/mldev.protoc new file mode 100644 index 00000000..dff5e8b8 --- /dev/null +++ b/doc/sysdoc/mldev.protoc @@ -0,0 +1,154 @@ +MLDEV/MLSLV protocol + +The MLDEV protocol is a binary file transfer protocol used between ITS +systems for the transfer of files. It depends heavily upon the ITS job +device feature and the ITS system calls and error codes. For a more +detailed description of the ITS system calls, read the ITS UUO and +symbolic system call manuals. + +The name MLDEV is historical, dating back to the days when this protocol +was used mostly to reference ML's file system from AI (and vice versa). +The MLDEV server is called MLSLV, for "ML slave". + +ICP is to socket 305 if doing mostly input, 307 if mostly output. + User commands: + +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 (Word count includes data words and byte count word) + arg1: # of bytes of data + args: Data, packed ILDB-style into at most 200 words + +CALLOC==4 Read allocate + Allocation in bytes + +CICLOS==5 Input CLOSE + Ignored argument + +COCLOS==6 Output CLOSE + Ignored argument + +CFDELE==7 DELETE or RENAME + arg1: Device + arg2: FN1 + arg3: FN2 + arg4: 0 or new FN1 + arg5: 0 or new FN2 + arg6: SNAME + +CRNMWO==10 RENAME while open + arg1: new FN1 + arg2: new FN2 + +CNOOP=11 No-op + arg: Echoed by the no-op 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 arguments that have significance + arg4: 1st argument to system call + ... + arg11: 8th argument to system call + +CREUSE==14 Reinitialize yourself, because we are about to be reused + by a new creator for a new file + Server replies + +Reply format: from slave +AOBJN pointer (RH = reply code) +Block of arguments + +R==,,-1 Reply codes: + +RDATA==1 Input data (word count includes data words and byte count word) + arg1: # of bytes of data + args: 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 + arg2arg11 are 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 data (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 data (if RFDATE wins) + +REOF==4 EOF on input + Ignored argument + +RFDELE==5 DELETE/RENAME 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 arguments: + arg2: Real device name + arg3: Real FN1 (as renamed) + arg4: Real FN2 + arg5: Real SNAME + +RNOOP==6 No-op reply + arg: Echo argument send by no-op command + +RACCES==7 Acknowledge access + arg: Transaction number from CACCES + +RSYSCL==10 Respond to system call. 9 arguments + arg1: ,,<# 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 + Ignored argument diff --git a/src/sysen2/mldev.103 b/src/sysen2/mldev.103 new file mode 100755 index 00000000..54babdbb --- /dev/null +++ b/src/sysen2/mldev.103 @@ -0,0 +1,1422 @@ +;-*-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 + 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] + 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: ,,<# 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 diff --git a/src/sysen2/mldev.104 b/src/sysen2/mldev.104 new file mode 100644 index 00000000..20164425 --- /dev/null +++ b/src/sysen2/mldev.104 @@ -0,0 +1,1422 @@ +;-*-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: ,,<# 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 diff --git a/src/sysen2/mlslv.77 b/src/sysen2/mlslv.77 new file mode 100755 index 00000000..584fed97 --- /dev/null +++ b/src/sysen2/mlslv.77 @@ -0,0 +1,824 @@ +;-*-MIDAS-*- + +TITLE BOJ SLAVE -- MLSLV, Works with MLDEV + +.XCREF A,B,C,D,E,TT,I,Q,J,R,W,H,P,T,U + +ICPSOC==123 ;This is the Postel-approved number + +A=1 +B=2 +C=3 +D=4 +E=5 +T=6 +TT=7 +I=10 +H=11 +J=12 +Q=13 +W=14 +P=15 +IOP=16 +U=17 + +CH==,,-1 ;BIT TYPEOUT MASK FOR CHANNEL NAMES + +CHNETI==1 +CHNETO==2 +CHDEV==4 + +DEFINE SYSCAL NAME,ARGS + .CALL [ SETZ ? SIXBIT /NAME/ ? ARGS ((SETZ))] +TERMIN + +MAXLOG==20 ;MAXIMUM # OF LOGIN TRIES +BUFL==400 ;SIZE OF BUFFER. SENDING TO MLDEV CAN USE FULL SIZE. + +DEFINE CHECK TAG,LEN +IFN .-TAG-,.ERR WRONG TABLE LENGTH +TERMIN + +LOC 42 + JSR TSINT +LOC 100 + +GO: .CLOSE 1, ;CLOSE DISK CHANNEL USED FOR LOADING + .SUSET [.RUNAM,,DEBUG] + HLLOS DEBUG ;IF WE ARE IN A LOGGED-IN TREE + AOSN DEBUG ;SOMEONE MUST BE DEBUGGING MLSLV. + .SUSET [.SJNAME,,[SIXBIT/MLSLV/]] ;IF NOT DEBUGGING, RECTIFY JNAME + .CALL [ SETZ + SIXBIT /SSTATU/ + 2000,,A ;IGNORE THE DIE TIME + SETZM SYSDBG] + JFCL + MOVE P,[-LPDL-1,,PDL-1] + SETZM ALLOC + SETZM NBFOXF + SETZM NBFIXF + MOVE A,[440800,,NBUFO] + MOVEM A,NBUFOP + MOVEI A,NBUFL + MOVEM A,NBUFOC + .SUSET [.SMASK,,[%PIIOC+%PIRLT+%PIILO+%PIMPV+%PIPDL]] + MOVE A,[600000,,[60.*60.]] + SKIPN DEBUG ;IF DEBUGGING, DON'T LIGHT FUSE + .REALT A, + JFCL + ;Find out what kind of server we're supposed to be + .SUSET [.RXJNAME,,A] + CAME A,[SIXBIT/TCP/] + JRST CHAICP +TCPICP: MOVEI A,CHNETI + MOVEI B,ICPSOC + PUSHJ P,NETWRK"TCPSRV + JSR LOGOUT + TLZ B,777000 ;Clear network number + TDNN B,[177700000] ;Try to reduce to old-style number + TRNE B,374 + JRST GO1 ;Can't + LDB A,[000200,,B] + LSH A,6 + LSH B,-9 + IOR B,A + JRST GO1 + +CHAICP: MOVEI A,CHNETI + MOVEI C,[ASCIZ/MLDEV/] + MOVEI D,8 + PUSHJ P,NETWRK"CHASRV + JSR LOGOUT +GO1: ANDI B,777 ;Kludgey unique number (low 9 bits of host) + MOVEM B,JOBUSR + MOVSI D,(SETZ) + .REALT D, + JFCL + JRST GO4 ;Start up + +;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. + +;[Next line is inoperative] +;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: ,,<# 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. + +GO4: SYSCAL WHYINT,[1000,,CHNETI ? 2000,,A ? 2000,,B ? 2000,,C] + JSR LOGOUT + CAIN A,%WYCHA + HLRZS C ;Non-zero if input available + JUMPN C,GO5 ;IF THERE ARE COMMANDS FOR US, HACK THEM. + SKIPGE EOFI + JRST GO5 + SKIPE C,ALLOC ;ELSE, IF WE HAVE MORE ALLOCATION, SEND MORE DATA. + JRST ALLI1 ;NO COMMANDS AND NO ALLOC => WAIT FOR COMMAND. +GO5: PUSHJ P,SYSFRC ;Force system output buffer before waiting + HRROI IOP,B ;Read command + PUSHJ P,NTIIOT + JUMPGE B,BYE2 + HRRZ A,B + CAIL A,CMAX + JSR LOGOUT + MOVEM B,LCMND' + JRST @CMDTB(A) + +;JUMP TO COMMAND HANDLER ROUTINE, LH(B) HAS - # ARGS TO READ OUT OF NET +CMDTB: OFFSET -. + BYE3 +COPENI:: OPNI +COPENO:: OPNO +CDATA:: IOTO +CALLOC:: ALLI +CICLOS:: CLSI +COCLOS:: CLSO +CFDELE:: FDEL1 +CRNMWO:: FDEL2 +CNOOP:: YNOOP +CACCES:: YACCES +CSYSCL:: YSYSCL +CREUSE:: YREUSE +CLOGIN:: LOGIN +CMAX:: OFFSET 0 + +OPNI: SKIPA A,[ROPENI] +OPNO: MOVEI A,ROPENO ;OPENI AND OPENO SAME EXCEPT FOR REPLY CODE. + PUSH P,A + HRRI B,DEV + PUSHJ P,NTIIOB ;READ THE FILENAMES AND MODE. + .SUSET [.SSNAME,,SNAME] + POP P,B + MOVE A,OPNM + ANDI A,2 + MOVEM A,BLOKMD ;WE MUST BE AWARE WHETHER USING BLOCK MODE. + SYSCAL OPEN,[4000,,OPNM ? 1000,,CHDEV + DEV ? FN1 ? FN2 ? SNAME + 3000,,C] + JRST OPNIL ;IF OPEN LOSES, REPORT THAT. + SETZM EOFI ;IT WON, REPORT THAT. + HRLI B,-11. + +;REPLY TO A SUCCESSFUL OPEN. B SHOULD HAVE REPLY HEADER, -11.,, +OPNRCH: SETO C, + PUSHJ P,OPNRC1 ;SEND FILE NAMES + SYSCAL FILLEN,[ 1000,,CHDEV + REPEAT 4,[ ? 2000,,DEVRCH+.RPCNT ]] + SETOM DEVRCH + MOVEI A,36. ;IF FILLEN FAILED, WE MUST ESTIMATE + MOVE B,OPNM ;THE BYTE SIZE: 7 IN UNIT ASCII MODE, + TRNN B,6 ;ELSE 36. + MOVEI A,7 + SKIPGE DEVRCH + MOVEM A,DEVRCH+1 + .RSYSI D, ;TEMPORARY CODE TO COMPENSATE FOR OLD SYSTEM + CAMG D,[SIXBIT/1040/] + JRST [ MOVEM A,DEVRCH+1 + MOVEM A,DEVRCH+3 + MOVE A,DEVRCH + MOVEM A,DEVRCH+2 + JRST .+1 ] + SKIPLE A,DEVRCH+1 + CAIL A,37. + .VALUE + SETOM DEVRCH+4 ;NOW READ THE FILE'S DATE + SYSCAL RFDATE,[ 1000,,CHDEV ? 2000,,DEVRCH+5] + SETZM DEVRCH+4 ;OR SAY IT HAS NONE. + MOVE IOP,[-6,,DEVRCH] + PUSHJ P,NETOFR + MOVE A,DEVRCH+1 + MOVEM A,BYTSIZ ;NOW FIGURE OUT HOW TO HACK THIS BYTE SIZE. + MOVEI A,36. + IDIV A,BYTSIZ + MOVEM A,BYTSWD + IMULI A,BUFL + MOVEM A,BUFSIZ + HRLZ A,BYTSIZ + LSH A,6 + IOR A,[440000,,BUF] + MOVEM A,BUFBP ;SET UP BP. TO BUFFER'S BEGINNING. + SETZM ALLOC + JRST GO4 + +OPNRC1: MOVE IOP,[-2,,B] + PUSHJ P,NETOUT + .CALL [SETZ + SIXBIT /RCHST/ + 1000,,CHDEV + 2000,,DEVRCH + 2000,,DEVRCH+1 + 2000,,DEVRCH+2 + 2000,,DEVRCH+3 + 2000,,DEVRCH+4 + 2000,,DEVRCH+5 + 2000,,DEVRCH+6 + SETZM DEVRCH+7] + JSR LOGOUT + MOVE IOP,[-4,,DEVRCH] + PUSHJ P,NETOUT + POPJ P, + +OPNIL: HRLI B,-1 ;REPLY TO FAILING OPEN. + MOVE IOP,[-2,,B] + PUSHJ P,NETOFR + JRST GO4 + +ALLI: HRRI B,C + PUSHJ P,NTIIOB ;READ ALLOC AMOUNT INTO C + MOVEM C,LALLOC' + ADDB C,ALLOC ;INCREASE ALLOC + SKIPGE EOFI ;CAN'T ACTUALLY TRANSFER ANYTHING IF AT EOF. + JRST GO4 +ALLI1: MOVE B,BUFSIZ + CAML C,B + MOVE C,B ;WE CAN'T IOT MORE THAN A BUFFERFULL AT ONCE. + SKIPN BLOKMD + JRST ALLI2 ;NOW GO DO THE XFRS IN UNIT MODE WITH SIOT, + MOVN B,C ;OR IN BLOCK MODE WITH IOT. + HRLZS B + HRRI B,BUF + .IOT CHDEV,B + MOVEI C,-BUF(B) ;HOW MANY BYTES DID WE GET? + SKIPGE B + SETOM EOFI ;NOT ALL WE ASKED FOR => AT EOF NOW. + JRST ALLI3 ;GO SEND OUR DATA (AND MAYBE EOF) TO MLDEV. + +ALLI2: IDIV C,BYTSWD ;ROUND DOWN BYTE COUNT TO MULTIPLE OF A WORD + IMUL C,BYTSWD ;SINCE SUPPOSED TO SEND FULLY POPULATED WORDS + JUMPE C,GO5 ;JUMP IF NOT ENOUGH ALLOC TO READ ANYTHING + MOVE B,BUFBP + MOVE A,C + SYSCAL SIOT,[1000,,CHDEV ? B ? A] + JSR LOGOUT + LDB D,[360600,,B] + CAIE D,44 ;MAKE B POINT AT THE FIRST WORD NOT READ INTO AT ALL. + AOS B + SKIPE A + SETOM EOFI + SUB C,A + +;NOW WE HAVE READ DATA FROM DEVICE INTO BUFFER. +;C HAS # BYTES READ. +;B POINTS AT 1ST UNUSED WORD OF BUF. +ALLI3: JUMPE C,ALLI4 + HRLZI IOP,-BUF(B) + MOVNS IOP ;- # WORDS CONTAINING DATA. + ADD IOP,[-1,,RDATA] + MOVEM IOP,HDR0 ;SET UP RDATA CMD CONTAINING THEM AND BYTE COUNT. + MOVEM C,HDR1 + ADD IOP,[-1,,HDR0-RDATA] + PUSHJ P,NETOUT ;Translate to bytes and send. But let the system + PUSHJ P,BUFFRC ;decide where to put in the packet boundaries. + MOVNS C + ADDM C,ALLOC ;DEDUCT BYTES SENT FROM ALLOCATION. +ALLI4: SKIPL EOFI ;NOW, IF WE REACHED EOF, TELL MLDEV THAT. + JRST GO4 ;ELSE HANDLE ANOTHER COMMAND. + ;NOTE WE MIGHT STILL HAVE SOME ALLOCATION LEFT. + ;IF SO, THEN WE WILL HANDLE IT AS SOON AS THERE + ;ARE NO COMMANDS PENDING. + +ALLEOF: HRROI B,REOF ;HERE WHEN WE REACH EOF: SEND REOF REPLY. + JRST REPLY1 + +IOTO: HRROI IOP,C ;HANDLE CDATA (DATE TO WRITE TO DEVICE) + PUSHJ P,NTIIOT ;READ BYTE COUNT. + ADD B,[1,,] + HRRI B,BUF ;READ THE DATA. + PUSHJ P,NTIIOB + SKIPE BLOKMD + JRST [ .IOT CHDEV,B + JRST GO4] ;IN BLOCK MODE, SEND OUT AS WORDS. + MOVE B,BUFBP + SYSCAL SIOT,[1000,,CHDEV ? B ? C] + JSR LOGOUT + JRST GO4 ;IN UNIT MODE, SEND OUT AS BYTES. + +CLSI: HRRI B,C + PUSHJ P,NTIIOB + .CLOSE CHDEV, + HRROI IOP,[RICLOS] + PUSHJ P,NETOFR + JRST GO4 + +CLSO: HRRI B,C + PUSHJ P,NTIIOB + .CLOSE CHDEV, + HRROI IOP,[ROCLOS] + PUSHJ P,NETOFR + JRST GO4 + +;HERE FOR CREUSE COMMAND, WHICH MEANS MLDEV IS ABOUT TO USE US FOR A DIFFERENT FILE +;AND WASNTS US TO REINITIALIZE EVERYTHING APPROPRIATE. +YREUSE: HRRI B,C ;IGNORE THE ARGUMENT. + PUSHJ P,NTIIOB + SETZM ALLOC ;DON'T EVEN TRY SENDING OUT MORE DATA. + HRROI IOP,[RREUSE] + PUSHJ P,NETOFR ;SO JUST ACKNOWLEDGE. + JRST GO4 + +LOGIN: HRRI B,UNAME ; READ LOGIN ID + PUSHJ P,NTIIOB + SETZM TRMNAM + MOVE A,[440600,,TRMNAM] + MOVEM A,TNAMBP + MOVEI A,6 + MOVEM A,TNAMCC ;6 SIXBIT CHARACTERS IN WORD + MOVE A,JOBUSR ;THE HOST AT THE OTHER END OF LINE + PUSHJ P,OCTPNT + MOVEI A,'J + PUSHJ P,SIXTYP + .SUSET [.RUIND,,A] ;THE USER INDEX IS MORE USEFUL + PUSHJ P,OCTPNT + MOVEI C,MAXLOG ;MAXIMUM LOGIN TRIES + SKIPA B,UNAME +LOGIN1: AOS UNAME + .CALL [ SETZ + SIXBIT /LOGIN/ + UNAME ;UNAME + TRMNAM ; "CONSOLE" (HOST AND USER INDEX) + SETZ B ] ; XUNAME + SOJG C,LOGIN1 ;KEEP TRYING UNTIL WE MAKE IT + HRROI IOP,[RLOGIN] ; AND ACKNOWLEDGE + PUSHJ P,NETOFR + JRST GO4 + +;LOGIN UTILITY ROUTINES + +OCTPNT: IDIVI A,10 ;THE NELSON RECURSIVE NUMBER PRINTER + HRLM B,(P) + SKIPE A + PUSHJ P,OCTPNT + HLRZ A,(P) + ADDI A,'0 +SIXTYP: SOSL TNAMCC ;MAXIMUM OF 6 CHARACTERS + IDPB A,TNAMBP +CPOPJ: POPJ P, + +FDEL1: HRRI B,DEV + PUSHJ P,NTIIOB + MOVEI A,[SETZ ? SIXBIT /RENAME/ + DEV ? FN1 ? FN2 ? FSNAM + FN2+1 ? FN2+2 + SETZB C] + SKIPE SNAME ; 0=>deleting + JRST FDEL5 + HRROI C,%ENSMD ; RETURN "MODE NOT AVAILABLE" ERROR IF NOT LOGGED IN + SKIPN UNAME + JRST FDEL4 + MOVEI A,[SETZ ? SIXBIT /DELETE/ + DEV ? FN1 ? FN2 ? FSNAM + SETZB C] +FDEL5: .CALL (A) + SKIPA ; Leave failure code in C if no skip + MOVEI C,-1 ; Set code of -1 to mean succeeded + HRROS C ; Set left half to -1 for RENAME/DELETE + ; Can't return the real name so just return code + ; Drop through to FDEL4 +FDEL4: MOVE B,[-1,,RFDELE] ; only sending status word + MOVE IOP,[-2,,B] ; Code is in "C". + PUSHJ P,NETOFR + JRST GO4 + +FDEL2: HRRI B,FN1 + PUSHJ P,NTIIOB + .CALL [ SETZ ? 'RENMWO ? 1000,,CHDEV ? FN1 ? FN2 + SETZB C] + SKIPA ; If failure leave code in C + MOVEI C,-1 ; Otherwise set -1 to mean success + ; Left half is zero here to mean reply to Rename while open + TRNN C,400000 ; RH sign will be on if we succeeded + JRST FDEL4 ; jump if call failed. + MOVE B,[-5,,RFDELE] + PUSHJ P,OPNRC1 ; Get the real file name and send it. + PUSHJ P,NETFRC + JRST GO4 + +YNOOP: HRRI B,C ;GET NOOP ARG + PUSHJ P,NTIIOB + HRROI B,RNOOP ;NOOP REPLY +REPLY1: MOVE IOP,[-2,,B] ;BLKO POINTER FOR NOOP REPLY + PUSHJ P,NETOFR + JRST GO4 ;BACK FOR NEXT COMMAND + +;HANDLE CACCES COMMAND +YACCES: HRRI B,B + PUSHJ P,NTIIOB ;GET TRANSACTION NUMBER FOR REPLY IN C + EXCH B,C ;AND ACCESS POINTER INTO B. NEW ALLOCATION IN D, USED ONLY IF INPUT. + .CALL [ SETZ + 'ACCESS + 1000,,CHDEV + SETZ B] ;PUT IT INTO DEV CHANNEL + JSR LOGOUT + SETZM EOFI + HRROI B,RACCES + MOVE IOP,[-2,,B] + PUSHJ P,NETOFR ;SEND REPLY + MOVE A,OPNM + TRNE A,1 ;IF OTHER END IS READING FILE, SEND WHAT WE'VE BEEN ALLOCATED. + JRST GO4 ;IF OTHER SIDE IS WRITING, WAIT FOR IT TO SEND MORE DATA. + MOVE C,D ;PROCESS NEW ALLOCATION SUPPLIED AS PART OF CACCES COMMAND, + MOVEM D,ALLOC + JRST ALLI1 ;THEN SEND NEW STUFF. + +;HANDLE REQUEST TO EXECUTE SYSTEM CALL. +YSYSCL: HRRI B,YSYSB + PUSHJ P,NTIIOB ;READ SYS CALL NAME AND ARGS. + MOVEI A,CHDEV ;1ST ARG IS NORMALLY DEV CHANNEL NUMBER, + MOVE B,YSYSB + CAME B,[SIXBIT/MLINK/] + MOVEM A,YSYSB+3 ;BUT FOR "MLINK" CALL, IT IS SENT BY MASTER. + MOVEM B,YSYSC+1 + MOVSI C,-NYSYSI + MOVSI D,(SETZ) + ANDCAM D,YSYSI(C) + AOBJN C,.-1 + SOS C,YSYSB+2 ;# OF INPUT ARGUMENTS-1 + IORM D,YSYSI(C) ;SET END OF ARG LIST AT APPROPRIATE PLACE + .CALL YSYSC + JRST [MOVSS A ? JRST YSYS1] + MOVEI A,1 ;SUCCESSFUL CALL RETURNS HERE - SAY WAS 1 SKIP. +YSYS1: MOVEM A,YSYSS + MOVE IOP,[-YSYSRL,,YSYSR] + PUSHJ P,NETOFR ;REPLY, GIVING MASTER VALUES RETURNED. + JRST GO4 + +TSINT: 0 +INTPC: 0 + MOVEM A,TSINTA ;IO INTR, CHECK SOCKET STATES + SKIPL A,TSINT + JRST TSFW +TSINTX: MOVE A,TSINTA + .DISMISS INTPC + +TSINTA: 0 + +TSFW: TRNN A,%PIIOC ;HERE FOR 1ST WORD INTERRUPT. + JSR LOGOUT + .SUSET [.RBCHN,,A] ;ONLY ONE WE CAN HANDLE IS AN IOC ERROR + CAIE A,CHDEV ;ON THE DEVICE BEING USED. + JSR LOGOUT ;IOC ERROR ON NET SOCKET MEANS MLDEV WANTS US TO DIE. + MOVSS A + ADD A,[.RIOS,,A] ;WHEN THAT HAPPENS, SEND OUT A RIOC COMMAND + .SUSET A ;CONTAINING THE IOC ERROR NUMBER. + LDB C,[330400,,A] + .DISMI [.+1] + HRROI B,RIOC + MOVE IOP,[-2,,B] + PUSHJ P,NETOFR + JRST GO4 ;ALSO ABORT WHATEVER WE WERE DOING. + +BYE1: JSR LOGOUT +BYE2: JSR LOGOUT +BYE3: JSR LOGOUT + +LOGOUT: 0 + SKIPE DEBUG + .VALUE + .LOGOUT + JRST .-2 + +;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 + JSR LOGOUT ;Probably connection closed + 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 ] + JSR LOGOUT ;Probably connection closed + 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). +NTIIOB: MOVE IOP,B + PUSHJ P,NTIIOT +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 ] + JSR LOGOUT ;Probably connection closed + SKIPE H + JSR LOGOUT ;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 + +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 + +LPDL==20 +PDL: BLOCK LPDL+4 + +PATCH: +PAT: BLOCK 40 + +RCH: BLOCK 10 ? STATE=RCH+4 ;THIS IS THE SOCKET STATE + +OPN: +DEV: 0 +FN1: 0 +FN2: 0 +SNAME: 0 +OPNM: 0 +FSNAM: 0 + BLOCK 10 ;SLOP FOR NET IOTS INTO HERE + +;LOGIN STUFF + +UNAME: 0 +TRMNAM: 0 +TNAMBP: 0 ;BYTE POINTER INTO UNAME +TNAMCC: 0 ;SIXBIT CHARACTER COUNT +JOBUSR: 0 ;THE FOREIGN USER +DEBUG: -1 ;DEBUG FLAG +SYSDBG: 0 ;SYSTEM BEING DEBUGGED FLAG +VERSIO: .FNAM1 + .FNAM2 + +BLOKMD: 0 ;-1 => DEVICE OPEN IN BLOCK MODE. +EOFI: 0 ;-1 => HAVE REACHED EOF ON INPUT +ALLOC: 0 ;-1 => ALLOCATION FOR DATA TO MLDEV, IN BYTES. + +HDR0: 0 ;HOLDS -N,,RDATA +HDR1: 0 ;HOLDS BYTE COUNT OF RDATA COMMAND. +BUF: BLOCK BUFL +BUFBP: 0 ;B.P. TO ILDB 1ST BYTE OF BUFFER. +BYTSIZ: 0 ;BYTE SIZE WE ARE XFERRING TO DEVICE. +BYTSWD: 0 ;# BYTES PER WORD. +BUFSIZ: 0 ;BUFFER SIZE IN BYTES. + +YSYSBL==11. +YSYSB: BLOCK YSYSBL + BLOCK 10 ;SLOP FOR NET IOTS INTO HERE + +YSYSR: 1-YSYSRL,,RSYSCL ;CODE FOR "REPLY TO SYSTEM CALL" +YSYSS: 0 ;ERROR CODE,,# SKIPS +YSYSV: BLOCK 10 ;VALUES RETURNED BY SYSTEM CALL GO HERE. +YSYSRL==.-YSYSR + +YSYSC: SETZ ;BLOCK FILLED IN FOR DOING SYSTEM CALL + SIXBIT/GAZONK/ ;NAME OF CALL STORED HERE + 4000,,YSYSB+1 ;CONTROL BITS + 3000,,A ;ERROR RETURN ARGUMENT +REPEAT 8,2000,,YSYSV+.RPCNT ;COLLECT OUTPUT ARGS +YSYSI: NYSYSI==8 +REPEAT NYSYSI, YSYSB+3+.RPCNT ;INPUT ARGS, SIGN BIT WILL GET TURNED ON IN LAST ONE + +DEVRCH: BLOCK 8 ;SPACE FOR .RCHST ON DSK + +$$HST3==1 +$$CHAOS==1 +$$TCP==1 +$$SERVE==1 + +.INSRT SYSENG;NETWRK + +LITTER: CONSTANTS +VARS:: VARIABLES + +END GO