Trailing-Edge
-
PDP-10 Archives
-
cuspmar86binsrc_2of2_bb-fp63a-sb
-
10,7/galaxy/pulsar/plrtap.mac
There are 3 other files named plrtap.mac in the archive. Click here to see a list.
TITLE PLRTAP - Tape Processing Module
SUBTTL Author: Clifford Romash/WLH/DC/NT 3-Aug-83
;
;
; COPYRIGHT (c) 1975,1976,1977,1978,1979,1980,1981,1982,
; 1983,1984,1985,1986
; DIGITAL EQUIPMENT CORPORATION
; ALL RIGHTS RESERVED.
;
; THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; AND COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE
; AND WITH THE INCLUSION OF THE ABOVE COPYRIGHT NOTICE. THIS
; SOFTWARE OR ANY OTHER COPIES THEREOF MAY NOT BE PROVIDED OR
; OTHERWISE MADE AVAILABLE TO ANY OTHER PERSON. NO TITLE TO
; AND OWNERSHIP OF THE SOFTWARE IS HEREBY TRANSFERRED.
;
; THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE
; WITHOUT NOTICE AND SHOULD NOT BE CONSTRUED AS A COMMITMENT
; BY DIGITAL EQUIPMENT CORPORATION.
;
; DIGITAL ASSUMES NO RESPONSIBILITY FOR THE USE OR RELIABILITY
; OF ITS SOFTWARE ON EQUIPMENT WHICH IS NOT SUPPLIED BY
; DIGITAL.
SEARCH GLXMAC
SEARCH ORNMAC ;For the WTO definitions
SEARCH PLRMAC
PROLOG (PLRTAP)
;THIS MODULE CONTAINS THE TAPE I/O ROUTINES FOR PULSAR. ALL ROUTINES
; ALL CALLED WITH 'B' CONTAINING THE ADDRESS OF THE TCB,
; AND RETURN WITH S1 CONTAINING A TRUE/FALSE INDICATOR.
;
;ARGUMENTS ARE PASSED IN S1 AND S2.
;ROUTINES IN THIS MODULE USE AC'S S1 AND S2 ONLY. ALL OTHER ACS
; ARE GUARANTEED TO BE PRESERVED.
SUBTTL Directory for PLRTAP
SUBTTL T$INIT -- Initialize PLRTAP
;CALLED DURING PULSAR INITIALIZATION TO INITIALIZE PLRTAP'S
; LOCAL DATABASE.
ENTRY T$INIT
T$INIT: POPJ P, ;JUST RETURN FOR NOW
SUBTTL T$OPEN -- Open A Magtape For I/O
;T$OPEN IS CALLED TO INITIALIZE A MAGTAPE FOR LABEL PROCESSING I/O
; IT IS CALLED WITH THE TCB ADDRESS IN 'B'
; IF T$OPEN SUCCEEDS, IT RETURNS TRUE/FALSE AND CALLS THE
; CALLING ROUTINE AS A CO-ROUTINE. ON THE CALLERS RETURN, IT CALLS
; T$RELE. IF MORE THAN ONE CALL TO T$OPEN IS MADE BEFORE THE
; ORIGINAL CALLER RETURNS, T$OPEN IS A NOOP WHICH RETURNS TRUE.
ENTRY T$OPEN
T$OPEN: $TRACE (T$OPEN,6)
LOAD S1,TCB.IO(B) ;GET IO STATUS
TXNE S1,TI.OPN ;IS DEVICE OPEN?
$RETT ;YES, DON'T DO ANYTHING
LOAD LT,TCB.LT(B) ;GET THE LABEL TYPE FROM THE TCB
PUSH P,T1 ;SAVE
PUSH P,T2 ; THE
PUSH P,T3 ; 'T'
PUSH P,T4 ; AC's
PUSHJ P,MAKBUF ;Make up some buffers for the TCB
MOVX T1,TI.OPN ;GET DEVICE IS OPEN BIT
IORM T1,TCB.IO(B) ;TURN IT ON
MOVEI T1,.TFLBG ;FUNCTION FOR LABEL GET
LOAD T2,TCB.DV(B) ;DEVICE NAME
MOVE T3,[2,,T1] ;AC FOR TAPOP.
SETZM TCB.DN(B) ;No device yet
; (in case offline during label get)
TAPOP. T3, ;GET THE LABEL DDB
$STOP (LGF,Label Get Failed)
STORE T3,TCB.DN(B) ;STORE LABEL DDB NAME IN TCB
MOVE T2,T3 ;USE IT AS DEVICE NAME FOR OTHER TAPOP.'S
MOVEI T1,.TFBSZ+.TFSET ;FUNCTION TO SET BLOCKSIZE
MOVX T3,BFRSIZ+1 ;GET BUFFER SIZE + A LITTLE EXTRA
MOVE T4,[3,,T1] ;AC FOR TAPOP.
TAPOP. T4, ;SET THE BLOCKSIZE
$STOP (CSB,Can't Set Blocksize)
MOVEI T3,.TFM8B ;INDUSTRY COMPATIBLE 8 BIT MODE
MOVEI T1,.TFMOD+.TFSET ;ASK TO SET IT
MOVE T4,[3,,T1] ;AC FOR TAPOP.
TAPOP. T4, ;SET MODE
$STOP (CSI,Can't Set Industry compatible mode)
REPEAT 0,<
LOAD T3,TCB.PS(B),TP.DEN ;GET DENSITY FROM THE TCB
JUMPE T3,OPEN.0 ;DON'T KNOW THE DENSITY
MOVEI T1,.TFDEN+.TFSET ;ARG TO SET IT
MOVE T4,[3,,T1] ;AC FOR TAPOP.
TAPOP. T4, ;SET THE DENSITY
$STOP (CSD,Can't Set Density)
OPEN.0:>;END REPEAT 0
MOVX S1,UU.DEL+.IODMP ;Get bit to disable error logging
MOVEM S1,TCB.FI(B) ;Light in FILOP I/O status word
MOVX S1,.FOMAU ;Update mode (Input and Output)
PUSHJ P,T$FILOP ;Do the FILOP
MOVX S1,FO.ASC ;Get assign ext channel bit
ANDCAM S1,TCB.FU(B) ;We've got a channel, don't ask again
MOVEI S1,PS.RDO!PS.RDH ;TRAP OFF-LINE AND HUNG DEVICE
PUSHJ P,I$PICD## ;CONNECT DEVICE TO PSI SYSTEM
SKIPT ;CHECK FOR ERRORS
$STOP (CCT,<Can't connect tape to PSI system>)
MOVX S1,.TFRDB ;SET UP TO READ 'READ-BACKWARDS' BIT
LOAD S2,TCB.DV(B) ;GET REAL DEVICE NAME
MOVE T1,[2,,S1] ;LOAD AC FOR TAPOP
CAIE LT,.TFLNV ;UNLABELD USER-EOT?
TAPOP. T1, ;NO - READ THE BIT
SETZ T1, ;ASSUME NOT READ-BACKWARDS
JUMPE T1,OPEN.1 ;IF NOT READING BACKWARDS,,CONTINUE
MOVX S1,LE.IOP ;ELSE GET POSITIONING ERROR
MOVEM S1,G$TERM## ;SET IT
MOVX S1,TS.ERR ;GET THE ERROR INTERLOCK
IORM S1,TCB.ST(B) ;AND SET IT ALSO
OPEN.1: POP P,T4 ;RESTORE
POP P,T3 ; THE
POP P,T2 ; 'T'
POP P,T1 ; AC's
MOVEI S1,T$RELE ;GET THE ADDRESS FOR CALLER TO RETURN TO
EXCH S1,0(P) ;EXCHANGE IT WITH CALLERS ADDRESS
PUSH P,S1 ;PUT CALLERS ADDRESS BACK ON STACK
MOVX S1,TS.ERR ;GET THE ERROR LOCK BIT
TDNN S1,TCB.ST(B) ;IS IT ON?
$RETT ;NO,,ALL'S OK !!!
$RETF ;ERROR WAS ON, RETURN FALSE
SUBTTL T$RELE -- Routine To Release Label IO Channel
;THIS ROUTINE IS CALLED AT THE END OF LABEL PROCESSING TO RELEASE
; THE IO CHANNEL USED FOR LABEL IO AND TO DO THE LABEL RELEASE
; TO START THE JOB WHICH WAS BLOCKED
;
;IT IS CALLED WITH 'B' CONTAINING THE ADDRESS OF THE TCB. AND RETURNS
; TRUE/FALSE
ENTRY T$RELEASE
T$RELE: $TRACE (T$RELE,6)
$CALL .SAVET ;SAVE SOME AC'S
PUSHJ P,I$PIRD## ;REMOVE PSI CONDITIONS
MOVE T4,TCB.IO(B) ;GET IO STATUS
MOVE S1,G$TERM## ;GET THE TERMINATION CODE
CAILE S1,LE.EOF ;IS IT ONE WHICH IS
CAIN S1,LE.BOT ;CONTINUABLE??
JRST RELE.1 ;YES, DON'T SET ERROR
MOVX S1,TS.SLR ;GET A BIT
TDNE S1,TCB.ST(B) ;SKIP LABEL RELEASE?
JRST RELE.1 ;YES
MOVX S1,TS.ERR ;GET THE ERROR INTERLOCK BIT
IORM S1,TCB.ST(B) ;AND TURN IT ON
MOVE S1,G$TERM## ;GET THE TERMINATION CODE
STORE S1,TCB.EC(B),TE.TRM ;STORE SO USER WILL GET THE SAME ERROR
RELE.1: LOAD S1,TCB.FU(B),TF.DVH ;Get channel #
RESDV. S1, ;RELEASE, BUT DON'T WRITE TAPE MARKS
JFCL ;Ignore the error
SETZM TCB.IC(B) ;ZAP INPUT CCW
SETZM TCB.OC(B) ;ZAP OUTPUT CCW
MOVE S1,TCB.ST(B) ;GET STATUS BITS
TXZ S1,TS.SLR ;CLEAR "SKIP LABEL RELEASE"
EXCH S1,TCB.ST(B) ;UPDATE
TXNE S1,TS.SLR ;SKIP LABEL RELEASE?
JRST RELE.2 ;YES
MOVEI T1,.TFLRL ;FUNCTION FOR LABEL RELEASE
LOAD T2,TCB.DV(B) ;GET THE REAL DEVICE NAME
JUMPE T2,RELE.3 ;No label ddb, quit
MOVE T3,G$TERM## ;GET TERMINATION CODE
MOVX S1,TS.ERR ;GET THE ERROR BIT
TDNE S1,TCB.ST(B) ;IS IT SET
LOAD T3,TCB.EC(B),TE.TRM ;YES, USE THE OLD CODE
IFN FTTRACE,<
SKIPE G$DEBUG ;Are we debugging?
$TEXT (,<Closing Label DDB with termination code of #^O/T3/>)
>;END OF FTTRACE CONDITIONAL
MOVE S1,[3,,T1] ;AC FOR TAPOP.
TAPOP. S1, ;SET THE TERM CODE
$STOP (LRF,Label Release Failed)
RELE.2: TXNN T4,TI.OAV ;SPECIAL AVR OPEN MODE
JRST RELE.3 ;NO, CONTINUE
MOVEI T1,.TFLDD ;YES, MUST DESTROY THE DDB
LOAD T2,TCB.DV(B) ;GET THE DEVICE NAME
MOVE T3,[2,,T1] ;AC FOR TAPOP
TAPOP. T3, ;DO THE LABEL DESTROY
JFCL ;IGNORE THE ERROR
SETZM TCB.IO(B) ;CLEAR THE I/O WORD
RELE.3: TXNN T4,TI.LND ;DOES LABEL DDB NEED TO BE DESTROYED?
JRST RELE.4 ;DON'T NEED TO DESTROY DDB
MOVEI T1,.TFLDD ;FUNCTION FOR LABEL DESTROY
LOAD T2,TCB.DS(B) ;OLD DEVICE NAME
MOVE T3,[2,,T1] ;AC FOR TAPOP
TAPOP. T3, ;DO THE LABEL DESTROY
JFCL ;IGNORE THE ERROR
RELE.4: MOVE T1,[TI.EOF!TI.EOT!TI.OPN!TI.BOT!TI.LND!TI.SOP] ;GET LOTSA BITS
ANDCAM T1,TCB.IO(B) ;CLEAR THEM
$RETT ;GIVE GOOD RETURN
SUBTTL T$NUNI -- Routine to Switch to New Unit
;THIS ROUTINE IS CALLED WITH S1 CONTAINING THE NEW UNIT NAME IN SIXBIT
; AND B POINTING TO THE TCB
;IT RETURNS WITH THE TCB SET UP TO USE THE NEW UNIT
;AND TRUE/FALSE
ENTRY T$NUNI
T$NUNI: $TRACE (T$NUNI,6,S1)
$CALL .SAVET ;SAVE SOME AC'S TO WORK IN
$SAVE <P1,P2> ;And some more regs
MOVE P1,S1 ;Save new device name
MOVE P2,B ;Save ptr to the TCB
PUSHJ P,G$FTCB## ;Ask for new device's TCB
SKIPT ;Found it?
$STOP (SND,<Switch units with non-existent device ^W/P1/>)
MOVX T1,TI.OPN ;Get channel opened bit
TDNE T1,TCB.IO(B) ;Is this DDB open?
$STOP (SIO,Switch units with OPEN Label DDB)
EXCH B,P2 ;Reset to our TCB, save new TCB
MOVE T3,P1 ;GET NEW DEVICE IN T3
LOAD T2,TCB.DV(B) ;AND OLD DEVICE TO T2
MOVEI T1,.TFLSU ;TAPOP FUNCTION TO SWITCH UNITS
MOVE T4,[3,,T1] ;AC FOR TAPOP.
TAPOP. T4, ;DO THE SWITCH UNITS
$STOP (CSU,Can't Switch Units)
STORE T3,TCB.DV(B) ;SAVE NEW DEVICE NAME
SKIPN TCB.DS(B) ;KEEP THE ORIGIONAL DRIVE NAME
STORE T2,TCB.DS(B) ;SAVE OLD DEVICE TO BE DESTROYED
MOVX T1,TI.LND ;FLAG FOR LABEL DDB NEEDS DESTUCTION
IORM T1,TCB.IO(B) ;TURN IT ON
STORE T2,TCB.DV(P2) ;Make new TCB look like old TCB
MOVE T1,TCB.CH(B) ;Get device dependent stuff
EXCH T1,TCB.CH(P2) ;Swap with old unit
MOVEM T1,TCB.CH(B) ;Save the new stuff
$RETT ;AND RETURN TRUE
SUBTTL T$SUNI -- Routine to Switch to Same Unit
T$SUNI::$TRACE (T$SUNI,6,S1)
$CALL .SAVET ;SAVE SOME ACS
MOVE T1,[3,,T2] ;SET UP UUO AC
MOVEI T2,.TFLSU ;FUNCTION CODE
MOVE T3,TCB.DV(B) ;GET DRIVE NAME
MOVE T4,T3 ;SAME UNIT, REMEMBER?
TAPOP. T1, ;KICK MONITOR
PUSHJ P,S..CSU ;SHOULDN'T FAIL
POPJ P, ;AND RETURN
SUBTTL T$LTYP -- IS THE DRIVE IN LABEL MODE
;CALLED WITH S1 CONTAINING THE UNIT NAME IN SIXBIT
T$LTYP:: $CALL .SAVET ;SAVE SOME TEMPS
MOVE T1,[XWD 3,T2] ;UUO ARGUMENT
MOVEI T2,.TFLBL ;FUNCTION TO GET LABEL TYPE
MOVE T3,S1 ;COPY THE DEVICE NAME
TAPOP. T1, ;GET THE LABEL TYPE
$STOP (RLT,Failed Reading Label Type)
SKIPE T1 ;BLP MODE
CAILE T1,.TFLIU ;IS IT A LEGAL TYPE
$RETF ;NO
$RETT ;YES, LEGAL LABEL TYPE
SUBTTL T$CKAV -- Check unit's acceptibility
;CALLED WITH S1 CONTAINING A UNIT NAME IN SIXBIT
T$CKAV::MOVE S2,S1 ;SAVE DEVICE NAME
DEVCHR S1, ;SEE IF THE DEVICE IS AVAILABLE
TXNE S1,DV.ASC!DV.ASP ;IS THE DEVICE OWNED BY SOMEONE?
$RETF ;YES, LOSE
$RETT ;NO, WIN
SUBTTL T$POS -- Position Tape
;T$POS IS CALLED WITH B CONTAINING THE TCB ADDRESS AND S1 CONTAINING
; THE DESIRED POSITIONING FUNCTION. POSITIONING FUNCTIONS
; ARE 3 CHARACTER SIXBIT CODES. LEGAL CODES ARE:
;
; 'REW' REWIND THE TAPE
; 'UNL' UNLOAD THE TAPE
; 'SBL' SKIP FORWARD 1 BLOCK
; 'SFL' SKIP FORWARD 1 FILE
; 'BBL' SKIP BACKWARD 1 BLOCK
; 'BFL' SKIP BACKWARD 1 FILE
; 'EOT' SKIP TO LOGICAL EOT
; 'DSE' DATA SECURITY ERASE
;RETURNS TRUE ALWAYS.
T$POS:: $TRACE (T$POS,6,S1)
$CALL .SAVE3 ;SAVE P1-P3
MOVSI P1,-PFUNCN ;MAKE AOBJN POINTER
POS.1: MOVE P2,PFUNCT(P1) ;GET THE FUNCTION
CAIN S1,(P2) ;DO THE COMPARE
JRST POS.2 ;GOT ONE
AOBJN P1,POS.1 ;AND LOOP
$STOP (IPF,Illegal Positioning Function)
POS.2: IFN FTTRACE,<
SKIPE G$DEBUG ;Are we debugging?
$TEXT (,<PULSAR (PLRTAP) positioning for ^T/@POS.T(P1)/>)
JRST POS.4 ;Skip over the in-line table
POS.T: [ASCIZ /REWIND/]
[ASCIZ /UNLOAD/]
[ASCIZ /SKIP ONE BLOCK/]
[ASCIZ /SKIP ONE FILE/]
[ASCIZ /EOT/]
[ASCIZ /BACKSPACE ONE BLOCK/]
[ASCIZ /BACKSPACE ONE FILE/]
POS.4:
>;END OF FTTRACE CONDITIONAL
MOVE S2,TCB.IO(B) ;GET I/O STATUS BITS
TXZ S2,TI.EOT!TI.EOF ;CLEAR EOT & EOF SINCE TAPE WILL MOVE
CAIN S1,'REW' ;REWIND?
TXOA S2,TI.BOT ;POSITIONING TO BOT (SKIP TO ZAP LEOT)
CAIN S1,'UNL' ;UNLOAD?
TXZ S2,TI.LET ;CLEAR LEOT
MOVEM S2,TCB.IO(B) ;UPDATE STATUS
PUSHJ P,T$CLRS ;CLEAR ANY PENDING I/O ERRORS
HLRZ P1,P2 ;PUT FUNCTION IN P1
LOAD P2,TCB.FU(B),TF.DVH ;GET THE CHANNEL NUMBER
MOVE P3,[2,,P1] ;LOAD ARG POINTER
CAXN P1,.TFUNL ;ABOUT TO DO UNLOAD?
SETOM G$UNL## ;YES, SET FLAG FOR OFFLINE TRAP
TAPOP. P3, ;AND DO IT
SKIPA S1,TCB.PI(B) ;FAILED - GET PSI WORD
JRST POS.5 ;ONWARD
TXNE S1,PS.RDH ;HUNG DEVICE?
PJRST TAPHNG ;YES
HRRZS P1 ;ISOLATE FUNCTION CODE
CAIN P1,.TFDSE ;DATA SECURITY ERASE?
$RETF ;EASY ONE TO HANDLE
TXNE S1,PS.RDO ;UNIT OFF-LINE?
JRST POS.6 ;YES
$STOP (PRF,Positioning Request Failed)
POS.6: CAXE P1,.TFREW ;Were we doing a rewind?
JRST POS.5 ;No, continue, else give it another try
SETZM TCB.PI(B) ;Clear the PSI word
SETZM TCB.WS(B) ;Clear the wait state
MOVE P3,[2,,P1] ;Get a pointer to try rewinding again
LOAD P2,TCB.FU(B),TF.DVH ;Get the channel number
MOVX P1,.TFREW ;Get the rewind code
TAPOP. P3, ;Do it
JFCL ;Let following catch error
POS.5: SETZM G$UNL## ;CLEAR 'UNLOADING' FLAG
MOVX S1,TS.NTP ;GET NO TAPE PRESENT BIT
CAXN P1,.TFUNL ;WAS IT AN UNLOAD?
IORM S1,TCB.ST(B) ;YES, SET APPROPRIATE FLAG
CAXE P1,.TFUNL ;WAS IT AN UNLOAD?
CAXN P1,.TFREW ;DOING A REWIND
$RETT ;DON'T WAINT ON ERROR
CAXE P1,.TFFSF ;Skip file?
CAXN P1,.TFBSF ;or backspace file?
PUSHJ P,G$OJOB## ;Yes, that'll take a while, service
; other tape requests
PUSHJ P,T$WAIT ;Wait for things to settle down
MOVX S1,.FOGET ;FILOP code to pull GETSTS
PUSHJ P,T$FILOP ;Get the bits
MOVE P1,S2 ;Save status bits
PUSHJ P,T$CLRS ;Go clear the status
MOVE S1,TCB.IO(B) ;GET I/O STATUS WORD
TRNE P1,IO.EOF ;EOF?
TXO S1,TI.EOF ;YES
TRNE P1,IO.BOT ;BOT?
TXO S1,TI.BOT ;YES
MOVEM S1,TCB.IO(B) ;UPDATE I/O STATUS WORD
TRNN P1,IO.EOF!IO.BOT ;ANY INTERESTING BITS?
JRST POS.3 ;NO
MOVX P2,CL.OUT ;Get suppress output close bit
IORM P2,TCB.FI(B) ;Turn it on,
MOVX S1,.FOCLS ;FILOP code to CLOSE
PUSHJ P,T$FILOP ;Close input side, clearing EOF
ANDCAM P2,TCB.FI(B) ;Clear the suppress output close bit
POS.3: TRNN P1,IO.IMP!IO.DER!IO.DTE ;ANY OTHER ERRORS? (IGNORE IO.BKT)
$RETT ;NO, RETURN
PJRST RETERR ;STORE ERROR IN G$TERM AND RETURN
;POSITIONING FUNCTION TABLE XWD TAPOP FUNCTION,SIXBIT CODE
PFUNCT: XWD .TFREW, 'REW' ;REWIND
XWD .TFUNL, 'UNL' ;UNLOAD
XWD .TFFSB, 'SBL' ;SKIP ONE BLOCK
XWD .TFFSF, 'SFL' ;SKIP ONE FILE
XWD .TFSLE, 'EOT' ;SKIP TO LOGICAL END OF TAPE
XWD .TFBSB, 'BBL' ;BACKSPACE ONE BLOCK
XWD .TFBSF, 'BFL' ;BACKSPACE ONE FILE
XWD .TFDSE, 'DSE' ;DATA SECURITY ERASE
PFUNCN=.-PFUNCT ;LENGTH OF POSITIONING DISPATCH TABLE
SUBTTL Tape I/O Routines
INTERN T$WRTM ;WRITE A TAPE MARK
INTERN T$WRRC ;WRITE A RECORD
INTERN T$RDRC ;READ A RECORD
INTERN T$CLOS ;DO A CLOSE OUTPUT
SUBTTL T$WRTM -- Write a Tape Mark
;CALLED TO WRITE A TAPE MARK.
T$WRTM: $TRACE (T$WRTM,6)
$CALL .SAVE2 ;SAVE P1 AND P2
MOVX S1,<TI.EOT!TI.EOF> ;GET BITS FOR EOT AND EOF
ANDCAM S1,TCB.IO(B) ; AND CLEAR THEM
MOVEI P1,.TFWTM ;GET TAPOP FUNCTION
LOAD P2,TCB.FU(B),TF.DVH ;GET THE CHANNEL NUMBER
MOVE S1,[2,,P1] ;LOAD ARG POINTER
TAPOP. S1, ;DO IT
CAIN S1,TPWWL% ;WRITE LOCKED TAPE?
JRST WRTM.1 ;ANALYZ I/O STATUS
$STOP (CWT,Can't Write Tape-mark)
WRTM.1: MOVX S1,.FOGET ;FILOP code to GETSTS
PUSHJ P,T$FILOP ;Get it
MOVE P1,S2 ;Get is status
TRNN P1,IO.DTE!IO.DER!IO.IMP ;ANY ERRORS?
$RETT ;NO, JUST RETURN
PUSHJ P,T$CLRS ;Clear the error status
PJRST RETERR ;STORE ERROR AND RETURN
SUBTTL T$WRRC -- Write A Record
;CALLED TO WRITE A RECORD ON TAPE
T$WRRC: $TRACE (T$WRRC,6,,<MOVEI S1,TCB.WB(B)
TLO S1,(POINT 8,0)
$TEXT (,<^M^J^Q/S1/>)>)
$CALL .SAVE1 ;SAVE A REGISTER
MOVX S1,<TI.EOT!TI.EOF> ;GET BITS FOR EOT AND EOF
ANDCAM S1,TCB.IO(B) ; AND CLEAR THEM
MOVX S1,.FOOUT ;FILOP code to do an OUT
PUSHJ P,T$FILOP ;Write the buffer
SKIPF ;Any errors?
$RETT ;NO ERRORS, GIVE GOOD RETURN
MOVE P1,S2 ;Save the error bits
PUSHJ P,T$CLRS ;Clear out the error bits
MOVX S1,TI.EOT ;OPERATION SAW EOT BIT
TRNE P1,IO.EOT ;DID IT?
IORM S1,TCB.IO(B) ;YES, TURN IT ON IN TCB
TRNN P1,IO.IMP!IO.DER!IO.BKT!IO.DTE ;ANY ERRORS?
$RETT ;NO, GIVE GOOD RETURN
PJRST RETERR ;STORE ERRORS AND RETURN
SUBTTL T$RDRC -- Read A Record
;CALLED TO READ A RECORD FROM MAGTAPE
T$RDRC: $CALL .SAVE3 ;SAVE SOME REGS
LOAD S1,TCB.IO(B),TI.DEC ;GET THE DO DEC COMPAT IO BIT
JUMPE S1,RDRC.1 ;DON'T CHANGE MODE IF NOT ON
LOAD P2,TCB.DN(B) ;GET NAME RETURNED BY LABEL GET
MOVEI P1,.TFMOD+.TFSET ;ARG TO TAPOP TO SET MODE
MOVEI P3,.TFMDD ;DEC COMPATIBLE MODE
MOVE S1,[3,,P1] ;AC FOR TAPOP.
TAPOP. S1, ;SET THE MODE
$STOP (CSM,Can't Set DIGITAL compatible Mode)
RDRC.1: MOVX S1,<TI.EOT!TI.EOF> ;GET BITS FOR EOT AND EOF
ANDCAM S1,TCB.IO(B) ; AND CLEAR THEM
MOVX S1,.FOINP ;FILOP code to do INPUT
PUSHJ P,T$FILOP ;Read next block
SKIPF ;OK?
IFE FTTRACE,< $RETT > ;ALL IS WELL
IFN FTTRACE,< JRST RDRC.9>
MOVE P1,S2 ;Save the error bits
TRNN P1,IO.IMP!IO.DER!IO.DTE!IO.EOF!IO.BKT ;ANY IO ERRORS?
$RETT ;NO, JUST FINISH UP
PUSHJ P,T$CLRS ;Clear the bits
TRNN P1,IO.EOF ;END OF FILE?
JRST RDRC.3 ;NO, PROCEED
MOVX S1,TI.EOF ;SAY END OF FILE SEEN
IORM S1,TCB.IO(B) ;IN THE TCB
MOVX P2,CL.OUT ;Get suppress output close bit
IORM P2,TCB.FI(B) ;Light in FILOP block
MOVX S1,.FOCLS ;FILOP code to CLOSE
PUSHJ P,T$FILOP ;Close the input side of tape
ANDCAM P2,TCB.FI(B) ; to clear EOF. Clear suppress bit
RDRC.3: TRNE P1,IO.IMP!IO.DER!IO.DTE ;ANY IO ERRORS?
PJRST RETERR ;YES, STORE ERROR AND RETURN
RDRC.9: $TRACE (T$RDRC,6,,<MOVEI S1,TCB.IB(B)
TLO S1,(POINT 8,0)
$TEXT (,<^M^J^Q/S1/>)>)
$RETT ;NO, RETURN NOW
SUBTTL T$CLOS -- Close Output
;CALLED TO DO A CLOSE OUTPUT AFTER WRITING LABELS
T$CLOS: $TRACE (T$CLOS,6)
$CALL .SAVE3 ;SAVE SOME REGS
SETZM TCB.FI(B) ;Clear Status bits
MOVX S1,<TI.EOT!TI.EOF> ;GET BITS FOR EOT AND EOF
ANDCAM S1,TCB.IO(B) ; AND CLEAR THEM
MOVX S1,.FOCLS ;FILOP code to close channel
PUSHJ P,T$FILOP ;Finished with the device
MOVX S1,.FOWAT ;Want to wait for I/O to finish
PUSHJ P,T$FILOP ; So do it...
MOVX S1,.FOGET ;FILOP code to GETSTS
PUSHJ P,T$FILOP ;Read the error bits
MOVE P1,S2 ;Pick bits out of FILOP block
TRNE P1,IO.IMP!IO.DER!IO.DTE ;ANY ERRORS?
PJRST RETERR ;YES, STORE ERROR AND RETURN
$RETT ;NO,,RETURN
SUBTTL Special Purpose Routines
;This routine takes a device name in S1.
;PULSAR doesn't know about this device, but assumedly, it is a magtape.
;This routine will try to get the user out of event wait by getting
;and releasing the label DDB.
T$LGET:: $TRACE (T$LGET,6,S1)
MOVEI T1,.TFLRL ;FUNCTION FOR LABEL RELEASE
MOVE T2,S1 ;COPY DEVICE NAME TO T2
MOVE T3,G$TERM## ;TERMINATION CODE
MOVE T4,[3,,T1] ;AC FOR TAPOP
TAPOP. T4, ;DO THE LABEL RELEASE
JFCL ;Oh well, user loses
MOVEI T1,.TFLDD ;LABEL DESTROY
MOVE T3,[2,,T1] ;AC FOR TAPOP
TAPOP. T3, ;DESTROY USELESS DDB
JFCL ;OH WELL, WE TRIED !!!
$RETT ;RETURN
;HERE TO CHECK WRITE RING STATUS OF TAPE.
;TAPE HAS BEEN REWOUND.
;RETURNS S2=1 IF TAPE IS WRITE-LOCKED (RING OUT), S2=0 IF NOT
T$WRCK:: $CALL .SAVET ;SAVE SOME REGISTERS
MOVEI T1,.TFWLK ;TAPOP. FUNCTION
LOAD T2,TCB.FU(B),TF.DVH ;GET DEVICE TO USE
MOVE T3,[2,,T1] ;AC FOR TAPOP.
TAPOP. T3, ;GET THE STATUS FROM THE TAPE
$STOP (CCR,Can't Check Ring status)
MOVE S2,T3 ;COPY RETURNED ANSWER TO S2
$RETT ;RETURN
SUBTTL T$FILOP - Routine to pull a FILOP for the TCB
;Call with S1/ FILOP function code
; B/ TCB addrs
;Returns - TRUE if FILOP skips
; FALSE if FILOP loses on an IN or OUT
; If the FILOP loses and we aren't doing IN or OUT, T$FILOP $STOPs
; For function .FOGET, the IO status bits are returned in S2
; If and IN or OUT fails, the IO status bits come back in S2 also
T$FILOP::
STORE S1,TCB.FU(B),RHMASK ;Stash desired opcode
FILO.0: SETZM S2 ;CLEAR S2
CAXN S1,.FOINP ;Doing input ?
MOVEI S2,TCB.IC(B) ;Yes, get input CCW list address
CAXN S1,.FOOUT ;Doint output ?
MOVEI S2,TCB.OC(B) ;Yes, get output CCW list address
SKIPE S2 ;Still null,,don't set
MOVEM S2,TCB.FI(B) ;Save the CCW
HRRI S2,TCB.FB(B) ;Aim at block
HRLI S2,FLPLEN ;And set the length
CAXE S1,.FOINP ;Doing input
CAXN S1,.FOOUT ; or output
TRNA ; No, don't wait
JRST FILO.1 ;Don't bother waiting & lenght ok
PUSHJ P,T$WAIT ;Yes, wait for any positioning
HRLI S2,2 ;The block lenght must now be 2
FILO.1: FILOP. S2, ;Do the work
SKIPA ;No, see if we can hack it
$RETT ;Wins, so does caller
MOVEI TF,0 ;CLEAR AC
EXCH TF,TCB.PI(B) ;GET INTERRUPT BITS AND CLEAR
TRNN TF,PS.RDO!PS.RDH ;OFF-LINE OR HUNG?
$RETF ;MUST BE A REAL I/O ERROR
TRNE TF,PS.RDH ;HUNG DEVICE?
JRST TAPHNG ;YES
TRNE TF,PS.RDO ;OFF-LINE?
JRST TAPOFL ;YES
$RETF ;SHOULDN'T GET HERE
TAPOFL: MOVX S1,TS.NTP ;GET NO TAPE PRESENT BIT
IORM S1,TCB.ST(B) ;SET FOR OPR NOTIFY
PUSHJ P,O$STAT## ;TELL THE OPERATOR
MOVX S1,TS.INI ;GET THE INITIALIZATION BIT
TDNE S1,TCB.ST(B) ;DOING THAT?
JRST TAPINI ;WAIT FOR DRIVE TO COME ONLINE
MOVE S1,TCB.DV(B) ;GET DEVICE NAME
PUSHJ P,T$CKAV ;SEE IF IN USE
JUMPT TAPKIL ;NO--KILL OFF THE TCB
PUSH P,TCB.FU(B) ;SAVE FILOP FUNCTION WORD
PUSH P,TCB.FI(B) ;AND I/O STATUS WORD
PUSHJ P,T$CLRS ;CLEAR ANY I/O ERRORS
POP P,TCB.FI(B) ;RESTORE
POP P,TCB.FU(B) ; ...
JRST TAPINI ;AND TRY AGAIN LATER
TAPHNG: MOVEI S1,LE.DER ;DEVICE
MOVEM S1,G$TERM## ; ERROR
MOVX S1,TS.SLR ;MAKE SURE USER GETS TERMINATION CODE
ANDCAM S1,TCB.ST(B) ; BY INSURING WE DO A LABEL RELEASE
$WTO (<Hung device>,,TCB.OB(B),$WTFLG(WT.SJI))
TAPKIL: PUSHJ P,T$RELE ;Clean up
MOVX S1,TS.KIL ;Get kill bit
IORM S1,TCB.ST(B) ;Lite so we flush this TCB
PUSHJ P,G$NJOB## ;Go away
$STOP (RKM,<Running a killed magtape TDB>)
TAPINI: PUSHJ P,G$NJOB## ;RUN ANOTHER JOB WHILE WE WAIT
LOAD S1,TCB.FU(B),RHMASK ;GET THE FILOP FUNCTION
JRST FILO.0 ;AND TRY AGAIN
SUBTTL T$CLRS - Clear IO status bits
;Call with B pointing to TCB.
;This routine will reset the IO status for that device
;The device must be OPENed on some channel
T$CLRS::
MOVX S1,UU.DEL+.IODMP ;Get bit to disable error logging
MOVEM S1,TCB.FI(B) ;Save in TCB's FILOP block
MOVX S1,.FOSET ;code to set IO status
PJRST T$FILOP ;Do it, and return
SUBTTL T$WAIT - Wait until I/O is done
;This routine will wait for I/O is complete in an attempt to put a
;stop to those annoying tape label problems that happen
;"once every two days when the moon is 3/4 full."
;Call: (B) = TCB address
T$WAIT::PUSHJ P,.SAVE3 ;Save some regs
MOVX P1,.TFWAT ;Get the wait function
LOAD P2,TCB.FU(B),TF.DVH ;Get the channel number
MOVE P3,[XWD 2,P1] ;Get the arg pointer
TAPOP. P3, ;Do it
$RETF ;Shouldn't happen
$RETT
SUBTTL Buffer builder and releaser routines
;MAKBUF - Routine to build input and output buffer rings for a TCB
;Call - with TCB addrs in B
;Return - True always
MAKBUF: MOVX S1,FO.ASC ;WE WILL WANT EXTENDED CHANNELS
MOVEM S1,TCB.FU(B) ; SO SET THAT
MOVEI S1,TCB.IB(B) ;GET INPUT BUFFER ADDRESS
ADD S1,[IOWD BFRSIZ+1,0] ;GEN AN INPUT CCW
MOVEM S1,TCB.IC(B) ;GEN INPUT COMMAND LIST
MOVEI S1,TCB.WB(B) ;GET OUTPUT BUFFER ADDRESS
ADD S1,[IOWD BFRSIZ+1,0] ;GEN AN OUTPUT CCW
MOVEM S1,TCB.OC(B) ;GEN OUTPUT COMMAND LIST
$RETT ;RETURN
SUBTTL Translate IO Error into Extended Error
SUBTTL Routine to Decode Error and Return
;ALWAYS CALLED WITH P1 CONTAINING THE IO STATUS WITH ONE OF
; IO.IMP, IO.DTE, OR IO.DER ON.
; STORES THE CORRECT CODE INTO G$TERM AND
; RETURNS FALSE
RETERR: TXNN P1,IO.DTE!IO.DER!IO.IMP ;ANY ERROR BIT ON?
$STOP (NEB,No Error Bit)
TXNE P1,IO.DTE ;DATA ERROR?
MOVEI S1,.TFTDE ;YES, RETURN DATA ERROR CODE FOR TAPOP
TXNE P1,IO.DER ;DEVICE ERROR?
MOVEI S1,.TFTDV ;YES, RETURN DEVICE ERROR CODE FOR TAPOP
TXNE P1,IO.IMP ;WRITE LOCK ERROR?
MOVEI S1,.TFTWL ;YES, RETURN WRITE LOCK ERROR CODE FOR TAPOP
MOVEM S1,G$TERM## ;SAVE TO RETURN TO USER
$RETF ;RETURN FALSE
END