Trailing-Edge
-
PDP-10 Archives
-
BB-4170G-SM
-
sources/magtap.mac
There are 58 other files named magtap.mac in the archive. Click here to see a list.
;<3A.MONITOR>MAGTAP.MAC.10, 19-Jul-78 01:36:41, Edit by MCLEAN
;I DID AN IOPIOF IN SWAPCD -- DEFINATELY A NO NO
;<3A.MONITOR>MAGTAP.MAC.9, 6-Jun-78 15:10:47, EDIT BY MILLER
;CHECK FOR NEGATIVE ENTRY IN MAGTAP MTOPR
;<3A-NEW>MAGTAP.MAC.8, 25-May-78 21:54:13, Edit by FORTMILLER
;ADD DX20 SUPPORT
;<3A.MONITOR>MAGTAP.MAC.7, 4-May-78 05:52:42, Edit by MCLEAN
;TEMP FIX TO REMOVE .MTT16
;<3A.MONITOR>MAGTAP.MAC.6, 2-May-78 23:05:53, Edit by MCLEAN
;PERMIT READ BACKWARDS FOR KS10
;<2BOSACK>MAGTAP.MAC.1, 24-Feb-78 01:41:48, EDIT BY BOSACK
;CHANGE TO NEW DEVICE/DATA ERROR BITS
;<3.SM10-RELEASE-3>MAGTAP.MAC.4, 9-Jan-78 16:29:10, EDIT BY ENGEL
;TCO #1890 FIX INCORRECT RECORD COUNT IN MTOPR .MOINF (REVERSE WORDS 6 AND 7)
;<3.SM10-RELEASE-3>MAGTAP.MAC.2, 13-Nov-77 14:41:03, Edit by MCLEAN
;READ BACKWARDS ILLEGAL ON KS10
;<3-MONITOR>MAGTAP.MAC.163, 7-Nov-77 13:03:47, EDIT BY KIRSCHEN
;MORE COPYRIGHT UPDATING...
;<3-MONITOR>MAGTAP.MAC.162, 5-Nov-77 00:13:11, EDIT BY CROSSLAND
;FIX MTOPR SO YOU CAN GET NUMBER OF HARD ERRORS.
;<3-MONITOR>MAGTAP.MAC.161, 12-Oct-77 13:56:52, EDIT BY KIRSCHEN
;UPDATE COPYRIGHT FOR RELEASE 3
;<3-MONITOR>MAGTAP.MAC.160, 5-Jul-77 14:24:29, EDIT BY HURLEY
;MOVE CHECKING OF EXISTENT DRIVES TO DEVICE
;<3-MONITOR>MAGTAP.MAC.159, 6-May-77 11:46:49, EDIT BY HURLEY
;ADD SET INPUT/OUTPUT AND ATTRIBUTE CHECK ENTRIES IN DISPATCH TABLE
;<3-MONITOR>MAGTAP.MAC.158, 3-May-77 13:20:02, Edit by HESS
;TCO 1736 - TAPE PROCESSING ADDED
;<3-MONITOR>MAGTAP.MAC.155, 24-Jan-77 10:46:02, EDIT BY HURLEY
;TCO 1719 - GET CORRECT NUMBER OF PAGES FOR BUFFERS WHEN USING INDUSTRY COMPATIBLE MODE
;<3-MONITOR>MAGTAP.MAC.154, 15-Jan-77 17:53:05, Edit by MCLEAN
;<3-MONITOR>MAGTAP.MAC.153, 15-Jan-77 17:25:39, Edit by MCLEAN
;<3-MONITOR>MAGTAP.MAC.152, 12-Jan-77 15:47:26, Edit by MCLEAN
;<3-MONITOR>MAGTAP.MAC.151, 11-Jan-77 15:51:45, Edit by MCLEAN
;<3-MONITOR>MAGTAP.MAC.150, 27-Dec-76 17:34:11, EDIT BY HURLEY
;<2-MONITOR>MAGTAP.MAC.149, 29-Nov-76 17:48:06, EDIT BY BOSACK
;<2-MONITOR>MAGTAP.MAC.148, 29-Nov-76 17:19:46, EDIT BY BOSACK
;<2-MONITOR>MAGTAP.MAC.147, 29-Nov-76 17:12:45, EDIT BY BOSACK
;TCO 1672 - FIX MTINDX BUG
;<2-MONITOR>MAGTAP.MAC.146, 14-Oct-76 19:27:26, EDIT BY HURLEY
;TCO 1598 - ADD OF%OFL BIT TO OPENF
;<2-MONITOR>MAGTAP.MAC.145, 11-Oct-76 09:21:33, EDIT BY HURLEY
;TCO 1583 - MAKE MAGTAPE WAITS BE DONE WITH HDISMS
;<2-MONITOR>MAGTAP.MAC.144, 6-Oct-76 09:09:44, EDIT BY HURLEY
;TCO 1568 - DONT CLEAR ABORTF UNLESS USER PROGRAM HAS SEEN THE ERROR
;<2-MONITOR>MAGTAP.MAC.143, 2-Sep-76 17:12:26, EDIT BY HALL
;MADE SYSERR ENTRY FOR DIRECTORY NUMBER CONTAIN USER NUMBER FROM JOBDIR
;<1B-MONITOR>MAGTAP.MAC.142, 10-JUN-76 20:01:13, EDIT BY BOSACK
;<1B-MONITOR>MAGTAP.MAC.141, 10-JUN-76 11:17:43, EDIT BY JMCCARTHY
;TCO 1370 - "ASSIGN MTA3" WORKS, EVEN WHEN THERE'S NO MTA3
;<1B-MONITOR>MAGTAP.MAC.140, 9-JUN-76 16:50:49, EDIT BY BOSACK
;<1B-MONITOR>MAGTAP.MAC.139, 9-JUN-76 16:09:01, EDIT BY BOSACK
;<1B-MONITOR>MAGTAP.MAC.138, 9-JUN-76 15:20:53, EDIT BY BOSACK
;TCO 1378 - FIX BUGCHKS AFTER REWIND WITHOUT CLOSE
;<1A-MONITOR>MAGTAP.MAC.137, 6-APR-76 15:23:54, EDIT BY HURLEY
;TCO 1216 - REVISITED
;<1A-MONITOR>MAGTAP.MAC.136, 1-APR-76 13:51:41, EDIT BY HURLEY
;TCO # 1230 - FIX SPELLING ERRORS IN BUGCHK MESSAGES
;<1MONITOR>MAGTAP.MAC.135, 23-MAR-76 18:14:46, EDIT BY HURLEY
;<1MONITOR>MAGTAP.MAC.134, 23-MAR-76 17:04:06, EDIT BY HURLEY
;TCO 1216 - MAKE ALL UNSUPPORTED DISPATCH ENTRIES RETURN AN ERROR CODE
;<2MONITOR>MAGTAP.MAC.133, 16-JAN-76 17:51:12, EDIT BY MURPHY
;<2MONITOR>MAGTAP.MAC.132, 8-JAN-76 18:35:11, EDIT BY HURLEY
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1976, 1977, 1978 BY DIGITAL EQUIPMENT CORPORATION, MAYNARD, MASS.
SEARCH PROLOG
SEARCH PHYPAR
TTITLE MAGTAP
;SPECIAL AC DEFINITIONS USED HEREIN
DEFAC (U,Q1) ;UNIT NUMBER
DEFAC (IOS,Q2) ;STATUS BITS FROM MTASTS
DEFAC (STS,P1) ;DEVICE STATUS
DEFAC (JFN,P2) ;JFN
DEFAC (DEV,P4) ;DEVICE DISPATCH ADR
;DEFAULT VALUES FOR MAGTAPES
MTSPCN==5 ;MAX # OF SPACING OPERATIONS AT 1 TIME
MINREC==4 ;MINIMUM # OF WORDS FOR OUTPUT RECORD
;BIT DEFINITIONS FOR LH OF MTASTS
OPN==1B0 ;UNIT HAS BEEN OPENED
OPND==:1B2 ;UNIT WAS OPENED FOR DUMP MODE
DMPWT==1B3 ;WAITING FOR A DUMP MODE OP TO FINISH
LTERR==1B4 ;ERROR OCCURED ON LAST DUMP MODE OPER.
BUFA==1B5 ;BUFFERS HAVE BEEN ASSIGNED
CLOF==1B6 ;CLOSF IN PROGRESS
MTOWT==1B7 ;MTOPR IN PROGRESS
MTIEL==1B8 ;INHIBIT ERROR LOGGING
;BITS IN RH OF MTASTS (DEFINED IN MONSYM)
;DATA STRUCTURE DEFINITIONS
DEFSTR (MTRS,MTANR1(U),35,18) ;RECORD SIZE IN HARDWARE BYTES
DEFSTR (MTDM,MTANR1(U),17,3) ;DATA MODE
DEFSTR (MTDN,MTANR1(U),14,4) ;DENSITY
DEFSTR (MTSTC,MTANR1(U),10,3) ;CLOSF FUNCTION COUNTER
DEFSTR (MTRBF,MTANR1(U),7,1) ;READING BACKWARDS FLAG
DEFSTR (MTPAR,MTANR1(U),6,1) ;PARITY
DEFSTR (MTFCN,MTANR1(U),5,4) ;LAST FUNCTION PERFORMED
DEFSTR (MTNTM,MTANR1(U),1,2) ;COUNT OF EOF'S WRITTEN
DEFSTR (MTBYT,MTANR2(U),17,18) ;INITIAL LH OF FILBYT
DEFSTR (MTBUF,MTANR2(U),35,18) ;POINTER TO START OF LIST OF BUF PAGES
DEFSTR (MTCUB,MTANR3(U),23,6) ;CURRENT USER BUFFER
DEFSTR (MTCSB,MTANR3(U),17,6) ;CURRENT SERVICE ROUTINE BUFFER
DEFSTR (MTUBW,MTANR3(U),11,6) ;USER BYTES PER WORD
DEFSTR (MTHBW,MTANR3(U),5,6) ;HARDWARE BYTES PER WORD
DEFSTR (MTCUP,MTANR4(U),35,18) ;CURRENT USER PAGE
DEFSTR (MTCIRB,MTANR4(U),17,18) ;CURRENT IORB IN USE
DEFSTR (MTUBP,MTANR5(U),35,18) ;USER BYTES PER PAGE
DEFSTR (MTUBB,MTANR5(U),17,18) ;USER BYTES PER BUFFER
DEFSTR (MTLIRB,MTANR6(U),35,18) ;LAST IORB ADR FOR DUMP MODE
DEFSTR (MTALTC,MTANR6(U),17,18) ;LAST TRANSFER COUNT
DEFSTR (MTNIR,MTARS1(U),35,6) ;# OF IORB'S QUEUED UP
DEFSTR (MTANIR,MTARS1,35,6) ;ABSOULTE VERSION OF MTNIR
DEFSTR (MTPPB,MTARS1(U),29,9) ;NUMBER OF PAGES PER BUFFER
DEFSTR (ABORTF,MTARS1,20,1) ;AN ERROR OCCURED AND IORB'S ABORTED
DEFSTR (IRFLG,MTIRSD,8,9) ;FLAGS FOR USE BY HIGH LEVEL ROUTINE
MSKSTR (IRBFR,MTIRSD,1B0) ;BUFFER READY FOR USER
MSKSTR (IRBFQ,MTIRSD,1B1) ;CURRENT BUFFER FLAG
MSKSTR (IRBFA,MTIRSD,1B2) ;ACTIVE FLAG, IORB BEING FILLED
; OR EMPTIED BY SERVICE ROUTINE
MSKSTR (IRBAB,MTIRSD,1B3) ;IORB ABORTED DUE TO AN ERROR
MSKSTR (IRBFF,MTIRSD,1B4) ;IORB IS FREE
DEFSTR (IRBUN,MTIRSD,17,9) ;UNIT NUMBER
DEFSTR (IRBPB,MTIRSD,35,18) ;POINTER TO BUFFER OF PAGE POINTERS
DEFSTR (IRBOC,MTIRSD+1,35,18) ;ORIGINAL COUNT
DEFINE MTERET (X) <
IFNB <X>,<
JRST [ MOVEI A,X
MOVX IOS,MT%DVE
IORB IOS,MTASTS(U)
TQO <ERRF>
RET]>
IFB <X>,<
JRST [ MOVX IOS,MT%DVE
IORB IOS,MTASTS(U)
TQO <ERRF>
RET]>>
;MAGTAPE DISPATCH TABLE
SWAPCD
MTADTB::DTBDSP (MTASET) ;SET DIRECTORY
DTBDSP (MTANAM) ;LOOKUP NAME
DTBDSP (MTAEXT) ;LOOKUP EXTENTION
DTBDSP (MTAVER) ;LOOKUP VERSION
DTBBAD (DESX9) ;PROTECTION INSERTION
DTBBAD (DESX9) ;ACCOUNT INSERTION
DTBBAD (DESX9) ;STATUS INSERTION
DTBDSP (MTAOPN) ;OPENF
DTBDSP (MTASQI) ;BIN/SIN
DTBDSP (MTASQO) ;BOUT/SOUT
DTBDSP (MTACLZ) ;CLOSF
DTBDSP (MTAREN) ;RENAME
DTBDSP (MTADEL) ;DELETE
DTBDSP (MTDMPI) ;DUMPI
DTBDSP (MTDMPO) ;DUMPO
DTBDSP (MTAMNT) ;MOUNT
DTBDSP (MTADSM) ;DISMOUNT
DTBDSP (MTINID) ;INIT DIRECTORY
DTBDSP (MTMTAP) ;MTOPR
DTBDSP (MTGTS) ;GETSTS
DTBDSP (MTSTS) ;SETSTS
DTBDSP (MTRECO) ;RECORD OUT
DTBDSP (RFTADN) ;READ TAD
DTBDSP (SFTADN) ;SET TAD
DTBDSP (BIOINP) ;SET JFN FOR INPUT
DTBDSP (BIOOUT) ;SET JFN FOR OUTPUT
DTBBAD (GJFX49) ;CHECK ATTRIBUTE
DTBLEN==:.-MTADTB ;GLOBAL LENGTH OF DISPATCH TABLE
;ROUTINE TO INITIALIZE THE MAGTAP DATA STRUCTURES
SWAPCD
MTAINI::MOVSI A,-MTAN ;SET UP TO INIT UNITS
MOVEI B,-1 ;NEED THIS CONSTANT
MTINI2: SETOM MTALCK(A) ;INIT LOCK WORD
SETZM MTASTS(A) ;ZERO STATUS WORD ALSO
HRRZM B,TLABL0(A) ;DISCONNECT MT FROM MTA
SETZM TLABL1(A) ;CLEAR MT STATUS
AOBJN A,MTINI2 ;LOOP BACK FOR ALL UNITS
RET ;ALL DONE
;ROUTINE TO MOUNT A MAGTAPE UNIT
MTAMNT: RETSKP
;ROUTINE TO DISMOUNT A MAGTAPE UNIT
MTADSM: RETSKP
;ROUTINE TO INITIALIZE THE DIRECTORY OF A MAGTAPE
MTINID: RETBAD (DESX9)
;ROUTINE TO SET THE DIRECTORY
MTASET: RETBAD (GJFX32) ;NO FILES IN DIR
;ROUTINE TO LOOKUP A NAME ON A MAGTAPE UNIT
MTANAM: RETBAD (DESX9)
;ROUTINE TO FIND AN EXTENTION
MTAEXT: RETBAD (DESX9)
;ROUTINE TO FIND A VERSION
MTAVER: MOVEI A,0
RETSKP
;ROUITNE TO DO RENAME ON A MAGTAPE
MTAREN: RETBAD (DESX9)
;ROUTINE TO DELETE
MTADEL: RETBAD (DESX9)
;ROUTINE TO GET MAGTAP STATUS BITS
MTGTS:: HLRZ U,DEV ;SET UP UNIT NUMBER
CALL UPDSTS ;UPDATE THE STATUS
RET ;NEED TO BLOCK
HRRZ A,MTASTS(U) ;GET CURRENT STATUS BITS
LOAD B,MTALTC ;GET LAST TRANSFER COUNT
XCTU [HRLM B,3] ;GIVE IT TO USER
LOAD B,MTDN ;GET DENSITY
DPB B,[POINTR A,MT%DEN] ;DOESNT HANDLE 1600 BPI TOO WELL
LOAD B,MTPAR ;GET PARITY
DPB B,[POINTR A,MT%EVP]
RET ;RETURN WITH STATUS IN A
;ROUTINE TO SET THE MAGTAP STATUS BITS
MTSTS:: STKVAR <MTSTSA,MTSTSE>
SETZM MTSTSE ;ZERO THE ERROR BIT
MOVEM A,MTSTSA ;SAVE NEW STATUS SETTING
HLRZ U,DEV ;SET UP UNIT NUMBER
CALL UPDSTS ;UPDATE THE STATUS
RET ;NEED TO BLOCK
MOVE A,MTASTS(U) ;GET CURRENT STATUS
TXNE A,MT%DAE!MT%DVE!MT%IRL!MT%EOF!MT%EOT
SETOM MTSTSE ;THERE WAS AN ERROR AT START OF THIS
MOVE A,MTSTSA ;GET BACK NEW SETTING
ANDI A,MT%DAE!MT%DVE!MT%IRL!MT%EOT!MT%EOF!MT%SER!MT%EVP!MT%DEN
MOVX B,MT%DAE!MT%DVE!MT%IRL!MT%EOT!MT%EOF!MT%SER!MT%EVP!MT%DEN
ANDCAM B,MTASTS(U) ;CLEAR BITS BEING SPECIFIED BY USER
IORB A,MTASTS(U) ;SET BITS FROM USER
LDB B,[POINTR A,MT%EVP] ;GET PARITY
STOR B,MTPAR
HRRZ B,MTCUTB(U) ;GET UDB ADDRESS
MOVE B,UDBCHR(B) ;GET THE CHARACTERISTICS WORD
TXNE B,UC.625 ;IS DRIVE CAPABLE OF 6250?
JRST MTSTS2 ;YES, DON'T STORE INTO DENSITY FIELD OF UDB
LDB B,[POINTR A,MT%DEN] ;AND DENSITY (NOT GOOD FOR 1600 BPI)
SKIPN B ;DEFAULT WANTED
JRST [ LOAD B,JSMTD ;YES, GET DEFAULT DENSITY
SKIPN B
MOVEI B,MTDFDN ;IF NO JOB DEFAULT, USE SYSTEM DEFAULT
JRST .+1]
STOR B,MTDN
MTSTS2: SKIPE MTSTSE ;ANY ERRORS AT START?
TXNE A,MT%DAE!MT%DVE!MT%IRL!MT%EOT!MT%EOF
RET ;IF THERE ARE STILL SOME ERRORS, RETURN
TQZ <ERRF,EOFF> ;CLEAR ERROR FLAGS
JE ABORTF,(U),R ;IF ABORTF NOT ON ALREADY, DONT CLEAR IT
SETZRO ABORTF,(U) ;ZERO THE ABORT FLAG
RET ;AND EXIT
;ROUTINE TO UPDATE MTASTS
; CALL UPDSTS
;RETURNS +1: NEEDS TO BLOCK
; +2: OK
UPDSTS: CALL SETWLK ;GO SET WRITE LOCK BIT CORRECTLY
LOAD A,MTFCN ;GET FUNCTION CODE OF LAST OPERATION
CAIE A,IRFRED ;READ?
CAIN A,IRFRDR ;OR READ BACKWARDS?
SKIPA IOS,MTASTS(U) ;YES
JRST UPDST1 ;NO, GO WAIT FOR ACTIVITY TO FINISH
TXNN IOS,OPND ;OPENED FOR SEQUENTIAL READ?
RETSKP ;YES, STATUS GETS UPDATED LATER
UPDST1: CALL MTACLW ;WAIT FOR ACTIVITY TO STOP
RET ;NEED TO BLOCK
CALL MTFLSH ;GO UPDATE STATUS FROM EACH IORB
TQZ <BLKF> ;DONT WANT TO BLOCK
CALL SETBOT ;SET BOT BIT IN STATUS WORD
RETSKP ;ALL DONE
;ROUTINE TO SET THE WRITE LOCK BIT CORRECTLY IN MTASTS
SETWLK: HRRZ A,MTCUTB(U) ;GET UDB ADR
MOVE A,UDBSTS(A) ;GET STATUS OF DRIVE
MOVX B,MT%ILW ;GET WRITE LOCK BIT IN STATUS WORD
ANDCAM B,MTASTS(U) ;START BY CLEARING IT
TXNE A,US.WLK ;IS THIS DRIVE WRITE LOCKED?
IORM B,MTASTS(U) ;YES, SET THE BIT IN THE STATUS WORD
RET ;ALL DONE
;ROUTINE TO SET UP MT%BOT
SETBOT: HRRZ A,MTCUTB(U) ;GET UDB ADR
MOVE A,UDBSTS(A) ;GET STATUS BITS
MOVX B,MT%BOT ;FIRST CLEAR THE BIT
ANDCAM B,MTASTS(U)
TXNE A,US.BOT ;AT BOT?
IORM B,MTASTS(U) ;YES, SET THE BIT
RET
;ROUTINE TO OPEN A MAG TAPE UNIT FOR READING OR WRITING
;CALLED BY OPENF
MTAOPN::HLRZ U,DEV ;SET UP UNIT NUMBER
TXNE STS,READF!WRTF ;MUST BE OPENED FOR AT LEAST ONE
TXNE STS,XCTF!RNDF!NONXF
RETBAD (OPNX15) ;ILLEGAL MODE FOR OPENING
SKIPN A,MTCUTB(U) ;GET UDB ADR
JRST MTAOFL ;IF NO UNIT, PRETEND IT IS OFF-LINE
HRRZS A ;GET ADDRESS ONLY
JN USOFL,(A),[CALL CHKOFL ;SEE IF OPENS ALLOWED IF OFFLINE
JRST MTAOFL ;NO
JRST .+1] ;YES
LDB A,[POINT 4,STS,35] ;GET DATA MODE
CAIE A,17 ;MUST BE 0 OR 17
JUMPN A,MTAILM ;ILLEGAL MODE IF NOT 0 OR 17
LOCK MTALCK(U),<CALL LCKTST> ;PREVENT MULTIPLE OPENS
MOVX IOS,OPN ;SEE IF UNIT IS ALREADY OPENED
TDNE IOS,MTASTS(U) ;...
JRST BUSY ;YES, DONT OPEN IT TWICE
CAIN A,17 ;DUMP MODE?
TXO IOS,OPND ;YES, REMEMBER THAT FOR CLOSE
TXC STS,WRTF!READF ;SEE IF OPEN FOR BOTH READ AND WRITE
TXCN STS,WRTF!READF ;ONLY ALLOWED IF DUMP MODE
CAIN A,17 ;OPEN FOR BOTH, IS THIS DUMP MODE?
SKIPA ;YES, OK
JRST MTAISM ;ILLEGAL SEQUENTIAL I/O MODE
MOVEM IOS,MTASTS(U) ;MARK THAT UNIT IS NOW OPENED
CALL SETWLK ;SET THE WRITE LOCK BIT CORRECTLY
MOVE IOS,MTASTS(U) ;GET STATUS AGAIN
TXNE IOS,MT%ILW ;IS DRIVE WRITE LOCKED?
TQNN <WRTF> ;YES, IS THIS A WRITE OPENF?
SKIPA ;NO, THEN DONT COMPLAIN ABOUT WRITE LOCK
JRST MTAWLK ;GO COMPLAIN THAT DRIVE IS WRITE LOCKED
MTOPNX: SETZM MTANR1(U) ;INITIALIZE PER UNIT STORAGE
SETZM MTANR2(U)
SETZM MTANR3(U)
SETZM MTANR4(U)
SETZM MTANR5(U)
SETZM MTANR6(U)
SETZM MTARS1(U)
LOAD A,JSMTR ;GET DEFAULT RECORD SIZE
SKIPG A ;IS THE DEFAULT SET?
MOVEI A,MTDFRS ;NO, USE SYSTEM DEFAULT VALUE
STOR A,MTRS ;USE THIS UNLESS CHANGED BEFORE BIN 1
LOAD A,JSMTM ;GET DATA MODE
SKIPG A ;IS IT SET YET?
MOVEI A,MTDFDM ;NO, USE SYSTEM DEFAULT VALUE
STOR A,MTDM
;..
;..
CALL SETBW ;SET UP BYTES PER WORD, ETC.
JRST MTOPNF ;FAILED
LOAD A,JSMTD ;AND ALSO GET THE DEFAULT DENSITY
SKIPG A ;SPECIFIED?
MOVEI A,MTDFDN ;NO, USE SYSTEM DEFAULT VALUE
STOR A,MTDN
LOAD A,JSMTP ;GET DEFAULT PARITY
STOR A,MTPAR ;STORE PARITY
SETZM FILCNT(JFN) ;INITIALIZE COUNT OF BYTES IN BUFFER
SETZM FILLEN(JFN) ;INITIALIZE LENGTH OF CURRENT BUFFER
SETZM FILBYN(JFN) ;AND BYTE POSITION
MOVEI A,^D36 ;SET UP BYTE POSITION
DPB A,PBYTPO ;STORE IN FILBYT(JFN)
HLRZ A,FILBYT(JFN) ;GET INITIAL BYTE POINTER
STOR A,MTBYT ;SAVE FOR LATER
SETZRO MTNIR ;INIT COUNT OF IORB'S IN QUEUE
MOVEI A,MTBUFN*MTIRBL ;NOW INITIALIZE THE IORB'S
IMULI A,(U) ;GET START OF IORB AREA
ADDI A,MTIRBF ;GET ABS ADR OF IORB
MOVSI B,-MTBUFN ;SET UP COUNT
MTAOP1: MOVSI C,(A) ;ZERO IORB
HRRI C,1(A)
SETZM 0(A)
BLT C,MTIRBL-1(A) ;INITIALIZED TO ALL ZEROS
SETONE IRBFF,(A) ;YES, MARK ALL BUFFERS AS FREE
STOR U,IRBUN,(A) ;SAVE UNIT NUMBER FOR INTERRUPT LEVEL
ADDI A,MTIRBL ;STEP TO NEXT IORB
AOBJN B,MTAOP1 ;LOOP BACK FOR ALL IORB'S
MOVEI A,MAXPPB*MTBUFN ;GET ADDRESS OF START OF LIST
IMULI A,(U) ; FOR THIS UNIT
ADDI A,MTAPBF ;ADD IN BASE ADR OF PAGE BUFFER AREA
STOR A,MTBUF ;REMEMBER ADR OF LIST
STOR A,MTCUP ;SET UP CURRENT P TO BE EMPTIED
SETZRO MTCUB ;START AT BUFFER 0
SETZRO MTCSB ;FOR BOTH USER AND SERVICE ROUTINE BUF'S
MOVE A,JOBNO ;GET USER PROGRAM NAME FOR SYSERR
MOVE B,JOBPNM(A)
HRRZ C,MTCUTB(U) ;GET UDB ADR
MOVEM B,UDBPNM(C) ;STORE PROGRAM NAME IN UDB
HRR B,JOBDIR(A) ;GET LOGGED-IN DIRECTORY
HRLI B,USRLH ;MAKE IT A USER NUMBER
MOVEM B,UDBUDR(C) ;STORE IT IN UDB ALSO
UNLOCK MTALCK(U) ;UNLOCK THE LOCK ON THIS UNIT
RETSKP ;SUCCESSFULLY OPENED
BUSY: SKIPA A,[OPNX9] ;UNIT ALREADY OPENED
MTOPNF: SETZM MTASTS(U) ;CLEAR STATUS WORD
UNLOCK MTALCK(U) ;UNLOCK THIS UNIT
RET ;NOT OPENED!
MTAILM: MOVEI A,OPNX14 ;ILLEGAL MODE
RET
MTAOFL: MOVEI A,OPNX8 ;DEVICE IS OFF-LINE
RET
MTAWLK: MOVEI A,OPNX25 ;RETURN WRITE LOCKED ERROR CODE
JRST MTOPNF ;OPENF FAILED
MTAISM: MOVEI A,OPNX15 ;ILLEGAL SEQUENTIAL I/O MODE
JRST MTOPNF ;GO UNLOCK AND BOMB OUT
;ROUTINE TO SET UP MTUBW, MTHBW, MTUBB, AND MTUBP
SETBW: LOAD A,MTDM ;GET DATA MODE
CAILE A,MTMXDM ;LEGAL MODE?
RETBAD (MTOX5) ;NO
MOVE A,HBWTB(A) ;GET BYTES PER WORD
STOR A,MTHBW ;SAVE HARDWARE BYTES PER WORD
LDB A,PBYTSZ ;GET SIZE OF USER BYTES
MOVEI C,^D36 ;GET USER BYTES PER WORD
SKIPN A ;SIZE = 0?
MOVEI A,^D36 ;YES, PRETEND IT IS WORD MODE
IDIV C,A ;GET BYTES PER WORD
STOR C,MTUBW ;USER BYTES PER WORD
LOAD A,MTRS ;NOW CALCULATE USER BYTES PER BUFFER
IMUL A,C ;RECORD SIZE * USER BYTES PER WORD
OPSTR <IDIV A,>,MTHBW ;NOW HAVE DESIRED VALUE
SKIPE B ;ANY REMAINING BITS IN RECORD?
AOS A ;YES, INCR USER BYTES PER BUFFER
STOR A,MTUBB ;SAVE COUNT OF USER BYTES PER BUFFER
IMULI C,PGSIZ ;GET USER BYTES PER PAGE
STOR C,MTUBP ;SAVE USER BYTES PER PAGE
IDIV A,C ;SEE IF RECORD SIZE TOO LARGE
SKIPE B ;GET NUMBER OF PAGES PER BUFFER
AOS A ;PARTIAL PAGE
CAILE A,MAXPPB ;WITHIN LEGAL RANGE?
RETBAD (MTOX4) ;NO
RETSKP ;EXIT OK
HBWTB: 1 ;TABLE OF HARDWARE BYTES PER WORD
1 ;36 BIT BYTES
6 ;6 BIT BYTES
5 ;7 BIT BYTES
4 ;8 BIT BYTES
1 ;36 BIT BYTES (HI-DENSITY)
MTMXDM==:.-HBWTB-1
;ROUTINE TO CLOSE A MAGTAPE UNIT
;CALLED BY CLOSF
MTACLZ::HLRZ U,DEV ;SET UP UNIT NUMBER
MOVX IOS,MTOWT!DMPWT ;CLEAR WAIT FLAGS
ANDCAB IOS,MTASTS(U)
TXNN IOS,CLOF ;ALREADY STARTED THE CLOSE?
JRST [ SETZRO MTSTC ;NO, INITIALIZE CLOSE FUNCTION COUNT
MOVX IOS,CLOF ;AND MARK THAT CLOSE IS IN PROGRESS
IORB IOS,MTASTS(U)
TXNN IOS,OPND ;DUMP MODE?
JRST .+1 ;NO
INCR MTSTC ;YES, DONT FORCE OUT LAST BUFFER
JRST .+1]
TXNE A,CZ%ABT ;AN ABORT TYPE CLOSE?
JRST MTACLA ;YES, GO ABORT
CALL MTACLW ;WAIT FOR ACTIVITY TO CEASE
RET ;NEED TO BLOCK
MOVE IOS,MTASTS(U) ;GET STATUS
TXNN IOS,BUFA!OPND ;ANY BUFFERS?
JRST MTACLR ;NO, NOTHING TO DO
TQNE <WRTF> ;WRITING?
JRST MTACL1 ;YES, GO CLOSE THE WRITE
TXNN IOS,OPND ;DUMP MODE
TQNN <READF> ;NO, READING?
JRST MTACLR ;NOTHING TO DO
SETZRO ABORTF,(U) ;CLEAR ERROR ABORT BIT
CALL MTPOS0 ;SEQUENTIAL READ, GO LEAVE TAPE IN
RET ; CORRECT POSITION
CALL MTACLW ;WAIT FOR ACTIVITY TO STOP
RET ;NEED TO BLOCK
JRST MTACLR
MTACL1: CALL MTACLW ;WAIT FOR ALL ACTIVITY TO STOP
RET ;NEED TO BLOCK
MOVE IOS,MTASTS(U) ;GET STATUS FLAGS
TXNE IOS,MT%DAE!MT%DVE ;ERROR IN PROGRESS?
RETBAD (IOX5) ;YES, GIVE ERROR RETURN
LOAD A,MTSTC ;GET CLOSE FUNCTION COUNT
CAIL A,MTACLN ;FINISHED YET?
JRST MTACLR ;YES, GO RELEASE PAGES
XCT MTACLT(A) ;PERFORM THE NEXT FUNCTION IN LIST
RET ;NEED TO BLOCK
INCR MTSTC ;STEP TO NEXT FUNCTION TO BE DONE
JRST MTACL1 ;LOOP BACK TIL CLOSE IS COMPLETE
MTACLT: CALL MTRECO ;FORCE OUT THE LAST PARTIAL BUFFER
CALL MTCHKE ;CHECK IF EOF'S NEED WRITING
CALL MTABKE ;THEN BACKSPACE OVER SECOND EOF
CALL MTFLSH ;FLUSH OUT ALL REMAINING IORBS
MTACLN==.-MTACLT ;NUMBER OF FUNCTIONS IN TABLE
MTACLA: NOSKED ;DONT ALLOW SCHEDULING
CALL MTAKIL ;KILL ALL REQUESTS IN QUEUE
OKSKED
MTCLA1: LOAD A,MTNIR ;GET NUMBER OF IORBS STILL ACTIVE
JUMPE A,MTACLR ;IF NONE, CLOSE OUT
MOVEI A,MTAWAT ;WAIT FOR IT TO FINISH
HRL A,U
MDISMS
JRST MTCLA1 ;LOOP BACK TO CHECK IF DONE
;ROUTINE TO CHECK IF EOF'S SHOULD BE WRITTEN
; CALL MTCHKE
;RETURNS +1: NEED TO BLOCK
; +2: EOF'S WRITTEN OR NOT NEEDED
MTCHKE: LOAD A,MTFCN ;GET LAST FUNCTION PERFORMED
CAIE A,IRFWRT ;A WRITE?
CAIN A,IRFWTM ;OR WRITE TAPE MARK?
SKIPA A,[2] ;YES, GO MAKE SURE TWO EOF'S ARE WRITTEN
RETSKP ;NO NEED FOR ANY EOF'S
CALLRET MTAWTM ;GO WRITE TAPE MARKS
;ROUTINE TO BACKSPACE OVER SECOND TAPE MARK
MTABKE: LOAD A,MTFCN ;GET LAST FUNCTION
CAIE A,IRFWTM ;MUST HAVE BEEN WRITE TAPE MARK
RETSKP ;NOTHING TO BE DONE IF NOT
LOAD A,MTNTM ;GET # OF TAPE MARKS WRITTEN
CAIE A,2 ;EXACTLY 2?
RETSKP ;NO, ALL DONE
CALL GETIRB ;GET AN IORB TO USE
RET ;MUST WAIT FOR ONE
MOVEI B,IRFBSB ;GET FUNCTION CODE OF BACKSPACE BLOCK
MOVEI C,1 ;DO ONE
CALL MTPIRQ ;QUEUE IT UP
RETSKP ;ALL DONE
;ROUTINE TO WAIT FOR ALL IORB'S TO BE FINISHED
; CALL MTACLW
;RETURNS +1: NEEDS TO BLOCK
; +2: NO IORB'S LEFT IN QUEUE
MTACLW: LOAD A,MTNIR ;GET NUMBER OF IORB'S IN QUEUE
JUMPE A,RSKP ;IF NONE, RETURN
MOVEI A,MTAWAT ;SET UP TO WAIT FOR REQUESTS TO FINISH
HRL A,U ;FOR THIS UNIT
TXO STS,BLKF ;SET WAIT FLAG FOR IO
RET ;AND GIVE NON-SKIP RETURN
MTACLR: CALL MTARLB ;RELEASE PAGES (IF ANY)
SETZM MTASTS(U) ;INITIALIZE STATUS
RETSKP ;CLOSE IS COMPLETE
;ROUTINE TO WAIT FOR ALL REQUESTS TO BE FINISHED
RESCD
MTAWAT::LOAD B,MTANIR,(A) ;GET NUMBER OF IORB'S OUTSTANDING
JUMPLE B,1(4) ;IF 0, RETURN +2
JRST 0(4) ;OTHERWISE CONTINUE WAITING
SWAPCD
;ROUTINE TO RETURN ALL IORBS TO THE FREE STATE AND CHECK FOR I/O ERRORS
; CALL MTFLSH
;RETURNS +1: NEED TO BLOCK
; +2: OK
MTFLSH: SAVEQ
CALL MTACLW ;WAIT FOR ALL QUIET
RET ;NEED TO BLOCK
MOVEI Q3,MTBUFN ;SET UP COUNT OF IORBS
MTFL0: CALL GETIRB ;GET NEXT IORB
JRST MTFL1 ;IGNORE ERRORS, (THEY WERE ADDED TO MTASTS)
CALL IRBDON ;YES, MARK IT DONE
JFCL ;IGNORE ERRORS
MTFL1: LOAD B,MTCSB ;STEP TO NEXT IORB
AOS B
IDIVI B,MTBUFN
STOR C,MTCSB
SOJG Q3,MTFL0 ;LOOP BACK FOR ALL IORBS
TQZ <BLKF> ;MAKE SURE WAIT FLAG IS NOT SET
RETSKP ;ALL FLUSHED OUT
;ROUTINE TO DO SEQUENTIAL INPUT FROM MAGTAPE
MTASQI::HLRZ U,DEV ;SET UP UNIT NUMBER
CALL MTAASB ;GO ASSIGN BUFFER SPACE (IF NEEDED)
MTERET () ;NO ROOM IN JSB FOR BUFFERS
MOVX IOS,MTOWT ;CLEAR MTOPR WAIT FLAG
ANDCAB IOS,MTASTS(U)
LOAD A,MTFCN ;GET LAST FUNCTION DONE
CAIE A,IRFRED ;LAST ONE A READ?
CAIN A,IRFRDR ;OR READ REVERSE?
JRST MTSQI6 ;YES, DONT NEED TO UPDATE STATUS
CALL UPDSTS ;UPDATE STATUS
RET ;NEED TO BLOCK
MTSQI6: CALL CHKERI ;SEE IF ANY ERRORS
RET ;YES, DONT GO ANY FURTHER
MOVE A,FILBYN(JFN) ;SEE IF THE BUFFER IS EMPTY YET
CAMGE A,FILLEN(JFN) ;...
JRST MTSQI1 ;NO, JUST STEP TO NEXT PAGE IN BUFFER
JUMPE A,MTSQI5 ;IF NO BUFFER YET, DONT CALL IRBDON
MTSQI0: CALL CLRINP ;CLEAR FILLEN ETC
MTERET () ;ERROR
MTSQI5: LOAD A,MTRS ;GET RECORD SIZE
MOVEI B,IRFRED ;MARK THAT A READ IS BEING DONE
LOAD C,MTRBF ;GET READ BACKWARDS FLAG
SKIPE C ;READING BACKWARDS?
MOVEI B,IRFRDR ;YES, GET CORRECT FUNCTION CODE
CALL MTIRQI ;QUEUE UP ANY FREE IORBS FOR FILLING
RET ;ERROR OCCURED
CALL GETUBF ;GET NEXT IORB TO BE EMPTIED
RET ;MUST WAIT FOR ONE TO FILL UP
JUMPE B,MTSQI0 ;IF NO CHARACTERS IN IORB, GET ANOTHER
OPSTR <IMUL B,>,MTUBW ;CALCULATE USER BYTES IN BUFFER
OPSTR <IDIV B,>,MTHBW ; HDW BYTES * USER BPW / HDW BPW
SKIPE C ;PARTIAL BYTE?
AOS B ;YES, COUNT TOTAL BYTES BY ONE
LOAD C,MTUBB ;GET MAX USER BYTES PER BUFFER
CAMLE B,C ;LIMIT TO MAX BYTES
MOVE B,C ;...
MOVEM B,FILLEN(JFN) ;THIS = # OF BYTES TO BE BIN'D OR SIN'D
SETZM FILBYN(JFN) ;SET BYTE NUMBER TO ZERO
SETZM FILCNT(JFN) ;ZERO COUNT TOO
JE MTRBF,,MTSQI1 ;READING BACKWARDS?
IDIVI B,PGSIZ ;YES, GET NUMBER OF PAGES OF DATA
SKIPE C ;PARTIAL PAGES INCLUDED
AOS B
MOVEI B,-1(B) ;PAGES GO FROM 0 TO N-1
OPSTRM <ADDM B,>,MTCUP ;START AT END OF LIST OF PAGES
;..
;..
MTSQI1: SKIPLE FILCNT(JFN) ;ARE THERE ANY MORE BYTES IN BUFFER
JRST MTSQI2 ;YES
LOAD A,MTCUP ;GET NEXT BUFFER PAGE TO BE EMPTIED
MOVE A,(A) ;GET VIRTUAL ADDRESS OF THE PAGE
OPSTR <HRL A,>,MTBYT ;SET UP BYTE POINTER
MOVEM A,FILBYT(JFN) ;SAVE BYTE POINTER FOR BIN/SIN
MOVE A,FILLEN(JFN) ;GET LENGTH OF BUFFER
SUB A,FILBYN(JFN) ;GET NUMBER OF BYTES LEFT IN BUFFER
LOAD B,MTUBP ;GET NUMBER OF USER BYTES PER PAGE
CAMLE A,B ;IS THERE MORE THAN 1 PAGE OF BYTES
MOVE A,B ;YES, LIMIT COUNT TO 1 PAGE ONLY
MOVEM A,FILCNT(JFN) ;SAVE COUNT OF BYTES IN THIS PAGE
JN MTRBF,,MTSQI3 ;IF READING BACKWARDS, GO FIX UP FILBYT
INCR MTCUP ;STEP TO NEXT PAGE IN BUFFER
MTSQI2: SOS FILCNT(JFN) ;NOW GET THE NEXT BYTE
AOS FILBYN(JFN) ;DECREMENT COUNT AND INCREMENT POSITION
ILDB A,FILBYT(JFN) ;GET BYTE FROM BUFFER
RET ;GIVE SUCCESSFUL RETURN
MTSQI3: DECR MTCUP ;STEP TO NEXT USER PAGE
MOVE C,FILLEN(JFN) ;GET NUMBER OF BYTES ON THIS PAGE
SUB C,FILBYN(JFN) ;GET NUMBER OF BYTES LEFT IN RECORD
IDIV C,B ;DIVIDE BY USER BYTES PER PAGE
JUMPE D,MTSQI2 ;IF ON A PAGE BOUNDRY, USE FULL COUNT
MOVEM D,FILCNT(JFN) ;IF FIRST TIME THRU, USE THIS COUNT
SUB B,D ;GET NUMBER OF BYTES TO SKIP
OPSTR <IDIV B,>,MTUBW ;SPLIT INTO WORDS AND BYTES
ADDM B,FILBYT(JFN) ;STEP OVER THE FULL WORDS
MTSQI4: SOJL C,MTSQI2 ;THEN STEP OVER BYTES (IF ANY)
IBP FILBYT(JFN)
JRST MTSQI4 ;LOOP BACK TIL ALL BYTES SKIPPED
;ROUTINE TO WAIT FOR AN IORB TO GO INACTIVE
;ACCEPTS IN A/ IORB ADR
; JRST MTAWTR
;RETURNS +1: ALWAYS, WITH BLKF SET AND A SET UP FOR MDISMS
MTAWTR: HRLI A,MTARWT ;SET UP FOR DISMIS
MOVSS A
TQO <BLKF> ;MARK THAT ROUTINE WANTS TO BLOCK
RET ;GO BLOCK
;ROUTINE TO WAIT FOR AN IORB TO BECOME READY
RESCD
MTARWT::JN IRBFA,(A),0(4) ;IF STILL ACTIVE, TAKE NON-SKIP RET
JRST 1(4) ;NO LONGER ACTIVE
SWAPCD
;ROUTINE TO DO SEQUENTIAL OUTPUT
;CALLED FROM IO
MTASQO::STKVAR <MTSQOB>
MOVEM A,MTSQOB ;SAVE THE BYTE
HLRZ U,DEV ;SET UP UNIT
MOVX IOS,MTOWT ;CLEAR MTOPR WAIT FLAG
ANDCAB IOS,MTASTS(U)
CALL CHKERO ;CHECK FOR ERRORS
RET ;THERE ARE SOME, EXIT NOW
CALL MTAASB ;ASSIGN BUFFERS IF NEEDED
MTERET () ;NO ROOM IN JSB FOR BUFFERS
SKIPG FILLEN(JFN) ;IS THIS THE VERY FIRST TIME THROUGH?
JRST [ CALL GETIRB ;GET NEXT IORB TO USE
RET ;WAIT FOR AN IORB
JRST MTSQO2] ;GO USE THIS BUFFER FOR FILLING
MOVE A,FILBYN(JFN) ;GET BYTE COUNT
CAMGE A,FILLEN(JFN) ;ANY BYTES LEFT IN THIS BUFFER?
JRST MTSQO1 ;YES, GO STEP TO NEXT PAGE
CALL MTSQO0 ;GO OUTPUT THE BUFFER
CALL GETIRB ;GET NEXT BUFFER FOR USER TO FILL
RET ;NONE AVAILABLE, GO WAIT FOR A BUFFER
MTSQO2: CALL CHKERO ;CHECK FOR ERRORS
RET ;ERRORS EXIST
LOAD A,MTUBB ;GET USER BYTES PER BUFFER
MOVEM A,FILLEN(JFN) ;SET UP NUMBER OF BYTES TO BE BOUT'ED
SETZM FILBYN(JFN) ;START AT BYTE 0
SETZM FILCNT(JFN) ;GUARANTEE TO SET UP FILCNT
MTSQO1: SKIPLE FILCNT(JFN) ;ANY BYTES LEFT ON THIS PAGE?
JRST MTSQO3 ;YES, GO FINISH OUT THIS PAGE
LOAD A,MTCUP ;GET POINTER TO CURRENT PAGE
INCR MTCUP ;STEP TO NEXT PAGE
MOVE A,(A) ;GET ADDRESS OF BUFFER PAGE
OPSTR <HRL A,>,MTBYT ;SET UP FILBYT
MOVEM A,FILBYT(JFN)
HRLI B,0(A) ;ZERO BUFFER
HRRI B,1(A)
SETZM 0(A)
BLT B,PGSIZ-1(A)
MOVE B,FILLEN(JFN) ;GET LENGTH OF BUFFER
SUB B,FILBYN(JFN) ;GET REMAINING BYTES IN BUFFER
LOAD A,MTUBP ;GET USER BYTES PER PAGE
CAML A,B ;ENOUGH BYTES LEFT IN BUFFER?
MOVE A,B ;NO, SET FILCNT CORRECTLY
MOVEM A,FILCNT(JFN) ;SET UP COUNT OF BYTES TO BE BOUT'ED
MTSQO3: SOS FILCNT(JFN) ;NOW PUT IN THE ORIGINAL BYTE
AOS FILBYN(JFN) ;KEEP THE COUNTS RIGHT
MOVE A,MTSQOB ;GET BACK THE BYTE
IDPB A,FILBYT(JFN) ;PUT THE BYTE INTO THE BUFFER
RET ;AND GIVE SUCCESSFUL RETURN
;ROUTINE TO WRITE OUT A PARTIAL BUFFER
; CALL MTRECO
;RETURNS +1: ERROR
; +2: DONE
MTRECO::HLRZ U,DEV ;SET UP UNIT NUMBER
MOVE IOS,MTASTS(U) ;GET STATUS BITS
TQNN <OPNF> ;CHECK OPENED
RETBAD (IOX2) ;NOT (CAN GET HERE ON MTOPR)
TQNE <WRTF> ;OPENED FOR WRITE?
TXNE IOS,OPND ;AND NOT IN DUMP MODE?
RETBAD (IOX9) ;NO, RECORD OUT LEGAL FOR SEQUENTIAL WRITE ONLY
SKIPLE FILLEN(JFN) ;ANY BUFFERS SET UP YET?
SKIPG FILBYN(JFN) ;YES, ANY THING IN THEM YET?
RETSKP ;NO, NOTHING TO DO
CALL MTSQO0 ;OUTPUT THE BUFFER
RETSKP ;ALL DONE
;ROUTINE TO OUTPUT A BUFFER AS SPECIFIED BY FILBYN, FILCNT, AND FILLEN
; CALL MTSQO0
;RETURNS +1: NEEDS TO BLOCK
; +2: BUFFER HAS BEEN QUEUED
MTSQO0: CALL GETCSB ;GET CURRENT IORB BEING USED
LOAD B,MTHBW ;GET RECORD SIZE FOR OUTPUT
LOAD D,MTUBW ;GET USER BYTES PER WORD
IMUL B,FILBYN(JFN) ;BYN * HBW / UBW
IDIV B,D
SKIPE C ;ANY PARTIAL BYTES?
AOS B ;YES, WRITE OUT PARTIAL BYTE
LOAD D,MTHBW ;NOW GET MIN # OF HDW BYTES PER RECORD
IMULI D,MINREC ;GET # OF BYTES IN MIN RECORD
CAMGE B,D ;IS THIS RECORD TOO SMALL?
MOVE B,D ;YES, MAKE IT THE MINIMUM SIZE
MOVEI C,IRFWRT ;FUNCTION IS WRITE
CALL MTAIRQ ;QUEUE UP THIS IORB
SETZM FILLEN(JFN) ;MARK THAT BUFFER WAS QUEUED UP
SETZM FILBYN(JFN)
SETZM FILCNT(JFN)
MOVX C,MT%EOT ;CHECK FOR EOT
TDNN C,MTASTS(U) ;...
RET ;NOT AT EOT
TQO <ERRF> ;SET ERROR FLAG
RET ;WILL BE NOTICED LATER
;ROUTINE TO ASSIGN BUFFER SPACE IN THE JSB
;THIS ROUTINE SETS UP MTBUF, MTCUB, AND MTNBF
;ACCEPTS U/ UNIT #
; CALL MTAASB
;RETURNS +1: NO ROOM IN JSB FOR BUFFERS
; +2: BUFFERS ASSIGNED
MTAASB: MOVX A,BUFA ;BUFFERS ALREADY ASSIGNED?
TDNE A,MTASTS(U) ;...
RETSKP ;YES, NO NEED TO GO ANY FURTHER
SAVEP ;SAVE PERMANENT ACS
LOAD B,MTRS ;GET RECORD SIZE
OPSTR <IDIV B,>,MTHBW ;GET NUMBER OF WORDS PER RECORD
ADDI B,PGSIZ-1 ;CALCULATE NUMBER OF PAGES REQUIRED
IDIVI B,PGSIZ ;...
CAILE B,MAXPPB ;WITHIN BOUNDS?
RETBAD (MTOX4) ;NO, RECORD SIZE TOO LARGE
STOR B,MTPPB ;SAVE PAGES PER BUFFER
LOAD P5,MTBUF ;SET UP BASE ADR OF LIST
LOAD P3,MTPPB ;SET UP COUNTER
IMULI P3,MTBUFN
MTAAS1: CALL ASGPAG ;GET A PAGE FROM JSB
JRST MTAAS2 ;NO MORE LEFT, GO RELEASE SPACE
HRRZM A,0(P5) ;STORE ADDRESS IN LIST
AOS P5 ;STEP POINTER TO LIST
SOJG P3,MTAAS1 ;LOOP BACK TIL ALL PAGES ASSIGNED
MOVX A,BUFA ;MARK THAT BUFFERS ARE NOW ASSIGNED
IORM A,MTASTS(U) ;...
RETSKP ;BUFFERS ASSIGNED
MTAAS2: LOAD A,MTPPB ;GET MAX NUMBER OF ASSIGNABLE PAGES
IMULI A,MTBUFN ;...
SUB P3,A ;GET NEGATIVE COUNT OF PAGES ASSIGNED
MTAAS3: AOJG P3,MTAAS4 ;ANY MORE PAGES TO BE RELEASED?
MOVE A,-1(P5) ;YES, GET ADDRESS
CALL RELPAG ;AND RELEASE IT
SOJA P5,MTAAS3 ;LOOP BACK TIL ALL PAGES RELEASED
MTAAS4: MOVEI A,IOX7 ;NO ROOM IN JSB FOR BUFFERS
RETBAD ;GIVE FAIL RETURN
;ROUTINE TO RELEASE ALL OF THE BUFFER PAGES
; CALL MTARLB
;RETURNS +1: ALWAYS
MTARLB: MOVX A,BUFA ;ARE THERE ANY BUFFERS ASSIGNED?
TDNN A,MTASTS(U) ;...
RET ;NO, DONT RELEASE ANY
SAVEP
LOAD P3,MTPPB ;GET COUNT OF NUMBER OF PAGES
IMULI P3,MTBUFN ;...
LOAD P5,MTBUF ;GET STARTING ADR OF LIST OF PAGES
MTARL1: HRRZ A,0(P5) ;GET NEXT PAGE TO BE RELEASED
CALL RELPAG ;RELEASE IT
AOS P5 ;STEP POINTER TO LIST
SOJG P3,MTARL1 ;LOOP BACK TIL ALL PAGES RELEASED
MOVX A,BUFA ;NOW MARK THAT THERE ARE NO BUFFERS
ANDCAM A,MTASTS(U) ;...
RET ;AND RETURN
;ROUTINE TO GET AN IORB TO USE AND STEP TO NEXT IORB
; CALL GETIRB
;RETURNS +1: NEED TO WAIT OR ERROR
; +2: A/ IORB ADR
GETIRB: CALL GETCSB ;GET CURRENT IORB ADR
JN IRBFA,(A),MTAWTR ;IF ACTIVE STILL, GO WAIT
JN IRBFF,(A),GETIR1 ;IF FREE, DONT CALL IRBDON
CALL SETSTS ;CHECK FOR ERRORS IN IORB
CALL IRBDON ;MARK IORB AS DONE
RET ;ERROR
GETIR1: LOAD B,MTCSB ;GET BUFFER NUMBER AGAIN
OPSTR <IMUL B,>,MTPPB ;GET OFFSET INTO LIST OF PAGES
OPSTR <ADD B,>,MTBUF ;ADD START ADR OF BUFFER
STOR B,MTCUP ;SAVE CURRENT PAGE BEING EMPTIED
SETONE IRBFQ,(A) ;MARK IT AS QUEUED UP
SETZRO <IRBAB,IRBFF,IRBFR,IRBFA>,(A)
RETSKP ;GIVE OK RETURN
;ROUTINE TO GET THE NEXT BUFFER TO BE GIVEN TO USER ON INPUT
; CALL GETUBF
;RETURNS +1: WAIT OR ERROR
; +2: A/ IORB ADR
; B/ # OF CHARACTERS IN BUFFER
GETUBF: CALL GTUBFA ;GET NEXT USER IORB
JRST GTUBF1 ;NONE AVAILABLE
CALL SETSTS ;SEE IF ANY ERRORS IN THIS IORB
CALL CHKERI ;SEE IF ANY ERRORS OR EOF
JRST [ PUSH P,A ;SAVE ERROR CODE
CALL GETCUB ;GET CURRENT IORB
CALL IRBDON ;RELEASE IT
JFCL
JRST PA1] ;GIVE ERROR RETURN
MOVE B,IRBCNT(A) ;GET # OF BYTES IN RECORD
RETSKP ;GOT ONE
GTUBF1: JUMPE A,[CALL GETCUB ;GET BACK THE IORB ADR
JRST MTAWTR] ;GO WAIT FOR ACTIVE BIT TO GO OFF
SKIPL A ;NONE QUEUED UP?
RETBAD () ;NO, JUST PLAIN ERROR
BUG(CHK,MTANOI,<GETUBF: NO QUEUED IORB'S FOR INPUT>)
JRST MTASIC ;GO BOMB
;ROUTINE TO GET A BUFFER FOR INPUTING
; CALL GTUBFA
;RETURNS +1: A = 0 ;NEED TO WAIT FOR ACTIVITY TO FINISH
; A = -1 ;NO IORB'S QUEUED UP FOR INPUT
; A POSITIVE ;ERROR CODE
; +2: A/ IORB ADR
GTUBFA: CALL GETCUB ;GET IORB FOR USER TO EMPTY
JN IRBFA,(A),RETZ ;GO WAIT FOR AN IORB
LOAD B,MTCUB ;GET BUFFER NUMBER AGAIN
OPSTR <IMUL B,>,MTPPB ;GET OFFSET INTO LIST OF PAGES
OPSTR <ADD B,>,MTBUF ;ADD START ADR OF BUFFER
STOR B,MTCUP ;SAVE CURRENT PAGE BEING EMPTIED
JN <IRBFF,IRBAB>,(A),GETUB1
LOAD C,ISFCN,(A) ;GET FUNCTION CODE
CAIE C,IRFRDR ;READ BACKWARDS?
CAIN C,IRFRED ;OR READ?
RETSKP ;YES, GIVE THIS BUFFER TO USER
CALL IRBDON ;MARK THIS BUFFER AS DONE
RET ;ERROR OCCURED
GETUB1: JRST RETO ;NONE QUEUED UP
;ROUTINE TO GET CURRENT USER IORB ADR
; CALL GETCUB
;RETURNS +1: ALWAYS, A/ IORB ADR
GETCUB: MOVEI A,MTBUFN
IMULI A,(U) ;GET BUFFER NUMBER FOR THIS UNIT
OPSTR <ADD A,>,MTCUB ;GET RELATIVE BUFFER NUMBER
IMULI A,MTIRBL
ADDI A,MTIRBF ;GET ACTUAL ADR
RET ;AND RETURN
;ROUTINE TO GET CURRENT IORB ADR
; CALL GETCSB
;RETURNS +1: ALWAYS, A/ IORB ADR
GETCSB: MOVEI A,MTBUFN
IMULI A,(U) ;GET BUFFER NUMBER FOR THIS UNIT
OPSTR <ADD A,>,MTCSB ;GET RELATIVE BUFFER NUMBER
IMULI A,MTIRBL
ADDI A,MTIRBF ;GET ACTUAL ADR
RET ;AND RETURN
;ROUTINE TO STEP TO NEXT USER BUFFER
; CALL STPCUB
;RETURNS +1: ALWAYS
STPCUB: LOAD B,MTCUB ;STEP USER BUFFER
AOS B
IDIVI B,MTBUFN ;MODULO NUMBER OF IORBS
STOR C,MTCUB ;SAVE NEW BUFFER NUMBER
RET
;ROUTINE TO CLEAR FILLEN, FILBYN, FILCNT AND AN IORB
CLRINP: SETZM FILLEN(JFN) ;MARK THAT THERE IS NO MORE BUFFER
SETZM FILBYN(JFN) ; IN CASE WE NEED TO BLOCK
SETZM FILCNT(JFN)
CALL GETCUB ;GET ADR OF THE BUFFER BEING USED
CALL IRBDON ;MARK IT DONE
RET ;SOME SORT OF ERROR OCCURED
CALL STPCUB ;STEP TO NEXT USER BUFFER
RETSKP
;ROUTINE TO MARK AN IORB AS DONE
;ACCEPTS IN A/ IORB ADR
; CALL IRBDON
;RETURNS +1: ERROR
; +2: A/ IORB ADR
IRBDON: JE IRBFQ,(A),IRBDN1 ;IF NOT QUEUED UP, ERROR
JN IRBFA,(A),IRBDN2 ;IF STILL ACTIVE, ERROR
SETZM IRBSTS(A) ;INIT THE IORB
SETZM IRBMOD(A)
SETZM IRBXFL(A) ;CLEAR OUT POINTER TO TRANSFER LIST
SETZRO <IRBFQ,IRBFR,IRBAB,IRBFA>,(A)
SETONE IRBFF,(A) ;MARK IT AS FREE
RETSKP ;FINISHED
IRBDN1: BUG(CHK,MTANOQ,<IRBDN1: IRBDON CALLED FOR NON-QUEUED UP IORB>)
JRST MTASIC
IRBDN2: BUG(CHK,MTANOA,<IRBDN2: IRBDON CALLED FOR AN ACTIVE IORB>)
MTASIC: MOVX A,MT%DVE ;MAKE THIS BE A HARD ERROR
IORM A,MTASTS(U)
MTERET (IOX8) ;SOFTWARE CONFUSION
;ROUTINE TO QUEUE UP AN IORB
;ACCEPTS IN A/ IORB ADR
; CALL QUEIRB
;RETURNS +1: ALWAYS
QUEIRB: MOVE IOS,MTASTS(U) ;GET STATUS BITS
MOVX C,IS.IER ;SEE IF USER DOESNT WANT ERROR RECOVERY
TXNE IOS,MT%SER ;...
IORM C,IRBSTS(A) ;DONT DO ANY ERROR RECOVERY ACTION
MOVX C,IS.IEL ;USER WANT TO IGNORE ERROR LOGGING?
TXNE IOS,MTIEL ;...
IORM C,IRBSTS(A) ;YES
LOAD B,MTCSB ;GET CURRENT IORB NUMBER
SETONE IRBFA,(A) ;MARK THIS IORB AS ACTIVE
LOAD C,ISFCN,(A) ;GET FUNCTION
LOAD D,MTFCN ;GET LAST FUNCTION
CAIE C,IRFRED ;READING?
JRST [ CAIE C,IRFRDR ;OR READ REVERSE?
JRST QUEIR1 ;NO, UPDATE MTCUB
CAIE D,IRFRDR ;YES, WAS LAST ONE A READ REVERSE TOO?
JRST QUEIR1 ;NO, SET POINTER TO BUFFER
JRST QUEIR2] ;YES, DONT RESET BUFFER POINTER
CAIE D,IRFRED ;LAST ONE A READ?
QUEIR1: STOR B,MTCUB ;NO, SET USER BUFFER POINTER HERE
QUEIR2: STOR C,MTFCN ;SET LAST FUNCTION
AOS B ;NOW STEP IORB NUMBER
IDIVI B,MTBUFN ;MODULO NUMBER OF IORBS
STOR C,MTCSB
INCR MTNIR ;COUNT UP NUMBER OF QUEUED IORBS
MOVE B,MTCUTB(U) ;GET CDB,,UDB
NOSKED ;PHYSIO REQUIRES NOSKED
CALL PHYSIO ;QUEUE UP REQUEST
OKSKED
RET ;RETURN
;ROUTINE TO CHECK AN IORB FOR ERRORS
; CALL CHKERI OR CALL CHKERO
;RETURNS +1: ERROR
; +2: OK, A-D UNCHANGED
CHKERI: MOVE IOS,MTASTS(U) ;GET STATUS BITS
TXNN IOS,MT%EOF!MT%DAE!MT%DVE!MT%IRL
RETSKP ;NO ERRORS OR EOF
JRST CHKER1
CHKERO: MOVE IOS,MTASTS(U) ;GET STATUS BITS
TXNN IOS,MT%DAE!MT%DVE!MT%IRL
RETSKP ;NO ERRORS
CHKER1: MOVEI A,IOX4 ;SET UP FOR EOF ERROR
TXNE IOS,MT%DAE!MT%DVE!MT%IRL ;ANY ERRORS?
SKIPA A,[IOX5] ;YES, GET ERROR CODE
TQOA <EOFF> ;MARK EOF FLAG
TQO <ERRF> ;OR ERROR FLAG
RET ;AND GIVE ERROR RETURN
;ROUTINE TO SET UP THE STATUS WORD
;ACCEPTS IN A/ IORB ADR
; CALL SETSTS
;RETURNS +1: ALWAYS
SETSTS: JN <IRBAB,IRBFF>,(A),R ;ABORTED OR FREE ARE OK
JE IRBFR,(A),R ;IF NEVER QUEUED UP, DONT SET STATUS
MOVE B,IRBSTS(A) ;GET STATUS BITS
MOVX C,MT%EOT!MT%BOT!MT%EOF ;SET UP TO TEST CONDITIONS
ANDCAM C,MTASTS(U) ;CLEAR THESE BITS FIRST
TXNN B,IS.TPM ;EOF SET?
TXZ C,MT%EOF ;NO
TXNN B,IS.EOT ;AT END OF TAPE?
TXZ C,MT%EOT ;NO
TXNN B,IS.BOT ;OR AT BEGINING OF TAPE
TXZ C,MT%BOT ;NO
TXNE B,IS.DTE ;DATA ERROR?
TXO C,MT%DAE ;YES
TXNE B,IS.DVE ;DEVICE (HARDWARE) ERROR?
TXO C,MT%DVE ;YES
TXNE B,IS.RTL ;RECORD TOO LONG?
TXO C,MT%IRL ;YES
IORB C,MTASTS(U) ;SET BITS IN STATUS WORD
LOAD D,ISFCN,(A) ;GET THE FUNCTION
CAIN D,IRFRDR ;READ BACKWARDS?
JRST SETST1 ;YES, CHECK RECORD LENGTH
CAIE D,IRFRED ;READ?
CAIN D,IRFWRT ;OR WRITE?
SETST1: SKIPA D,IRBCNT(A) ;YES, CHECK RECORD LENGTH
JRST SETST2 ;NO, DONT SET MT%IRL
STOR D,MTALTC ;REMEMBER THIS FOR MTGTS
OPSTR <SUB D,>,IRBOC,(A) ;SUBTRACT ORIGINAL COUNT
TXNE C,OPND ;DUMP MODE?
SKIPN D ;YES, MUST BE 0 ELSE ERROR
JRST SETST2 ;NO RECORD LENGTH ERROR
MOVX C,MT%IRL ;SET UP FOR RECORD LENGTH ERROR
TXNN B,IS.TPM ;SAW A TAPE MARK THIS TIME?
IORB C,MTASTS(U) ;NO, SET MT%IRL IN MTASTS
SETST2: RET ;ALL DONE
;ROUTINE TO CHECK IF AN IORB SHOULD BE ABORTED
;ACCEPTS IN A/ IORB ADR
; CALL MTCHKA ;CALLED FROM PHYTM2
;RTURNS +1: ABORT THE IORB
; +2: OK
RESCD
MTCHKA: LOAD B,IRBUN,(A) ;GET UNIT NUMBER
JE ABORTF,(B),RSKP ;IF ABORT FLAG = 0, GIVE OK RETURN
SETONE IRBAB,(A) ;MARK THAT THE IORB WAS ABORTED
RET ;LET PHYSIO MARK THIS AS DONE
SWAPCD
;ROUTINE TO QUEUE UP IORB'S FOR FILLING
;ACCEPTS IN A/ RECORD SIZE
; B/ FUNCTION CODE
; CALL MTIRQI
;RETURNS +1: ERROR
; +2: SUCCESSFUL
MTIRQI: STKVAR <MTIRQR,MTIRQF>
MOVEM A,MTIRQR ;SAVE THE RECORD SIZE
MOVEM B,MTIRQF ;SAVE FUNCTION CODE
MTIRQ0: CALL GETCSB ;GET ADR OF THIS IORB
JN IRBFA,(A),RSKP ;IF IORB IS STILL ACTIVE, ALL DONE
JN IRBAB,(A),MTIRQ1 ;IF ABORTED, USE THIS IORB
LOAD B,IRBFQ,(A) ;GET QUEUED FLAG
LOAD C,ISFCN,(A) ;GET FUNCTION CODE OF THIS IORB
CAIE C,IRFRDR ;READ BACKWARDS
CAIN C,IRFRED ;OR READ AHEAD?
JUMPN B,RSKP ;YES, CAUGHT UP WITH USER
MTIRQ1: CALL GETIRB ;GET NEXT IORB (SHOULD NOT BLOCK)
RET ;AN ERROR OCCURED
MOVE B,MTIRQR ;GET RECORD SIZE
MOVE C,MTIRQF ;AND FUNCTION CODE
CALL MTAIRQ ;QUEUE UP THIS IORB FOR READING
JRST MTIRQ0 ;LOOP BACK TILL CAUGHT UP WITH EMPTIER
;ROUTINE TO QUEUE 1 IORB FOR FILLING
;ACCEPTS IN A/ ADR OF IORB TO BE USED
; B/ RECORD SIZE
; C/ FUNCTION CODE
; CALL MTIRQ1
;RETURNS +1: ALWAYS
MTAIRQ: STKVAR <MTIRQA,MTIRQB,MTIRQC,MTIRQP,MTIRQT,MTIRQF>
MOVEM A,MTIRQA ;SAVE ADDRESS OF IORB
MOVEM B,MTIRQT ;SAVE SIZE OF RECORD
MOVEM B,IRBCNT(A) ;STORE CHARACTER COUNT
STOR B,IRBOC,(A) ;SAVE ORIGINAL COUNT FOR CHKERR
MOVEM C,MTIRQF ;SAVE FUNCTION FOR LATER
STOR C,ISFCN,(A) ;STORE FUNCTION CODE
ADDI A,MTIRTL ;GET POINTER TO IO LIST AREA
MOVEM A,MTIRQC ;SAVE FOR STORING LIST LATER
LOAD B,MTPPB ;GET PAGES PER BUFFER
MOVEM B,MTIRQP ;SAVE THIS COUNT
OPSTR <IMUL B,>,MTCSB ;THEN GET START OF AREA FOR THIS BUFFER
OPSTR <ADD B,>,MTBUF ;GET ADR OF PAGE TO BE FILLED
MOVEM B,MTIRQB
MOVE A,MTIRQA ;GET IORB ADR AGAIN
STOR B,IRBPB,(A) ;SAVE ADR OF LIST OF PAGES FOR MTAINT
MTIRQ2: HRRZS A,(B) ;ZERO PHYSICAL PAGE IN CASE NOT LOCKED
SKIPG MTIRQT ;ANY MORE BYTES TO BE TRANSFERED?
JRST [ MOVE C,MTIRQC ;NO, GO END TRANSFER LIST
JRST MTIRQ4]
CALL MLKMA ;LOCK DOWN THIS PAGE
MOVE B,MTIRQB ;GET INDEX INTO PAGE LIST AGAIN
HRLM A,(B) ;STORE PHYSICAL PAGE ADDRESS
MOVE B,MTIRQF ;GET FUNCTION
CAIE B,IRFRED ;READING?
CAIN B,IRFRDR ;OR READ REVERSE?
CALL MRKMPG ;YES, MARK THAT PAGE IS MODIFIED
MOVE B,MTIRQB ;GET PAGE NUMBER AGAIN
HLRZ B,(B) ;...
LSH B,PGSFT ;GET ADDRESS FROM PAGE NUMBER
LOAD A,MTHBW ;GET HARDWARE BYTES PER WORD
IMULI A,PGSIZ ;ASK FOR A PAGE TO BE FILLED
CAMLE A,MTIRQT ;ENOUGH BYTES FOR A FULL PAGE?
MOVE A,MTIRQT ;NO, JUST DO THE REMAINDER OF BYTES
SUBM A,MTIRQT ;DECREMENT THE COUNT OF BYTES LEFT
MOVNS MTIRQT ;SUBM DOESNT DO WHAT WAS DESIRED
OPSTR <HRL A,>,MTDM ;GET MODE OF TRANSFER
;..
;..
MOVE D,MTIRQF ;GET FUNCTION AGAIN
CAIE D,IRFRED ;READING?
CAIN D,IRFRDR ;OR READING BACKWARDS
SKIPA ;YES
JRST MTIRQ3 ;NO
JE MTRBF,,MTIRQ3 ;READING BACKWARDS?
TRO B,777 ;START AT END OF THIS PAGE
TXO A,1B0 ;YES, TELL PHYSIO THAT
MTIRQ3: HLRZ C,MTCUTB(U) ;GET CDB FOR THIS UNIT
CALL PHYCCW ;GET IOWD FOR TRANSFER LIST
MOVEM A,@MTIRQC ;SAVE IOWD IN TRANSFER LIST
AOS B,MTIRQB ;STEP TO NEXT PAGE
AOS C,MTIRQC ;STEP POINTER TO IORB TRANSFER LIST
SOSLE MTIRQP ;ANY MORE PAGES TO BE DONE?
JRST MTIRQ2 ;LOOP BACK FOR ALL IOWD'S
MTIRQ4: SKIPLE MTIRQP ;IF USED ALL PAGES IN LIST, DONT SETZM
SETZM 0(C) ;END TRANSFER LIST WITH A ZERO
MOVE A,MTIRQA ;GET POINTER TO IORB
STOR C,IRBTL,(A) ;SAVE POINTER TO TAIL
MOVEI C,MTIRTL(A) ;GET POINTER TO TRANSFER LIST HEAD
STOR C,IRBHD,(A) ;STORE HEAD POINTER
CALL SETMOD ;SET UP MODE WORD
MOVE D,[MTCHKA,,MTAINT] ;NOW SET UP INTERRUPT LEVEL HANDLER ADR
MOVEM D,IRBIVA(A) ;IN IORB
CALLRET QUEIRB ;GO QUEUE UP THE IORB
;ROUTINE TO SET UP MODE WORD IN IORB
;ACCEPTS IN A/ IORB ADR
; CALL SETMOD
;RETURNS +1: ALWAYS - IORB ADR STILL IN A
SETMOD: LOAD D,MTDM ;SET UP DATA MODE
STOR D,IRBDM,(A)
LOAD D,MTDN ;SET UP DENSITY
STOR D,IRBDN,(A)
LOAD D,MTPAR ;AND SET UP PARITY
STOR D,IRBPAR,(A)
RET
;ROUTINE TO MARK THAT IORB IS READY AND UNLOCK BUFFER PAGES
;CALLED AT INTERRUPT LEVEL BY PHYSIO
;ASSUMES IN A/ ADR OF IORB
; CALL MTAINT
;RETURNS +1: ALWAYS
RESCD
MTAINT: LOAD B,IRBFA,(A) ;MAKE SURE THIS IORB IS REALLY ACTIVE
JUMPE B,NOACTV ;IF 0, A FATAL STATE OF CONFUSION
MOVE B,IRBSTS(A) ;GET STATUS BITS FROM IORB
TXNE B,IS.ERR!IS.TPM ;ERROR OR EOF?
JRST MTAINE ;YES, GO FLUSH ALL QUEUED REQUESTS
MTAIN0: CALLRET MTAIND ;NO, GO UNLOCK PAGES AND MARK DONE
MTAINE: TXNN B,IS.TPM!IS.DTE!IS.DVE!IS.WGU!IS.NRT
JRST MTAIN0 ;DONT ABORT FOR NO GOOD REASON
SAVEQ ;GET SOME PERMANENT ACS
LOAD U,IRBUN,(A) ;GET UNIT NUMBER
CALL MTAIND ;UNLOCK PAGES
CALLRET MTAKIL ;KILL ALL IORBS LEFT ON QUEUE
NOACTV: BUG(HLT,MTARIN,<MTAINT: INTERRUPT RECEIVED FOR NONACTIVE IORB>)
SWAPCD
;ROUTINE TO KILL ALL QUEUED UP REQUESTS
RESCD
MTAKIL: STKVAR <MTAKLA>
SETONE ABORTF,(U) ;MARK THAT IORB'S SHOULD BE ABORTED
MOVE A,MTCUTB(U) ;SET UP CDB ,, UDB FOR PHYKIL
CALL PHYKIL ;DEQUEUE ALL IORB'S
MTAKL1: HRRZM A,MTAKLA ;SAVE ADR OF NEXT IORB
JUMPE A,R ;IF NONE, RETURN
HRRZS A ;CLEAR HIGH ORDER BITS
SETONE IRBAB,(A) ;MARK IORB AS BEING ABORTED
HRRZ B,IRBIVA(A) ;GET INTERRUPT LEVEL ROUTINE TO CALL
CALL 0(B) ;CLEAN UP IORB
HRRZ A,@MTAKLA ;GET NEXT IORB
JRST MTAKL1 ;LOOP BACK TIL ALL IORB'S DEQUEUED
SWAPCD
;ROUTINE TO DEQUEUE ONE IORB
RESCD
MTAIND: SAVEQ ;SAVE ALL PERMANENT ACS USED
MOVX B,IRBFR ;MARK THAT BUFFER IS READY
IORM B,MTIRSD(A)
MOVX B,IRBFA ;AND CLEAR ACTIVE BIT
ANDCAM B,MTIRSD(A)
LOAD U,IRBUN,(A) ;GET UNIT NUMBER
LOAD B,MTPPB ;GET COUNT OF PAGES THAT NEED UNLOCKING
MOVNS B ;SET UP FOR AOBJN POINTER
LOAD Q3,IRBPB,(A) ;GET ADDRESS OF LIST OF LOCKED PAGES
HRL Q3,B ;Q3 = -MTPPB ,, ADR OF LOCKED PAGES
MTAIN1: HLRZ A,(Q3) ;GET PHYSICAL ADR OF LOCKED PAGE
JUMPE A,MTAIN2 ;IF AT END OF LOCKED PAGES, STOP
CALL MULKCR ;UNLOCK IT
AOBJN Q3,MTAIN1 ;LOOP BACK TILL ALL PAGES UNLOCKED
MTAIN2: DECR MTNIR ;DECREMENT NUMBER OF REQUESTS PENDING
RET ;AND RETURN
SWAPCD
;JSYS TO SET UP LOGICAL TO PHYSICAL CORRESPONDENCE. ;INPUT IS:
; USER A/ SLAVE,,UNIT NUMBER
; USER B/ SERIAL NUMBER
.MTALN::MCENT
MOVX B,SC%WHL!SC%OPR
TDNN B,CAPENB ;IS THIS A PRIVILEGED JOB?
ITERR (WHELX1) ;NO. COMPLAIN
HRLI A,600002 ;MAGTAPE TYPE
CALL CHKDES ;MAKE SURE IS A VALID UNIT
ITERR() ;CAN'T GET IT
HLRZ U,DEV ;GET UNIT
XCTU [SKIPN B,B] ;A VALID SERIAL #
ITERR () ;NO
XCTU [HLRZ P5,A] ;GET DEVICE TYPE
SKIPN P5 ;IS THERE ONE?
MOVEI P5,.MTT45 ;NO ASSUME 45
JRST MTALN1 ;GO TO RESIDENT CODE
RESCD
MTALN1: IOPIOF ;DISABLE INTERRUPTS
MOVSI P3,-MTAN ;SET UP TO SEARCH ALL UNITS
MTLUN1: SKIPN C,MTCUTB(P3) ;GET UDB ADDRESS FOR THIS UNIT
JRST MTLUN2 ;NONE THERE. FORGET IT
HRRZ D,C ;GET ADDRESS ONLY
CAME B,UDBDSN(D) ;IS THIS THE ONE?
JRST MTLUN2 ;NO. KEEP LOOKING
LOAD P6,USTYP,(D) ;GET TYPE OF SLAVE
CAIE P6,0(P5) ;MATCH?
JRST MTLUN2 ;NOPE TRY NEXT ENTRY
CAIN U,0(P3) ;IS THIS ALREADY CORRECT?
JRST MTALNX ;YES. JUST RETURN GOOD
MOVX B,OPN ;SEE IF UNIT NOW ASSIGNED
TDNN B,MTASTS(U) ;IS THIS ONE BEING USED?
TDNE B,MTASTS(P3) ;IS IT NOW BEING USED?
JRST [ IOPION ;TURN DISKS BACK ON
ITERR (OPNX7)] ;UNAVAILABLE
EXCH C,MTCUTB(U) ;SWITCH ASSIGNMENTS
MOVEM C,MTCUTB(P3) ;DITTO
MTALNX: IOPION ;ENABLE I/O
JRST MRETN ;GOOD
MTLUN2: AOBJN P3,MTLUN1 ;DO ALL UNITS
IOPION ;TURN DISKS ON AGAIN
ITERR() ;NONE FOUND
SWAPCD ;SET SWAP CODE
;MTOPR JSYS
;ACCEPTS IN B/ OPERATION
; CALL MTMTAP
;RETURNS +1: ROUTINE WANTS TO BLOCK (BLKF SET) OR ERROR
; +2: DONE
MTMTAP::STKVAR <MTMTAO,MTMTAE>
MOVEM B,MTMTAO ;SAVE OPERATION CODE
HLRZ U,DEV ;SET UP UNIT NUMBER
MOVX IOS,DMPWT ;CLEAR DUMP MODE WAIT FLAG
ANDCAB IOS,MTASTS(U)
SKIPL B ;LEGAL OPERATION?
CAIL B,MTMTBL ;LEGAL OPERATION?
RETBAD (MTOX1) ;NO, ERROR
TXNN IOS,MTOWT ;SKIP INTI IF NOT FIRST TIME
TQNE <OPNF> ;OPENED?
SKIPA ;YES - SKIP INIT
JRST [ CALL MTNOPN ;NO - INIT STORAGE
RET ;PASS ERROR UP
JRST .+1]
CALL MTACLW ;ALWAYS WAIT FOR ACTIVITY TO STOP
RET ;NEED TO BLOCK
CALL UPDSTS ;UPDATE STATUS
RET ;NEED TO BLOCK
MOVE B,MTMTAO ;GET BACK OPERATION CODE
ROT B,-1 ;GET INDEX INTO OPERATION TABLE
HLRZ A,MTMTAB(B) ;GET EVEN ENTRY
SKIPGE B ;ODD ENTRY DESIRED?
HRRZ A,MTMTAB(B) ;YES, GET RIGHT HALF WORD
JUMPE A,[MOVEI A,MTOX1 ;ILLEGAL FUNCTION IF 0
JRST MTMTPE]
CALL 0(A) ;DO THE OPERATION
MTMTPE: TDZA B,B ;ERROR OR WAIT
SETO B, ;SUCCESSFUL
MOVX C,MTOWT ;ALWAYS CLEAR WAIT BIT
ANDCAM C,MTASTS(U)
JUMPN B,RSKP ;IF SUCCESSFUL, RETURN NOW
TQNE <BLKF> ;BLOCKING?
IORM C,MTASTS(U) ;YES, REMEMBER THIS FOR NEXT PASS
RET
;ROUTINE TO INIT DRIVE STORAGE IF IT IS NOT OPENED
MTNOPN: LOCK MTALCK(U),<CALL LCKTST>
CALL MTOPNX ;INIT DATA BASE
RET ;ERROR , PASS ON
RETSKP ;OK - RETURN
;TABLE OF MTOPR FUNCTIONS
MTMTAB: MTACLE,,MTAREW ;(0,1) CLEAR ERRORS ,, REWIND
MTARBK,,MTATPM ;(2,3) SET READ BACKWARDS ,, EOF
MTASDM,,MTASRS ;(4,5) SET DATA MODE ,, SET RECORD SIZE
MTAFRC,,MTABRC ;(6,7) FORWARD RECORD ,, BACKWARD RECORD
MTAEOT,,MTARWU ;(10,11) SKIP TO EOT ,, REWIND & UNLOAD
MTARDN,,MTAERT ;(12,13) READ DENSITY ,, ERASE TAPE
MTARDM,,MTARRS ;(14,15) GET DATA MODE ,, GET REC SIZE
MTAFFL,,MTABFL ;(16,17) FORWARD FILE ,, BACKWARD FILE
MTASPA,,MTARPA ;(20,21) SET PARITY ,, READ PARITY
MTANRB,,MTRECO ;(22,23) GET # OF BYTES LEFT IN RECORD ,, OUTPUT RECORD
MTASDN,,MTAINF ;(24,25) SET DENSITY ,, GET TAPE INFO
MTARDR,,MTASID ;(26,27) READ DIRECTION ,, SET REEL ID
MTAIEL,,RSKP ;(30,31) INHIBIT ERROR LOGGING,,WAIT NOP
MTALOC,,MTTLS ;(32,33) ATTACH MT TO MTA,,TAPE LABEL SET
MTTLG,,MTULR ;(34,35) TAPE LABEL GET,,USER LABEL READ
MTULW,,0 ;(36,37) USER LABEL WRITE,,ERROR
MTMTBL==<.-MTMTAB>*2 ;MAXIMUM LEGAL FUNCTION CODE
;ROUTINE TO CLEAR ERRORS
MTACLE: MOVX A,MT%DVE!MT%DAE!MT%IRL!MT%EOT!MT%EOF
TDNN A,MTASTS(U) ;ANY ERRORS SHOWING?
RETSKP ;NO, DONT CLEAR ABORTF
ANDCAM A,MTASTS(U)
SETZRO ABORTF,(U)
TQZ <ERRF,EOFF> ;CLEAR STS ALSO
RETSKP ;EXIT SUCCESSFULLY
;ROUTINE TO SET OR CLEAR THE READ BACKWARDS FLAG
MTARBK: CALL MTPOS0 ;POSITION TAPE TO WHERE USER EXPECTS IT
RET ;NEED TO BLOCK
UMOVE T1,3 ;GET NEW VALUE
STOR T1,MTRBF ;SAVE NEW SETTING OF FLAG
RETSKP ;EXIT
;ROUTINE TO POSITION TAPE TO WHERE USER THINKS IT SHOULD BE
; CALL MTPOS0
;RETURNS +1: NEEDS TO BLOCK
; +2: DONE
MTPOS0: MOVEI A,0 ;SET UP TO POSITION HEAD CORRECTLY
JE MTRBF,,MTPOS1 ;READING BACKWARDS?
CALLRET MTFRC0 ;NO, MOVE TAPE FORWARD OVER READ AHEAD
MTPOS1: CALLRET MTBRC0 ;BACK UP OVER READ AHEAD
;ROUTINE TO READ THE DIRECTION OF READ TRANSFER
MTARDR: LOAD T1,MTRBF ;GET READ BACKWARDS FLAG
UMOVEM T1,3 ;GIVE IT TO USER
RETSKP
;ROUTINE TO SET DATA MODE
MTASDM: SAVEQ
XCTU [HRRZ Q3,3] ;GET NEW DATA MODE
CAILE Q3,MTMXDM ;LEGAL?
RETBAD (MTOX5) ;NO, ILLEGAL DATA MODE
CALL MTAPBO ;OUTPUT PARTIAL BUFFER IF ANY
RET ;NEEDS TO BLOCK
SKIPN Q3 ;IS THIS 0?
LOAD Q3,JSMTM ;YES, GET JOB DEFAULT
SKIPN Q3 ;IS THAT NOT SET YET?
MOVEI Q3,MTDFDM ;YES, USE SYSTEM DEFAULT
STOR Q3,MTDM ;STORE NEW DATA MODE
CALL MTARLB ;RELEASE ANY BUFFERS
SETZM FILLEN(JFN) ;THROW AWAY ANY DATA IN BUFFERS
SETZM FILBYN(JFN)
SETZM FILCNT(JFN)
CALLRET SETBW ;SET UP OTHER PARAMETERS BASED ON MODE
;ROUTINE TO READ DATA MODE
MTARDM: LOAD T1,MTDM ;GET DATA MODE
UMOVEM T1,3 ;RETURN IT TO USER
RETSKP ;AND GIVE SUCCESSFUL RETURN
;ROUTINE TO SET RECORD SIZE
MTASRS: MOVE IOS,MTASTS(U) ;GET STATUS
TXNE IOS,OPND ;DUMP MODE IN EFFECT?
RETBAD (MTOX3) ;YES, ERROR
TXNE IOS,BUFA ;BUFFERS ASSIGNED YET?
RETBAD(MTOX2) ;YES, RECORD SIZE MUST BE SET BEFORE I/O IS DONE
XCTU [HRRZ T1,3] ;GET NEW SIZE
STOR T1,MTRS ;STORE NEW RECORD SIZE
CALLRET SETBW ;GO COMPUTE NEW PARAMETERS
;ROUTINE TO READ RECORD SIZE
MTARRS: LOAD T1,MTRS ;GET RECORD SIZE
UMOVEM T1,3 ;RETURN IT TO USER
RETSKP ;AND GIVE SUCCESSFUL RETURN
;ROUTINE TO SET REEL I.D.
MTASID: MOVE T1,CAPENB ;CHECK CAPABILITIES
TRNN T1,SC%WHL!SC%OPR ;WHEEL OR OPERATOR?
RETBAD (MTOX7) ;NO, NOT PRIVILEGED TO DO THIS FUNCTION
UMOVE T1,3 ;GET I.D.
HRRZ T2,MTCUTB(U) ;GET UDB ADR
MOVEM T1,UDBVID(T2) ;STORE NEW I.D.
RETSKP
;ROUTINE TO SET ERROR LOGGING FLAG
MTAIEL: MOVX T1,MTIEL ;GET FLAG
ANDCAM T1,MTASTS(U) ;CLEAR IT
XCTU [SKIPE 3] ;USER WANT TO SET IT?
IORM T1,MTASTS(U) ;YES
RETSKP
;ROUTINE TO SET DENSITY
MTASDN: XCTU [HRRZ T1,3] ;GET NEW DENSITY
CAILE T1,MTMXDN ;LEGAL?
RETBAD (MTOX6) ;NO, ILLEGAL DENSITY
SKIPN T1 ;WANT DEFAULT?
LOAD T1,JSMTD ;YES, GET JOB DEFAULT
SKIPN T1 ;GOT ONE YET?
MOVEI T1,MTDFDN ;NO, USE SYSTEM DEFAULT
STOR T1,MTDN ;STORE IT
RETSKP
;ROUTINE TO READ THE DENSITY
MTARDN: LOAD T1,MTDN ;GET THE DENSITY
UMOVEM T1,3 ;RETURN IT TO USER
RETSKP ;AND GIVE SUCCESSFUL RETURN
;ROUTINE TO SET PARITY
MTASPA: UMOVE T1,3 ;GET NEW PARITY SETTING
STOR T1,MTPAR ;SAVE IT
RETSKP
;ROUTINE TO READ PARITY SETTING
MTARPA: LOAD T1,MTPAR ;GET PARITY SETTING
UMOVEM T1,3 ;RETURN IT TO USER
RETSKP ;AND GIVE SUCCESSFUL RETURN
;ROUTINE TO GET THE NUMBER OF BYTES LEFT IN BUFFER
MTANRB: MOVE IOS,MTASTS(U) ;GET STATUS
TXNE IOS,OPND ;MUST BE SEQUENTIAL I/O MODE
RETBAD (MTOX3) ;THIS FUNCTION NOT LEGAL FOR DUMP MODE
SKIPE T1,FILLEN(JFN) ;ANY BUFFER SET UP
SUB T1,FILBYN(JFN) ;YES, GET NUMBER OF BYTES REMAINING
UMOVEM T1,3 ;RETURN IT TO USER
RETSKP ;AND GIVE SUCCESSFUL RETURN
;ROUTINE TO RETURN INFORMATION ABOUT A TAPE
MTAINF: SAVEPQ ;SAVE PERMANENT ACS
UMOVE P3,3 ;GET POINTER TO ARGUMENT BLOCK
HRRZ Q3,MTCUTB(U) ;GET POINTER TO UDB
XCTU [HRRZ P5,0(P3)] ;GET COUNT OF WORDS TO BE RETURNED
CAILE P5,MTIFTL ;TOO MANY?
RETBAD (MTOX8) ;YES, ARGUMENT BLOCK TOO LONG
MOVNS P5
HRLZS P5 ;SET UP AOBJN POINTER
MTAIFL: AOS P3 ;STEP POINTER TO ARGUMENT BLOCK
XCT MTINFT(P5) ;GET NEXT WORD
UMOVEM T1,0(P3) ;STORE IT IN USER'S BLOCK
AOBJN P5,MTAIFL ;LOOP BACK UNTIL DONE
RETSKP
MTINFT: MOVEI T1,1 ;TAPE TYPE CODE
MOVE T1,UDBVID(Q3) ;TAPE ID
CALL MTASER ;DRIVE SERIAL NUMBER
MOVE T1,UDBRED(Q3) ;FRAMES READ
MOVE T1,UDBWRT(Q3) ;FRAMES WRITTEN
MOVE T1,UDBPS2(Q3) ;RECORD # WITHIN CURRENT FILE
MOVE T1,UDBPS1(Q3) ;FILE # ON TAPE
MOVE T1,UDBSRE(Q3) ;SOFT READ ERRORS
MOVE T1,UDBSWE(Q3) ;SOFT WRITE ERRORS
MOVE T1,UDBHRE(Q3) ;HARD READ ERRORS
MOVE T1,UDBHWE(Q3) ;HARD WRITE ERRORS
MTIFTL==.-MTINFT
;ROUTINE TO GET SERIAL # OF UNIT
MTASER: HRRZ B,UDBDSN(Q3) ;GET DRIVE SERIAL #
MOVE C,udbslv(Q3) ;GET SLAVE NUMBER
DPB C,[POINT 3,B,17]
MOVE C,UDBADR(Q3) ;GET TM02 NUMBER
DPB C,[POINT 3,B,14]
MOVE A,UDBCDB(Q3) ;GET CHANNEL #
MOVE C,CDBADR(A)
DPB C,[POINT 3,B,11]
MOVE A,B ;RETURN CHAN,CONTRL,UNIT ,, SERIAL #
RET
;ROUTINE TO REWIND THE TAPE
MTAREW: CALL MTARWX ;FINISH OUTPUT/CLEAR INPUT
RET ;NEEDS TO BLOCK
CALL GETIRB ;GET AN IORB TO USE
RET ;NEED TO WAIT FOR ONE TO BE FREE
MOVEI B,IRFREW ;GET REWIND FUNCTION CODE
MTARW1: MOVEI C,1 ;DO ONE OPERATION
CALL MTPIRQ ;QUEUE UP THIS REQUEST
RETSKP ;ALL DONE
;ROUTINE TO REWIND AND UNLOAD
MTARWU: CALL MTARWX ;FINISH OUTPUT/CLEAR INPUT
RET ;NEEDS TO BLOCK
CALL GETIRB ;GET AN IORB
RET
MOVEI B,IRFRUN ;SET UP OPERATION CODE
JRST MTARW1 ;GO DO THE OPERATION
;COMMON ROUTINE FOR REWINDS TO FINISH OUTPUT OR CLEAR INPUT
MTARWX: TQNE <OPNF> ;IF NOT OPENED
TXNE IOS,OPND ;DUMP MODE?
RETSKP ;YES - DO NOTHING
TQNN <WRTF> ;WRITING?
JRST MTRWXR ;NO
CALLRET MTAPBO ;YES - DO PARTIAL BUFFER OUTPUT
MTRWXR: SKIPN FILBYN(JFN) ;BUFFER EXIST?
RETSKP ;NO
CALL CLRINP ;YES - CLEAR IT
MTERET() ;ERROR
RETSKP
;ROUTINE TO ERASE GAP
MTAERT: TQNE <OPNF> ;MUST BE OPENED
TQNN <WRTF> ;MUST BE OPENED FOR WRITE
RETBAD (IOX2) ;ILLEGAL WRITE ATTEMPT
CALL MTAPBO ;OUTPUT PARTIAL BUFFER IF ANY
RET ;NEEDS TO BLOCK
CALL GETIRB ;GET AN IORB TO USE
RET
MOVEI B,IRFERG ;GET OPERATION CODE
JRST MTARW1 ;GO DO OPERATION
;ROUTINE TO FORCE OUT ANY PARTIAL BUFFER
; CALL MTAPBO
;RETURNS +1: NEED TO BLOCK
; +2: OK
MTAPBO: CALL MTRECO ;OUTPUT RECORD
JFCL ;NOT DOING SEQUENTIAL OUTPUT
CALLRET UPDSTS ;WAIT FOR IT TO STOP WRITING
;ROUTINE TO SKIP TO END OF TAPE
MTAEOT: MOVE IOS,MTASTS(U) ;GET FLAGS
TXNE IOS,MTOWT ;FIRST TIME THRU?
JRST MTAET1 ;NO
CALL MTABRC ;FIRST TIME, DO A BACKSPACE
RET ;NEED TO BLOCK
MTAET2: SETZRO MTSTC ;SET COUNT OF EOF'S SEEN TO ZERO
CALL MTAFFL ;FORWARD SPACE OVER A FILE
RET ;NEED TO BLOCK
JRST MTAET1 ;GO SEE IF NEXT RECORD IS AN EOF ALSO
MTAET1: CALL UPDSTS ;GET CURRENT STATUS
RET ;NEED TO BLOCK
LOAD A,MTFCN ;GET LAST OPERATION DONE
CAIN A,IRFBSB ;BACKSPACE?
JRST MTAET2 ;YES, GO START SEARCHING FOR EOT
MOVE IOS,MTASTS(U) ;GET STATUS
TXNN IOS,MT%EOF ;AT END OF FILE?
JRST MTAET2 ;NO, GO SKIP A FILE
INCR MTSTC ;STEP STATE CODE
LOAD A,MTSTC ;GET COUNT OF EOF'S SEEN
CAIL A,2 ;LESS THAN 2?
JRST MTAET3 ;NO, FOUND EOT
CALL MTAFRC ;SPACE FORWARD ONE RECORD
RET ;NEED TO BLOCK
JRST MTAET1 ;GO SEE IF ON ANOTHER EOF
MTAET3: CAIE A,2 ;JUST FOUND THE SECOND TAPE MARK?
RETSKP ;NO, MUST BE DONE NOW
CALLRET MTABRC ;YES, BACKSPACE OVER SECOND EOF
;ROUTINE TO SPACE OVER A FILE
MTAFFL: MOVE IOS,MTASTS(U) ;GET THE STATUS
TXNN IOS,MTOWT ;FIRST TIME THRU?
JRST MTAFF1 ;YES, DO A SPACE WITHOUT CHECKING EOF
MTAFF0: CALL UPDSTS ;UPDATE THE STATUS WORD
RET ;NEED TO BLOCK
MOVE IOS,MTASTS(U) ;GET STATUS
TXNE IOS,MT%EOF ;HIT A TAPE MARK YET?
RETSKP ;YES, ALL DONE
SKIPA A,[MTSPCN] ;GET MAX # OF RECORDS TO DO AT A TIME
MTAFF1: MOVEI A,1 ;DO 1 RECORD FOR THE FIRST TIME ONLY
CALL MTFRC0 ;GO SPACE FORWARD A BIT
RET ;NEED TO BLOCK
JRST MTAFF0 ;LOOP BACK TIL A TAPE MARK SEEN
;ROUTINE TO SPACE THE TAPE FORWARD ONE RECORD
MTAFRC: MOVEI A,1 ;SPACE FORWARD ONE RECORD
CALLRET MTFRC0 ;DO THE WORK
MTFRC0: STKVAR <MTAFRS>
MOVEM A,MTAFRS ;SAVE THE SPACING COUNT
MOVE IOS,MTASTS(U) ;GET CURRENT STATUS
TQNE <OPNF> ;IF NOT OPENED
TXNE IOS,OPND ;IN DUMP MODE?
JRST MTFRC2 ;YES, JUST GO DO OPERATION
TQNE <WRTF> ;WRITING?
JRST [ CALL MTRECO ;YES, WRITE OUT ANY PARTIAL BUFFERS
RET ;NEED TO BLOCK
JRST MTFRC2] ;GO SPACE
SETZ B, ;SPECIFY THAT DIRECTION IS FORWARD
CALL MTBCNT ;COUNT THE READ AHEAD BUFFERS
RET ;ERROR
MOVEM A,MTAFRS ;SAVE COUNT OF RECORDS TO SPACE OVER
MTFRC2: SKIPG MTAFRS ;ANYTHING TO DO?
RETSKP ;NO
CALL GETIRB ;GET AN IORB TO USE
RET ;NEED TO BLOCK
MOVEI B,IRFFSB ;GET FUNCTION CODE
MOVE C,MTAFRS ;GET COUNT OF RECORDS TO SPACE OVER
CALL MTPIRQ ;DO THE SPACING OPERATION
RETSKP ;ALL DONE
;ROUTINE TO BACKSPACE OVER ONE FILE
MTABFL: MOVE IOS,MTASTS(U) ;GET FLAGS
TXNN IOS,MTOWT ;FIRST TIME THRU?
JRST MTABF1 ;YES, GO DO A BACKSPACE
MTABF0: CALL UPDSTS ;UPDATE THE STATUS WORD
RET ;NEED TO BLOCK
MOVE IOS,MTASTS(U) ;GET UPDATED STATUS WORD
TXNE IOS,MT%EOF!MT%BOT ;HIT TAPE MARK YET?
RETSKP ;YES, ALL DONE
SKIPA A,[MTSPCN] ;GET MAX # OF RECORDS TO DO AT A TIME
MTABF1: MOVEI A,1 ;DO 1 RECORD FOR THE FIRST TIME ONLY
CALL MTBRC0 ;BACKSPACE SOME
RET ;NEED TO BLOCK
JRST MTABF0 ;LOOP BACK TILL EOF HIT
;ROUTINE TO BACKSPACE ONE RECORD
MTABRC: MOVEI A,1 ;SET UP TO BACK SPACE ONE RECORD
CALLRET MTBRC0 ;DO IT
MTBRC0: STKVAR <MTABRN>
MOVEM A,MTABRN ;STORE COUNT OF RECORDS TO SPACE OVER
MOVE IOS,MTASTS(U) ;GET STATUS BITS
TQNE <OPNF> ;IF NOT OPENED
TXNE IOS,OPND ;DUMP MODE?
JRST MTBRC2 ;YES, GO DO THE OPERATION DIRECTLY
TQNE <WRTF> ;WRITING?
JRST [ CALL MTRECO ;YES, FORCE OUT THE LAST PARTIAL BUFFER
RET ;NEED TO BLOCK
JRST MTBRC2] ;THEN GO BACKSPACE
SETO B, ;SPECIFY THAT DIRECTION IS BACKWARDS
CALL MTBCNT ;COUNT BUFFERS OF READ AHEAD
RET ;ERROR
MOVEM A,MTABRN ;SAVE COUNT OF RECORDS TO SKIP OVER
MTBRC2: SKIPG MTABRN ;ANYTHING TO DO?
RETSKP ;NO
MOVE IOS,MTASTS(U) ;GET STATUS AGAIN
TXNE IOS,MT%BOT ;AT TAPE MARK ALREADY?
RETSKP ;YES, DONT DO ANYTHING
CALL GETIRB ;GET AN IORB TO USE
RET ;MUST WAIT
MOVEI B,IRFBSB ;SET UP TO DO THE BACKSPACE
MOVE C,MTABRN ;GET COUNT OF RECORDS TO SKIP
CALL MTPIRQ ;GO QUEUE UP THIS REQUEST
RETSKP ;AND EXIT
;ROUTINE TO COUNT THE BUFFERS OF READ AHEAD
;ACCEPTS IN A/ THE COUNT OF RECORDS TO SKIP
; B/ 0 = SPACING FORWARD
; -1= SPACING BACKWARDS
; CALL MTBCNT
;RETURNS +1: ERROR
; +2: COUNT OF RECORDS TO SPACE OVER IN AC A
MTBCNT: STKVAR <MTBCTA>
MOVEM A,MTBCTA ;SAVE STARTING COUNT
JE MTRBF,,MTBCT0 ;IF NOT READING BACKWARDS, NOT SPECIAL
SETCA B, ;READING BACKWARDS, COMPLEMENT B
MTBCT0: JUMPN B,MTBCT3 ;GO COUNT BUFFERS
MOVE A,FILLEN(JFN) ;GET CURRENT END OF BUFFER
CAMG A,FILBYN(JFN) ;ANY BYTES LEFT IN BUFFER?
JUMPE A,MTBCT1 ;IF NO BUFFER SET UP, DONT CLEAR IT
CALL CLRINP ;AT END OF BUFFER, CLEAR FILLEN
RET ;ERROR
MTBCT1: SOSGE MTBCTA ;ANYTHING MORE TO DO?
JRST MTBCT2 ;NO
CALL GTUBFA ;GET A BUFFER IF ANY
JRST MTBCT2 ;NONE THERE
CALL SETSTS ;UPDATE THE ERROR AND STATUS WORDS
CALL IRBDON ;JUST THROW THIS AWAY INSTEAD OF SPACING
RET
CALL STPCUB ;DONE WITH THIS IORB
JRST MTBCT1 ;LOOP BACK TILL DONE
MTBCT2: AOS A,MTBCTA ;GET COUNT OF RECORDS TO SKIP
RETSKP ;AND EXIT
MTBCT3: SKIPG FILLEN(JFN) ;ANY BUFFER SET UP?
JRST MTBCT4 ;NO, JUST COUNT QUEUED UP BUFFERS
CALL CLRINP ;YES, CLEAR OUT THE BUFFER IN PROGRESS
RET ;ERROR OCCURED
MTBCT4: CALL GTUBFA ;GET NEXT BUFFER QUEUED UP
JRST [ MOVE A,MTBCTA ;NO MORE, GET COUNT
RETSKP] ;AND RETURN
CALL SETSTS ;UPDATE THE STATUS
MOVX B,IS.BOT ;HIT BOT?
TDNN B,IRBSTS(A) ;IF YES, NO TAPE MOVED SO DONT COUNT UP
AOS MTBCTA ;COUNT UP NUMBER OF RECORDS TO PASS OVER
CALL IRBDON ;MARK THIS BUFFER AS DONE
RET ;ERROR OCCURED
CALL STPCUB ;STEP TO NEXT USER BUFFER
JRST MTBCT4 ;LOOP BACK TIL ALL QUEUED UP IORBS DONE
;ROUTINE TO QUEUE A MTOPR REQUEST
;ACCEPTS IN A/ IORB ADR
; B/ FUNCTION CODE
; C/ COUNT
; CALL MTPIRQ
;RETURNS +1: ALWAYS
MTPIRQ: STOR B,ISFCN,(A) ;SAVE FUNCTION CODE IN IORB ALSO
MOVEM C,IRBCNT(A) ;SAVE COUNT IN IORB
STOR C,IRBOC,(A) ;SAVE ORIGINAL COUNT ALSO
MOVE C,[MTCHKA,,MTPINT] ;NOW SET UP INTERRUPT LEVEL HANDLER ADR
MOVEM C,IRBIVA(A) ;SAVE IT IN IORB
SETZRO MTCIRB ;CLEAR DUMP MODE MEMORY OF IORB
CALL SETMOD ;SET UP DENSITY ETC.
SETZRO ABORTF,(U) ;ALWAYS DO THE OPERATION
CALLRET QUEIRB ;QUEUE UP THE REQUEST
;ROUTINE TO BE CALLED AT INTERRUPT LEVEL WHEN IORB IS DONE
RESCD
MTPINT: LOAD B,IRBFA,(A) ;MAKE SURE THIS IORB IS ACTIVE
JUMPE B,NOACTV ;IF NOT, BUGHLT
MOVX B,IRBFR ;MARK THAT BUFFER IS READY
IORM B,MTIRSD(A)
MOVX B,IRBFA ;AND CLEAR ACTIVE BIT
ANDCAM B,MTIRSD(A)
LOAD B,IRBUN,(A) ;GET UNIT NUMBER
DECR MTANIR,(B) ;COUNT DOWN # OF BUSY IORB'S
RET ;AND EXIT
SWAPCD
;ROUTINE TO WRITE A TAPE MARK
MTATPM: TQNN <OPNF> ;FILE OPENED?
RETBAD (IOX2) ;NO - ERROR
CALL MTAPBO ;OUTPUT PARTIAL BUFFERS IF ANY
RET ;NEED TO BLOCK
LOAD A,MTFCN ;GET LAST FUNCTION
CAIN A,IRFWTM ;TAPE MARK?
JRST MTTPM1 ;YES
SETZRO MTNTM ;NO, SET COUNT TO 0
MTTPM1: CALL GETIRB ;GET AN IORB TO USE
RET ;NEED TO BLOCK
MOVEI B,IRFWTM ;WRITE A TAPE MARK
MOVEI C,1 ;JUST 1
CALL MTPIRQ ;QUEUE IT UP
CALL NTMINC ;INCREMENT # OF TAPE MARKS WRITTEN
RETSKP ;ALL DONE
;ROUTINE TO WRITE N TAPE MARKS
;ACCEPTS IN A/ NUMBER OF TAPE MARKS TO BE WRITTEN
; CALL MTAWTM
;RETURNS +1: NEED TO BLOCK
; +2: DONE
MTAWTM: STKVAR <MTAWTC>
TQNN <WRTF> ;MUST BE OPENED FOR WRITE
RETBAD (IOX2) ;ILLEGAL ATTEMPT TO WRITE
MOVEM A,MTAWTC ;SAVE NUMBER OF TAPE MARKS TO WRITE
LOAD B,MTFCN ;GET LAST FUNCTION TO BE DONE
CAIN B,IRFWTM ;WAS A TAPE MARK JUST WRITTEN?
JRST MTWTM1 ;YES
SETZRO MTNTM ;NO, CLEAR COUNT OF TAPE MARKS WRITTEN
MTWTM1: LOAD B,MTNTM ;GET COUNT OF TAPE MARKS WRITTEN
CAML B,MTAWTC ;WRITTEN ENOUGH YET?
RETSKP ;YES, EXIT
CALL GETIRB ;GET AN IORB TO USE
RET ;NONE AVAILABLE, GO WAIT
MOVEI B,IRFWTM ;GET FUNCTION CODE
MOVEI C,1 ;ONE OPERATION
CALL MTPIRQ ;QUEUE UP REQUEST
CALL NTMINC ;INCREMENT # OF EOF'S WRITTEN
JRST MTWTM1 ;LOOP BACK TIL ALL WRITTEN
;ROUTINE TO INCREMENT # OF TAPE MARKS WRITTEN
NTMINC: LOAD T1,MTNTM ;GET NUMBER OF TAPE MARKS
CAIGE T1,2 ;ONLY COUNT TO 2
AOS T1 ;INCREMENT COUNT
STOR T1,MTNTM ;STORE COUNT
RET
;ROUTINE TO ATTACH AN MTA TO A GIVEN MT
;C(3) := UNIT,,FCN
MTALOC: MOVE T1,CAPENB ;GET CAPABILITIES
TXNN T1,SC%WHL!SC%OPR ;*** CHECK FOR TLP INSTEAD ***
RETBAD (MTOX7)
XCTU [HRRZ T1,3] ;GET USER FCN
CAILE T1,MXUFCN ;CHECK MAX
RETBAD (MTOX1)
JRST @MTALTB(T1) ;DISPATCH
MTALTB: DTBDSP (SETVV) ;(0) SET VOLUME VALID
DTBDSP (SETMTU) ;(1) SET MT UNIT #
DTBDSP (CLRVV) ;(2) CLEAR VOLUME VALID
DTBDSP (CLRMTU) ;(3) CLEAR MT UNIT #
DTBDSP (PUTVOL) ;(4) SET VOLUME INFO
DTBDSP (GETVOL) ;(5) GET VOLUME INFO
MXUFCN==.-MTALTB-1
;ROUTINES TO DO DUMP MODE IO TO AND FROM MAGTAPE
;CALLED FROM IO AND TAPE
;ACCEPTS IN A/ IOWD
MTDMOX::TDZA B,B ;FLAG FOR EXEC ADDRS
MTDMPO::SETO B, ;FLAG FOR USER ADDRS
TRVAR <MTDMOT,MTDMOF,MTDMAD>
MOVEM B,MTDMAD ;SAVE FOR LATER
MOVEM A,MTDMOT ;SAVE IOWD
SETOM MTDMOF ;MARK THAT A DUMPO WAS DONE
HLRZ U,DEV ;SET UP UNIT NUMBER
MOVE IOS,MTASTS(U) ;GET STATUS BITS
TQNN <WRTF> ;OPENED FOR WRITE?
RETBAD (IOX2) ;NO
CALL CHKERO ;ANY ERRORS?
RET ;YES
JRST MTDMO1 ;ENTER COMMON CODE
MTDMIX::TDZA B,B ;FLAG FOR EXEC ADDRS
MTDMPI::SETO B, ;FLAG FOR USER ADDRS
TRVAR <MTDMOT,MTDMOF,MTDMAD>
MOVEM B,MTDMAD ;SAVE FLAG
MOVEM A,MTDMOT ;SAVE IOWD
SETZM MTDMOF ;MARK THAT A DUMPI WAS DONE
HLRZ U,DEV ;SET UP UNIT NUMBER
TQNN <READF> ;OPENED FOR READ?
RETBAD (IOX1) ;NO
LOAD A,MTFCN ;GET LAST FUNCTION DONE
CAIE A,IRFRED ;LAST ONE A READ?
CAIN A,IRFRDR ;OR READ REVERSE?
JRST MTDMI0 ;YES, DONT NEED TO UPDATE STATUS
CALL UPDSTS ;UPDATE STATUS
RET ;NEED TO BLOCK
MTDMI0: CALL CHKERI ;ANY ERRORS OR EOF?
RET ;YES
MTDMO1: MOVX IOS,MTOWT ;CLEAR MTOPR WAIT FLAG
ANDCAB IOS,MTASTS(U)
TXC IOS,OPN!OPND ;OPENED FOR DUMP MODE
TXCE IOS,OPN!OPND ; AND OPENED?
RETBAD (DUMPX2) ;NO, MUST BE MODE 17 FOR DUMPI/O
TXNE IOS,DMPWT ;IN A DUMP MODE WAIT?
JRST MTDMI1 ;YES, GO SEE IF WAIT IS FINISHED
;..
;..
CALL GETIRB ;GET AN IORB TO USE
RET ;NEED TO WAIT FOR ONE
MOVEI B,IRFRED ;SET FUNCTION
LOAD C,MTRBF ;GET READ BACKWARDS FLAG
SKIPE C ;READING BACKWARDS?
MOVEI B,IRFRDR ;YES, GET CORRECT FUNCTION CODE
SKIPE MTDMOF ;OPENED FOR WRITE
MOVEI B,IRFWRT ;YES, SET WRITE FUNCTION
MOVE C,MTDMOT ;GET THE IOWD
LOAD D,MTCIRB ;GET LAST IORB IN USE
STOR D,MTLIRB ;SAVE IT FOR STATUS CHECK LATER
STOR A,MTCIRB ;SAVE CURRENT IORB ADR
CALL MTDIRQ ;GO BUILD AN IORB AND CALL PHYSIO
RETBAD ;FAILED, GIVE ERROR RETURN
MTDMI1: CALL MTDWAT ;WAIT FOR APPROPRIATE TIME
RET ;ROUTINE WANTS TO BLOCK
LOAD A,MTLIRB ;GET ADR OF LAST IORB
TQNN <NWTF> ;IN NO-WAIT MODE?
LOAD A,MTCIRB ;NO, GET CURRENT IORB
JUMPE A,MTDMI2 ;IF NONE, OK
CALL SETSTS ;SEE IF ANY ERRORS OCCURED
MTDMI2: SKIPE MTDMOF ;WRITING?
JRST [ CALL CHKERO ;YES, CHECK FOR ERRORS
RET ;THERE ARE ERRORS
JRST MTDMI3]
CALL CHKERI ;CHECK FOR ERRORS OR EOF
RET ;TAKE ERROR RETURN
MTDMI3: MOVE IOS,MTASTS(U) ;GET STATUS
SKIPE MTDMOF ;WRITING?
TXNN IOS,MT%EOT ;AND AT EOT?
RETSKP ;NO, ALL DONE
RETBAD (IOX5) ;RETURN ERROR
;ROUTINE TO QUEUE AN IORB FOR PHYSIO
;ACCEPTS IN A/ IORB ADR
; B/ FUNCTION CODE
; C/ IOWD TO BE TRANSFERED (IN CONTEXT OF USER PROGRAM)
; CALL MTDIRQ
;RETURNS +1: ALWAYS
MTDIRQ: STKVAR <MTDIRA,MTDIRC,MTDIRI,MTDIRM,MTDIRT,MTDIRL,MTDIRF,MTDIRZ>
MOVEM A,MTDIRI ;SAVE IORB ADR
MOVEM B,MTDIRF ;SAVE FUNCTION CODE
HRRI C,1(C) ;MAKE IOWD POINT TO FIRST WORD
HRRZM C,MTDIRA ;SAVE ADDRESS OF FIRST WORD
HLRO B,C ;GET COUNT
MOVNM B,MTDIRC ;SAVE POSITIVE COUNT
MOVE B,MTDIRA ;NOW CALCULATE NUMBER OF PAGES
ADD B,MTDIRC ;GET END OF USER BUFFER
SOS B ;GET ADR OF LAST WORD REFERENCED
TRZ B,777 ;GET PAGE ADDRESS
TRZ C,777 ; OF START AND END OF BUFFER
SUBI B,(C) ;GET # OF PAGES -1
LSH B,-PGSFT
CAILE B,MAXPPB-2 ;LEGAL LENGTH? (LEAVING ROOM FOR 0 WORD)
RETBAD (DUMPX3) ;NO, NOT ENOUGH ROOM IN IORB FOR IOWD'S
MOVE A,MTDIRI ;GET IORB ADR
LOAD D,ISFCN,(A) ;GET THE FUNCTION CODE
SKIPE D ;IT SHOULD BE ZERO
BUG(CHK,MTAORN,<MTDIR0: MAGTAPE IORB OVERRUN>)
ADDI A,MTIRTL ;GET ADDRESS OF START OF TRANSFER LIST
MOVEM A,MTDIRZ ;SAVE POINTER TO START OF LIST
MOVE D,MTDIRF ;GET FUNCTION
CAIE D,IRFRDR ;READING BACKWARDS?
JRST MTDIR0 ;NO
ADDI A,0(B) ;YES, PUT ENTRIES IN FROM END OF LIST
MTDIR0: MOVEM A,MTDIRL
SKIPN MTDMAD ;EXEC XFER?
JRST [ MOVE B,U ;YES - GET UNIT #
LSH B,1 ; TIMES 2
ADDI B,TLABBP ; INDEX INTO POINTER LIST
JRST MTDR1A]
LOAD B,MTCSB ;GET ADDRESS OF LIST OF LOCKED PAGES
IMULI B,MAXPPB ;USED AT INTERRUPT LEVEL TO UNLOCK
OPSTR <ADD B,>,MTBUF ;GET ABSOLUTE ADR OF LIST
MTDR1A: MOVEM B,MTDIRM ;SAVE FOR LATER
MOVE A,MTDIRI ;GET ADR OF IORB
STOR B,IRBPB,(A) ;STORE LIST ADR IN IORB
LOAD B,MTHBW ;GET BYTES PER WORD
IMUL B,MTDIRC ;GET TOTAL BYTES IN TRANSFER
MOVEM B,IRBCNT(A) ;SET UP COUNT IN IORB
STOR B,IRBOC,(A) ;SAVE COUNT TWICE FOR CHKERR
;..
;..
MTDIR1: SETZM @MTDIRM ;ZERO THIS LIST ELEMENT FIRST
SKIPG MTDIRC ;ANY MORE WORDS TO BE TRANSFERED?
JRST MTDIR3 ;NO, GO POST REQUEST
MOVE A,MTDIRA ;GET ADDRESS OF FIRST WORD
IDIVI A,PGSIZ ;GET OFFSET WITHIN PAGE
MOVEI C,PGSIZ ;GET NUMBER OF WORDS LEFT ON PAGE
SUB C,B ;...
CAMLE C,MTDIRC ;NOW SEE IF THERE ARE ENOUGH LEFT
MOVE C,MTDIRC ;NO, JUST TRANSFER THE REMAINDER
MOVEM C,MTDIRT ;SAVE COUNT
SUBM C,MTDIRC ;UPDATE THE COUNT
MOVNS MTDIRC ;DO WHAT SUBM DOESNT
LSH A,PGSFT ;GET ACTUAL ADDRESS
SKIPE MTDMAD ;SKIP IF EXEC PAGE
TXO A,1B0 ;MARK THIS AS A USER PAGE
CALL MLKMA ;LOCK DOWN THE PAGE
MOVEM A,@MTDIRM ;SAVE PHYSICAL ADDRESS FOR UNLOCKING
MOVE B,MTDIRF ;GET FUNCTION
CAIE B,IRFRED ;READING?
CAIN B,IRFRDR ;OR READ REVERSE?
CALL MRKMPG ;YES, MARK THAT PAGE IS MODIFIED
MOVE B,@MTDIRM ;GET PHYSICAL PAGE FOR PHYCCW
LSH B,PGSFT ;MAKE IT INTO AN ADDRESS
MOVE C,MTDIRA ;GET USER ADDRESS AGAIN
ANDI C,777 ;LOW ORDER BITS ONLY
IOR B,C ;SET STARTING WORD WITHIN PAGE
MOVE C,MTDIRT ;GET COUNT OF WORDS ON THIS PAGE
ADDM C,MTDIRA ;UPDATE THE ADDRESS OF USER BUFFER
LOAD A,MTHBW ;GET # OF HARDWARE BYTES PER WORD
IMUL A,MTDIRT ;GET # OF BYTES TO BE TRANSFERED
OPSTR <HRL A,>,MTDM ;ADD IN MODE OF TRANSFER
MOVE D,MTDIRF ;GET FUNCTION CODE
CAIE D,IRFRDR ;READING BACKWARDS?
JRST MTDIR2 ;NO
ADDI B,-1(C) ;YES, START AT LAST WORD OF BLOCK
TXO A,1B0 ;SET BIT 0 TO INDICATE BACKWARDS
MTDIR2: HLRZ C,MTCUTB(U) ;GET CDB FOR THIS UNIT
CALL PHYCCW ;GET TRANSFER COMMAND
MOVEM A,@MTDIRL ;SAVE COMMAND IN TRANSFER LIST
MOVE D,MTDIRF ;GET FUNCTION
CAIN D,IRFRDR ;READING BACKWARDS?
SOSA MTDIRL ;YES, STEP BACK THROUGH LIST
AOS MTDIRL ;STEP TO NEXT ITEM IN TRANSFER LIST
AOS MTDIRZ ;STEP POINTER TO END OF LIST
AOS MTDIRM ;STEP TO NEXT ITEM IN PAGE LIST
JRST MTDIR1 ;LOOP BACK TILL FINISHED
MTDIR3: MOVE C,MTDIRZ ;GET POINTER TO TAIL OF TRANSFER LIST
SETZM 0(C) ;END WITH A ZERO
MOVE A,MTDIRI ;GET ADR OF IORB
STOR C,IRBTL,(A) ;SAVE ADR OF TAIL IN IORB
MOVEI C,MTIRTL(A) ;GET POINTER TO TRANSFER LIST HEAD
STOR C,IRBHD,(A) ;STORE HEAD POINTER
CALL SETMOD ;SET UP DENSITY, DATA MODE, PARITY
MOVE D,MTDIRF ;GET FUNCTION CODE
STOR D,ISFCN,(A) ;PUT IT IN IORB
MOVE D,[MTCHKA,,MTDINT] ;NOW SET UP INTERRUPT LEVEL HANDLER ADR
MOVEM D,IRBIVA(A) ; IN IORB
CALL QUEIRB ;QUEUE THE IORB
RETSKP ;GIVE OK RETURN
;ROUTINE TO WAIT FOR APPROPRIATE EVENT AFTER QUEUEING IORB
; CALL MTDWAT
;RETURNS +1: ROUTINE WANTS TO BLOCK
; +2: WAITING IS NOT NECESSARY
MTDWAT: LOAD A,MTNIR ;GET NUMBER OF REQUESTS IN QUEUE
JUMPE A,MTDWTR ;IF 0, RETURN IMMEDIATELY
TQNE <NWTF> ;"NO WAIT" MODE?
CAILE A,1 ;YES, WAIT FOR COUNT TO GO TO 1
JRST MTDWT0 ;MUST WAIT
MTDWTR: MOVX IOS,DMPWT ;MARK THAT WAITING IS OVER
ANDCAB IOS,MTASTS(U)
RETSKP ;GIVE SKIP RETURN
MTDWT0: MOVX IOS,DMPWT ;MARK THAT WE ARE WAITING
IORB IOS,MTASTS(U)
MOVEI A,MTAWAT ;GET ADR OF ROUTINE TO DO TEST
TQNE <NWTF> ;IF "NO WAIT" MODE,
MOVEI A,MTDWT1 ; THEN WAIT FOR COUNT TO GO TO 1
HRL A,U ;GET UNIT NUMBER
TQO <BLKF> ;SET BLOCK FLAG
RET ;AND GIVE NON-SKIP RETURN
;ROUTINE TO WAIT FOR COUNT OF REQUESTS TO GO TO 1
RESCD
MTDWT1::LOAD B,MTANIR,(A) ;GET COUNT OF OUTSTANDING REQUESTS
CAILE B,1 ;DOWN TO 1 YET?
JRST 0(4) ;NO
JRST 1(4) ;YES, WAIT IS OVER
SWAPCD
;ROUTINE TO HANDLE AN INTERRUPT FROM END OF A DUMP MODE REQUEST
RESCD
MTDINT: LOAD B,IRBFA,(A) ;MAKE SURE THE IORB IS ACTIVE
JUMPE B,NOACTV ;IF NOT, THEN BUGHLT
MOVE B,IRBSTS(A) ;GET STATUS OF REQUEST
TXNE B,IS.ERR!IS.TPM ;ERROR OR TAPE MARK?
JRST MTDINE ;YES, GO ABORT OTHER IORBS
MTDIN0: CALLRET MTDIND ;NO, GO UNLOCK THIS IORB
MTDINE: TXNN B,IS.WGU!IS.TPM!IS.DTE!IS.DVE!IS.NRT
JRST [ LOAD C,ISFCN,(A) ;GET FUNCTION
CAIN C,IRFWRT ;WRITING?
TXNN B,IS.EOT ;YES, THEN CHECK FOR EOT ALSO
JRST MTDIN0 ;NO, THIS IS NOT AN ERROR
JRST .+1] ;EOT ABORTS FURTHER WRITES
SAVEQ
LOAD U,IRBUN,(A) ;SET UP UNIT NUMBER FOR MTAKIL
CALL MTDIND ;CLEAN UP THE CURRENT IORB FIRST
CALLRET MTAKIL ;THEN ABORT ALL OTHER IORBS
MTDIND: SAVEQ ;SAVE PERMANENT ACS USED
MOVX B,IRBFR ;MARK THAT BUFFER IS READY
IORM B,MTIRSD(A)
MOVX B,IRBFA ;AND CLEAR ACTIVE BIT
ANDCAM B,MTIRSD(A)
LOAD U,IRBUN,(A) ;GET UNIT NUMBER
LOAD Q3,IRBPB,(A) ;GET POINTER TO LIST OF PAGES TO UNLOCK
HRLI Q3,-MAXPPB ;SET UP AOBJN POINTER
MTDIN1: MOVE A,0(Q3) ;GET PAGE TO UNLOCK
JUMPE A,MTDIN2 ;IF 0, REACHED END OF LIST
CALL MULKCR ;UNLOCK THE PAGE
AOBJN Q3,MTDIN1 ;LOOP BACK FOR ALL PAGES
MTDIN2: DECR MTNIR ;DECREMENT COUNT OF REQUESTS IN QUEUE
RET ;AND RETURN
SWAPCD
TNXEND
END