;;; Copyright (c) 1999 Massachusetts Institute of Technology ;;; ;;; This program is free software; you can redistribute it and/or ;;; modify it under the terms of the GNU General Public License as ;;; published by the Free Software Foundation; either version 3 of the ;;; License, or (at your option) any later version. ;;; ;;; This program is distributed in the hope that it will be useful, ;;; but WITHOUT ANY WARRANTY; without even the implied warranty of ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ;;; General Public License for more details. ;;; ;;; You should have received a copy of the GNU General Public License ;;; along with this program; if not, write to the Free Software ;;; Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ;******************************** ;** ;** TO BE DONE: ;** ;** RECORDS LONGER THAN 1K ;** AUTOMTAIC DETERMINATION OF DENSITY AND RECORD LENGTH WHEN READING ;** ALLOW CLOSE WHEN TAPE HAS BEEN TAKEN OFF ;** BE MORE FORGIVING OF CONTROLLER LOSSAGE ;** PASS .MTAPE TO JOB DEVICE ;** HAVE AN IGNORE ERRORS SWITCH ;** THIS HORRIBLE BLETCHEROUS IOT CODE SHOULD BE REDESIGNED ;** ;******************************** IFN TM10A,TM10B==0 IFE TM10A,TM10B==1 IFN TM10A,INFORM IO BUSS MAG TAPE,1 IFN TM10B,INFORM DATA CHANNEL MAG TAPE,1 MSCBL==8 ; COMMAND BUFFER LENGTH MGQDLL==6 ; INTERUPT LEVEL PDL IF2 IFN MNUMB-140600, .ERR IMPLICIT DEPENDENCY ON MNUMB MSEOFP==210100 ;HIGH BIT OF MNUMB IN MEMBLT IS EOF FLAG MSCHN==140500 ;OTHER 5 BITS OF MNUMB IN MEMBLT IS DRIVE NUMBER MTXP==410300,, ;XPORT NUMBER MUNITF==170300 ; UNIT FIELD IN MTC CONI MNOPIN==10000 MWRITE==4000 MW3IN==14000 MSPRR==7000 MREAD==2000 MSPFR==6000 MSPFF==16000 MSPRF==17000 MREWND==1000 MRWNDD==11000 MWEOF==5000 MGNRTY==10. ;NUMBER OF READ RETRIES SUBTTL MAG TAPE OPEN ROUTINE ; C/ MODE,,DEV ; D/ MODE (ROT 1) 4.9=1=>OUTPUT ; I/ DEVICE NUMBER ; R/ IOCHNM WORD POINTER MAGTO: SKIPL W,I ; GET DEVICE CAIL W,NMTCS ; TO BIG? JRST OPNL1 ; NO SUCH DEVICE MOVSI T,%MAREW TDNE T,MSRAC(W) ; REWINDING PUSHJ P,UFLS ; YES, THEN WAIT CONO PI,CLKOFF ; DON'T WANT STATUS CHANGED FROM UNDER ME SKIPGE MTUSE(W) ; CHECK FOR FIRST USER JRST MAGTU1 ; FIRST CAME U,MTUSR(W) ;SAME USER JRST OPNL10 ; DIFFERENT USER IS ERROR MOVE B,D EQV B,MSCRW(W) SKIPL B ; CHECK FOR SECOND OPEN IN SAME DIRECTION JRST OPNL2 ; WRONG DIRECTION MAGTU: MOVEM U,MTUSR(W) ; STORE USER SETZM MSCRW(W) ; INDICATE READ UNTIL FOUND TO BE OTHERWISE TLNE C,1 ; READ OR WRITE SETOM MSCRW(W) ;INDICATE WRITE AOS MTUSE(W) ;INDICATE 1 MORE USER PUSHJ P,SOSSET MTUSE(W) ; SOS IF PCLSRED CONO PI,CLKON ; LET UM GET ME PUSHJ P,MTSTAT ; GET CONIS OF 340 AND 344 IN I AND J MOVE A,MSRAC(W) TLNE A,%MAERR ; PI ERROR MEANS DEVICE NOT THERE JRST MTOL1 TRNN J,200040 JRST OPNL7 ; DEVICE NOT ONLINE SKIPN MSCRW(W) ;WRITING? JRST MTOW1 TRNE J,10 ; AND WRITE LOCKED JRST OPNL26 ; DEVICE WRITELOCKED SKIPE MSRAC(W) ; WRITING TRNN J,4000 ;EOT? JRST MTOW1 ; NO MOVSI A,%MAETW+%MAERR ; IF WRITE AND EOT,MAKE .IOT GIVE IOC ERROR BUT LET OPEN WIN IORM A,MSRAC(W) MTOW1: TRNN J,400000 ; XPORT HUNG JRST MTOW2 ; OK TRNN J,20000 ; OK IF REWINDING JRST OPNL7 ;DEVICE NOT WORKING MTOW2: TLNN C,400 ; GET CORE DUMP MODE JRST MTOW3 TLNN C,300 JRST MTOW3 TLC C,300 TLCE C,300 ; IBM AND DENSITY 800 BPI OK JRST OPNL12 ; MODE NOT AVAILABLE MTOW3: ;BY THIS POINT OPEN WILL WIN PUSHJ P,LSWDEL ; RELEASE MTUSE SWITCH MOVEI A,MTCCHN_3 ;SET UP MAG TAPE CONO IFN TM10A, TRO A,1 ; DATA PI CHANNEL LDB B,[300200,,C] ; GET DENSITY FROM OPEN SKIPN B MOVEI B,3 SUBI B,1 ; CONVERT TO PROPER PARITY DPB B,[060200,,A] TLNN C,400 ; CORE DUMP TRO A,20000 ; YES TLNN C,40 ; PARITY CHECK TRO A,40000 ; SET ODD PARITY DPB W,[170300,,A] ; SET UNIT NUMBER MOVEM A,MTCONO(W) ; STORE IT LDB B,[330300,,C] ; GET WORDS PER BLOCK TRC B,7 MOVEI A,10 LSH A,(B) ;NUMBER OF WORDS PER RECORD MOVEM A,MTBLKS(W) ;BLOCKSIZE LDB A,[230200,,C] ; GET MODE (BUT NOT READ/WRITE BIT) HLR C,MTOPTB(A) ; GET INPUT DISPATCH TLNE D,400000 ; OPEN FOR OUTPUT? HRR C,MTOPTB(A);CHANGE TO OUTPUT IF SO MOVEM C,(R) ;STORE IN IOCHNM DPB W,[MTXP(R)] ; STORE XPORT NUMBER JRST POPJ1 ; SKIP RETURN MTOPTB: MTUAIX,,MTUAOX MTBIX,,MTBOX MTUIIX,,MTUIOX MTBIX,,MTBOX MAGTU1: SETZM MSBUFP(W) ; INDICATE NO BUFFERS ON CHAIN SETZM MSNBOL(W) ; ANOTHER WAY OF SAYING ABOVE SETZM MSMPRC(W) ; BUFFER WORDS REMAINING SETZM MSMPRP(W) ; POINTER TO BUFFERS SETOM MTMDN(W) ;NO BUFFER AT MP SETOM MGCABN(W) ;NONE AT PI SETZM MSRAC(W) MOVEI A,2 MOVEM A,MTCEFW(W) ; NUMBER OF EOF'S WRITTEN MOVSI A,%MANWT IORM A,MSRAC(W) ; INDICATE NOTHING WRITTEN ON TAPE JRST MAGTU MTOL1: SETZM MSRAC(W) JRST OPNL1 SUBTTL MAG TAPE INPUT .IOT ROUTINES SKIPA B,[SIOKT] MTUAI: MOVEI B,CHRKTI ;UNIT ASCII INPUT MOVE E,[440700,,5] JRST MTREAD SKIPA B,[SIOKT] MTUII: MOVEI B,CHRKTI ;UNIT IMAGE MOVE E,[444400,,1] JRST MTREAD MTBI: MOVE E,[444400,,1] ;BLOCK INPUT MOVEI B,BLKT MTREAD: LDB W,[MTXP(R)] ; W <= XPT # PUSHJ P,MTIECK MOVEM P,MTPSAV(W) ; SAVE P FOR EOF RETURN JSP B,(B) ;BLKT,CHRKT,SIOKT MSMPRP(W) ;LOC OF NEXT WORD MSMPRC(W) ;COUNT REMAINING SETZ MTRBG ; GET NEW BUFFER (SETZ FOR CHRKT RETURN ON EOF) MTRBD ; DISCARD BUFFER JRST 4,. PUSHJ P,MTRBFW ; FLUSH INSTRUCTION WAIT FOR BUFFERS TO COME FROM PI ;MAG TAPE READ BUFFER GET ROUTINE ; BUFFER ASSUMED TO HAVE COME IN FROM PI LEVEL. (I.E. MTRBFW WAS CALLED) MTRBG: SKIPG MSNBOL(W) ;ANY BUFFER AVAILABLE? JRST MTRBG3 ;NO, MUST BE ERROR OR EOF CONO PI,UTCOFF HLRZ A,MSBUFP(W) ; GET IN POINTER HRRZ TT,MSBUFP(W) ; GET OUT POINTER MOVEM TT,MTMDN(W) ; STORE BUFFER ACTIVE AT MP CAMN A,TT ;IN = OUT? JRST MTRBG1 ; YES LDB T,[MLO,,MEMBLT(TT)] ; BACK POINTER TO NEXT BLOCK HRRM T,MSBUFP(W) ;STORE NEW OUT POINTER JRST MTRBG2 MTRBG1: SETZM MSBUFP(W) ;EMPTY BUFFER LIST MTRBG2: SOS MSNBOL(W) ; ONE LESS BUFFER ON LIST CONO PI,UTCON LDB J,[MWC,,MEMBLT(TT)] ;WORD COUNT OF BLOCK MOVEM J,MTBLKS(W) ;SAVE FOR MTAPE 13 LSH TT,10. ;MAKE BLOCK NUMBER AN ADDRESS MOVEM TT,MSMPRP(W) JRST SIOBGX MTRBG3: SKIPGE MSRAC(W) .SEE %MAEOF JRST [ MOVSI T,%MAEFA ;THE EOF IS NOW NO LONGER READ-AHEAD ANDCAM T,MSRAC(W) ;TELL THE USER ABOUT IT JRST POPJ2 ] PUSHJ P,MTIECK JRST 4,. ;BULLSHIT, WHY DID MTRBFW SKIP? ;MAG TAPE READ BUFFER DISCARD ROUTINE MTRBD: SKIPGE A,MTMDN(W) ; ANY BUFFERS JRST MOVTWJ ;SET UP T FOR BUFFER WAIT,RETURN CONO PI,UTCOFF ; SHUT UP WORLD SETOM MTMDN(W) ; NO BUFFER ACTIVE AT M.P. SETZM MSMPRC(W) LDB TT,[MSEOFP,,MEMBLT(A)] ;GET EOF FLAG FROM PI PUSHJ P,MGMEMR ;RETURN MEM, TURN UTCON JUMPN TT,MTRBD2 ;EOF? MOVTWJ: MOVE T,W ; T NEEDS CHANNEL NUMBER FOR BUFFER WAIT UFLUSH POPJ P, ;ALSO MTRBG, MTRBFW RELY ON THIS SETTING T MTRBD2: MOVSI A,%MAEOF ; SET EOF IORM A,MSRAC(W) JRST MOVTWJ ;MAG TAPE READ WAIT FOR DATA ROUTINE MTRBFW: SKIPG MSNBOL(T) ; ANY FREE BUFFERS ON LIST? SKIPGE MSRAC(T) .SEE %MAEOF JRST POPJ1 ;INPUT AVAILABLE, OR AT EOF, UNHANG MOVE TT,MSRAC(T) TLNE TT,%MAERR ; CHECK FOR ERRORS JRST POPJ1 ;WAKE UP SO YOU CAN GET YOUR IOC ERROR TLNE TT,%MARAC ; IF NOT ALREADY DONE SO, SEND OUT A CALL FOR TAPE READ POPJ P, PUSH P,W ;THIS BEING DONE UNDER A UFLS. ONLY T GOOD PUSH P,B MOVE W,T MOVEI B,MGREAD ;WHERE TO GO AT PI LEVEL MOVEI T,MSCBL ;MAKE SURE THAT THERE IS ROOM IN THE RING BUFFER CAMG T,MSCMDC(W) JRST MTRBW2 ; NO ROOM, GO AWAY MOVSI TT,%MARAC IORM TT,MSRAC(W) ;READ IS ACTIVE NOW, OR WILL BE SHORTLY PUSHJ P,MTCMD1 MTRBW2: MOVE T,W POP P,B POP P,W POPJ P, SUBTTL MAG TAPE OUTPUT .IOT ROUTINES SKIPA B,[SIOKT] MTUAO: MOVEI B,CHRKT ;UNIT ASCII OUTPUT MOVE E,[440700,,5] JRST MTWRIT SKIPA B,[SIOKT] MTUIO: MOVEI B,CHRKT ;UNIT IMAGE OUTPUT MOVE E,[444400,,1] JRST MTWRIT MTBO: MOVE E,[444400,,1] ; BLOCK OUT MOVEI B,BLKT MTWRIT: LDB W,[MTXP(R)] ; GET XPORT NUMBER PUSHJ P,MTIECK HRLZI A,%MAETW ; END OF TAPE CHECK TDNE A,MSRAC(W) JRST IOCER9 JSP B,(B) SETZ MSMPRP(W) ;LOC OF WORD MSMPRC(W) ; COUNT SETZ MTWBFG ; GET NEW BUFFER MTWBFD ; WRITE OUT BUFFERS JRST 4,. TRNA ;NO WAIT FOR BUFFER ;MAG TAPE WRITE BUFFER GET ROUTINE MTWBFG: PUSHJ P,MTIECK PUSHJ P,TCALL ; TURN OFF UTC JRST IOMQ POPJ P, ;GO BACK NO SKIP IF NO CORE MOVEM A,MTMDN(W) ; STORE ACTIVE BUFFER NUMBER MOVEI T,MUMGB DPB T,[MUR,,MEMBLT(A)] ; TELL WORLD THAT IT IS A MAG TAPE BUFFER DPB W,[MSCHN,,MEMBLT(A)] ; CHANNEL NUMBER SETZM TT DPB A,[121000,,TT] ;CONVERT BLOCK NUMBER TO ADDRESS IN TT MOVE J,MTBLKS(W) ;GET WRITE BLOCK SIZE JRST SIOBGX ;MAG TAPE WRITE BUFFER DISCARD ROUTINE MTWBFD: PUSHJ P,MTIECK SKIPGE A,MTMDN(W) POPJ P, MOVEI T,MSCBL CAMG T,MSCMDC(W) PUSHJ P,UFLS ; MAKE SURE ROOM IN COMMAND BUFFER EXISTS IN CASE OF PCLSRING MOVE T,MTBLKS(W) ; DISCARD BUFFER. FIRST SEE HOW BIG IT IS SUB T,MSMPRC(W) CONO PI,UTCOFF ;CAN'T TOLERATE ANY HANKY PANKY SETOM MTMDN(W) ;CLEAR IT SETZM MSMPRC(W) ; CLEAR COUNT JUMPE T,MEMR ; DON'T DO ANYTHING BUT RETURN BLOCK IF NO WORDS DPB T,[MWC,,MEMBLT(A)] ; STORE WORD COUNT SKIPG MSNBOL(W) ; LIST STARTED YET? JRST MTWBD1 ;NO HLRZ TT,MSBUFP(W) ; GET OLD IN POINTER DPB A,[MLO,,MEMBLT(TT)] ;CHAIN BACK SKIPA MTWBD1: HRRM A,MSBUFP(W) ; START NEW LIST HRLM A,MSBUFP(W) ; IN = OUT = (A) MTWBD2: SETZM TT DPB TT,[MLO,,MEMBLT(A)] ; INDICATE END OF LIST AOS MSNBOL(W) ; ONE MORE BUFFER ON LIST CONO PI,UTCON PUSH P,B MOVEI B,MGWRIT PUSHJ P,MTCMD MOVSI B,%MANWT ANDCAM B,MSRAC(W) SETZM MTCEFW(W) ; INDICATE SOMETHING WRITTEN JRST POPBJ ; RETURN SUBTTL MTCMD - GIVE COMMAND TO PI LEVEL ;PUSHJ P,MTCMD ;RH(W) HAS XPORT NUMBER ;RH(B) HAS ADDR OF INTERUPT ROUTINE MTCMD: MOVEI T,MSCBL ; COMAND BUFFER LENGTH CAMG T,MSCMDC(W) ;COMAND COUNT PUSHJ P,UFLS ; WAIT FOR ROOM MTCMD1: MOVE T,MTCMBP(W) ; GET POINTER TO RING BUFFER AOBJN T,.+2 SUB T,[MSCBL,,MSCBL] ; REACHED END OF BUFFER, RING IT MOVEM B,(T) ; STORE COMMAND MOVEM T,MTCMBP(W) ; STORE NEW POINTER CONO PI,UTCOFF AOS MSCMDC(W) ; INDICATE ONE MORE COMMAND JRST MSTRTR ; START UP PI ROUTINE SUBTTL MTIECK - CHECK FOR IOC ERROR MTIECK: PUSH P,A ; CHECK FOR IOTERR MOVE A,MSRAC(W) TLNN A,%MAERR ; ERROR AT PI? JRST POPAJ SKIPLE MSCMDC(W) PUSHJ P,UFLS ; LET PI CLEAR BEFORE MUNGING BUFFERS SKIPL A,MTMDN(W) PUSHJ P,MEMR SETOM MTMDN(W) SETZM MSMPRP(W) SETZM MSMPRP(W) PUSHJ P,MTCBFF ; FREE CHAIN POP P,A MOVE T,MGCMTS(W) ; GET CONI MTS, TRNE T,440000 ; XPT HUNG,ILLOP JRST IOCER1 TRNE T,23600 ; PAR ERROR,R/C, RLI,DL,BT JRST IOCER3 ; IRRECORVERABLE DATA ERROR TRNE T,4000 ; EOT JRST IOCER9 ; EOT, DEV FULL MOVE A,MGEOFR(W) ; LOGICAL EOT CAIL A,2 JRST IOCER9 JRST IOCER3 ; UNKNOWN, GIVE IRR DATA SUBTTL MAG TAPE .STATUS ROUTINE STAMTC: LDB W,[MTXP(R)] ; LOAD W DPB A,[60300,,D] ; OPEN MODE PUSHJ P,MTSTAT LDB A,[.BP %MAETW_22,MSRAC(W)] ; EOT ON WRITE LDB B,[.BP %MAETR_22,MSRAC(W)] ; EOT ON READ IOR A,B DPB B,[140100,,D] ;EOT LDB A,[20100,,J] TRC A,1 DPB A,[150100,,D] ; 7 OR 9 LDB A,[160100,,MTCONO(W)] TRC A,1 DPB A,[200100,,D] ;PARITY LDB A,[60200,,MTCONO(W)] ; DENSITY ADDI A,1 CAIN A,3 SETZM A ; 800 IS 00 DPB A,[160200,,D] LDB A,[.BP %MARCE_22,MSRAC(W)] ; READ COMPARE ERROR DPB A,[130100,,D] MOVE A,MTCONO(W) TRNN J,4 ; 7 TRACK TRNE A,20000 ; OR CORE DUMP POPJ P, ; THEN DONE TRO D,140000 ; IBM, 9 TRACK AND 800 BPI POPJ P, ;RCHST ROUTINE FOR MAG TAPE RCHMGT: HLRZ E,(R) ;OPEN-MODE IS KEPT IN LH OF IOCHNM WORD - HOW CONVENIENT! LDB J,[MTXP(R)] ;GET THE MAG TAPE DRIVE NUMBER MOVSI J,'MT0(J) ;RETURN THAT DRIVE'S DEVICE NAME. TRZ E,(.BM MTXP) ;CLEAR THE PLACE IN THE OPEN-MODE THAT HAS THE DRIVE #. JRST POPJ1 ;SKIP SO THAT J OVERRIDES BUILT-IN DEVICE NAME. EBLK SUBTTL MAG TAPE STORAGE AREA MGVTC: 0 ; 1 SCRATCH WORD FOR VIRGIN TAPE CHECK MGRWCD: BLOCK NMTCS ; REWIND COMMAND MGEOTT: BLOCK NMTCS ; TIMEOUT FOR VIRGIN TAPE MGJDTI: 0 ; WAIT FOR JOB DONE TIME OUT MGEOFR: BLOCK NMTCS ; NUMBER OF EOFS SINCE LAST READ MGNWRD: 0 ; NUMBER OF WORDS READ IN A PI LEVEL READ MTPSAV: BLOCK NMTCS ; STORAGE TO RESTORE P ON EOF MSRAC: BLOCK NMTCS ; MAG TAPE GENERAL GARBAGE %MA==1,,525252 %MAEOF==400000 ; 4.9 EOF ON READ %MAETR==200000 ; 4.8 EOT ON INTERNAL READ %MAETW==100000 ; 4.7 EOT ON WRITE %MAERR==040000 ; 4.6 PI ERROR %MARCE==020000 ; 4.5 READ COMPARE ERROR %MACTH==014000 ; 4.4 CORE ALLOCATOR SAYS STOP ; 4.3 " (WHY 2 BITS?) %MASTP==002000 ; 4.2 STOP READ AHEAD %MANWT==001000 ; 4.1 NOTHING WRITTEN ON TAPE YET %MAEFA==000400 ; 3.9 EOF SEEN ON READ-AHEAD, USER HASN'T SEEN YET %MAESO==000200 ; 3.8 EOF READ SINCE OPEN %MAMSO==000100 ; 3.7 TAPE MOVED SINCE FIRST OPEN %MAREW==000040 ; 3.6 REWINDING FLAG %MARAC==000020 ; 3.5 READ ACTIVE FLAG MGTBZY: -1 ; FLAG TO GET INTURPT STARTED MTCONO: REPEAT NMTCS,\.RPCNT_17+20 ; MAIN CONO STORAGE MGUNIT: -1 ; UNIT EXPECTING INTERUPT MGCMTS: BLOCK NMTCS ; PI CONI MTS STORAGE MGCMTC: BLOCK NMTCS ; PI MTC STORAGE MGWCW: 0 ; WAIT FOR CONTROL WORD WRITTEN FLAG LMIOWD: 0 ; LAST MIOWD MGERRC: BLOCK NMTCS ; ERROR COUNT MTMFNC: BLOCK NMTCS ; .MTAPE FUNCTION STORAGE MTMCNT: BLOCK NMTCS ; .MTAPE COUNT MTMTAP: BLOCK NMTCS ; MTAPE CALL WORD MTCEFW: BLOCK NMTCS ; NUMBER OF EOF'S WRITTEN AT CLOSE MSCMDC: REPEAT NMTCS,0 ; NUMBER OF COMMANDS MSBUFP: REPEAT NMTCS,0 ; MAG TAPE BUFFER POINTER IN,,OUT MSCRW: BLOCK NMTCS ; -1=>OUTPUT 0=>INPUT MSMPRC: BLOCK NMTCS ; WORDS LEFT IN BUFFER MSMPRP: BLOCK NMTCS ;NEXT WORD IN BUFFER MTMDN: REPEAT NMTCS,-1 ; BLOCK ACTIVE AT MP MTUSE: REPEAT NMTCS,-1 ; NUMBER OF CHANNELS OPEN ON THIS MTAPE MTUSR: REPEAT NMTCS,-1 ; USER INDEX OF XPORT MSNBOL: BLOCK NMTCS ; NUMBER OF BUFFERS ON LIST MGCABN: REPEAT NMTCS,-1 ; BUFFER ACTIVE AT PI LEVEL MTBLKS: BLOCK NMTCS ; WRITE, BUFFER SIZE ; READ, SIZE OF LAST RECORD READ MGQDLP: REPEAT NMTCS,-MGQDLL,,CONC MGQD,\.RPCNT,-1 ;QDL POINTER REPEAT NMTCS,[ CONC MSCB,\.RPCNT,: BLOCK MSCBL ; COMMAND BUFFER MGRCV ; TO RING BUFFER MGNCMD ; GET NEW COMMAND CONC MGQD,\.RPCNT,: BLOCK MGQDLL IFE .RPCNT,MSLCTB==.-MSCB0 ; LENGTH OF EACH TABLE ] MTCMBP: REPEAT NMTCS,-MSCBL-1,,CONC MSCB,\.RPCNT,-1 ; INPUT TO COMMAND TABLE MGCMBP: REPEAT NMTCS,4400,,CONC MSCB,\.RPCNT,-1 ; OUTPUT FROM COMAND TABLE IFE KL10P,MIOWD: BLOCK 2 ; CHANNEL PROGRAM IFN TM10A,[ MGDBRK: 0 CONO MTS,1 JRST 12,@MGDBRK ];TM10A MGEMTC: 0 ;CONI MTC, AT LAST ERROR MGEMTS: 0 ;CONI MTS, AT LAST ERROR BBLK SUBTTL MAG TAPE PI LEVEL ;ROUTINES TO GET INTERUPT ROUTINES STARTED MGXGO: MOVE Q,MGQDLP(W) ;GET QDLPOINTER PUSHJ P,QPOPJ ;CALL ROUTINE . SHOULD FINISH WITH POPJ P,OR PUSHJ Q,CPOPJ ;PUSHJ Q,CPOPJ IF ROUTINE WANTS TO RETURN ;POPJ P, IF AT END OF COMAND. AND NEW IS TO BE GOTTEN MOVEM Q,MGQDLP(W) ; STORE NEW QDL POPJ P, MGRCV: MOVNI A,MSCBL+1 ;AT END OF COMAND LIST,RING IT ADDM A,MGCMBP(W) ;RING THE BUFFER MGNCM1: ILDB B,MGCMBP(W) ; GET NEW COMMAND JRST (B) MGNCMD: AOBJN Q,MGNCM1 ; AT BOTTOM OF QDL, SIMULATE PUSHJ AND GET NEW COMMAND JRST 4,. ;QDL POINTER CLOBBERED QPOPJ1: AOS (Q) QPOPJ: POPJ Q, MSTRTR: CONO PI,UTCOFF ; GET MAGTAPE INTURPT STARTED SETZM MGTBZY CONO PI,MTCRQ CONO PI,UTCON POPJ P, ;HERE FOR MAG TAPE FLAG CHANNEL INTERUPT MGHBRK: SKIPGE W,MGUNIT ; LOAD UNIT JRST MGUBRK ;NO ONE WANTS IT LDB B,[MUNITF,,A] CAME W,B ; UNITS AGREE JRST 4,. ; WE MUST NOT MIX UNITS MOVE J,C PUSH P,[DSKEX] IFN TM10B,[ TLNE C,160 JRST MGERR ];TM10B TRNE C,40000 JRST MGERR JRST MGXGO MGSBRK: SETOM MGTBZY ;HERE FOR ANY RANDOM MP PI STARTUP MOVEI B,NMTCS-1 SKIPG MSCMDC(B) ;ANY COMMANDS IN BUFFER MGSBK1: SOJGE B,.-1 SKIPGE B ;LAST UNIT? JRST DSKEX ; THEN GOTO DSKEX MOVE W,B PUSH P,B MOVSI B,%MACTH TDNN B,MSRAC(W) ; CORE ALLOCATOR SAYING GO AWAY PUSHJ P,MGXGO ; START UP THAT ROUTINE POP P,B JRST MGSBK1 ; ANY MORE? MGUBRK: LDB W,[MUNITF,,A] ; WHO CAUSED INTERUPT? MOVE B,MTCONO(W) CONO MTC,(B) CONO MTS,31 ; CLEAR INTERUPT JRST DSKEX ; ROUTINE TO WAIT FOR JOB DONE TO SET MGWTJD: CONI MTS,J TRNE J,440000 ;SKIP IF STARTED SUCCESSFULLY JRST MGERR ;JOB-DONE ISN'T EVER GOING TO SET MGWJD1: CONI MTS,J SKIPN MGJDTI ; TIME OUT? JRST MGWJD2 MOVE T,TIME CAML T,MGJDTI JRST MGERR MGWJD2: TRNN J,100 ; JOB DONE? JRST MGOVER ; NOT SET CONI MTS,J CONI MTC,I ; GET CONI MTC MOVEM J,MGCMTS(W) MOVEM I,MGCMTC(W) SKIPE MGWCW ; SHOULD I WAIT FOR CONTROL WORD WRITTEN PUSHJ Q,MGWCWC ; CHECK TO SEE IF IT IS WRITTEN SETZM MGWCW ;CLEAR FLAG CONO MTS,30 ; CLEAR CHANNEL CONDITIONS MOVE B,MTCONO(W) CONO MTC,(B) ; RELESE MTC, CLEAR JOB DONE IFN TM10B,[ TLNE J,160 POPJ Q, ;CHANNEL ERROR ] TRNE J,463600 POPJ Q, ; RANDOM OTHER NON PERFECTIONS, NOT NECESSARILY ERRORS JRST QPOPJ1 ; SUCCESS ; GET XPORT MGGXPT: CONSO MTS,2 ; LOAD NEXT UNIT SET? JRST MGOVER ; NO, WAIT FOR IT MOVEM W,MGUNIT MOVE T,TIME ADDI T,10.*30. ; TIME OUT IN 10. SECONDS MOVEM T,MGJDTI MOVE B,MTCONO(W) CONO MTC,MNOPIN(B) ; SELECT DRIVE PUSHJ Q,MGWJD1 JFCL ; WAIT FOR JOB DONE, BUT ALLOW ANY ERRORS SETZM MGJDTI POPJ Q, MGOVER: CONSZ MTS,440020 ; ANY PROBLEMS? JRST MGERR ;TAPE HUNG, ILL FUNCTION, CHANNEL ERROR SOS (Q) POPJ P, ;ERROR MGERR: CONI MTS,MGEMTS CONI MTC,MGEMTC MOVSI T,%MARAC ;READ NOT ACTIVE, FOR SURE ANDCAM T,MSRAC(W) SETZM MSCMDC(W) ; NO COMMANDS SETOM MGUNIT ; CLEAR UNIT WAIT FLAG SETZM MGJDTI IFN TM10B,[ TLNE J,160 ; CHANNEL ERROR? BUG PAUSE,[MTAPE: CHANNEL ERROR, STATUS=],OCT,J,[MICWA+1=],OCT,MICWA+1,[MIOWD=],OCT,MIOWD ];TM10B SKIPL A,MGCABN(W) ; ANY PI BUFFERS? PUSHJ P,IMEMR SETOM MGCABN(W) HRLZI B,%MAERR ; PI ERROR IORM B,MSRAC(W) ; STORE IN STATUS WORD MOVE Q,[-MGQDLL,,MGQD0-1] MOVE T,MSLCTB IMUL T,W ADD Q,T ; RESTORE Q PUSH P,Q MOVE Q,[-MSCBL-1,,MSCB0-1] ADD Q,T MOVEM Q,MTCMBP(W) ; INITIALIZE MP AND PI COMMND POINTERS MOVE Q,[4400,,MSCB0-1] ADD Q,T MOVEM Q,MGCMBP(W) MOVSI B,%MAREW ANDCAM B,MSRAC(W) ; CLEAR REWINDING SKIPN MSCRW(W) ; DONE IF READING JRST POPQJ SKIPN MSNBOL(W) ; ANY BUFFERS ON LIST? JRST POPQJ MGERR1: HRRZ A,MSBUFP(W) PUSHJ P,MTICL1 PUSHJ P,IMEMR SOSLE MSNBOL(W) ; ANY MORE JRST MGERR1 SETZM MSBUFP(W) ;EMPTY LIST JRST POPQJ MGWCWC: IFN TM10B,[ SKIPE MICWA+1 ; CONTROL WORD WRITTEN? POPJ Q, CONO MTS,4 ; TELL IT TO WRITE IT MGWCW1: SKIPE MICWA+1 JRST MGWCW2 ; DONE PUSHJ Q,CPOPJ ; WAIT JRST MGWCW1 MGWCW2: MOVE I,MGCMTC(W) MOVE J,MGCMTS(W) ;RESTORE STATUS TLO J,10 ;SET CONTROL WORD WRITTEN ] ;END OF IFN TM10B POPJ Q, IFN TM10A,[ MGDCSI: SKIPA A,[BLKI MTC,MIOWD] MGDCSO: MOVE A,[BLKO MTC,MIOWD] MOVEM A,MAGLOC MOVE A,[JSR MGDBRK] MOVEM A,MAGLOC+1 POPJ Q, ] ;END OF IFN TM10A SUBTTL MAG TAPE PI LEVEL WRITE MGWRIT: PUSHJ Q,MGGXPT ; GET XPORT TRNE J,600010 ; WRITE LOCKED,HUNG OR REWINDING JRST MGERR MOVEM W,MGUNIT ; SET UNIT MOVSI A,%MACTH ; CORE ALLOC WANT QUIT TEMPORARLY TDNE A,MSRAC(W) JRST MGWRT4 HRRZ A,MSBUFP(W) ; GET BUFFER POINTER HLRZ B,MSBUFP(W) ; IN POINTER SOS MSNBOL(W) ; ONE LESS BUFFER MOVEM A,MGCABN(W) ; BUFFER ACTIVE AT PI SKIPN MSCRW(W) ; WRITING JRST 4,. CAME A,B ; IN = OUT JRST MGWRT1 SETZM MSBUFP(W) ; EMPTY BUFFER LIST JRST MGWRT2 MGWRT1: LDB B,[MLO,,MEMBLT(A)] ; BACK POINTER HRRM B,MSBUFP(W) ; NEW OUT POINTER MGWRT2: LDB B,[MWC,,MEMBLT(A)] ; WORD COUNT MOVNS B ; NEGATE HRLZS B ; FORM COUNT IFN KL10P, LSH B,4 ; SHIFT IF KL10 DATA CHANNEL IFN KL10P, MOVE R,A ; SAVE CORE PAGE NUMBER FOR CACHE SWEEP LSH A,10. ; FORM WORD POINTER SUBI A,1 HRRM A,B ; CHANNEL POINTER IN B IFN TM10B, DATAO MTS,[MICWA] ; SET TO GO TO MAG TAPE IFN TM10A, PUSHJ Q,MGDCSO MOVEM B,MIOWD MOVEM B,LMIOWD ; LAST MIOWD SETZM MIOWD+1 ; TELL CHANNEL TO STOP IFN KL10P,[ PUSHJ P,CSHSWP ; UNLOAD BUFFER FROM CACHE INTO CORE CAI ] MOVE B,MTCONO(W) CONO MTC,MWRITE(B) ; DO IT PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE JRST MGWBT ; WRITE BLANK TAPE AND TRY AGAIN MGWRT3: MOVE A,MGCABN(W) ; GET BUFFER NUMBER HRLZI B,%MAETW+%MAERR ; END OF TAPE CHECK TRNE J,4000 ; END POINT IORM B,MSRAC(W) ; TELL MP LDB T,[MUR,,MEMBLT(A)] CAIE T,MUMGB ; DO I OWN BLOCK JRST 4,. SETOM MGCABN(W) ; NO BUFFER ACTIVE AT PI PUSHJ P,IMEMR ; GIVE BACK BUFFER MOVSI A,%MAMSO IORM A,MSRAC(W) ; TAPE MOVEMENT JRST MGCMDR MGWBT: IFN TM10B, SETZM MIOWD ; WRITE BLANK TAPE OVER POSSIBLE BAD SPOT IFN TM10A,[ MOVE A,[-1,,MGVTC-1] MOVEM A,MIOWD ; ONE RECORD ] TRNE J,644010 ; BAD TYPES OF ERRORS JRST MGERR MOVE B,MTCONO(W) CONO MTC,MSPRR(B) ; REVERSE 1 RECORD PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE JRST MGERR ; ERROR MOVE B,LMIOWD MOVEM B,MIOWD ; RESTORE MIOWD MOVE B,MTCONO(W) CONO MTC,14000(B) ; WRITE WITH EXTENDED EOR PUSHJ Q,MGWTJD ; WAIT JRST MGWBT ; INFINITE RETRIES ; JRST MGERR ; ERRORS JRST MGWRT3 MGWRT4: PUSHJ Q,CPOPJ ; WAIT A WHILE JRST MGWRIT SUBTTL MAG TAPE PI LEVEL READ MGREAD: PUSHJ Q,MGGXPT ; GET XPORT MGRD0: TRNE J,600000 ; UNIT HUNG OR REWINDING OR EOT JRST MGERR MOVE B,MGEOFR(W) ; EOF'S READ CAIL B,2 JRST MGERR MOVEM W,MGUNIT ; STORE UNIT NUMBER SKIPE MSCRW(W) ; MAKE SURE READING JRST 4,. MOVSI B,%MACTH ; CORE ALLOCATOR WANT OUT TDNN B,MSRAC(W) PUSHJ P,IOMQ JRST MGROVR ; WAIT FOR IT MOVEM A,MGCABN(W) ; STORE ACTIVE BUFFER AT PI LEVEL MOVEI B,MUMGB DPB B,[MUR,,MEMBLT(A)] ; CLAIM BLOCK HRREI B,-MGNRTY ; NUMBER OF RETRIES MOVEM B,MGERRC(W) ; STORE ERROR COUNT IFN KL10P, MOVE R,A LSH A,10. ; FORM ADDRESS SUBI A,1 IFE KL10P, HRLI B,-2000 IFN KL10P, HRLI B,-2000_4 HRR B,A MOVEM B,LMIOWD ; STORE LAST IOWD FOR RETRY IFN TM10B, DATAO MTS,[MICWA] ; SET CHANNEL STARTING ADDRESS IFN TM10A, PUSHJ Q,MGDCSI IFN TM10B, SETZM MICWA+1 SETZM MIOWD+1 MGRD1: MOVEM B,MIOWD ; CHANNEL COMMAND MOVEI B,2000 MOVEM B,MGNWRD ; ASSUME AT FIRST THAT THE RECORD TO BE READ HAS 2000 WORDS IFN KL10P,[ PUSHJ P,CSHSWP ; ENSURE NO RESIDUE OF THIS PAGE IN CACHE CAIA ] MOVE B,MTCONO(W) CONO MTC,MREAD(B) ; DO IT IFN TM10B, SETOM MGWCW ; TELL IT TO WAIT FOR CONTROL WORD WRITTEN PUSHJ Q,MGWTJD ; WAIT FOR JOB DONE JRST MGRERR MGRD2: SKIPG A,MGCABN(W) BUG ;BUFFER SHOULDN'T BE -1, WOULD SCREW UP MEMBLT SETOM MGCABN(W) ; NO BUFFER ACTIVE AT PI HLRZ T,MSBUFP(W) ;LAST BUFFER IN SETZM B DPB B,[MLO,,MEMBLT(A)] ; BACK POINTER IS 0 SKIPG MSNBOL(W) HRRM A,MSBUFP(W) ; ONE BUFFER MEANS IN = OUT HRLM A,MSBUFP(W) ; NEW IN POINTER SKIPLE MSNBOL(W) DPB A,[MLO,,MEMBLT(T)] ; CHAIN BACK BUFFERS AOS C,MSNBOL(W) ; ONE MORE BUFFER ON LIST (COUNT TO C) MOVE B,MGNWRD DPB B,[MWC,,MEMBLT(A)] ; NUMBER OF WORDS IN BUFFER TRNE J,10000 ;EOF? JRST [ MOVSI B,%MAESO+%MAEFA ;YES IORM B,MSRAC(W) SETO B, DPB B,[MSEOFP,,MEMBLT(A)] AOS A,MGEOFR(W) CAIL A,2 JRST MGRD4 ; LOGICAL EOT, SPACE BACK OVER IT JRST .+2 ] SETZM MGEOFR(W) ; NO EOF MOVSI A,%MAMSO IORB A,MSRAC(W) ; TAPE MOVEMENT TRNE J,4000 ; EOT? JRST MGRD3 TRNN J,10000 ;IF NO EOF, NOT 6 BUFFERS YET, CAIL C,6 JRST MGRD5 TLNN A,%MASTP JRST MGRD0 ; AND NO REQUEST TO STOP, KEEP READING MGRD5: MOVSI A,%MASTP+%MARAC ;GIVE UP FOR NOW, CLEAR READ ACTIVE ANDCAM A,MSRAC(W) JRST MGCMDR ;MP LEVEL WILL SEND NEW READ COMMAND WHEN READY MGRD3: DPB B,[MSEOFP,,MEMBLT(A)] ;PHYSICAL EOT DPB B,[420100,,MSRAC(W)] .SEE %MAETR ; INDICATE EOT ON READ JRST MGRD5 ; RETURN MGRD4: MOVSI A,%MAESO+%MARAC+%MASTP ;SECOND EOF, LOGICAL EOT ANDCAM A,MSRAC(W) JRST MGSPRF MGRERR: IFN TM10B,[ TLNE J,160 JRST MGERR ; CHANNEL ERROR ] TRNE J,642000 JRST MGERR TRNE J,20600 JRST MGMRT ; DATA TYPE OF ERROR OR OVERRUN, MAYBE TRY AGAIN ;RECORD LENGTH ERROR, ADJUST MGNWRD IFN TM10B, HRRZ A,MICWA+1 IFN TM10A, HRRZ A,MIOWD HRRZ B,LMIOWD SUB A,B IFN TM10B, SOS A ; CHANNEL FUNNYNESS CAIN A,1 ; POS EOF IS ALL JRST MGRER2 MGRER1: MOVEM A,MGNWRD JRST MGRD2 MGRER2: TRNE J,14000 ; 1 WORD, EOF? EOT? SETZM A ; YES, THIS RECORD HAS ZERO LENGTH, IT JUST CARRIES MSEOFP JRST MGRER1 MGMRT: AOSL MGERRC(W) JRST MGERR ; TOO MANY ERRORS IFN TM10B, SETZM MIOWD IFN TM10A,[ MOVE A,[-1,,MGVTC-1] MOVEM A,MIOWD ; ONE RECORD PUSHJ Q,MGDCSO ] MOVE B,MTCONO(W) CONO MTC,MSPRR(B) ; REVERSE RECORD PUSHJ Q,MGWTJD JRST MGERR ; NO ERRORS ALLOWED IFN TM10A, PUSHJ Q,MGDCSI ; PUT BACK PI 1 BLKI MOVE B,LMIOWD JRST MGRD1 ; TRY AGAIN MGROVR: PUSHJ Q,CPOPJ JRST MGREAD SUBTTL MAG TAPE PI LEVEL SPACE MGSPCF: PUSHJ Q,MGGXPT ; GET XPORT SPACE FORWARD TRNE J,600000 JRST MGERR MGSPC: MOVEM W,MGUNIT MOVE B,MGRWCD(W) ; GET COMMAND ADD B,MTCONO(W) IFN TM10B,[ SETZM MIOWD DATAO MTS,[MICWA] ] IFN TM10A,[ MOVE A,[-1,,MGVTC-1] MOVEM A,MIOWD PUSHJ Q,MGDCSO ] CONO MTC,(B) ; DO IT PUSHJ Q,MGWTJD JRST MGERR ; NO RETRIES TRNN J,10000 ; EOF SETZB B,MGEOFR(W) TRNE J,10000 AOS B,MGEOFR(W) CAIL B,2 ;TOO MANY EOF'S JRST MGSPRF MGCMDR: SOS MSCMDC(W) ; GENERAL EXIT ROUTINE SETOM MGUNIT SKIPG MSCMDC(W) POPJ P, ; NO MORE MOVE B,MTCONO(W) CONO MTC,MNOPIN(B) ; INTERUPT WHEN UNIT READY MOVEM W,MGUNIT ; RESTORE UNIT NUMBER PUSHJ Q,MGWTJD JRST MGERR SETOM MGUNIT POPJ Q, ; MORE MGSPFR: MOVEI B,MSPFR ; SPACE FOR RECORD MOVEM B,MGRWCD(W) MOVSI B,%MAMSO IORM B,MSRAC(W) ; TAPE MOVEMENT JRST MGSPCF MGSPFF: MOVSI B,%MAESO TDZE B,MSRAC(W) JRST MGCMDR ; EOF ALREADY READ DURING THE READ AOS MSCMDC(W) ;SO IT WILL RETURN MOVEI B,MSPFR MOVEM B,MGRWCD(W) PUSHJ Q,MGSPCF SKIPE MGEOFR(W) JRST MGCMDR ; EOF READ ON SPACE RECORD. DONE MOVEI B,MSPFF MOVEM B,MGRWCD(W) JRST MGSPCF MGSPRR: MOVEI B,MSPRR MOVEM B,MGRWCD(W) MOVSI B,%MAMSO IORM B,MSRAC(W) JRST MGSPCR MGSPCR: PUSHJ Q,MGGXPT ; SPACE REVERSE TRNE J,600000 ; ERR JRST MGERR TRNE J,100000 ; BOT JRST MGCMDR ; THEN DO NOTHING MOVEM W,MGUNIT MOVE B,MGRWCD(W) ADD B,MTCONO(W) IFN TM10B,[ SETZM MIOWD DATAO MTS,[MICWA] ] IFN TM10A,[ MOVE A,[-1,,MGVTC-1] MOVEM A,MIOWD PUSHJ Q,MGDCSO ] CONO MTC,(B) PUSHJ Q,MGWTJD JRST MGERR TRNE J,10000 SOSGE MGEOFR(W) ; ONE LESS EOF SETZM MGEOFR(W) JRST MGCMDR MGSPRF: MOVEI B,MSPRF ; REVERSE FILE MOVEM B,MGRWCD(W) MOVSI A,%MAESO ; EOF READ IN FORWARD DIRECTION TDNN A,MSRAC(W) JRST MGSPCR AOS MSCMDC(W) ; YES DO IT TWICE PUSHJ Q,MGSPCR MOVSI B,%MAESO ANDCAM B,MSRAC(W) ; TURN OFF FLAG JRST MGSPCR ; SECOND TIME MGRWD1: PUSHJ Q,MGGXPT ; REWIND MOVEM W,MGUNIT MOVE B,MGRWCD(W) ; GET COMMAND ADD B,MTCONO(W) CONO MTC,(B) PUSHJ Q,MGWTJD ; WAIT JRST MGERR SETZM MGEOFR(W) MOVSI A,%MAMSO ANDCAM A,MSRAC(W) ;CLEAR TAPE MOTION MGRWD2: TRNN J,200000 ; STILL REWINDING? JRST MGRWD3 ; NO PUSHJ Q,CPOPJ ; WAIT CONI MTS,J MOVEM J,MGCMTS(W) JRST MGRWD2 MGRWD3: MOVE T,TIME ;WAIT 1 SECOND MORE ADDI T,30. ;THIS IS AN ATTEMPT TO FIX A HARDWARE BUG MOVEM T,MGJDTI MGRWD4: MOVE T,TIME CAML T,MGJDTI JRST [ SETZM MGJDTI POPJ Q, ] PUSHJ Q,CPOPJ JRST MGRWD4 MGRWND: MOVEI B,MREWND ; NORMAL REWIND CAIA MGRWDM: MOVEI B,MRWNDD ; REWIND AND DISMOUNT MOVEM B,MGRWCD(W) PUSHJ Q,MGRWD1 MOVSI A,%MAMSO+%MAREW ANDCAM A,MSRAC(W) JRST MGCMDR MGSEOT: PUSHJ Q,MGGXPT ; SKIP TO LOGICAL EOT TRNE J,600000 JRST MGERR MOVEM W,MGUNIT TRNE J,100000 ; BOT? JRST MGVTCK ; VIRGIN TAPE CHECK MGNVT: MOVE B,MTCONO(W) IFN TM10A,[ PUSHJ Q,MGDCSO MOVE A,[-1,,MGVTC-1] MOVEM A,MIOWD ; ONE RECORD ] IFN TM10B, SETZM MIOWD CONO MTC,MSPRR(B) ; SPACE REVERSE FIRST PUSHJ Q,MGWTJD ; WAIT JRST MGERR SETZM MGEOFR(W) AOS MGEOFR(W) MGEOT2: MOVE B,MTCONO(W) CONO MTC,MSPFF(B) ; SKIP FORWARD FILE PUSHJ Q,MGWTJD JRST MGERR MOVSI B,%MAETR ; EOT CHECK TRNE J,4000 IORM B,MSRAC(W) ; TELL MP MOVE B,MTCONO(W) IFN TM10A,[ MOVE A,[-1,,MGVTC-1] MOVEM A,MIOWD ; ONE RECORD ] IFN TM10B, SETZM MIOWD CONO MTC,MSPFR(B) ; SPACE FORWARD RECORD PUSHJ Q,MGWTJD JRST MGERR MOVSI B,%MAETR ; EOT AGAIN TRNE J,4000 IORM B,MSRAC(W) ; TELL MP TRNN J,10000 ; EOF ALSO? JRST MGEOT2 ; NO, TRY AGAIN MOVE B,MTCONO(W) ; YES, NOW GO BACK OVER LAST CONO MTC,MSPRF(B) PUSHJ Q,MGWTJD JRST MGERR MOVSI B,%MAEOF+%MAETR ; TELL MP,EOF IORM B,MSRAC(W) JRST MGCMDR MGVTCK: MOVE T,TIME ADDI T,60. ; TWO SECOND TIME OUT MOVEM T,MGEOTT(W) ; EOT TIME IFN TM10B,[ SETZM MIOWD DATAO MTS,[MICWA] ] IFN TM10A,[ MOVE A,[-1,,MGVTC-1] MOVEM A,MIOWD PUSHJ Q,MGDCSO ] MOVE B,MTCONO(W) CONO MTC,MREAD(B) ; DO READ, WAIT EITHER FOR JOB DONE OR TIME OUT MGVTC1: CONI MTS,J MOVEM J,MGCMTS(W) TRNE J,100 ; J D? JRST MGNVT ; NOT VIRGIN TAPE TRNE J,440000 JRST MGERR ; ERRORS? MOVE T,MGEOTT(W) CAMG T,TIME ; TIME UP? JRST MGVT ; YES PUSHJ Q,CPOPJ ; WAIT JRST MGVTC1 MGVT: MOVE B,MTCONO(W) CONO MTS,31 CONO MTC,MNOPIN(B) ; NO-OP WAIT FOR JOB DONE PUSHJ Q,MGWTJD JFCL ; SEE IF I CARE IF THERE ARE ERRORS MOVEI B,MREWND MOVEM B,MGRWCD(W) PUSHJ Q,MGRWD1 ; REWIND SETZM MGEOFR(W) AOS MGEOFR(W) JRST MGCMDR ; RETURN MGMEOT: PUSHJ Q,MGGXPT TRNE J,600000 JRST MGERR MOVEM W,MGUNIT SKIPE MTCEFW(W) ;HOW MANY EOF WRITTEN? JRST MGMET1 AOS MSCMDC(W) ; SO WILL RETURN AOS MTCEFW(W) PUSHJ Q,MGWEOF MGMET1: MOVE A,MTCEFW(W) SOSLE A JRST MGMET2 AOS MSCMDC(W) AOS MTCEFW(W) PUSHJ Q,MGWEOF MGMET2: MOVE A,MSRAC(W) TLNE A,%MANWT ; BACK OVER LAST? JRST MGMET3 ; NO AOS MSCMDC(W) ; SO IT WILL RETURN PUSHJ Q,MGSPRF MGMET3: MOVSI A,%MANWT IORM A,MSRAC(W) JRST MGCMDR ; DONE ; WRITE EOF MGWEOF: PUSHJ Q,MGGXPT TRNE J,600010 JRST MGERR MOVEM W,MGUNIT MOVE B,MTCONO(W) CONO MTC,MWEOF(B) PUSHJ Q,MGWTJD JRST MGERR MOVSI A,%MAMSO IORM A,MSRAC(W) ; TAPE MOVEMENT JRST MGCMDR ; RETURN MGSTAT: PUSHJ Q,MGGXPT ; GETS STATUS JRST MGCMDR MGW3IN: PUSHJ Q,MGGXPT TRNE J,600010 JRST MGERR MOVEM W,MGUNIT IFN TM10B,[ SETZM MIOWD DATAO MTS,[MICWA] ] IFN TM10A,[ MOVE A,[-1,,MGVTC-1] MOVEM A,MIOWD PUSHJ Q,MGDCSO ] MOVE B,MTCONO(W) CONO MTC,MW3IN(B) ; WRITE THE RANDOM WORD PRECEEDED BY 3 INCHES OF BLANK TAPE PUSHJ Q,MGWTJD JFCL ; ALLOW BAD TAPE ERROR JRST MGSPRR ; NOW SPACE RECORD REVERSE OVER THE ONE WORD SUBTTL .MTAPE UUO ;.MTAPE AC, ; AC/ CHNM,COMMAND ; COMMAND/ COUNT,,FUNCTION AMTAPE: XCTR XR,[HLRZ R,(J)] TRNE R,-NIOCHN JRST ILUUO HRRZM R,UUAC(U) ; SO THAT ERRORS WILL BE REPORTED ON THE ; CORRECT CHANNEL ADDI R,IOCHNM(U) ; FORM IOCHNM POINTER HRRZ A,(R) ; A: CLSTB/IOTTB index CAIL A,MTUAIX ; Min index for tape CAILE A,MTBOX ; Max POPJ P, ; Laconic error reportage. LDB W,[MTXP(R)] ; GET XPORT NUMBER CAME U,MTUSR(W) ; SAME USER POPJ P, ; NO UMOVE J,(J) MOVEM J,MTMTAP(W) ; SAVE J HRRZ A,MTMTAP(W) PUSHJ P,MTIECK UMOVE A,(A) HRRZM A,MTMFNC(W) ;STORE FUNCTION HLREM A,MTMCNT(W) ;AND COUNT SKIPN MTMCNT(W) ;A COUNT OF ZERO ALWAYS MEANS ONE, FOR COMPATIBILITY AOS MTMCNT(W) ; WITH THE OLD CODE. HRRZS A CAIL A,NMTAPC ; LEGAL COMMAND POPJ P, ; NO AOS (P) ; SKIP RETURN JRST @MTAPDT(A) MTAPDT: MTHANG ;0 HANG TILL TAPE MOTION DONE MTRWND ;1 REWIND MTRWDM ;2 REWIND AND DISMOUNT MTWEOR ;3 WRITE EOR IF APPROPRIATE MTW3IN ;4 WRITE 3 INCHES OF BLANK TAPE MTWEOF ;5 WRITE EOF MTSPR ;6 SPACE RECORDS MTSPF ;7 SPACE FILES MTSPEOT ;10 SPACE TO EOT MTSTOP ;11 STOP ALL COMMAND ASSOCIATED WITH THIS COMMAND MTSBKS ;12 SET BLOCK SIZE (TO COUNT) MTRBKS ;13 READ BLOCK SIZE (TO AC) NMTAPC==.-MTAPDT MTSBKS: MOVE A,MTMCNT(W) ;DESIRED BLOCKSIZE CAIL A,4 ;CHECK REASONABLENESS CAILE A,2000 SOSA (P) ;FAIL IF TOO BIG OR TOO SMALL MOVEM A,MTBLKS(W) ;OK, CHANGE WRITE-BUFFER SIZE POPJ P, MTRBKS: MOVE A,MTBLKS(W) JRST APTUAJ MTHANG: SKIPLE MSCMDC(W) ; HANG UNTILL ALL MOTION FINISHED PUSHJ P,UFLS JRST MTIECK MTRWND: MOVEI B,MGRWND ; REWIND MTRWD1: SKIPE MSCRW(W) JRST MTSOSP MOVSI A,%MAREW IORM A,MSRAC(W) JRST MTCMD MTRWDM: MOVEI B,MGRWDM ; REWIND AND DISMOUNT JRST MTRWD1 ;"WRITE END OF RECORD" - THIS IS REALLY THE FORCE SYSTEM CALL, OR SHOULD BE. MTWEOR: SKIPG MTMDN(W) ; ANY BUFFERS STARTED POPJ P, ; NO SKIPE MSCRW(W) ; WRITING JRST MTWBFD ; DISCARD BUFFER MTSOSP: SOS (P) ; NOT WRITING, ERROR POPJ P, MTWEOF: SKIPN MSCRW(W) ; WRITING? JRST MTSOSP ; NO PUSHJ P,MTWEOR MOVEI B,MGWEOF ; WRITE EOF AOS MTCEFW(W) MOVSI TT,%MANWT ANDCAM TT,MSRAC(W) ; SOMETHING WRITTEN JRST MTCMD MTW3IN: SKIPN MSCRW(W) ; WRITING? JRST MTSOSP MOVEI B,MGW3IN SETZM MTCEFW(W) MOVSI TT,%MANWT ANDCAM TT,MSRAC(W) JRST MTCMD ;SPACE RECORDS, +=FORWARD, -=BACK MTSPR: SKIPE MSCRW(W) ; NOT ALLOWED IF WRITING JRST MTSOSP PUSHJ P,MTFLRA ;FLUSH READ-AHEAD, FIND OUT HOW FAR OFF WE ARE ADD B,C ;NUMBER OF RECORDS TAPE IS AHEAD OF USER (EOF=RECORD) MOVNS B ;SUBTRACT THIS FROM USER'S REQUEST ADDB B,MTMCNT(W) JUMPE B,CPOPJ ;IF COUNT IS NOW ZERO, WE ARE DONE MTSPR1: PUSHJ P,MTCNTR ;UPDATE USER'S COPY IN CASE PCLSR JUMPG B,MTSPFR ; SPACE FORWARD MOVEI B,MGSPRR ; SPACE REVERSE PUSHJ P,MTCMD AOSGE B,MTMCNT(W) JRST MTSPR1 ;MORE POPJ P, MTSPFR: MOVEI B,MGSPFR PUSHJ P,MTCMD SOSLE B,MTMCNT(W) JRST MTSPR1 ;MORE POPJ P, ;THIS ROUTINE FLUSHES READAHEAD. CALL BEFORE DOING A SPACING OPERATION ;THIS DOESN'T ACTUALLY UNDO THE EFFECT ON THE DRIVE ;OF THE READ-AHEAD. IT DOES MAKE SURE THAT READ-AHEAD'S EFFECT CAN'T ;CHANGE, THEN RETURNS IN B THE NUMBER OF RECORDS AHEAD (NON-NEGATIVE) ;AND IN C THE NUMBER OF EOF'S AHEAD (0 OR 1). IF CALLED TWICE IT WILL ;RETURN ZERO THE SECOND TIME. BE SURE TO UPDATE YOUR PARAMETERS. MTFLRA: PUSHJ P,MTCNTR ;FIRST, ENSURE WRITEABILITY, MUSTN'T PCLSR IN MTCNTR LATER MOVSI B,%MASTP MOVSI T,%MARAC IORM B,MSRAC(W) ;IF READ IS ACTIVE, TELL IT TO STOP TDNE T,MSRAC(W) ;AWAIT CESSATION OF READ PUSHJ P,UFLS ;IF THIS PCLSR'S OUT WITH %MASTP SET, NO GREAT HARM DONE. ANDCAM B,MSRAC(W) ;THEN TURN OFF %MASTP, THINGS ARE NOW QUIET SKIPLE MSCMDC(W) ;BEFORE MESSING WITH BUFFERS, WAIT FOR PI TO QUIESCE PUSHJ P,UFLS MOVE B,MSNBOL(W) ;NUMBER OF BUFFERS = NUMBER OF RECORDS LDB C,[.BP (%MAEFA),MSRAC(W)] ;1 IF PAST EOF WHICH THE USER DOESN'T KNOW ABOUT MOVSI T,%MAEFA ;NOW GET RID OF THE READ-AHEAD ANDCAM T,MSRAC(W) JRST MTCBFF MTSPF: SKIPE MSCRW(W) ; NOT ALLOWED IF WRITING JRST MTSOSP PUSHJ P,MTFLRA ;FLUSH READ-AHEAD MOVN B,C ;NUMBER OF FILES TAPE IS AHEAD OF USER ADDB B,MTMCNT(W) JUMPE B,CPOPJ ;DONE MTSPF1: PUSHJ P,MTCNTR ;UPDATE USER'S COUNT IN CASE OF PCLSR JUMPG B,MTSPFF ; SPACE FORWARD FILES MOVEI B,MGSPRF PUSHJ P,MTCMD AOSGE B,MTMCNT(W) JRST MTSPF1 ;MORE POPJ P, MTSPFF: MOVEI B,MGSPFF PUSHJ P,MTCMD SOSLE B,MTMCNT(W) JRST MTSPF1 ;MORE POPJ P, MTCNTR: HRRZ A,MTMTAP(W) MOVE T,MTMFNC(W) HRL T,MTMCNT(W) UMOVEM T,(A) POPJ P, MTSTAT: SKIPLE MSCMDC(W) ; WAIT TILL ALL COMMANDS DONE PUSHJ P,UFLS MOVEI B,MGSTAT ; GET CONI'S PUSHJ P,MTCMD ; GIVE TO PI SKIPLE MSCMDC(W) ; WAIT TILL DONE PUSHJ P,UFLS MOVE I,MGCMTC(W) MOVE J,MGCMTS(W) POPJ P, MTSPEOT: MOVEI B,MGSEOT ; SPACE TO LOGICAL EOT JRST MTCMD ;NOTE THIS IS INDEPENDENT OF READ-AHEAD MTSTOP: CONO PI,UTCOFF ;THIS DOESN'T DEAL WITH READ-AHEAD, PROBABLY OK SETZM MSCMDC(W) ;NO MORE COMANDS MOVE Q,[-MGQDLL,,MGQD0-1] MOVE T,MSLCTB IMUL T,W ADD Q,T MOVEM Q,MGQDLP(W) ; RESTORE Q MOVE Q,[-MSCBL-1,,MSCB0-1] ADD Q,T MOVEM Q,MTCMBP(W) ; INITIALIZE MP AND PI COMAND POINTERS MOVE Q,[4400,,MSCB0-1] ADD Q,T MOVEM Q,MGCMBP(W) SKIPL A,MTMDN(W) PUSHJ P,IMEMR ; RELEASE MP BUFFER SETOM MTMDN(W) SETZM MSMPRP(W) SETZM MSMPRC(W) ; SO BLKT WON'T GET UNHAPPY PUSHJ P,MTCBFF ; FLUSH BUFFER LIST CAME W,MGUNIT ; SAME UNIT? JRST UTCONJ SETOM MGUNIT ; SO INTERUPT WILL GO AWAY CONI MTC,I ; SEE WHAT DRIVE IS BEING TALKED TO LDB B,[MUNITF,,I] CAME W,B JRST UTCONJ ; IF NOT SAME UNIT, DON'T DO ANYTHING MOVE B,MTCONO(W) CONO MTS,31 ; STOP THE TAPE CONO MTC,(B) ; CLEAR INTERUPTS SKIPGE A,MGCABN(W) ; ANY BUFFERS ACTIVE AT PI JRST UTCONJ ; NO PUSHJ P,IMEMR ; RETURN IT SETOM MGCABN(W) JRST UTCONJ SUBTTL MAG TAPE CLOSE ROUTINES MTOCL: LDB W,[MTXP(R)] SOSL MTUSE(W) POPJ P, ; NOT ONLY CHANNEL OPEN AOS MTUSE(W) ; INCASE PCLSRED MOVSI A,%MAERR ;ERROR? TDNE A,MSRAC(W) PUSHJ P,MTOCL3 ; MOVEI T,MSCBL-4 ; CAMG T,MSCMDC(W) ; PUSHJ P,UFLS ; WAIT FOR ROOM FOR THREE COMMANDS SKIPL MTMDN(W) ; MAG TAPE OUTPUT CLOSE PUSHJ P,MTWBFD ; WRITE OUT BUFFERS ; MOVEI B,MGWEOF ; WRITE OUT TWO EOF(S) ; SKIPE MTCEFW(W) ; JRST MTOCL2 ; MAY HAVE BEEN PCLSRED ;MTOCL1: PUSHJ P,MTCMD ; AOS MTCEFW(W) ; ONE MORE CLOSE EOF WRITTEN ;MTOCL2: MOVE A,MTCEFW(W) ; SOSG A ; DON'T WRITE EOF IF PCLSRED ; PUSHJ P,MTCMD ; DO IT TWICE ; SKIPG A ; AOS MTCEFW(W) ; MOVEI B,MGSPRF ; MOVE A,MSRAC(W) ; TLNN A,1000 ; PUSHJ P,MTCMD ; NOW BACK UP OVER ONE ; MOVSI A,1000 ; IORM A,MSRAC(W) MOVEI B,MGMEOT ; MAKE EOT PUSHJ P,MTCMD SKIPLE MSCMDC(W) ; NOW WAIT TILL DONE PUSHJ P,UFLS MOVEI A,1 MOVEM A,MGEOFR(W) SKIPL MTMDN(W) ;ANY ACTIVE BUFFERS JRST 4,. SKIPL MGCABN(W) JRST 4,. SKIPE MSNBOL(W) JRST 4,. SETOM MTUSR(W) SETOM MTUSE(W) SETZM MSRAC(W) POPJ P, MTOCL3: SKIPL A,MTMDN(W) PUSHJ P,MEMR ; IF BUFFER AROUND,FLUSH IT SETOM MTMDN(W) SETZM MSMPRC(W) POPJ P, MTICL: LDB W,[MTXP(R)] SOSL MTUSE(W) ; LAST USER POPJ P, AOS MTUSE(W) MOVEI T,1 CAMGE T,MSCMDC(W) ; ALLOW ONE COMMAND IF REWINDING PUSHJ P,UFLS ; ALL COMMANDS DONE MOVE T,MSRAC(W) TLNE T,%MAREW ; REWINDING? JRST MTICL3 ; YES SKIPLE MSCMDC(W) ; NO, WAIT TILL COMMAND DONE PUSHJ P,UFLS MTICL3: SKIPL MGCABN(W) ; ANY PI BUFFERS LEFT JRST 4,. PUSHJ P,MTRBD ;GET RID OF M.P. BUF, IF ANY SETOM MTUSR(W) PUSHJ P,MTCBFF ; FREE BUFFERS SOS MTUSE(W) MOVE T,MSRAC(W) TLNE T,%MAREW ; DON'T HAVE TO SKIP TO EOF IF REWINDING JRST MTICL2 MOVSI A,20 TDNE A,(R) ;CHECK TO SKIP TO EOF JRST MTICL2 MOVSI A,%MAMSO TDNN A,MSRAC(W) ;TAPE MOVEMENT JRST MTICL2 ; NO SKIPE MGEOFR(W) ;NO TIMING CONFLECT HERE SINCE WE WAITED FOR PI TO CLEAR JRST MTICL2 ;NOTE THAT THIS DISPOSES OF A READ-AHEAD EOF. PUSHJ P,MTSTAT MOVE B,MGCMTS(W) TRNE B,100000 JRST MTICL2 MOVEI B,MGSPFF PUSHJ P,MTCMD SKIPLE MSCMDC(W) PUSHJ P,UFLS MTICL2: MOVSI T,%MAREW ANDM T,MSRAC(W) ;CLEAR ALL BUT REWINDING POPJ P, ; NO, DONE MTCBFF: SKIPN MSNBOL(W) ;ANY BUFFERS ON CHAIN? POPJ P, HRRZ A,MSBUFP(W) ;YES, FREE ONE PUSHJ P,MTICL1 ; FIX CHAIN PUSHJ P,MEMR ; RETURN BUFFER SOSLE MSNBOL(W) ;ANY MORE? JRST MTCBFF SETZM MSBUFP(W) ;EMPTY LIST POPJ P, MTICL1: LDB T,[MLO,,MEMBLT(A)] ; GET BACK POINTER HRRM T,MSBUFP(W) POPJ P,