;-*-MIDAS-*- TITLE BOJ JOB MLDEV, Uses MLSLV on other system ;;; Updated 2019-01-23 by EJS to cause NO SUCH DEVICE error if host ;;; not found in host table. 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). dskdev: sixbit /DSK/ ; DSK device nitses==:40 ;Room for plenty? itses: block nitses 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. ;; get ITS table move b,[-nitses,,itses] move c,[sixbit /ITSNMS/] .getsys b, .value ;; Parse device name. ;; A special case is hhSHOE which is the only four-char device ;; Otherwise, the form is either ;; HH, HHH, xHH, xHHH, HHDDD, DDDHH, HHHDDD or DDDHHH. ;; 0. Check for SHOE ldb c,[003000,,a] ; get last four characters camn c,[sixbit / SHOE/] ; is it the SHOE device? jrst doshoe ;; 1. If RH is empty: HH or HHH hrrz b,a skipn b ;anything in RH? jrst [ move b,a ;No, so check if we have an ITS name call isitsp jrst .+1 ;no, go on jrst gotits ] ;; 1b. could it be xHH or xHHH? "x" for eXperimental. ldb c,[.bp (770000),a] cain c,'X jrst [ move b,a lsh b,6 ;Maybe: lose X call isitsp jrst .+1 ;X but not followed by ITS name move a,b ;Remember host in A jrst gotits ] ;; 2. if len = 5: HHDDD or DDDHH ldb c,[.bp (000077),a] jumpn c,trysix ;Non-zero last char, so len = 6 ldb b,[.bp (777700),a] ;Get first two chars call isitsp jrst [ hrlz b,a ;wasn't HHDDD, try DDDHH call isitsp jrst notits jrst gotddd ] ;; was HHDDD move c,a lsh c,12. ;remove HH movem c,jbcdev move a,b jrst gothst trysix: ;; 3. HHHDDD or DDDHHH hllz b,a ;Check if LH is HHH call isitsp jrst [ hrlz b,a ;Check if RH is HHH call isitsp jrst notits jrst gotddd ] ;; It was HHHDDD hrlzm a,jbcdev move a,b jrst gothst ;; Device is SHOE, check if it is preceded by HH doshoe: ldb b,[.bp (777700),a] ; get 2-character hostname lsh b,30. ; left justify hostname call isitsp jrst notits ;Wasn't an ITS name! lsh c,12. ; left justify device movem c,jbcdev ; set remote device move a,b jrst gothst ;; Got an ITS name in A, default to DSK devcie gotits: move b,dskdev movem b,jbcdev jrst gothst ;; Got DDDhh or DDDhhh, device in LH(a), host in B gotddd: hllzm a,jbcdev ;save DDD move a,b ;get HH jrst gothst ;; here we've determined that hostname is invalid, check for special device notits: ;; @@@@ BV: I suggest this hackery is removed, since these hosts don't exist in those configurations ifn 0,[ MOVS C,JBCDEV CAIN C,'XGP ;XGP THROUGH THE NET TO AI FROM ML/MC/DM JRST [ MOVEI A,'AI JRST GOTHSX] CAIN A,'GLP ;GOULD THROUGH THE NET TO MX JRST [ MOVEI A,'MX JRST GOTHSX] CAIN A,'DVR ;DVR THROUGH THE NET TO MC FROM AI/ML/DM JRST [ MOVEI A,'MC JRST GOTHSX] CAIN A,'DVS ;DVS THROUGH THE NET TO MC FROM ML/DM JRST [ MOVEI A,'MC JRST GOTHSX] CAIN A,'TPL ;TPL THROUGH THE NETWORK FOR MC JRST [ 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 GOTHSX ] ] ;HOST NOT RECOGNIZED NSD: MOVSI A,%ENSDV JRST NOGO2 ;; Check if B has the name of an ITS, if so, skip return ;; Messes up T isitsp: movsi t,-nitses isitz0: camn b,itses(t) jrst popj1 ;match, skip return skipe itses(t) aobjn t,isitz0 popj p, ;A CONTAINS SIXBIT HOST, left-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 JRST NSD ; if we can't lookup host address -> no such device MOVEM A,HOSTN' ;Host number MOVEM TT,NETWRK' ;Network number PUSHJ P,NETWRK"HSTUNMAP ;Don't need host table any more .VALUE move a,jbcdev ;Get parsed device 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