;-*-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