Trailing-Edge
-
PDP-10 Archives
-
AP-D543V_SB
-
tapuuo.mac
There are 13 other files named tapuuo.mac in the archive. Click here to see a list.
TITLE TAPUUO - MAGTAPE USER INTERFACE FOR TOPS10 - V14112
SUBTTL T.HESS/TAH/TW 07 NOV 78
SEARCH F,S
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (C) 1974,1975,1976,1977,1978 BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
XP VTPUUO,14112 ;DEFINE VERSION NUMBER FOR STORAGE MAP
SALL
TAPUUO:: ENTRY TAPUUO
;DISPATCH TABLE
POPJ P, ;(-4) SPECIAL ERROR STATUS
JRST REGSIZ## ;(-3) USE DEFAULT
JRST TPMINI##(P2) ;(-2) INITIATION
JRST TPMHNG ;(-1) HUNG DEVICE
TPMDSP::JRST TPMREL ;(0) RELEASE
JRST TPMCLS ;(1) CLOSE OUTPUT
JRST TPMOUT ;(2) OUTPUT
JRST TPMIN ;(3) INPUT
JRST TPSETF ;(4) LOOKUP
JRST TPSETF ;(5) ENTER
JRST TPMDOU ;(6) DUMP OUTPUT
JRST TPMDIN ;(7) DUMP INPUT
POPJ P, ;(10) USETO
POPJ P, ;(11) USETI
POPJ P, ;(12) UGETF
JRST CPOPJ1## ;(13) RENAME
JRST TPCLSI ;(14) CLOSE INPUT
POPJ P, ;(15) UTPCLR
JRST MTAPE0 ;(16) MTAPE UUO
IFE FTTLAB,<
TPSETF==CPOPJ1## ;DUMMY ENTRIES
TPCLSI==CPOPJ##
>
;RANDOM DDB BYTE POINTERS
TDYMOD::POINT 4,TDVSTS##(F),11
TDYDEN::POINT 4,TDVSTS##(F),7
TDYDN1::POINT 4,TDVSTS##(F),35 ;FOR SET DENSITY
TDYBYT::POINT 9,TDVSTS##(F),11 ;PARITY/DENSITY/MODE
PDENS:: POINT 2, DEVIOS(F),28
;RANDOM DDB STATUS
D.RDBK==(1B0) ;READ BACKWARDS
D.NRLT==(1B1) ;NEXT RECORD AT LOW THRESHOLD
;(1B2) UNUSED
D.EPAR==(1B3) ;USE EVEN PARITY (7TK ONLY)
COMPAT==<RB.D16>B31+<RB.MBY>B35
;BITS IN S (DEVIOS)
IOERRS==IODERR!IODTER!IOBKTL!IOIMPM ;ALL I/O ERRORS
OFFLIN==(1B1) ;UNIT IS OFF LINE
OFLUNH==(1B2) ;OFF-LINE UNIT NOT READY
IFN FTTLAB,<
FINP==(1B3) ;FIRST INPUT OPERATION
LBLNED==(1B4) ;LABELING ACTION NEEDED
LBLWAT==(1B5) ;WAITING FOR LABEL PROCESS
LBLSTP==(1B6) ;STOP I/O BECAUSE OF ERROR
FOUT==(1B7) ;FIRST OUTPUT OPERATION
FSTOP==FINP!FOUT ;FIRST I/O OPERATION
LBLEOF==(1B8) ;EOF SEEN
>
MTSNAR==:(1B9) ;SET-RETRY BIT (UUOCON,COMCON USE)
IOSRTY==:(1B10) ;IF ON, NO ERROR RETRY (TXIKON)
;POINTERS TO LABEL STATUS WORD IN UDB
IFN FTTLAB,<
TUYLTP::POINT 4,TUBLBL##(U),35 ;LABEL TYPE
TUYRQT: POINT 4,TUBLBL##(U),27 ;REQUEST TYPE CODE
TUYINF: POINT 6,TUBLBL##(U),23 ;ADDITIONAL INFO
TUYJBN: POINT 9,TUBLBL##(U),17 ;JOB NUMBER
>
IFN FTMTSET,<
PMTRTY::POINT 1,DEVIOS(F),9
>
SUBTTL INPUT UUO
TPMIN:: PUSHJ P,SAVE2## ;SAVE P1,P2
PUSHJ P,INSET ;SET UP ACS ETC.
IFN FTTLAB,<
TLZN S,LBLSTP ;LBL PCS WANT US TO STOP?
JRST TPMINA ;NO - PROCEED
TRNN S,IODEND ;EOF ONLY?
PJRST TPSTP0 ;NO - RETURN
MOVEI P1,0 ;YES - FIX THINGS FOR UUOCON
PJRST RDEOF ;...
>
TPMINA: PUSHJ P,SETRED ;SET READ OP
PUSHJ P,GENIOR ;GENERATE IORB
JRST TPMINF ;WHOOPS (UNABLE TO GET STORAGE)
MOVEI T2,DEPAIO ;ASYNC I/O?
TDNE T2,DEVAIO(F)
JRST ASYNCI ;YES - GO TO IT
MOVEM T1,TDVIOR##(F) ;NO - REMEMBER THIS IORB
PUSHJ P,TAPRQT## ;PLACE AT END OF QUEUE
PUSHJ P,KONWAT ;WAIT FOR KONTROLLER
;RETURN HERE P1 := IORB
SKIPGE TRBLNK(P1) ;AOK??
JRST TPMFLS ;FLUSH REQUEST ARE RETURN TO USER
IFN FTKI10!FTKL10,<
SKIPN DEVEVM(F) ;HAVE EVM?
PUSHJ P,RSTEVM## ;NO - GET IT IF NECESSARY
>
TPMIN1: PUSHJ P,TPMXCI ;RELOCATE DEVIAD & XCT .+1
EXCTUX <LDB T2,[POINT 17,0(T1),17]> ;SIZE OF BUFFER
SOJLE T2,TPMFLS ;LOSE IF TOO SMALL (0 OR 1)
MOVNS T2 ;NEGATE SIZE
HRLZS T2 ;TO LH
HRRI T2,1(T1) ;MAKE GENUINE IOWD
MOVE T1,P1 ;IORB PNTR IN T1
SETZ T4, ;DO WHOLE BUFFER
PUSHJ P,MAKLST ;GET IOWD LIST
JRST TPMFLS ;FLUSH IF NO SPACE
TRO S,IOACT ;SET I/O ACTIVE
PUSHJ P,STOIOS## ;SET/RESET HUNG DEVICE TIMER
MOVEI T1,INPDUN ;WHERE TO GO WHEN DONE
HRRM T1,TRBIVA(P1) ;STORE IT
TPSWST:
IFN FTKL10,<
PUSHJ P,TPMSWP ;SWEEP CACHE IF NOT TM10A
>
TPSTRT: MOVE T1,P1 ;IORB TO T1 FOR TAPSER
PJRST TAPSIO## ;TELL TAPSER TO TAKE IT AWAY
;ROUTINE TO FLUSH REQUEST AND RETURN IORB / SET IMPROPER MODE
TPMFLS: PUSHJ P,TAPFLS## ;FLUSH UNIT
PUSHJ P,TPMRI1 ;T1 := IORB
PUSHJ P,SETIOD## ;REVIVE USER
PUSHJ P,CLRACT##
;ROUTINE TO SET IMPROPER MODE AND RETURN
TPMINF: IFN FTKI10!FTKL10,<
PUSHJ P,RTEVM## ;RETURN RESOURCES
>
TRO S,IOIMPM ;LITE A BIT
PJRST STOIOS##
;HERE WHEN INPUT DONE
; P1 := IORB
;U,W,F SETUP
INPDUN: PUSHJ P,SETIOS ;SET UP S AND CHECK ERRORS
JSP P2,INPERR ;PONDER PROBLEM
MOVE T1,P1 ;COPY IORB PNTR TO T1
LDB T2,PRBFCN## ;GET FCN
CAIN T2,RB.FRB ;READ BACKWARDS?
TRNN S,IOBOT ;YES - AT BOT?
TRNE S,IODEND ;SEEN EOF?
JRST RDEOF ;YES - TELL HIM
IFN FTKI10!FTKL10&FTDX10,< ;ONLY FOR TU70'S
MOVE T1,TKBCNT##(W) ;NUMBER OF RECORDS WE DID
SOJLE T1,INPDN2 ;IF MORE THAN 1,
PUSHJ P,SVEUF## ;MAKE JOB ADDRESSABLE
MOVE T1,DEVIAD(F) ;GET BUFFER ADDRESS
EXCTUX <LDB T3,[POINT 17,0(T1),17]>
SUBI T3,1 ;WORDCOUNT OF ALL BUT LAST RECORD
LDB T1,PIOMOD## ;IF BYTE MODE
CAIN T1,BYTMOD
MOVE T3,TRBRCT(P1) ;GET BYTE-COUNT
INPDN1: SOSG TKBCNT##(W) ; (WOULD HAVE STOPPED EARLY ON LENGTH ERROR
JRST INPDN2 ; IF THE WRDCNT WAS WRONG)
MOVE T1,DEVIAD(F)
EXCTUU <HRRM T3,1(T1)> ;STORE WRDCNT IN BUFFER
PUSHJ P,ADVBFF## ;MOVE TO NEXT BUFFER
JFCL
JRST INPDN1 ;AND KEEP ON GOING
INPDN2:>
MOVE T1,P1
LDB T4,PRBMOD## ;GET MODE
IFN FTKI10!FTKL10&FTDX10,<
MOVSI T2,RB.SEN ;IS THERE AN ERROR IN NEXT RECORD (CHAN CHAINING)?
TDNE T2,TRBSTS(P1) ; (BUT THIS RECORD IS OK)
JRST [ANDCAM T2,TRBSTS(P1) ;YES - HENCE RECORD LENGTH IS RIGHT
JRST INPDN3] ; SO ENSURE THAT LH(WORD 0) WILL BE USED AS REC SIZE
>
MOVE T2,TRBRCT(P1) ;GET CHARS READ
MOVEM T2,TUBCCR##(U) ;SAVE COUNT FOR TAPOP
IDIV T2,TMODTB##(T4) ;CONVERT TO WORDS
SKIPE T3 ;RESIDUE?
ADDI T2,1 ; ADJUST ACCORDINGLY
INPDN3: PUSHJ P,TPMXCI ;RELOCATE DEVIAD, XCT .+1
EXCTUX <LDB T3,[POINT 17,0(T1),17]> ;GET BUFFER SIZE+1
CAIG T2,-1(T3) ;RECORD .LTE. BUFFER?
SKIPA T4,TRBRCT(P1) ;YES, T2=WORDS, T4=BYTES
SKIPA T4,TMODTB(T4) ;NO, T2=SIZE OF BUF
JRST INPDN4
MOVEI T2,-1(T3)
IMULI T4,(T2) ;T4=THAT NUMBER OF BYTES?
INPDN4: LDB T3,PIOMOD##
CAIN T3,BYTMOD ;BYTE MODE DDB?
MOVE T2,T4 ;YES, STORE NO OF BYTES READ
PUSHJ P,TPMXCI ;GET C(DEVIAD) AGAIN
EXCTUU <HRRM T2,1(T1)> ;STORE IN HEADER
PUSHJ P,TPMRCW ;RETURN XFER LIST
PUSHJ P,ADVBFF## ;ADVANCE BUFFERS
JRST TPSWSP ;NO MORE STOP IO
PUSHJ P,SETIOD## ;REVIVE USER
MOVEM S,DEVIOS(F) ;SAVE CORRECT IOS
MOVE T1,P1 ;SET UP IORB PNTR
LDB P2,PRBFCN## ;GET FCN BACK
PUSHJ P,TPIOGO ;SET IORB
JRST TPSWSP ;NO MORE - STOP I/O
JRST TPMIN1 ;START NEXT READ
TPIOGO: TRNN S,IOTEND!IOERRS ;ANY ERRORS / EOT
PUSHJ P,QDECR ;DECREMENT QUANT
POPJ P, ;NO MORE - RETURN
MOVE T1,P1 ;GET IORB PNTR
MOVEI T2,RB.ACT ;MARK REQUEST ACTIVE
PUSHJ P,STOIOR ;STORE INFO IN IORB
JFCL ;NO WAY
PJRST CPOPJ1## ;GIVE SKIP RETURN
;ROUTINE TO HANDLE EOF/BOT AND STOP TAPE
RDEOF: TRZ S,IODEND ;CLEAR EOF
TLO S,IOEND ;SAY PAYS END SEEN
PUSHJ P,TPMXCI ;GET C(DEVIAD)
EXCTXU <MOVEM S,-1(T1)> ;STORE IOS IN BUFFER HEADER
IFN FTTLAB,<
JUMPE P1,TPSTP0 ;JUMP IF NO IOLIST
>
PUSHJ P,TPMRCW ;RETURN CCW LIST
TPMSTP: PUSHJ P,TPMRIO ;RETURN IORB
TPSTP0:
IFN FTKI10!FTKL10,<
PUSHJ P,RTEVM## ;RETURN EVM IF ANY
>
PUSHJ P,SETIOD## ;REVIVE HIM
PUSHJ P,CLRACT## ;CLEAR IOACTIVE
HLLZS TKBSTS##(W) ;SET CNTR TO ZERO
PJRST STOIOS## ;STASH IOS & EXIT
TPSWSP:
IFN FTKL10,<
PUSHJ P,TPMSWP ;SWEEP CACHE IF NOT TM10A
>
JRST TPMSTP ;NOW STOP IO
;ROUTINE TO RETURN IOWD LIST , P1 := IORB
TPMRCW: HRRE T1,TRBXCW(P1) ;FETCH CHL LIST
CAIG T1,100 ;ALLOW FOR COUNT
POPJ P, ;RETURN
IFN FTKI10!FTKL10,<
PJRST RTNIOW## ;ELSE RETURN WHOLE LIST
>
IFN FTKA10,<
JRST TPMRI1 ;RETURN 4-WD BLOCK
>
;ROUTINE TO RETURN IORB AND DE-Q IT
TPMRIO: PUSHJ P,TAPREM## ;HAVE TAPSER PRUNE QUEUE
; RETURN PNTR TO IORB IN T1
TPMRI1: MOVE T2,T1 ;GIV4WD LIKES IT IN T2
MOVEI T1,1 ;# OF BLOCKS
PJRST GIV4WD## ;RETURN 4-WD BLOCK
;ROUTINE TO DECREMENT KONTROLLER QUANTA - SKIP RETURN IF NON-ZERO
QDECR: HRRZ T1,TKBSTS##(W) ;GET QUANTA
SOSL T1 ;DECR SKIP IF NEG
HRRM T1,TKBSTS##(W) ;STORE RESULT
JUMPG T1,CPOPJ1## ;SKIP RET IF STILL POSITIVE
POPJ P, ;QUANTUM GONE TO 0, GIVE UP
SUBTTL OUTPUT UUO
TPMOUT: PUSHJ P,SAVE2## ;SAVE P1,P2
PUSHJ P,OUTSET ;SET UP FOR OUTPUT
SKIPGE TUBREC##(U) ;IS RECORD COUNT NEGATIVE?
SETZM TUBREC##(U) ;YES, INITIALIZE TO ZERO
IFN FTTLAB,<
TLZE S,LBLSTP ;WANT TO STOP NOW?
JRST TPSTP0 ;STOP ON LABEL ERROR
>
MOVEI P2,RB.FWT ;FUNCTION WRITE
PUSHJ P,GENIOR ;MAKE AN IORB
JRST TPMINF ;UNABLE TO GET STORAGE
MOVEI T2,DEPAIO ;ASYNC I/O?
TDNE T2,DEVAIO(F)
JRST ASYNCO ;YES - GO TO IT
MOVEM T1,TDVIOR##(F) ;NO - WAIT FOR THIS ONE
PUSHJ P,TAPRQT## ;QUEUE IT UP
PUSHJ P,KONWAT ;WAIT FOR CONTROLLER
;RETURN WITH P1 := IORB
SKIPGE TRBLNK(P1) ;THINGS IN SHAPE
JRST TPMFLS ;NO - U LOSE
IFN FTKI10!FTKL10,<
SKIPN DEVEVM(F) ;HAVE EVM
PUSHJ P,RSTEVM## ;NO - GET IT IF NECESSARY
>
TPMOU1: PUSHJ P,TPMXCO ;GET C(DEVOAD)
EXCTUX <HRRZ T2,1(T1)> ;GET WORD COUNT FROM BUFFER
JUMPE T2,ADVOUT ;HANDLE EMPTY BUFFER SPECIAL
LDB T3,PIOMOD## ;MODE OF DDB
CAIE T3,BYTMOD ;BYTE MODE?
JRST [SETZM T4 ;NO
JRST TPMOU2]
LDB T3,PRBMD2## ;YES, CONVERT TO WORDS
MOVE T4,T2 ;KEEP BYTE COUNT AROUND
IDIV T2,TMODTB##(T3)
SKIPE T3
ADDI T2,1 ;T2=NUMBER OF WORDS
TPMOU2: MOVNS T2 ;-N
HRLZS T2 ;PUT IN LH
HRRI T2,1(T1) ;BUFFER ADDRS
MOVE T1,P1 ;IORB PNTR TO T1
PUSHJ P,MAKLST ;MAKE CHL XFER LIST
JRST TPMFLS ;FLUSH REQUEST
TRO S,IOACT ;SET I/O ACTIVE
PUSHJ P,STOIOS## ;SET/RESET HUNG DEVICE TIMER
MOVEI T1,OUTDUN ;WHERE TO GO WHEN FINISHED
HRRM T1,TRBIVA(P1) ;STORE IN IORB
PJRST TPSWST ;START DEVICE
;HERE WHEN OUTPUT DONE, P1 := IORB
OUTDUN: PUSHJ P,SETIOS ;SET UP S W/ TAPE INFO
JSP P2,OUTERR ;TRY TO FIX WRITE ERROR
PUSHJ P,SETIOD## ;REVIVE USER
MOVEM S,DEVIOS(F) ;SAVE S IN DDB
PUSHJ P,TPMRCW ;RETURN XFER LIST
IFN FTTLAB,<
TRNE S,IOTEND ;EOT SEEN YET?
JRST LBLEOT ;YES - INVOKE LBL PCS
>
IFN FTKI10!FTKL10&FTDX10,< ;ONLY FOR TU70'S
OUTDN1: SOSG TKBCNT##(W) ;FOR ALL BUT THE LAST BUFFER,
JRST OUTDN2
PUSHJ P,ADVBFE## ;TELL UUOCON THAT IT'S FULL
JFCL
JRST OUTDN1 ;AND TRY THE NEXT
OUTDN2:>
PUSHJ P,ADVBFE## ;ADVANCE BUFFER
JRST TPMSTP ;NO MORE STOP IO
MOVEI P2,RB.FWT ;TRY TO WRITE ON
PUSHJ P,TPIOGO ;...
JRST TPMSTP ;NO MORE RETURN
JRST TPMOU1 ;CONTINUE WRITING
;HERE TO ADVANCE BUFFER IF ONE FOUND EMPTY
ADVOUT: PUSHJ P,ADVBFE## ;CYCLE
SKIPA ;NO NEXT BUFFER
JRST TPMOU1 ;TRY THIS ONE
PUSHJ P,SETIOD## ;REVIVE USER
PUSHJ P,CLRACT## ;...
TPMFLX: PUSHJ P,TAPFLS## ;ELSE FLUSH REQUEST
IFN FTKI10!FTKL10,<
PUSHJ P,TPMRI1 ;RETURN IORB
PJRST RTEVM## ;AND EVM IF ANY
>
IFN FTKA10,<
PJRST TPMRI1 ;RETURN IORB
>
IFN FTTLAB,<
;ENTER HERE TO PROCESS EOT AND SEND MSG TO LBL PCS
LBLEOT: PUSHJ P,ADVBFE## ;ADVANCE BUFFERS
JFCL ;IGNORE
PUSHJ P,LBLCHK ;LABEL PROCESSING?
TLOA S,LBLNED ;YES - SEND MSG ETC.
PJRST TPMSTP ;ELSE PROCESS AS BEFORE
TRZ S,IOTEND ;CLEAR EOT NOW
MOVEI T1,LR.EOT ;SET TYPE EOT
DPB T1,TUYRQT ; IN LBL MESSAGE
PJRST TPMSTP ; AND STOP IO
>
SUBTTL DUMP-MODE I/O
TPMDOU: PUSHJ P,SAVE2## ;SAVE P1,P2
PUSHJ P,OUTSET ;SET FOR OUTPUT
SKIPGE TUBREC##(U) ;IS RECORD COUNT NEGATIVE?
SETZM TUBREC##(U) ;YES, INITIALIZE TO ZERO
JRST TPMDMP ;TO COMMON ROUTINE
TPMDIN: PUSHJ P,SAVE2## ;SAVE P1,P2
PUSHJ P,INSET ;SET FOR INPUT
TPMDMP:
IFN FTTLAB,<
TLZE S,LBLSTP ;LBL ERROR?
POPJ P, ;YES, RETURN NOW
>
PUSHJ P,DMPSET ;SET UP IORB & WAIT FOR CTL
PJRST TPMINF ;LOSAGE
PUSHJ P,COMCHK## ;GET 1ST IOWD & BOUNDARIES
JUMPN S,ADRXIT ;ADDRESS CHECK?
MOVE S,DEVIOS(F) ;RESTORE S
JUMPE T1,TPMFLS ;OR NULL LIST - EXIT
PUSHJ P,SAVT## ;SAVE T1 (IOWD)
MOVEM T2,TDVSUL##(F) ;SAVE USER UPPER LIMIT
MOVEM T3,TDVSLL##(F) ; AND USER LOWER LIMIT
TPDNXT: MOVEM M,TDVSVM##(F) ; AND M (UUO)
MOVEM T1,-1(P) ;SAVE T1 IN CASE OFL
PUSHJ P,ADJIOW ;ADJUST IOWDS IF NECESSARY
;RETURNS IOWD IN T2
PUSHJ P,TPMDGO ;START I/O
JRST TPMFLS ;CAN'T - MAKLST LOST
PUSHJ P,WAIT1## ;WAIT FOR I/O TO CEASE
IFN FTKL10,<
TLNN S,IO ;WRITING?
PUSHJ P,TPMSWP ;NO, MUST SWEEP CACHE
>
IFN FTTLAB,<
PUSHJ P,LBLCKS ;CHECK FOR LABEL EXPECTED
JFCL ;IGNORE THIS RETURN
TLNE S,LBLNED ;NEED LABELS?
PUSHJ P,LBLMSG ;YES, SEND THE MESSAGE
TLZ S,LBLSTP ;GET RID OF THIS BIT
>
TLNE S,IOSTBL ;ARE WE IN TROUBLE?
JRST TPDOFL ;YES - CHECK OFFLINE
TRNE S,IODEND!IOBOT!IOERRS ;ERRORS?
POPJ P, ;YES - EXIT
PUSHJ P,DMPSET ;GEN IORB FOR NEXT IOWD
PJRST TPMINF ; NO ROOM - LOSE
MOVE M,TDVSVM##(F) ;RESTORE SAVED STUFF
MOVE T2,TDVSUL##(F)
MOVE T3,TDVSLL##(F) ;...
PUSHJ P,NXCMR## ;GET NEXT IOWD
JUMPN S,ADRXIT ;JUMP IF ADR CHK
MOVE S,DEVIOS(F) ;S CLOBBERED BY NXCMR!
JUMPE T1,TPMFLX ;ALL DONE IF ZERO
JRST TPDNXT ;SAVE M AND TRY NEXT
;ROUTINE TO HANDLE OFF-LINE UNIT IN DUMP MODE
TPDOFL: TLZ S,OFFLIN!IOSTBL ;CLEAR BITS
PUSHJ P,CKTC10 ;CHECK TC10 CROCK
PUSHJ P,HNGSTP## ;CALL ATTEN TO OURSELVES
PUSHJ P,DMPSET ;GEN IORB ETC.
PJRST TPMINF ;NO ROOM
MOVE T1,-1(P) ;RESTORE IOWD
JRST TPDNXT ;TRY AGAIN
;ROUTINE TO START DUMP MODE I/O
TPMDGO: MOVE T1,P1 ;IORB TO T1
SETZ T4, ;NOT BYTE-MODE, DO ALL OF IOWD
PUSHJ P,MAKLSD ;GEN IO XFER LIST
POPJ P, ;WHOOPS
CONSO PI,II.IPA ;DON'T SET IF AT INT LVL
PUSHJ P,SETACT## ;SET I/O ACTIVE
HLLOS TKBSTS##(W) ;GRNTEE CONTROLLER
MOVEI T1,DMPDUN ;WHERE TO GO WHEN DONE
HRRM T1,TRBIVA(P1) ;SAVE IN IORB
AOS 0(P) ;GIVE SKIP RETURN
PJRST TPSWST ;GO START DEVICE
;COME HERE ON DONE INTERUPT FOR DUMP MODE I/O
DMPDUN: PUSHJ P,SETIOS ;SET UP S
JSP P2,DMPERR ;ERROR RETURN
PUSHJ P,TPMRCW ;RETURN XFER LIST
MOVE T2,TRBRCT(P1) ;BYTE COUNT OF LAST REC
MOVEM T2,TUBCCR##(U) ;SAVE FOR TAPOP
TRNN S,IODEND!IOBOT!IOERRS ;ERRORS?
SKIPN T1,TDVREM##(F) ;ANY PARTIAL LEFT?
JRST TPMSTP ;STOP NOW
PUSHJ P,ADJIOW ;MUNG IOWD IF NECESSARY
TLNN S,IO ;INPUT?
SKIPE TDVREM##(F) ;YES - DONE?
SKIPA T1,P1 ;NO - PROCEED
JRST TPMSTP ;YES - SHUT DOWN
PUSH P,T2 ;SAVE IT
LDB P2,PRBFCN## ;GET FCN BACK
MOVEI T2,RB.ACT ;MAKE IORB ACTIVE AGAIN
PUSHJ P,STOIOR ;STORE INFO IN IORB
JFCL ;UNLIKELY
POP P,T2 ;RESTORE IOWD
PUSHJ P,TPMDGO ;START IT UP
JRST TPMFLS ;FLUSH - MAKLST LOST
POPJ P, ;EXIT INTERUPT
;ROUTINE TO PERFORM IOWD HACKING FOR MODE 16
;DESIRED IOWD IN T1, RETURN ADJUSTED IOWD IN T2
ADJIOW: MOVE T2,T1 ;MOVE TO T2 IN CASE
SETZM TDVREM##(F) ;CLEAR REMAINDER
TRNE S,1B35 ;WE HAVE NOTHING TO DO?
POPJ P, ;MODE 17 - RETURN
TLNE S,IO ;OUTPUT/INPUT?
JRST [LDB T4,PBUFSZ## ;OUTPUT - GET BUFFER SIZE
MOVNI T4,-1(T4) ;- BLOCK SIZE
JRST ADJIO1] ;JOIN COMMON CODE
LDB T4,[POINT RB.MDS,TRBLNK(P1),RB.MDP] ;INPUT - GET MODE
MOVE T3,TRBRCT(P1) ;CHAR COUNT OF LAST RECORD OR ZERO
IDIV T3,TMODTB##(T4) ;CONVERT TO WORDS
SKIPE T4 ;CHECK REMAINDER
ADDI T3,1 ;ADJUST IF NECESSARY
MOVNI T4,(T3) ;NEGATE
ADJIO1: HLRE T1,T2 ;SIZE OF XFER
CAML T1,T4 ;DOES IT FIT?
POPJ P, ;YES - JUST RETURN
SUB T1,T4 ;NEW WORDCOUNT
SUB T2,T4 ;NEW ADDRESS
HRL T2,T1 ;ADJUSTED IOWD
MOVEM T2,TDVREM##(F) ;SAVE FOR LATER
TLNN S,IO ;OUTPUT?
POPJ P, ;NO - THEN DONE
ADD T2,T4 ;RE-ADJUST IOWD FOR NOW
HRL T2,T4 ;-BS,,ADDRS OPTIMAL
POPJ P, ;RETURN
;HERE ON ADDRESS CHECK AT UUO LEVEL
ADRXIT: PUSHJ P,TPMFLS ;FLUSH REQUEST
PJRST ADRERR## ;AND STOP USER
;SET UP IORB FOR DUMP I/O
;RETURN P1 := IORB , CONTROLLER SCHEDULED
DMPSET: MOVEI P2,RB.FWT ;ASSUME WRITE
TLNN S,IO ;IS IT?
PUSHJ P,SETRED ;NO - GET READ FCN
TRNN S,1B35 ;MODE 16?
CAIE P2,RB.FRB ;YES - READ BACKWARDS?
PUSHJ P,GENIOR ;GENERATE IORB
POPJ P, ;NO ROOM - LOSE
MOVEM T1,TDVIOR##(F) ;REMEMBER THIS ONE
PUSHJ P,TAPRQT## ;QUEUE IT UP
PUSHJ P,KONWAT ;WAIT TILL NOTICED
;RETURN WITH P1 := IORB
IFN FTKI10!FTKL10,<
SKIPN DEVEVM(F) ;KI ONLY
PUSHJ P,DMPEV## ;RESTORE EVM IF NECESSARY
>
JRST CPOPJ1## ;SKIP RETURN
SUBTTL RELEASE AND CLOSE UUO'S
TPMREL: PUSHJ P,WAIT1## ;WAIT FOR I/O TO CEASE
MOVEI T1,0 ;RESET TO ZERO MODE
DPB T1,TDYMOD ;INTO THE DDB
MOVSI T1,D.RDBK!D.NRLT!D.EPAR
ANDCAM T1,TDVSTS##(F) ;CLEAR THIS STUFF TOO
HLRZ U,TDVUDB##(F) ;GET UDB PNTR
IFN FTTLAB,<
TLNE S,LBLWAT ;WAITING FOR LABELS
POPJ P, ;YES, DO NOTHING NOW
>
PUSHJ P,TPMRLW ;WAIT TILL DESELECTED
TPMRL2: PUSHJ P,TAPKIL## ;KLANK CTL
PJRST TPMDQ ;UNWIND Q , PNTR IN T1
TPMRLW: MOVSI T1,TKSSEL##
TDNN T1,TUBSTS##(U) ;TAPE SHOULD NOT BE SELECTED
POPJ P, ;OK TO PROCEED
PUSHJ P,TSLEE1 ;SLEEP 1 SEC (REWINDS LIKE TO
; STRETCH THEIR LEGS SLOWLY!)
JRST TPMRLW ;SEE IF SUCCESSFUL
;CLOSE (WRITE TM,TM,BSB)
TPMCLS: TLNN F,OUTPB ;ANY OUTPUTS
POPJ P, ;NO -RETURN
LDB T1,PIOMOD## ;GET MODE
CAIGE T1,SD ;DUMP MODE?
PUSHJ P,OUT## ;NO - DUMP PARTIAL BUFFER
PUSHJ P,WSYNC## ;WAIT FOR I/O TO STOP
IFN FTTLAB,<
HLRZ U,TDVUDB##(F) ;SET UP UDB ADDRS
LDB J,PJOBN## ;RESTORE J
PUSHJ P,LBLCHK ;NEED LABELING?
JRST TPCLSO ;YES - SEND CLOSE MSG
>
PUSHJ P,SAVE2## ;SAVE P1,P2
MOVSI T1,TKSOFL##
TDNN T1,TUBSTS##(U) ;TAPE UNLOAD?
TRNE S,IOBOT ;TAPE AT BOT (REW) ?
POPJ P, ;YES, DON'T WRITE EOF'S
PUSHJ P,IOSET ;SET UP U
TPMCL1: MOVEI P2,RB.FTM ;WRITE TAPE MARK
PUSHJ P,GENIOR ;GENERATE IORB
JRST TPMINF ;WHOOPS
MOVEM T1,TDVIOR##(F) ;IORB TO REMEMBER
PUSHJ P,TAPRQT## ;Q IT UP
PUSHJ P,GENIOR ;ANOTHER REQUEST
JRST TPMINF
PUSHJ P,TAPRQT## ;ADD TO QUEUE
MOVEI P2,RB.FBR ;BACK OVER LAST TM
PUSHJ P,GENIOR ;MAKE ANOTHER IORB
JRST TPMINF ;LOSER
PUSHJ P,TAPRQT## ;Q IT
PUSHJ P,KONWAT ;NOW WAIT YOUR TURN
;P1 := FIRST IORB
PUSHJ P,SETACT## ;SET I/O ACTIVE
MOVEI T1,CLSDUN ;WHERE TO GO ON ENDING INT
HRRZM T1,TRBIVA(P1) ;STORE IN IORB
MOVEI T1,1 ;SET FOR ONE OP
HRRM T1,TRBXCW(P1) ;INTO IORB
PUSHJ P,TPSTRT ;GO START IT
PUSHJ P,WSYNC## ;WAIT FOR IT TO STOP
TRZ S,IODEND ;CLEAR EOF ON WRITE
PJRST STOIOS## ;STORE S AND RETURN
;ROUTINE TO PERFORM CLOSE INTERUPT ACTION
CLSDUN: PUSHJ P,SETIOS ;SET UP S FOR ERROR CHECK
JSP P2,OUTERR ;GO HANDLE ERROR
TRNE S,IOIMPM ;WRITE LOCKED?
JRST CLSWLK ;YES - FLUSH REMAINDER
PUSHJ P,TPMRIO ;REMOVE ITEM
HRRZ T1,TUBQUE##(U) ;GET NEXT ITEM
MOVEI T2,RB.ACT ;MARK ACTIVE
DPB T2,PRBRQS##
MOVEI P2,CLSDUN ;ASSUME HERE AGAIN
LDB T2,PRBFCN## ;GET FCN
CAIN T2,RB.FBR ;BACKSPACE RECORD?
MOVEI P2,TPMISP ;YES - GO HERE INSTEAD
HRRZM P2,TRBIVA(T1) ;SAVE NEXT INT ADDRS
HLLOS TKBSTS##(W) ;GRNTEE STILL KEEP KONTROLLER
MOVEI T2,1 ;ONLY ONE OP PSE
HRRM T2,TRBXCW(T1) ;...
PJRST TAPSIO## ;START DEVICE
;HERE IF WRITE LOCKED ON CLOSE
CLSWLK: PUSHJ P,TPMRL2 ;FLUSH Q AND STOP I/O
PJRST TPSTP0 ;...
IFN FTTLAB,<
;ROUTINE TO SET FIRST OPERATION
TPSETF: TLO S,FSTOP ;GET BIT
MOVEM S,DEVIOS(F) ;SET IT
PJRST CPOPJ1## ;SKIP RETURN
;ROUTINE TO HANDLE INPUT CLOSE OPERATION
TPCLSI: HLRZ U,TDVUDB##(F) ;SET UDB ADDRS
PUSHJ P,LBLCHK ;NEED LABELING?
TLNN F,INPB ;YES - ANY INPUTS??
POPJ P, ;NO - RETURN
MOVEI T1,LR.CLI ;SET REQUEST TYPE
JRST TPCLSX ;PICK UP COMMON CODE
;ROUTINE TO HANDLE CLOSE OUTPUT OPERATION
TPCLSO: MOVEI T1,LR.CLO ;SET REQUEST TYPE
TPCLSX: DPB T1,TUYRQT ; INTO UDB
TLO S,FSTOP ;SET FIRST OP ALSO
PJRST LBLMSG ;INFORM LBL PCS
>
SUBTTL MTACHR AND MTARID UUO'S
;MTACHR UUO
MTACHR::HLRE T2,T1 ;GET LH ARG FROM USER
JUMPLE T2,MTACHX ;JUMP IF OLD STYLE
SUBI T2,1 ;ACCOUNT FOR WORD USED TO PASS DEVICE NAME
CAILE T2,TPCHMX## ;CHECK RANGE
JRST MTACHX ;MIGHT BE NUMERIC LOGICAL NAME
PUSHJ P,SAVE1## ;SAVE P1
MOVN P1,T2 ;NEGATE LEN IN P1
HRLZS P1 ;TO LH
HRR M,T1 ;FIXUP M TO POINT TO USER AREA
PUSHJ P,GETWRD## ;GET FIRST WORD OF BLOCK
JRST RTM1## ;OUT OF BOUNDS
PUSHJ P,MTACHS ;SCAN FOR DDB (ARG IN T1)
JRST RTM1## ;NO SUCH MTA
;RETURN DDB IN F, UDB IN U
HRRI P1,TUBRID##(U) ;POINT TO UDB INFO AREA
MTACH1: MOVE T1,0(P1) ;GET VALUE
PUSHJ P,PUTWR1## ;STORE IN USER BLOCK (INCR M)
JRST RTM1## ;OUT OF BOUNDS
AOBJN P1,MTACH1 ;LOOP TILL DONE
MOVE T1,TUBCHR##(U) ;GET CHARACTERISTICS WORD
PJRST STOTC1## ;STORE IN AC AND EXIT
;HERE WHEN ARG IS CHL # OR DEVICE NAME
MTACHX: PUSHJ P,MTACHS ;LOOK FOR DDB (ARG IN T1)
PJRST RTM1## ;NO SUCH MTA
PJRST STOTC1## ;STORE T1
MTARID::PUSHJ P,PRVJ## ;NEED PRIVS
PUSHJ P,DVCNSG## ;LOOK FOR DDB
PJRST RTM1## ;NO PRIVS OR NO DDB
MOVE T1,DEVMOD(F) ;MAKE SURE ITS AN MTA
IFN FTNUL,<
TLNN T1,DVTTY ;...
>
TLNN T1,DVMTA ;....
JRST RTM1## ;ERROR RETURN
HLRZ U,TDVUDB##(F) ;SET UP UDB PNTR
MOVE T1,TUBCRD##(U) ;SEE IF ANY READS OR WRITES
IOR T1,TUBCWR##(U) ;SINCE LAST UNLOAD
JUMPE T1,MTARIX ;OK IF ZERO
PUSHJ P,TPDCPY ;NO - COPY TO SHADOW AREA
IFN FTEL,<
LDB T1,PJOBN## ;GET OWNING JOB #
CAME T1,J ;IS IT US?
JUMPN T1,MTARIX ;OK IF NO ERROR
MOVEI T1,.ERTPS ;SET UP CODE FOR DAEMON
HRL T1,F ;GET DDB ADDRESS FOR DAEMON
PUSHJ P,DAERPT## ; WAKE DAEMON
>
MTARIX: PUSHJ P,GETWD1## ;GET REEL ID
MOVEM T1,TUBRID##(U) ;STORE IN UDB
PJRST CPOPJ1## ;GIVE SKIP RETURN
;ROUTINE TO SCAN FOR MTA DDB AND SET UP F AND U
;CALLED WITH T1 := SOMETHING THAT DVCNSG LIKES
;ALSO UPDATE TUBCHR AND RETURN INFO IN T1
MTACHS: PUSHJ P,DVCNSG## ;LOOK FOR DDB
POPJ P, ;ERROR RETURN
MOVE T1,DEVMOD(F) ;PREPARE TO TEST DDB
TLNN T1,DVTTY ;IS THIS DEVICE NUL?
TLNN T1,DVMTA ;NO. IT IS A MTA?
POPJ P, ;NOPE - ERROR
HLRZ U,TDVUDB##(F) ;SET U := UDB ADDRS
PUSHJ P,GETDEN ;GET CURRENT DENSITY
DPB T1,[POINT 3,TUBCHR##(U),35]
MOVEI T1,1B31+1B32 ;BITS FOR TUBCHR
MOVEI T2,TUC7TK## ;CHECK 7 TRACK
TDNN T2,TUBCNF##(U) ;IS IT?
TRZ T1,1B31 ;NO - CLEAR BIT
MOVSI T2,TUSWTL## ;CHECK WRITE LOCKED
TDNN T2,TUBSTS##(U) ;IS IT?
TRZ T1,1B32 ;NO - CLEAR BIT
IORM T1,TUBCHR##(U) ;SET APPROPRIATE BITS
TRC T1,1B31+1B32 ;COMPLEMENT BITS
ANDCAB T1,TUBCHR##(U) ;AND CLEAR OTHERS
JRST CPOPJ1## ;GIVE GOOD RETURN
;ROUTINE TO SAVE DAEMON INFO IN SHADOW AREA AND CLEAR
;STATISTICS BLOCK FOR MOUNT OR UNLOAD PROCESSING
TPDCPY: HRLI T2,TUBRID##(U) ;GEN COPY PNTR
HRRI T2,TUBDDA##(U) ; TO DAEMON DUMP AREA
BLT T2,TUBDDE##(U) ;...
SETZM TUBRID##(U) ;NOW CLEAR AREA
HRLI T2,TUBRID##(U) ;GEN CLEAR PNTR
HRRI T2,TUBRID##+1(U)
BLT T2,TUBCLE##(U) ;END OF AREA TO CLEAR
POPJ P, ;RETURN
SUBTTL TAPOP. UUO
IFN FTTAPOP,<
;TAPOP. UUO OR CALLI 154
;UUO TO PERFORM MISCELLANEOUS FUNCTIONS FOR A SPECIFIC TAPE UNIT
;
;CALL: MOVE AC,[+N,,ADR]
; CALLI AC,154
; ERROR RETURN
; NORMAL RETURN
UTAPOP::PUSHJ P,SAVE4## ;SAVE AC'S
MOVE P4,T1 ;SAVE USER ARG IN P4
HRR M,T1 ;ADDRS OF BLOCK
HLRE T2,T1 ;GET LENGTH
CAIL T2,2 ;VALID LENGTH?
PUSHJ P,GETWRD## ;YES - GET ARG (FCN CODE)
PJRST ECOD4## ; NO - ERROR
JUMPLE T1,RTZER## ;RETURN 0 IF BAD FCN
MOVE P1,T1 ;SAVE FCN IN P1
PUSHJ P,GETWR1## ;GET NEXT ARG (DEVICE SPEC)
PJRST ECOD4##
PUSHJ P,DVCNSG## ;SEARCH FOR IT
PJRST ECOD2## ;NO SUCH
MOVSI T1,DVMTA ;CHECK ON TAPE UNIT
TDNN T1,DEVMOD(F) ;...
PJRST ECOD2## ;NOPE
MOVSI T1,DVTTY ;CHECK IF ALSO TTY
TDNE T1,DEVMOD(F)
PJRST CPOPJ1## ;NUL WINS
MOVE S,DEVIOS(F) ;SET UP STATUS
TRNN P1,1000 ;IF NOT A READ
PUSHJ P,WAIT## ;WAIT FOR ALL IO TO COMPLETE
HLRZ U,TDVUDB##(F) ;SET UP UDB PNTR
HRRZ T1,P1 ;GET FCN CODE
TRNE T1,3000 ;READ/SET CODE?
JRST TAPRSQ ;YES - GO HANDLE
CAIG T1,TAPLN0 ;NO - CHECK LEGAL
SKIPN TAPTB0(T1) ;EXISTS?
PJRST RTZER## ;ILLEGAL FCN CODE
MOVE P3,TAPTB0-1(P1) ;GET TABLE ENTRY
TLNN P3,(TAP.NP) ;NEED POKE PRIVS?
JRST CHKRED ;NO - TRY OTHERS
MOVSI T1,JP.POK ;YES - CHECK HIS PRIVS
PUSHJ P,PRVBIT## ;...
PJRST 0(P3) ;OK - DISPATCH
JRST ECOD1## ;NO - GIVE ERROR RETURN
CHKRED: TLNN P3,(TAP.RP) ;NEED READ PRIVS?
JRST CHKWRT ;NO - PROCEED
PUSHJ P,TREDOK ;YES - CHECK THEM
PJRST ECOD1## ;NOT ENOUGH PRIVS
CHKWRT: TLNN P3,(TAP.WP) ;NEED WRITE PRIVS?
PJRST 0(P3) ;NO - JUST CALL ROUTINE
PUSHJ P,TWRTOK ;YES - CHECK THEM
PJRST ECOD1## ;NOT ENOUGH
PJRST 0(P3) ;DISPATCH
;HERE IF FCN CODE IS IN THE RANGE 2000-3777
TAPRSQ: ANDI P1,777 ;MASK FCN CODE
TRZE T1,1000 ;READ CODE?
JRST TAPRED ;YES - TRY IT
CAIGE T1,2000+TAPLN1 ;CHECK RANGE
SKIPN P3,TAPTB1(P1) ; AND VALIDITY
PJRST RTZER## ;INVALID
TAPSET: HLRZ T2,P4 ;CHECK ARG LIST
CAIL T2,3 ;AT LEAST 3
PUSHJ P,GETWR1## ;GET NEXT ARG
PJRST ECOD4## ;ADDRS ERROR
MOVE P2,T1 ;SAVE IT IN P2
PUSHJ P,TWRTOK ;CHECK WRITE PRIVS
PJRST ECOD1## ;ERROR RETURN
LDB T1,TAPSYR ;LEGAL - RANGE CHK REQ'D?
JUMPE T1,TAPST1 ;JUMP IF NO
TLNE P3,(TAP.FC) ;SETTING FRAME-COUNT?
JUMPE P2,TAPST1 ;YES, 0 IS LEGAL
MOVE T2,TAPSRT-1(T1) ;MAX VALUE IN RH
HLRZ T3,T2 ; MIN VALUE IN LH
CAIG P2,(T2) ;.GT. MAX VALUE?
CAIGE P2,(T3) ; OR .LT. MIN VALUE?
PJRST ECOD3## ;ARG OUT OF RANGE
TLNN P3,(TAP.FC) ;SETTING FRAME COUNTER?
JRST TAPST1
LDB T2,TDYMOD ;YES, DO WE KNOW MODE?
JUMPE T2,TAPST1
MOVE T1,P2 ;YES, CONVERT TO NUMBER OF WORDS
IDIV T1,TMODTB##(T2)
SKIPE T2
ADDI T1,1
ADDI T1,1 ;ALLOW FOR OVERHEAD WORD
DPB T1,PBUFSZ## ;AND SAVE BUFFER SIZE
TAPST1: TLNE P3,(TAP.SA!TAP.FC) ;SET ALLOWED?
JRST TAPST2 ;YES - DO IT
TLNN P3,(TAP.PS) ;NO - NEED PRIVS
PJRST ECOD5## ;NOHOW!
MOVSI T1,JP.POK ;NEED PRIVS TO SET
PUSHJ P,PRVBIT## ;GO CHECK
SKIPA ;OK RETURN
PJRST ECOD1## ;NOPE
TAPST2: TLNE P3,(TAP.SP)
JRST 0(P3)
DPB P2,0(P3) ;SET BIT (BYTE)
JRST CPOPJ1## ;GIVE GOOD RETURN
;HERE TO HANDLE READ FUNCTIONS
TAPRED: CAIGE T1,TAPLN1 ;CHECK VALID ARG
SKIPN TAPTB1(P1) ; AND EXISTANCE
PJRST RTZER## ;RETURN ZERO
PUSHJ P,TREDOK ;CHECK PRIVS
PJRST ECOD1## ;NOPE
MOVE P3,TAPTB1(P1) ;GET TABLE ENTRY
TLNE P3,(TAP.DN) ;DENSITY?
JRST TAPRD1 ;YES - SPECIAL
TLNE P3,(TAP.SP) ;SPECIAL ROUTINE?
JRST 0(P3) ;YES - CALL IT
LDB T1,0(P3) ;NO - GET VALUE
PJRST STOTC1## ;STORE IT & SKIP RETURN
;HERE TO HANDLE DENSITY READ
TAPRD1: PUSHJ P,GETDEN ;GET DENSITY ARG
PJRST STOTC1## ;STORE ETC.
;ROUTINES TO CHECK PRIVS FOR READ OR WRITE
TREDOK: PUSHJ P,SAVE2## ;SAVE P1,P2
MOVSI P1,PVSPYM ;SPY PRIVS
JRST CKMTA
TWRTOK: PUSHJ P,SAVE2## ;SAVE P1,P2
MOVSI P1,JP.POK ;POKE PRIVS
CKMTA: LDB P2,PJOBN## ;GET OWNERS JOB #
CAMN P2,J ;IS IT US?
JRST CPOPJ1## ;YES - DO WHAT U WANT
EXCH P1,T1 ;NO - FURTHER CHECKING REQ'D
PUSHJ P,PRVBIT##
AOS (P) ;OK - SET FOR SKIP
MOVE T1,P1 ;RESTORE T1
POPJ P, ;RETURN
;TABLES FOR TAPOP. UUO
;CONTENTS OF TAPTB0 ARE AS FOLLOWS
;BITS 0-5 ARE CORRESPONDING MTAPE CODE IF ANY
;BITS 6-12 ARE FLAGS FOR DETERMINING VALIDITY
;RH IS ROUTINE ADDRS
TAP.RP==1B6 ;NEED READ PRIVS FOR THIS FCN
TAP.WP==1B7 ;NEED WRITE PRIVS FOR THIS FCN
TAP.NP==1B8 ;NEED JACCT / [1,2] PRIVS
DEFINE TMAC(MTCOD,BITS,ROU),<
EXP <MTCOD>B5+BITS+ROU
>
TAPTB0: TMAC (MT.WAT,TAP.RP,TAPOPM) ;1 - WAIT FOR UNIT AVAIL
TMAC (MT.REW,TAP.WP,TAPOPM) ;2 - REWIND
TMAC (MT.UNL,TAP.WP,TAPOPM) ;3 - REWIND & UNLOAD
TMAC (MT.FSR,TAP.WP,TAPOPM) ;4 - SKIP RECORD
TMAC (MT.FSF,TAP.WP,TAPOPM) ;5 - SKIP FILE
TMAC (MT.SET,TAP.WP,TAPOPM) ;6 - SKIP TO LEOT
TMAC (MT.BSR,TAP.WP,TAPOPM) ;7 - BACKSPACE RECORD
TMAC (MT.BSF,TAP.WP,TAPOPM) ;10 - BACKSPACE FILE
TMAC (MT.WTM,TAP.WP,TAPOPM) ;11 - WRITE TAPE MARK
TMAC (MT.WLG,TAP.WP,TAPOPM) ;12 - WRITE LONG GAP
TMAC (0,TAP.WP,TPMDSE) ;13 - DATA SECURITY ERASE
TMAC (0,TAP.WP,TPMWET) ;14 - WRITE LEOT
IFN FTTLAB,<
TMAC (0,TAP.NP,TPMLBG) ;15 - LABEL GET
TMAC (0,TAP.NP,TPMLBR) ;16 - LABEL RELEASE
TMAC (0,TAP.NP,TPMLSU) ;17 - SWAP UNITS
TMAC (0,TAP.NP,TPMLDD) ;20 - DESTROY LABEL DDB
TMAC (0,TAP.WP,TPMFEV) ;21 - FORCE EOV
TMAC (0,TAP.WP,TPMURQ) ;22 - USER REQUEST
>
IFE FTTLAB,< ;;; DUMMIES
0 ;15
0 ;16
0 ;17
0 ;20
0 ;21
0 ;22
>
TMAC (0,TAP.NP,TPMSMM) ;23 - SET MAINT MODE
TMAC (0,TAP.NP,TPMCMM) ;24 - CLEAR MAINT MODE
TAPLN0==.-TAPTB0
;CONTENTS OF TAPTB1 ARE AS FOLLOWS
;BITS 0-5 ARE INDEX INTO RANGE TABEL IF ANY
;BITS 6-12 ARE FLAGS FOR DETERMINING VALIDITY
;RH IS ADDRS OF BYTE PNTR
TAP.DN==1B6 ;SPECIAL DENSITY ACTION
TAP.SA==1B7 ;SET ALLOWED
TAP.PS==1B8 ;PRIV SET ONLY
TAP.SP==1B9 ;SPECIAL ACTION
TAP.FC==1B10 ;SET FRAME COUNT
TAPTB1: TMAC (0,0,<[POINT 36,TUBFES##(U),35]>) ;1000 - FINAL ERROR DISPOSITION
TMAC (1,TAP.DN+TAP.SA,TDYDN1) ;1001 - DENSITY
TMAC (0,0,TUYKTP##) ;1002 - KONTROLLER TYPE
IFN FTRDBACK,<
TMAC (0,TAP.SA,<[POINT 1,TDVSTS##(F),0]>) ;1003 - READ BACKWARDS
>
IFE FTRDBACK,< ;DUMMY FOR RDBACK
0
>
TMAC (0,TAP.SA,<[POINT 1,TDVSTS##(F),1]>) ;1004 - LOW THRESHOLD
TMAC (0,TAP.SA,<[POINT 1,TDVSTS##(F),3]>) ;1005 - EVEN PARITY
TMAC (2,TAP.SA,PBUFSZ##) ;1006 - BLOCKSIZE
TMAC (3,TAP.SA,TDYMOD) ;1007 - MODE
TMAC (0,TAP.PS,<[POINT 1,TUBCNF##(U),18]>) ;1010 - TRACK INFO
TMAC (0,0,<[POINT 1,TUBSTS##(U),2]>) ;1011 - WRITE LOCK
TMAC (0,0,<[POINT 36,TUBCCR##(U),35]>) ;1012 - CHAR CNT
TMAC (0,TAP.PS,<[POINT 36,TUBRID##(U),35]>) ;1013 - REELID
TMAC (0,0,PMTCRC##) ;1014 - CRC
TMAC (0,0,<[POINT 18,TUBSTS##(U),17]>) ;1015 - UNIT STATUS
TMAC (0,TAP.SP,TAPSTS) ;1016 - STATISTICS
TMAC (0,0,<[POINT 36,TUBIEP##(U),35]>) ;1017 - INITIAL ERROR POINTER
TMAC (0,0,<[POINT 36,TUBFEP##(U),35]>) ;1020 - FINAL ERROR POINTER
TMAC (0,TAP.SP,TAPIES) ;1021 - INITIAL ERROR STATS
TMAC (0,TAP.SP,TAPFES) ;1022 - FINAL ERROR STATS
TMAC (0,0,<[POINT 36,TUBTRY##(U),35]>) ;1023 - # RETRIES
IFN FTTLAB,<
TMAC (4,TAP.SA,TUYLTP) ;1024 - LABEL TYPE
TMAC (0,TAP.PS,TUYLTP) ;1025 - LABEL TYPE (PRIV SET)
TMAC (0,0,PDVESE##) ;1026 - LABEL TERMINATION CODE
>
IFE FTTLAB,< ;;; DUMMIES
0 ;1024
0 ;1025
0 ;1026
>
TMAC (0,TAP.PS,<[POINT 1,TUBCNF##(U),20]>) ;1027 - DIAG MODE SET
TMAC (0,TAP.PS,<[POINT 1,TUBCNF##(U),21]>) ;1030 - FORCE SENSE
TMAC (5,TAP.FC,PBUFRM##) ;1031 : MAX FRAME COUNT
TMAC (0,0,<[POINT 5,TUBCNF##(U),27]>) ;1032 - DENSITY CAPABILITIES
IFN FTTLAB,<
TMAC (0,TAP.SP!TAP.SA,TAPRLP) ;1033 - READ LABEL PARAMETERS
>
IFE FTTLAB,<
0 ;1033 - DUMMY
>
TAPLN1==.-TAPTB1
;RANGE TABLE FOR TAPOP UUO
TAPSRT: 0,,5 ;1 - DENSITY
NOISEW##,,^D4095 ;2 - BLOCKSIZE
0,,5 ;3 - MODE
IFN FTTLAB,< LT.SL,,LT.MAX ;4 - LABEL TYPE>
IFE FTTLAB,< 0 >
NOISE##,,<^D4095*6>-1 ;5 - MAX FRAME-COUNT
TAPSYR: POINT 6,TAPTB1(P1),5 ;POINTER TO RANGE INDEX
TAPMTP: POINT 6,TAPTB0-1(P1),5 ;POINTER TO MTAPE EQUIVALENT
;ROUTINE TO LINK TAPOP. FCNS TO MTAPE FCNS
TAPOPM: PUSHJ P,PIOSET ;SET UP ACS, UDB, ETC.
JUMPE J,ECOD6## ;ERROR IN NO OWNER
LDB T1,TAPMTP ;GET MTAPE FCN CODE
HRR M,T1 ;MAKE M LOOK LIKE IN MTAPE
AOS (P) ;SET FOR SKIP RETURN
PJRST MTAP0 ;ISSUE MTAPE CMD
;SPECIAL ROUTINE FOR STATISTICS (1016)
;LH(P4) := LEN OF ARG BLOCK , RH(M) := LOC OF LAST ARG
TAPSTS: HLRZ T2,P4 ;GET LENGTH
SUBI T2,2 ;CORRECT FOR ARGS
JUMPLE T2,ECOD4## ;NOT ENOUGH ARGS
CAILE T2,TPCHMX## ;COMPARE AGAINST MAX
MOVEI T2,TPCHMX## ;OUT OF RANGE - USE MAX
MOVN P1,T2 ;NEGATE LENGTH
HRLZS P1 ;MOVE TO LH
HRRI P1,TUBRID##(U) ;BASE ADDRS OF STATS
TAPOPL: MOVE T1,0(P1) ;FETCH WORD
PUSHJ P,PUTWR1## ;STORE IN USER AREA
JRST RTM1## ;OUT OF BOUNDS
AOBJN P1,TAPOPL ;CONTINUE TILL DONE
PJRST CPOPJ1## ;THEN GIVE SKIP RETURN
;SPECIAL ROUTINE FOR ERROR INFO (1021/1022)
TAPIES: SKIPA P1,TUBIEP##(U) ;GET INITIAL ERROR PNTR
TAPFES: MOVE P1,TUBFEP##(U) ;GET FINAL ERROR PNTR
ADDI P1,0(U) ;RELOCATE PNTR
HLRZ T2,P4 ;GET USER LEN
MOVNI T2,-2(T2) ;NEGATE AND ADJUST FOR ARGS
JUMPGE T2,ECOD4## ;NOT ENOUGH ARGS
HLRE T3,P1 ; -LEN OF ERROR BLOCK
CAMLE T2,T3 ;CHECK VALIDITY
HRL P1,T2 ;YES - USE USERS ARG
JRST TAPOPL ;JOIN COMMON CODE
;ROUTINE TO HANDLE DATA SECURITY ERASE
TPMDSE: PUSHJ P,PIOSET ;SET ACS ETC.
IFN FTTLAB,<
MOVEI T1,40(P1) ;GENERATE SPECIAL CODE
PUSHJ P,LBLSLP ;WAIT FOR LBL PCS TO FINISH
PUSHJ P,LBLPOS ;CHECK FOR LBL PCS
PJRST CPOPJ1## ;ALL DONE - RETURN
>
JUMPE J,ECOD6## ;ERROR IF NO OWNER
MOVEI P2,RB.FSE ;FCN TO P2
MOVEI P3,TPMDE0 ;USE WITH LONG TIMEOUT WRITE
PUSHJ P,MTAP2 ;START OP
PUSHJ P,TPSKPW ;WAIT TILL DONE
MOVEI P2,RB.FLG ;NOW DO 14 ERASE GAP OPS
MOVEI P3,TPMDE1
AOS (P) ;GIVE SKIP RETURN
PJRST MTAP2 ;START OP
;HERE TO PERFORM WRITE OP WITH LONG TIMOUT
TPMDE0: MOVEI T1,WRTDUN ;WHERE TO GO ON COMPLETION
HRRZM T1,TRBIVA(P1) ;SAVE IT
MOVEI T1,DSETIM## ;SET A LONG HUNG TIMER GOING
MOVEM T1,TKBTIM##(W) ; TO CATCH PROBLEMS (SINCE IOACT=0)
PJRST TPSTRT ;GO START THE OPERATION
;HERE ON KONTROLLER AVAILABLE
TPMDE1: MOVEI T1,^D14 ;SET COUNT
HRRM T1,TRBXCW(P1) ;INTO IORB
PJRST TPMWRT ;START I/O
;ROUTINE TO WRITE LEOT (TM,TM,BSB)
TPMWET:
PUSHJ P,PIOSET ;SET ACS ETC.
IFN FTTLAB,<
MOVEI T1,40(P1) ;SPECIAL CODE
PUSHJ P,LBLSLP ;WAIT FOR LBL PCS TO FINISH
PUSHJ P,LBLPOS ;CHECK LABELER
PJRST CPOPJ1## ;THROUGH - EXIT
>
JUMPE J,ECOD6## ;ERROR IF NO OWNER
AOS (P) ;SET SKIP RETURN
PJRST TPMCL1 ;JOIN CLOSE CODE
IFN FTTLAB,<
;TAPE LABEL GET -- SET UP DDB IF NONE AND CONTINUE UNIT
TPMLBG: MOVE T1,DEVNAM(F) ;GET PHYS NAME
MOVEI T2,'''L' ;CONVERT TO SECONDARY NAME
DPB T2,[POINT 12,T1,11]
PUSH P,T1 ;SAVE IT
PUSH P,F ;SAVE DDB PNTR
PUSHJ P,DEVPHY## ;SEARCH FOR EXISTANCE
SKIPA ;NOT FOUND
JRST [POP P,P1 ;FOUND - PRUNE PDL
POP P,T1 ;...
JRST TPLBG1] ;AND CONTINUE PROCESSING
TPLBGA: MOVEI T2,SPROTO ;SIZE OF DDB
PUSHJ P,GETWDS## ;ALLOCATE STORAGE
JRST [MOVEI T1,1 ;FAILED
IFN FTPSCD,<
AOS %MTASL## ;COUNT MTA GENERATED SLEEP
>;END IFN FTPSCD
PUSHJ P,SLEEP## ;WAIT FOR SOME TO APPEAR
JRST TPLBGA] ;TRY AGAIN
POP P,P1 ;GET OLD DDB PNTR INTO P1
MOVE F,T1 ;SET UP NEW PNTR
HRLI T1,LPROTO ;LOC IF PROTOTYPE
BLT T1,SPROTO-1(F) ;MOVE INTO PLACE
POP P,DEVNAM(F) ;GIVE IT A NAME
MOVEI T1,DEPEVM ;NOW GET THIS CORRECT
TDNE T1,DEVTYP(P1) ;IF OLD DDB NEEDED EVM
IORM T1,DEVTYP(F) ; THEN THIS ONE DOES ALSO
DPB J,PJOBN## ;ASSIGN TO THIS JOB
HLRZ T1,DEVSER(P1) ;FIX UP LINKS OF
HRLM T1,DEVSER(F) ; DDB CHAIN TO
HRLM F,DEVSER(P1) ; INCLUDE THIS NEW ONE
MOVE T1,TDVKDB##(P1) ;GET UDB / KDB PNTRS
MOVEM T1,TDVKDB##(F) ;INTO NEW DDB
HRLM F,TUBDDB##(U) ;LINK TO SECONDARY PNTR IN UDB
MOVSI T1,TUBQUE##(U) ;AND SET UP NEW EMPTY QUEUE
EXCH T1,TUBQUE##(U) ;EXCHANGE PNTRS
MOVEM T1,TDVSVQ(F) ;SAVE IN NEW DDB
MOVE T1,DEVNAM(F) ;GET NAME OF NEW DDB
PUSHJ P,STOTAC## ;STORE FOR USER
AOS 0(P) ;SET FOR SKIP RETURN
PJRST TAPCNT## ;ALLOW UNIT TO BE SCHEDULED AGAIN
;;; STILL IN FTTLAB CONDITIONAL
TPLBG1: MOVE T1,TDVSTS##(P1) ;GET PAR/DEN/MODE, USERS SET
MOVEM T1,TDVSTS##(F) ;AND STORE IN LABEL DDB
;TAPE LABEL RELEASE -- TRY TO GET JOB RUNNING AGAIN
TPMLBR: HLRZ P1,TUBDDB##(U) ;2ND DDB ADDRS
JUMPE P1,TPLBR1 ;OK IF NO DDB
HRRZS TUBDDB##(U) ;CLEAR SECONDARY DDB
TPLBR1: AOS 0(P) ;SET FOR SKIP RETURN
HLRZ T1,P4 ;USERS LENGTH
CAIL T1,3 ;CHECK FOR POSSIBLE 3RD ARG
PUSHJ P,GETWR1 ;FETCH IT
MOVEI T1,0 ;ASSUME ZERO
DPB T1,PDVESE##
TLZN S,LBLWAT ;CHECK IF WAITING
JRST TPLBRU ;NO - UNWIND REQUESTS
MOVEM S,DEVIOS(F)
LDB T1,PJOBN## ;GET JOB NUMBER
JUMPE T1,TPLBRU ;IF NONE - EXIT
EXCH T1,J ;SAVE J - SET OTHER JOB #
LDB T2,PJBSTS## ;GET JOB STATUS
EXCH T1,J ;RESTORE J
CAIN T2,STOPQ## ;IS JOB STOPPED?
PJRST TAPHLD## ;YES - JUST SET NS
PJRST EWAKE## ;ELSE WAKE HIM UP
;HERE TO JUST QUIETLY DE-Q OLD INFO
TPLBRU: MOVSI T1,TUBQUE##(U) ;SET Q TO NULL STATE
EXCH T1,TUBQUE##(U) ;AND FETCH OLD INFO
TLZ T1,-1 ;CLEAR LH
PJRST TPMDQ ;SLUURRRRP!
;ROUTINE TO SWITCH TWO UNITS FOR TAPE LABELING
;CALL - F := CURRENT DDB
TPMLSU: MOVE P2,T2 ;SAVE PRED.
HLRZ T1,P4 ;GET USERS LENGTH
CAIL T1,3 ;MIN OF 3
PUSHJ P,GETWR1## ;GET NAME OF NEW DEVICE
PJRST ECOD4## ;BAD ARG ADDRS
MOVE P1,F ;SAVE OLD DDB ADDRS
PUSHJ P,DEVPHY## ;LOOK FOR NEW ONE
PJRST ECOD2## ;SEARCH LOST
MOVSI T1,DVMTA ;GRNTEE IT IS A MTA
TDNN T1,DEVMOD(F) ;...
PJRST ECOD2## ;SORRY 'BOUT THAT
MOVE P3,T2 ;SAVE PRED.
MOVE T1,DEVNAM(F) ;GET NEW NAME
EXCH T1,DEVNAM(P1) ;EXCHANGE WITH OLD ONE
MOVEM T1,DEVNAM(F) ;AND SAVE IN NEW DDB
SKIPE DEVLOG(P1) ;WAS THERE A LOGICAL NAME
JRST TPLSU1 ;YES - OK THEN
MOVEM T1,DEVLOG(P1) ;NO - USE OLD PHYSICAL NAME
EXCH F,P1 ;CONFUSE THINGS
PUSH P,J ;SAVE J
LDB J,PJOBN## ;REAL OWNERS JOB #
PUSHJ P,SETDVL## ;FIX UP LOGICAL NAME TABLE
EXCH F,P1 ;PUT THINGS BACK
POP P,J ;...
TPLSU1: HLRZ T1,DEVSER(P1) ;SUCCESSOR TO 1SR UNIT
HLRZ T2,DEVSER(F) ;SUCCESSOR TO 2ND UNIT
HRLM F,DEVSER(P2) ;MAKE PRED (1ST) POINT AT 2ND
HRLM P1,DEVSER(P3) ;MAKE PRED (2ND) POINT AT 1ST
CAIN T2,(P1) ;MAKE 1ST POINT AT SUCC (2ND)
MOVE T2,F ; IF 1ST = SUCC 2ND, POINT 1ST AT 2ND
HRLM T2,DEVSER(P1)
CAIN T1,(F) ;POINT 2ND AT SUCC (1ST)
MOVE T1,P1 ; OR AT 1ST
HRLM T1,DEVSER(F)
MOVEI T1,GTLEN##-1
TPLSU2: HRRZ T2,GENTAB##(T1)
CAIN T2,(F)
HRRM P1,GENTAB##(T1)
CAIN T2,(P1)
HRRM F,GENTAB##(T1)
SOJGE T1,TPLSU2
MOVE T1,TDVKDB##(P1) ;EXCHANGE UNIT / KONTROLLER PNTRS
EXCH T1,TDVKDB##(F)
MOVEM T1,TDVKDB##(P1)
HRRM F,TUBDDB##(U) ;FIX UDB / DDB PNTR
MOVE P2,U ;OLD UDB PNTR
HLRZ U,TDVKDB##(P1) ;GET NEW UDB ADRS
MOVE T2,TUBLBL##(U) ;EXCHANGE LABEL INFO IN UDBS
EXCH T2,TUBLBL##(P2)
MOVEM T2,TUBLBL##(U) ;...
HRRM P1,TUBDDB##(U) ;AND SET PNTR
MOVE F,P1 ;MAKE F POINT AT NEW DDB
HLRZ P1,TUBDDB(P2) ;GET OLD SECONDARY DDB PNTR
JUMPE P1,CPOPJ1## ;QUIT NOW IF NONE
MOVE T1,TDVKDB##(F) ;GET NEW UNIT/KONTROLLE PNTR
MOVEM T1,TDVKDB##(P1) ;SAVE IT IN LABEL DDB
HRLM P1,TUBDDB##(U) ;MAKE NEW UDB HAVE SECOND DDB
HRRZS TUBDDB##(P2) ;AND OLD DDB HAVE NONE
JRST CPOPJ1## ;SKIP EXIT
;ROUTINE TO SEND FORCE EOV MESSAGE TO LBL PCS
TPMFEV: MOVE S,DEVIOS(F) ;SET UP S
PUSHJ P,LBLCHK ;CHECK FOR LBL PROCESS
SKIPA T1,[LR.EOV] ;REQUEST CODE
PJRST ECOD7## ;NO LABEL PROCESS
PUSHJ P,LBLSLP ;WAIT FOR LBL PCS TO FINISH
DPB T1,TUYRQT ;REQUEST TYPE
MOVEI T1,0 ;ZERO ADDITIONAL INFO
DPB T1,TUYINF ;...
TPMSND: PUSHJ P,LBLMSG ;SEND MESSAGE AND BLOCK
LDB T1,PDVESE##
JUMPE T1,CPOPJ1## ;SKIP RETURN IF NO ERROR
PJRST ECOD10## ;ELSE ERROR
;ROUTINE TO SEND USER REQUEST FOR LABEL PROCESSING
TPMURQ: MOVE S,DEVIOS(F) ;SET UP S
PUSHJ P,LBLCHK ;SEE IF LBL PCS
SKIPA T1,[LR.URQ] ;YES - REQUEST TYPE
PJRST ECOD7## ;ERROR
PUSHJ P,LBLSLP ;WAIT FOR LBL PCS TO FINISH
DPB T1,TUYRQT ;REQUEST TYPE
HLRZ T1,P4 ;GET USER LENGTH ARG
CAIL T1,3 ;CHECK FOR ENUF ARGS
PUSHJ P,GETWR1## ;FETCH NEXT
PJRST ECOD4## ;TOO FEW ARGS
CAILE T1,77 ;CHECK RANGE
JRST ECOD3## ;OUT OF BOUNDS
DPB T1,TUYINF ;STASH IN UDB
PJRST TPMSND ;SEND MESSAGE
;ROUTINE TO DESTROY LABEL DDB AND GIVE BACK ITS STORAGE
TPMLDD: HLRZ T1,TUBDDB##(U) ;GET 2ND DDB ADDR
JUMPN T1,ECOD12## ;THRERE IS ONE, ERROR
MOVE T1,DEVNAM(F) ;GET PHYS NAME
MOVEI T2,'''L' ;CONVERT TO SECONDARY NAME
DPB T2,[POINT 12,T1,11]
PUSHJ P,DEVPHY## ;GO FIND IT
JRST CPOPJ1## ;NOT THERE, JUST RETURN
LDB T1,PJOBN## ;GET THIS DDB'S OWNER
CAME T1,J ;IS IT THE GUY DOING RELEASE
JRST ECOD6## ;NO, ERROR - NOT ASSIGNED
PUSHJ P,WAIT1## ;WAIT FOR I/O TO STOP
MOVEI T1,MT0DDB## ;GET START OF MAGTAPE DDB'S
TPMLD1: MOVE T2,T1
HLRZ T1,DEVSER(T2) ;GET SUCCESSOR
SKIPN T1 ;END ?
STOPCD CPOPJ##,DEBUG,LDN, ;TT LABEL DDB NOT FOUND
CAIE T1,(F) ;IS SUCCESSOR THE ONE WE
JRST TPMLD1 ;NO, TRY NEXT
AOS 0(P) ;SET FOR SKIP RETURN
MOVE T1,DEVSER(F) ;GET LINK FROM DB TO BE DESTROYED
HLLM T1,DEVSER(T2) ;SAVE IN PREDESSOR
HRRZ T1,USRHCU## ;GET HIGHEST CHANNEL IN USE
TPMLD2: HRRZ T2,USRJDA##(T1) ;GET DDB ADDR FOR THIS CHANNEL
CAIE T2,(F) ;IS IT INITED ON THIS CHANNEL
SOJGE T1,TPMLD2 ;NO, LOOP FOR MORE
SKIPL T1 ;LOOP EXPIRED?
SETZM USRJDA##(T1) ;NO, CLEAR OUT THIS CHANNEL
MOVEI T1,SPROTO ;SIZE OF DDB
HRRZ T2,F ;ADDR
PJRST GIVWDS## ;GIVE BACK STORAGE AND RETURN
;READ/SET LABEL PARAMETERS
TAPRLP: HRR M,P4 ;POINT AT USER'S FUNCTION
PUSHJ P,LBLCHK ;CHECK FOR LBL PCS
JRST TAPRL0 ;THERE IS ONE, GO AHEAD
PUSHJ P,GETWRD## ;GET USER'S FUNCTION
PJRST ECOD4## ;ADDRESS ERROR
HLRZ T2,TUBDDB(U) ;GET SECOND DDB
CAIE T2,(F) ;OURS
PJRST ECOD7## ;NO, NO LBL PCS
TRNE T1,2000 ;SET FUNCTION
JRST TAPSLP ;YES, DO IT
JRST TAPRL1 ;DO READ
TAPRL0: PUSHJ P,GETWRD## ;GET USER'S FUNCTION
PJRST ECOD4## ;ADDR ERROR
PUSHJ P,LBLSLP
TRNE T1,2000 ;SET FUNCTION?
JRST TAPSLP ;YES
TLZN S,FINP ;HAS FIRST INP BEEN DONE?
JRST TAPRL1 ;YES, PROCEED
MOVEI T1,LR.FIN ;REQUEST FOR FIRST INPUT
DPB T1,TUYRQT ;SAVE IN TUB
MOVEM S,DEVIOS(F) ;SAVE S
PUSHJ P,LBLMSG ;SEND MESSAGE
LDB T1,PDVESE## ;CHECK ERROR BITS
JUMPN T1,ECOD10## ;GIVE ERROR TO USER
TAPRL1: ADDI M,1 ;POINT AT WHERE TO START STORING
HLRZ T2,P4 ;GET LENGTH
SUBI T2,2 ;CORRECT FOR ARG'S
JUMPLE T2,ECOD4## ;NOT ENOUGH ARG'S
CAILE T2,TLPMAX## ;BIGGER THAN MAX?
MOVEI T2,TLPMAX## ;YES, USE MAX
MOVN P1,T2 ;NEGATE LENGTH
HRLZS P1 ;MOVE TO LH
HRRI P1,TUBRFM##(U) ;BASE OF LABEL PARAMETER AREA
JRST TAPOPL ;USE EXISTING ROUTINE TO RETURN BLOCK
TAPSLP: HLRZ T2,P4 ;GET LENGTH OF USER'S ARG BLOCK
SUBI T2,2 ;ACCOUNT FOR FIRST 2 ARG'S
JUMPLE T2,ECOD4## ;NOT ENOUGH ARGS
CAILE T2,TLPMAX## ;BIGGER THAN MAX
MOVEI T2,TLPMAX## ;YES, USE MAX
MOVN P1,T2 ;GET NEGATIVE LENGTH
HRLZS P1 ; INTO LH FOR AOBJN
HRRI P1,TUBRFM##(U) ;POINT AT START OF AREA
ADDI M,1 ;POINT M AT DEVICE ARG WORD
TAPSL1: PUSHJ P,GETWR1## ;GET NEXT ARGUMENT
PJRST ECOD4## ;NOT THERE, ERROR
MOVEM T1,0(P1) ;STORE IN TUB
AOBJN P1,TAPSL1 ;GET ALL ARGUMENTS
MOVEI T1,TLPMAX##
SUB T1,T2
JUMPLE T1,CPOPJ1##
ADDI P1,1
SETZM (P1)
SOJG T1,.-2
JRST CPOPJ1## ;SKIP RETURN
> ;;;; END IFN FTTLAB
> ;;;; END IFN FTTAPOP
IFE FTTAPOP,<
UTAPOP:: POPJ P, ;NOT IMPLEMENTED
>
;ROUTINE TO TAKE CTL OFF-LINE AND SET MAINT MODE
TPMSMM: HRRZ W,TUBKDB##(U) ;GET KDB ADDRS
MOVE T3,TKBIUN##(W) ;GET UDB PNTR
TPMSM1: SKIPN T2,0(T3) ;SEE IF UNIT EXISTS
JRST TPMSM2 ;NO - TRY NEXT
HRRZ F,TUBDDB##(T2) ;GET DDB PNTR
LDB T1,PJOBN## ;OWING JOB NUMBER
CAME T1,J ;IT HAD BETTER BE ME
JRST ECOD11## ;ELSE ERROR
TPMSM2: AOBJN T3,TPMSM1 ;LOOP TILL ALL UNITS DONE
CONO PI,PIOFF## ;TURN OFF WORLD
HLLZS TKBCSO##(W) ;REMOVE FROM CONSO CHAIN
MOVSI T1,TKSMNT## ;SET MAINT MODE BIT
IORM T1,TKBSTS##(W) ;IN KDB
CONO PI,PION## ;RESTORE WORLD
MOVEM J,TKBJOB##(W) ;SAVE HIS JOB NUMBER
MOVE T1,TKBICP##(W) ;INFO USER WOULD LIKE
PJRST STOTC1## ;AND SKIP RETURN
;ROUTINE TO RESTORE CTL AND CLEAR MAINT MODE
TPMCMM: HRRZ W,TUBKDB##(U) ;GET KDB PNTR
TPMCM1: CAME J,TKBJOB##(W) ;DOES THIS JOB HAVE KONTROLLER?
JRST ECOD11## ;NO - LOSE
SETZM TKBJOB##(W) ;YES, HE DOESN'T ANY MORE
HRRZ T4,TKBDSP##(W) ;ADDRS OF CTL DEP CODE
PUSHJ P,TPKINI##(T4) ;DISPATCH TO LOWER LEVEL INIT
MOVSI T1,TKSMNT## ;BIT TO CLEAR NOW
ANDCAM T1,TKBSTS##(W) ; IN KDB
PJRST CPOPJ1## ;AND RETURN
IFN FTMDA,<
;ROUTINE TO CALL MDA ON TAPE ON-LINE
TPMONL::PUSH P,W ;IPCSER WIPES W
MOVE T1,TUBDDB##(U)
MOVE T1,DEVNAM(T1)
MOVEI T2,.TYMTA ;A MAGTAPE
PUSHJ P,SNDMDC## ;TELL MDC
JFCL
JRST WPOPJ## ; AND RETURN
>
SUBTTL MTAPE UUO
;MTAPE UUO
MTAPE0::PUSHJ P,SAVE3## ;SAVE P1,P3
PUSHJ P,WAIT## ;WAIT FOR ALL PREVIOUS IO TO COMPLETE
PUSHJ P,PIOSET ;SET UP ACS
HRRZ T1,M ;GET RH OF UUO
CAIE T1,MT.DEC ;CHECK SPECIAL JUNK
CAIN T1,MT.IND ; FOR 9-TK TAPES
JRST TPM9TK ;SET/CLR 4/4.5 BYTE MODE
CAIN T1,MT.STL ;SPECIAL LOW THRESHOLD
JRST TPMLOW ; TM10 ONLY
MTAP0: CAIG T1,MT.MAX ;CHECK VALID ARG
SKIPN P3,MTDTBL(T1) ;GET TABLE ENTRY
JRST UUOERR## ;ERROR IF NOT IMPLEMENTED
IFN FTTLAB,<
PUSHJ P,LBLSLP ;WAIT FOR LABEL PCS
JUMPE T1,MTAP1 ;DON'T CALL LBL PLS ON NOOP
PUSHJ P,LBLPOS ;CHECK LBLPCS
POPJ P, ;HE DID IT FOR YOU
JRST MTAP1 ;PROCEED
>
MTAP: CAIG T1,MT.MAX ;CHECK VALID ARG
SKIPN P3,MTDTBL(T1) ;GET TABLE ENTRY
JRST UUOERR## ;ERROR IF NOT IMPLEMENTED
MTAP1: HLRZ P2,P3 ;FCN INTO P2
MTAP2: PUSHJ P,GENIOR ;GENERATE IORB
JRST TPMINF ;WHAT ELSE???
MOVEM T1,TDVIOR##(F) ;WAIT TILL READY
HRRM P3,TRBIVA(T1) ;SAVE INT VECTOR
PUSHJ P,TAPRQT## ;QUEUE IT UP
MOVSI T1,TKSOFL## ;IF KONTROLLER IS OFF-LINE,
TDNE T1,TKBSTS##(W)
JRST POSOFL ;COMPLAIN TO USER AND OPER
PUSHJ P,KONWAT ;WAIT FOR KONTROLLER
;P1 := IORB UPON RETURN
MOVSI T1,TKSOFL## ;SEE IF UNIT IS OFFLINE
TDNE T1,TUBSTS##(U) ;??
JRST POSOFL ;YES - INFORM WORLD
HRRZ T1,TRBIVA(P1) ;GET ROUT ADDRS
JUMPN T1,0(T1) ;DO SPECIAL ROUTINE
MTAPG1: MOVEI T1,1 ;ONE OP ONLY
MTAPGO: HRRM T1,TRBXCW(P1) ;...
MOVEI T1,TPMISP ;WHERE TO GO WHEN DONE
MTAPG2: HRRZM T1,TRBIVA(P1) ;SAVE IT
MOVEI T1,TAPTIM## ;SET A HUNG TIMER GOING
MOVEM T1,TKBTIM##(W) ; (NOT DEVCHK SINCE IOACT=0)
PJRST TPSTRT ;GO STRT OP
;ENTER HERE TO HANDLE OFFLINE DEVICE IF MTAPE UUO
;C(T1) := TKSOFL
POSOFL: ANDCAM T1,TUBSTS##(U) ;CLEAR FLAG
PUSHJ P,TPMFLX ;FLUSH CURRENT REQUEST
POSOF1: TLZ S,IOSTBL!OFFLIN ;CLEAR THESE ALSO
PUSHJ P,CKTC10 ;CHECK ON TC10C
PUSHJ P,HNGSTP## ;INFORM ALL
MOVSI P2,OFLUNH ;PRESERVE THIS BIT
AND P2,DEVIOS(F) ;AROUND CALL TO IOSET
PUSHJ P,PIOSET ;RESET ACS
IORM P2,DEVIOS(F) ;RESTORE BIT IF ON
HRRZ T1,M ;GET FCN BACK IN T1
JRST MTAP ;CONTINUE
;DISPATCH TABLE FOR MTAPE UUO FUNCTIONS
MTDTBL: RB.FYB,,TPMNOP ;0-WAIT
RB.FRW,,TPMREW ;1-REWIND
0 ;2-ILLEGAL
RB.FTM,,TPMWRT ;3-WRITE TAPE MARK
0 ;4-ILLEGAL
0 ;5-ILLEGAL
RB.FSR,,0 ;6-FORWARD SKIP RECORD
RB.FBR,,0 ;7-BACKWARD SKIP RECORD
RB.FBR,,TPMSET ;10-SKIP TO LEOT (BACKUP FIRST)
RB.FRU,,TPMUNL ;11-REWIND AND UNLOAD
0 ;12-ILLEGAL
RB.FLG,,TPMWRT ;13-WRITE 3" BLANK TAPE
0 ;14-ILLEGAL
0 ;15-ILLEGAL
RB.FSR,,TPMFSF ;16-FORWARD SKIP FILE
RB.FBR,,TPMBSF ;17-BACKWARD SKIP FILE
;HERE ON MTAPE 0
TPMNOP: MOVE S,DEVIOS(F)
MOVSI T1,TUSBOT## ;IS DRIVE AT BOT?
TDNE T1,TUBSTS##(U)
TRO S,IOBOT ;YES
MOVEM S,DEVIOS(F) ;LIGHT BIT IF AT BOT
JRST TPMFLX ;THROW AWAY IORB AND RETURN
;HERE TO PERFORM SOME SORT OF WRITE FUNCTION
TPMWRT: MOVEI T1,WRTDUN ;WHERE TO GO
JRST MTAPG2
;HERE WHEN DONE (CHECK ERRORS)
WRTDUN: SETZM TKBTIM##(W) ;CLEAR HUNG TIMER
PUSHJ P,SETIOS ;SET UP S
JSP P2,OUTERR ;ATTEMPT RECOVERY
PJRST TPMSTP ;STOP I/O AND RETURN
;INTERUPT AT END OF SPACING OP
TPMISP: SETZM TKBTIM##(W) ;NO LONGER HAVE MTAPE GOING
PUSHJ P,SETIOS ;SET UP S
JSP P2,SPERR ;HANDLE SPACING ERROR
PJRST TPMSTP ;WIND IT DOWN
;ROUTINE TO SET/CLR 4/5 BYTE 9 TRACK MODE
TPM9TK: MOVEI T1,TUC7TK## ;7-TRACK BIT
TDNE T1,TUBCNF##(U) ;SEE IF ITS OK
POPJ P, ;FORGET IT IF 7TK
HRRZ T1,M ;RESTORE T1
CAIE T1,MT.DEC ;IS IT DEC MODE?
JRST TPSETI ;NO - SET INDUSTRY COMPAT
MOVEI T2,RB.MCD ;YES - SET NORMAL MODE
DPB T2,TDYMOD ;SET IN MODE FIELD OF DDB
POPJ P, ;RETURN
;HERE TO SET INDUSTRY COMPATIBLE MODE (WHATEVER THAT IS)
TPSETI: MOVEI T1,COMPAT ;SET BYTE IN STATUS WORD
DPB T1,TDYBYT
POPJ P, ;RETURN
;SET LOW THRESHOLD FOR TM10 CONTROLLERS
TPMLOW: MOVSI T2,D.NRLT ;NEXT REC AT LOW THRESHOLD
IORM T2,TDVSTS##(F) ;SET IN DDB
POPJ P, ;RETURN
;HERE TO HANDLE UNLOAD. SETUP COUNTERS, REPORT TO DAEMON
;AND BITCH AT USER AND OPERATOR. (PS - CHECK SET WATCH MTA)
TPMUNL:
SETO P2, ;REMEMBER THIS IS AN UNLOAD
AOSA TUBTUN##(U) ;TOTAL UNLOADS
TPMREW: SETZ P2, ;CLEAR UNLOAD FLAG
MOVSI T1,TUSREW## ;SET REWINDING NOW!
IORM T1,TUBSTS##(U) ;...
PUSHJ P,MTAPG1 ;START OPERATION
PUSHJ P,TPMRLW ;WAIT TILL DISCONNECTED
JUMPE P2,TPMRW1 ;NO MSG IF REWIND
MOVE T1,TUBCRD##(U) ;ANYTHING TO TALK ABOUT?
IOR T1,TUBCWR##(U) ;..
IOR T1,TUBHRE##(U) ;THERE IS IF ANY HARD ERRORS
IOR T1,TUBHWE##(U) ;..
SKIPE T1 ;NO
PUSHJ P,TPSTAT ;YES - PRINT STATS
PJRST STOIOS##
TPMRW1: TRO S,IOBOT ;SET BOT
MOVSI T1,TKSOFL##
TDNN T1,TUBSTS##(U) ;CHECK OFF-LINE
PJRST STOIOS##
ANDCAM T1,TUBSTS##(U) ;CLEAR OFL BIT
JRST POSOF1 ;INFORM USER
;ROUTINE TO PRINT TAPE STATISTICS AND CALL DAEMON
TPSTAT: PUSHJ P,SAVE2## ;SAVE P1,P2
PUSH P,W ;SAVE US FROM SCNSER
MOVE P1,F ;HIDE DDB IN P1
MOVE P2,U ;HIDE UDB IN P2
IFN FTWATCH,<
PUSHJ P,TTYFUW## ;SET UP F AND U
LDB J,PJOBN## ;GET CORRECT J
MOVSI T1,JW.WMT ;CHECK IF HE WANTS TO SEE IT
TDNN T1,JBTWCH##(J) ;?
>
JRST TPSTA3 ;JUST TELL OPR & DAEMON
TPSTA0: PUSHJ P,CRLF## ;PRINT CRLF
PUSHJ P,PRLBK## ;LEFT BRACKET
MOVE T2,DEVNAM(P1) ;GET DEVICE NAME
PUSHJ P,PRNAME## ;RPINT IT
PUSHJ P,INLMES## ;PRINT A COLON
ASCIZ ":"
SKIPE T2,TUBRID##(P2) ;SEE IF REEL ID
PUSHJ P,PRNAME## ;YES - PRINT IT
SKIPN TUBCRD##(P2) ;READ STATS?
JRST TPSTA1 ;NO - JUMP AROUND
PUSHJ P,INLMES##
ASCIZ " READ(C/H/S) = "
MOVE T1,TUBCRD##(P2) ;CHARS READ
PUSHJ P,PRTDIG##
PUSHJ P,PRSLSH## ;SLASH
MOVE T1,TUBHRE##(P2) ;HARD READ ERRORS
PUSHJ P,PRTDIG##
PUSHJ P,PRSLSH## ;SLASH
MOVE T1,TUBSRE##(P2) ;SOFT READ ERRORS
PUSHJ P,PRTDIG##
SKIPN TUBCWR##(P2) ;ANYTHING WRITTEN ALSO
JRST TPSTA2 ;NO - FINISH UP
;;; FALLIN TPSTA1
TPSTA1: PUSHJ P,INLMES##
ASCIZ " WRITE(C/H/S) = "
MOVE T1,TUBCWR##(P2) ;CHARS WRITTEN
PUSHJ P,PRTDIG##
PUSHJ P,PRSLSH## ;SLASH
MOVE T1,TUBHWE##(P2) ;HARD WRITE ERRORS
PUSHJ P,PRTDIG##
PUSHJ P,PRSLSH## ;SLASH
MOVE T1,TUBSWE##(P2) ;SOFT WRITE ERRORS
PUSHJ P,PRTDIG##
TPSTA2: PUSHJ P,PRRBKC## ;RIGHT BRACKET
TLZ U,-1 ;RH ONLY
CAMN U,OPRLDB## ;THIS DA OPR?
JRST TPSTA4 ;YES - DONE
TPSTA3: HRRZ U,OPRLDB## ;NO - GET OPR LINE
JRST TPSTA0 ;DO OVER
TPSTA4: MOVE U,P2 ;RESTORE UDB PNTR
MOVE F,P1 ; AND DDB PNTR
PUSHJ P,TPDCPY ;COPY STATS TO SHADOW AREA
IFN FTEL,<
MOVEI T1,.ERTPS ;SET UP CODE FOR DAEMON
HRL T1,F ;SET UP DDB FOR DAEMON
PUSHJ P,DAERPT## ;PROD DAEMON
>
POP P,W ;RESTORE KDB
MOVE S,DEVIOS(F) ;RESTORE S
POPJ P, ;RETURN
;ROUTINE TO PERFORM SKIP FILE AS MULTIPLE SKIP RECORDS
TPMFSF: PUSHJ P,TPSKPS ;CALL SKIP SET
;RETURN WITH S SETUP
TRNE S,IODEND!IODERR ;SEEN EOF OR DEVICE ERROR?
POPJ P, ;RETURN
TPMFS0: MOVEI T1,MT.FSF ;GO 'ROUND AGAIN
JRST MTAP ;...
;ROUTINE TO PERFORM BACKSPACE FILE
;USES MULTIPLE BACKSPACE RECORDS UNTIL BOT OR EOF IS SEEN
TPMBSF: PUSHJ P,TPSKPS ;CALL SKIP SET
;RETURN WITH S SETUP
TRNE S,IODEND!IOBOT!IODERR
POPJ P, ;RETURN
MOVEI T1,MT.BSF ;CALL BACKSPACE AGAIN
JRST MTAP ;SKIP SOME MORE
;ROUTINE CALLED TO SET UP MULTIPLE SKIPPING OPERATION
;RETURN S WITH STATUS OF OUTCOME
TPSKPS: HRRZ T1,-1(P) ;HAVE WE JUST BEEN HERE?
CAIE T1,TPSKPX+1 ; (IF SO, WE CAME THROUGH HNGSTP)
JRST TPSKP0 ;NO, CARRY ON
POP P,(P) ;YES, REMOVE LAST 2 CALLS FROM
POP P,(P) ; LIST SO AS NOT TO GET AN EPO
TPSKP0: HRRZ T1,TKBSTS##(W) ;GET QUANTUM
PUSHJ P,MTAPGO ;START OP
TPSKPW: MOVEI T1,MT.WAT ;WAIT OP CODE
TPSKPX: PUSHJ P,MTAP ;GO EXECUTE
MOVE S,DEVIOS(F) ;SET UP S
POPJ P, ;RETURN
;ROUTINE TO SKIP TO LOGICAL EOT
TPMSET: PUSHJ P,MTAPG1 ;DO BSR FIRST
PUSHJ P,TPSKPW ;WAIT
TPMST1: PUSHJ P,TPMFS0 ;FORWARD SKIP FILE
TRNE S,IODERR ;DEVICE ERROR
POPJ P, ;YES - RETURN
MOVEI T1,MT.FSR ;PLUS ONE RECORD
PUSHJ P,MTAP ;...
PUSHJ P,TPSKPW ;WAIT TILL DONE
TRNE S,IODERR ;DEVICE ERROR?
POPJ P, ;YES - RETURN
TRNN S,IODEND ;2ND EOF?
JRST TPMST1 ;NO - TRY AGAIN
MOVEI T1,MT.BSR ;BACKSPACE OVER EOF
PJRST MTAP ;RETURN
SUBTTL DIAG UUO
;ROUTINE TO GET CONTROLLER/UNIT NUMBERS
DIAMTA::HLRZ U,TDVUDB##(F) ;UNIT
HRRZ T1,TUBKDB##(U)
LDB T2,[POINT 7,TKBCSO##(T1),9]
LDB T1,PUNIT##
LDB T3,TUYKTP##
CAIE T3,K.TM2
LSH T1,3
LSH T2,2
HRL T1,T2
AOS (P)
PJRST STOTAC##
SUBTTL ERROR RECOVERY
;HERE ON TAPE UNIT HUNG FROM CLOCK1
TPMHNG: HLRZ U,TDVUDB##(F) ;GET UNIT PNTR
PUSHJ P,TAPHNG## ;INFORM LOWER LEVEL
TPMDQ: PUSHJ P,SAVE2## ;SAVE P1,P2
SKIPN P1,T1 ;SEE IF THERE WAS ONE
POPJ P, ;NO - JUST EXIT
TPMDQ1: CAIN P1,TKBERB##(W) ;CHECK FOR ERROR IORB
JRST [HRRZ P2,TRBLNK(P1) ;TRY NEXT IF IT IS
JRST TPMDQ2] ;CHECK DONE
PUSHJ P,TPMRCW ;RETURN XFER LIST IF ANY
MOVE T2,P1 ;SET FOR GIV4WD
MOVEI T1,1 ;ONE BLOCK
HRRZ P2,TRBLNK(P1) ;GET LINK
PUSHJ P,GIV4WD## ;RETURN IORB
TPMDQ2: SKIPE P1,P2 ;CHECK FOR MORE
JRST TPMDQ1 ;YES - RETURN IT
POPJ P, ;DONE - EXIT
;HERE FROM GIVRES IN ERRCON
TPFREE::MOVEI F,MT0DDB## ;ADDRS OF FIRST DDB
PUSH P,U ;SAVE U
TPFRE1: MOVE T1,DEVMOD(F) ;GET TYPE INFO
TLNN T1,DVMTA ;STILL A MTA
JRST TPFRE2 ;DONE
LDB T1,PJOBN## ;YES - GET OWNING JOB
CAMN T1,J ;BELONG TO US?
PUSHJ P,TPMHLD ;YES - GO SET ON HOLD
HLRZ F,DEVSER(F) ;LINK TO NEXT
JUMPN F,TPFRE1 ;AND CONTINUE
TPFRE2: MOVEI W,MT0KDB## ;START AT FIRST KONTROLLER
PUSH P,M
TLO M,400000
TPFRE3: PUSHJ P,TPMCM1 ;RELEASE MAINT MODE IF SET
JFCL
HRRZ W,TKBKDB##(W) ;NEXT KONTROL
JUMPN W,TPFRE3 ;TEST IT IF THERE
POP P,M
PJRST UPOPJ## ;DONE IF NONE LEFT
TPMHLD::HLRZ U,TDVUDB##(F) ;SET UP UDB PNTR
HRRZ W,TUBAKA##(U) ;AND KDB IF SELECTED
IFN FTTLAB,<
HLRZ T1,TUBDDB##(U) ;CHECK 2ND DDB
JUMPE T1,TPHLD1 ;IF NONE THEN OK
CAIE T1,(F) ;IS THIS OURS
POPJ P, ;NO - THEN EXIT
>
TPHLD1: TRNN S,IOACT ;ACTIVE?
PJRST TAPHLD## ;NO - CALL TAPSER
MOVSI T1,TUSNS## ;ELSE SET NO SCHED
IORM T1,TUBSTS##(U) ; AND WAIT FOR I/O TO CEASE
POPJ P,
;ROUTINE CALLED FROM TAPSER WHEN KONTROLLER IS FOUND OFF-LINE
TPMOFL::MOVSI T1,TKSSIL## ;BIT FOR SILENCE
TDNN T1,TKBSTS##(W) ;WANT TO HEAR?
SKIPGE DEBUGF## ; FOR ANY REASON
POPJ P, ; DEBUG MODE OR SILENCED
PUSHJ P,SAVE2## ;SAVE P1,P2
MOVE P1,U ;UDB ADDRS TO P1
MOVE P2,W ;KDB ADDRS TO P2
HRRZ U,OPRLDB## ;GET OPR ADDRS TO SEND MSG
PUSHJ P,INLMES## ;NOW INFORM HIM
ASCIZ "
%% TAPE CONTROLLER "
MOVE T2,TKBNAM##(P2) ;NAME
ADD T2,['A'-'0',,0]
PUSHJ P,PRNAME## ;PRINT IT
PUSHJ P,INLMES## ;REST OF MSG
ASCIZ " IS OFF-LINE
"
MOVE U,P1 ;RESTORE STUFF
MOVE W,P2 ;...
POPJ P, ;RETURN
;ROUTINE TO SET SILENCE IF C(T1) IS A TAPE KONTROLLER
;CALL: MOVE T1,<KONTROLLER ID>
; PUSHJ P,TPMSIL
; RETURN HERE IF OK
; RETURN HERE TO PROCEED
;T1 - PRESERVED
TPMSIL::PUSH P,T1 ;SAVE ARG
SUB T1,['A'-'0',,0] ;ADJUST FOR CTL NAME
PUSH P,W ;SAVE W
MOVEI W,MT0KDB## ;GET FIRST KDB
TPMSLL: CAMN T1,TKBNAM##(W) ;THIS ONE?
JRST TPMSL1 ;YES - SET BIT
HRRZ W,TKBKDB##(W) ;NO - LINK TO NEXT
JUMPN W,TPMSLL ;CHECK NEXT IF IT EXISTS
POP P,W ;RESTORE W
PJRST TPOPJ1## ;SKIP RETURN
TPMSL1: MOVSI T2,TKSSIL## ;BIT TO SET IN KDB
IORM T2,TKBSTS##(W) ;...
POP P,W
PJRST TPOPJ## ;RETURN
;OUTPUT ERROR DETECTED - CHECK FOR WRITE LOCK
DMPERR: ;DUMP MODE ERRORS
OUTERR: TRNE S,IOIMPM ;WRITE LOCKED?
JRSTF @P2 ;YES - JUST RETURN
;INPUT AND SPACING ERROR
; ALSO COMMON CODE TO OUTPUT ERRORS
SPERR:
INPERR: MOVSI T1,TUSREW## ;CLR REWINDING INFO
ANDCAM T1,TUBSTS##(U) ;ON ANY ERROR
HLRZ T1,TRBSTS(P1) ;GET ERROR INFO
IFN FTTLAB,<
TLNE S,LBLNED ;NEED PROCESSING?
JRST ERRLBL ;YES - SCHEDULE
>
MOVE T4,TUBIEP##(U) ;INITIAL ERROR POINTER
ADDI T4,0(U) ;RELOCATE
HLRE T2,T4 ;-LEN OF AREA
MOVNS T2 ; +LEN
ADDI T2,-1(T4) ;LOC+N-1
HRR T3,TUBFEP##(U) ;FINAL ERROR STATUS
ADDI T3,0(U) ;RELOCATE
HRL T4,T3 ; FORM BLT WORD
BLT T4,0(T2) ;MAKE COPY FOR DAEMON
MOVE T2,TUBREC##(U) ;POSITION BEFORE LAST REC
SUBI T2,1 ;ASSUME THE TAPE MOVED
HRL T2,TUBFIL##(U) ;SAVE POSITION BEFORE ERROR IN CASE
MOVEM T2,TUBPBE##(U) ; TAPERP NOT CALLED
MOVE T2,TRBRCT(P1) ;SAVE CHAR COUNT OF REC
MOVEM T2,TUBCCR##(U) ; IN TUB FOR DAEMON
TRNE T1,RB.SOL ;OFF-LINE?
JRST ERROFL ;YES, HANDLE IT
TRNN T1,RB.SER!RB.SRE ;NON-RECOV OR RECOVERED
TRNE S,IONRCK ;USER WANT JUST TO TRY?
JRST ERRX1 ;JUST LOG ERROR & EXIT
SETZM TUBTRY##(U) ;CLEAR ATTEMPT COUNTER
IFN FT5UUO,<
MOVEI T2,DEPDER ;ERROR RETRY DISABLED?
TDNE T2,DEVSTA(F)
JRST ERRX1 ;YES, LOG AND EXIT
>
TRZ S,IOERRS ;ALL ERRORS
MOVEM S,DEVIOS(F) ;CLEAR THESE FOR NOW
PJRST TAPERP## ; AND TRY TO RECOVER
;HERE TO HANDLE UNIT OFF-LINE (FLUSH IORB AND RETURN TO UUO LEVEL
IFN FTTLAB,<
ERRLBL: MOVEI T1,LR.TM ;ASSUME TAPE MARK
DPB T1,TUYRQT ;PUT IN CORRECT REQUEST
MOVE T1,P1 ;LOC OF IORB
LDB T1,PRBFCN## ;WHAT WE'RE DOING
CAIE T1,RB.FRD ;IF A READ,
CAIN T1,RB.FRB
TLOA S,LBLEOF ; TURN ON A FUNNY BIT
JRST ERROF1 ; AND CLEAR IODEND SO AS NOT
TRZA S,IODEND ; TO CONFUSE UUOCON
>
ERROFL: TLO S,OFFLIN ;SET OFF-LINE IN DEVIOS
IFN FTEL,<
TRNN T1,RB.SMO ;MONITOR DIRECTED OFF-LINE ?
JRST ERROF1 ;NO -
MOVSI T1,(1B1) ;MDO IS UNRECOVERABLE
IORM T1,TUBTRY##(U) ;
MOVEI T1,.ERTAP ;INDICATE TAPE ERROR
HRL T1,F ;WITH DDB
PUSHJ P,DAEERR## ;GO TELL DAEMON
>
ERROF1: PUSHJ P,TPMRCW ;RETURN XFER LIST IF ANY
PUSHJ P,TPMRIO ;RETURN IORB
HLLZS TKBSTS##(W) ;SET QUANTA TO ZERO
PJRST DEVERR## ;SET ERROR AND RETURN
;HERE WHEN TAPSER EITHER GAVE UP OR RECOVERED THE ERROR
ERRX1: TRNE T1,RB.SRE ;RECOVERED?
JRST ERRX2 ;YES - REPORT IF NECESSARY
TLNE S,IO ;CHECK INPUT/OUTPUT
AOSA TUBHWE##(U) ;HARD WRITE ERROR
AOS TUBHRE##(U) ;HARD READ ERROR
MOVSI T1,(1B1) ;FLAG FOR DAEMON
IORM T1,TUBTRY##(U) ;...
JRST ERRX3 ;GO LOG IT
;HERE ON RECOVERED ERRORS - CHECK IF LOGGING STILL ON
;ALSO DON'T LOG ERRORS THAT RECOVERED ON 1 RETRY
ERRX2: TRZ S,IOERRS ;ALL ERROR FLGS
MOVEM S,DEVIOS(F) ;CLEAR ANY EXTRANEOUS BITS
TLNE S,IO ;WHICH WAY
AOSA TUBSWE##(U) ;SOFT WRITE ERROR
AOS TUBSRE##(U) ;SOFT READ ERROR
IFN FTEL,<
HRRZ T1,TUBTRY##(U) ;NO OF RETRIES
SKIPE [MTELOG##] ;LOG ALL ERRORS?
SOJLE T1,ERRX4 ;NO, GO IF WE WON ON 1ST RETRY
MOVE T1,TUBSWE##(U) ;CHECK TOTAL SOFT ERRORS
ADD T1,TUBSRE##(U)
CAILE T1,MTDAEM## ;BEYOND THRESHOLD?
JRST ERRX4 ;YES - DON'T LOG IT
ERRX3: MOVEI T1,.ERTAP ;CODE FOR DAEMON
HRL T1,F ;SET UP DDB ADDR FOR DAEMON
PUSHJ P,DAEERR ;LOG IT
ERRX4:>
IFE FTEL,<ERRX3:>
TRNE S,IODERR
AOS TUBTDE##(U) ;TOTAL DEVICE ERRORS
TRNE S,IODTER
AOS TUBTME##(U) ;TOTAL MEDIA ERRORS
JRSTF @P2 ;RETURN
SUBTTL UTILITY ROUTINES
;ROUTINE TO RELOCATE I/O BUFFER ADDRS
;CALL:; PUSHJ P,TPMXCI, OR TPMXCO
; <INSTR TO EXECUTE W/ T1 RELOCATED>
; RETURN HERE WITH T1 ALREADY RELOCATED
;ALL ACS EXCEPT T1 ARE PRESERVED
;INSTR MUST NOT REFERENCE P1-P4
TPMXCO: SKIPA T1,DEVOAD(F) ;USE OUTPUT BUFFER
TPMXCI: MOVE T1,DEVIAD(F) ;USE INPUT BUFFER
IFN FTKI10!FTKL10,<
PUSHJ P,SAVE2## ;SAVE P1-P2
MOVE P2,@-3(P) ;GET INSTR TO XCT
MOVE P1,DEVTYP(F) ;SEE WHAT WE HAVE
TRNN P1,DEPEVM ;SKIP IF NOT TM10A
MOVEI T1,@T1 ;RELOCATE KA STYLE
CONSZ PI,II.IPA ;SKIP IF AT UUO LEVEL
PUSHJ P,SVEUF## ;ELSE - SET UP UBR
TRNN P1,DEPEVM ;SKIP IF NO TM10A
TLZ P2,(<17B12>) ;CLEAR AC FIELD
XCT P2 ;CLANK INSTR
>
IFN FTKA10,<
MOVEI T1,@T1 ;RELOCATE
XCT @0(P) ;XCT
>
JRST CPOPJ1## ;RETURN & SKIP OVER INSTR
;ROUTINE TO GENERATE A PENDING IORB
;CALL: MOVE P2,FUNCTION
; PUSHJ P,GENIOR
; ... ERROR IF NO FREE SPACE
; RETURN HERE T1 := IORB
GENIOR: MOVEI T2,1 ;ONLY WANT ONE
PUSHJ P,GET4WD## ;GET 4 WORDS
POPJ P, ;SIGH
MOVEI T2,RB.RPN ;REQUEST PENDING
ROT T2,-RB.RQP-1 ;PUT IN PROPER PLACE
MOVEM T2,TRBLNK(T1) ;STASH
GNIOR1: DPB P2,PRBFCN## ;AND FUNCTION
LDB T2,TDYBYT ;GET MODE/PAR/DEN
DPB T2,PRBBYT## ;SET INTO IORB
SETZM TRBSTS(T1) ;CLEAR REST OF BLOCK
SETZM TRBRCT(T1)
SETZM TRBIVA(T1) ;...
JRST CPOPJ1## ;GIVE GOOD RETURN
;ROUTINE TO SET UP CURRENT IORB
STOIOR: ROT T2,-RB.RQP-1 ;POSITION STATUS
HLLM T2,TRBLNK(T1) ;STORE IN LHS
JRST GNIOR1 ;CONTINUE SETUP
;ROUTINE TO WAIT FOR TAPE KONTROLLER
KONWAT: MOVSI T1,TKSOFL## ;IF UNIT IS OFF-LINE
TDNN T1,TUBSTS##(U) ; DONT CALL MSEEP
PUSHJ P,CKREW ;CHECK FOR REWINDING
JRST KONWTN ;NOW SEE IF SELECTED
KONWT1: PUSHJ P,TAPCNT## ;MAKE SURE SCHED IS LISTENING
MOVEI T1,EV.TKW ;WAIT FOR TAPE KONTROLLER
PUSHJ P,KSLEEP ;WAIT FOR EVENT
;RETURN WHEN READY
KONWTN: MOVSI T1,TKSSEL## ;SEE IF WE GOT ONE
TDNN T1,TUBSTS##(U) ;??
JRST KONWT1 ;NOPE - TRY AGAIN
HRRZ P1,TUBQUE##(U) ;SET P1 TO POINT TO IORB
CAME P1,TDVIOR##(F) ;THIS THE RIGHT ONE?
JRST KONWT2 ;NO - SNOOZE SOME MORE
HRRZ W,TUBAKA##(U) ;SET UP W - KDB ADDRS
SETZM TDVIOR##(F) ;CLEAR THIS ONE NOW
POPJ P, ;RETURN
KONWT2: SKIPE TRBIVA(P1) ;IS THIS A "REAL" IORB?
JRST KONWT1 ;YES, REST ASSURED THAT SOMETHING WILL HAPPEN
PUSHJ P,TAPREM## ;NO, ITS AN IORB WHICH WILL NEVER BE USED
JRST KONWTN ; SO FLUSH IT AND TRY THE NEXT IORB
;ROUTINE TO WAIT FOR DRIVE TO FINISH REWINDING
CKREW: MOVSI T2,TUSREW## ;CHECK FOR REWIND
TDNN T2,TUBSTS##(U) ;...
POPJ P, ;NOPE - RETURN
PUSH P,TDVIOR##(F) ;SAVE IORB PNTR
CKREW1: MOVEI T1,TUCIRD## ;SEE IF THIS UNIT
TDNE T1,TUBCNF##(U) ; WILL GIVE US AN INTERUPT
JRST CKREW2 ;WHEN IT FINISHES REWINDING
MOVSI T1,TKSSTD## ;NO - UNIT ALREADY ACTIVE?
TDNE T1,TUBSTS##(U) ;...
JRST CKREW2 ;YES - HAVEN'T STARTED REWINDING YET
MOVEI P2,RB.FYB ;QUE UP WAIT REQUEST
PUSHJ P,GENIOR ;GEN IORB
JRST CKREW2 ;WAIT AND TRY AGAIN
MOVEM T1,TDVIOR##(F) ;STASH AWAY
PUSHJ P,TAPRQH## ;PUT AT HEAD OF Q
PUSHJ P,KONWTN ;WAIT FOR SELECTION
;RETURN P1 := IORB
MOVEI T1,CKREWD ;GO HERE ON INTERUPT
HRRM T1,TRBIVA(P1) ;...
PUSHJ P,TPSTRT ;GO START I/O?
MOVEI T1,EV.REW ;WAIT FOR REWIND STATUS
PUSHJ P,MSLEEP ;...
;FALL INTO CKREW2
;PREVIOUS PAGE FALLS INTO THIS
CKREW2: MOVSI T2,TUSREW## ;SEE IF STILL REWINDING
TDNN T2,TUBSTS##(U) ;...
JRST NOREW ;NO MORE
PUSHJ P,TAPHLD## ;DON'T USE US WHILE SPEEPING
MOVEI T1,2 ;SLEEP 2 SEC
PUSHJ P,TSLEEP ;ZZZZ
PUSHJ P,TAPCNT## ;OK - START LOOKING AGAIN
JRST CKREW1 ;CHECK SOME MORE
;HERE WHEN NOT REWINDING
NOREW: POP P,TDVIOR##(F) ;RESTORE WORLD
POPJ P, ;RETURN
;HERE ON STATUS INTERUPT
CKREWD: MOVE T1,J ;JOB #
PUSHJ P,EWAKE## ;WAKE IT
MOVE S,DEVIOS(F) ;SET UP S
PJRST TPMSTP ;SHUT DOWN CTL
;ROUTINE TO SET UP INTERESTING ACS
;SET UP - U,J
SETACS: HLRZ U,TDVUDB##(F) ;GET UNIT PNTR
HRRM F,TUBCUR##(U) ;LINK UDB TO CURRENT DDB
LDB J,PJOBN## ;GET JOB OWNING DDB
POPJ P, ;AND RETURN
;SPECIAL ROUTINE USED BY NON-IO REQUESTS
PIOSET: PUSHJ P,SETACS ;SET UP ACS
MOVE S,DEVIOS(F)
JUMPE J,CPOPJ## ;EXIT NOW IF NOBODY THERE
JRST IOSET0 ;CONTINUE OPERATION
;ROUTINE TO SLEEP,RESTORE S
TSLEE1: MOVEI T1,1 ;SLEEP 1 SEC
TSLEEP: MOVE J,.C0JOB## ;SET UP J FOR SLEEP
IFN FTPSCD,<
AOS %MTASL## ;COUNT MTA GENERATED SLEEP
>;END IFN FTPSCD
PUSH P,F
PUSHJ P,SLEEP##
POP P,F
MOVE S,DEVIOS(F) ;NEW UNIT STATE
POPJ P,
;SETUP ROUTINES FOR INPUT AND OUTPUT
INSET: TLZA S,IO
OUTSET: TLO S,IO
IOSET: PUSHJ P,SETACS ;GET GOOD THINGS
JUMPE J,CPOPJ## ;RETURN IF NO OWNER
IFN FTTLAB,<
PUSHJ P,LBLSLP ;WAIT FOR LABEL PROCESS TO FINISH
PUSHJ P,LBLCKS ;DETERMINE IF PROCESSING NEEDED
JFCL ;IGNORE THIS RETURN
>
HRRZ W,TUBKDB##(U)
MOVSI T1,TKSOFL## ;IF KONTROLLER ISN'T OK
TLZE S,OFFLIN ;OFFLINE IN DEVIOS?
TDNN T1,TUBSTS##(U) ;OFFLINE IN RUBSTS?
TDNE T1,TKBSTS##(W) ;NO. KONT OFFLINE?
JRST SETOFL ;YES. INDICATE IT.
IFN FTTLAB,<
MOVEI T1,FINP!LBLNED ;ASSUME INPUT
TLNE S,IO ;IS IT?
MOVEI T1,FOUT!LBLNED ;NO, CHECK OUTPUT
TLNE S,(T1) ;PROCESSING NEEDED?
JRST SETLBL ;YES, INVOKE LBL PCS
>
IOSET0: TLZ S,OFLUNH ;CLR THIS
LDB T1,TDYMOD ;SEE IF WE HAVE A MODE
JUMPN T1,IOSET1 ;JUMP IF MODE SET
MOVEI T1,RB.MCD ;DEFAULT TO 4.5 BYTE MODE
LDB T2,PIOMOD## ;GET MODE
CAIN T2,BYTMOD ;BYTE MODE
MOVEI T1,RB.MBY ;YES
MOVEI T2,TUC7TK## ;UNLESS 7 TRACK
TDNE T2,TUBCNF##(U) ;??
MOVEI T1,RB.M7T ;THEN USE 7-TRACK MODE
DPB T1,TDYMOD ;PUT IT BACK
IOSET1: CAIE T1,RB.M7T ;SEE IF 7 TRACK
JRST IOSET2 ;NO - DON'T PLAY WITH PARITY
MOVSI T1,D.EPAR ;GET BIT
ANDCAM T1,TDVSTS##(F)
TRNE S,IOPAR ;WANT EVEN OR ODD PARITY?
IORM T1,TDVSTS##(F)
IOSET2: PUSHJ P,GETDEN ;GET CORRECT DENSITY
DPB T1,TDYDEN ;STORE IN DDB
PJRST STOIOS## ;RETURN
;HANDLE OFF LINE MESSAGES AND CLEAR ERRORS FOR RE-TRY
;ALSO CHECK FOR TC10C SPECIAL ACTION
SETOFL: PUSHJ P,CKTC10 ;TC10C CROCK!!!
PUSHJ P,HNGSTP## ;OUTPUT MESSAGE
PJRST IOSET ;RESET ACS AND RETURN
;TC10C CONTROLLER SPECIAL ACTION FOR OFF-LINE AT BOT
CKTC10: LDB T1,TUYKTP## ;GET KONTROLLER TYPE
CAIN T1,K.TC1 ;IS IT ONE OF THOSE?
TLCE S,OFLUNH!OFFLIN ;BEEN HERE BEFORE?
JRST [TLZ S,OFFLIN ;YES, SAY OFF-LINE
JRST STOIOS##]
CKTC1A: MOVEM S,DEVIOS(F) ;REMEMBER FIRST TRY
PUSHJ P,TSLEE1 ;SLEEP FOR 1 SEC
JRST CPOPJ1## ;TRY AGAIN - IT MIGHT BE BACK
IFN FTTLAB,<
;ROUTINE TO CHECK TAPE LABEL STATUS AND FIRST OPERATION
;SKIP RETURN IF NO PROCESSING TO BE DONE
LBLCHK: TLZE S,IOBEG ;CHECK FOR FIRST I/O
TLO S,FSTOP ;AND SET THIS ONE
LBLCK1: HLRZ T1,TUBDDB##(U) ;GET 2ND DDB
CAIN T1,(F) ;OURS?
JRST LBLCK2 ;YES - NO LABELING THEN
SKIPN %SITLP## ;SKIP IF OK TO SEND
JRST LBLCK2 ;NO PROCESSING
LDB T1,TUYLTP ;GET LABEL TYPE
JUMPE T1,LBLCK2 ;IF NO LABELS, CLEAR SOME FLAGS
TDZ S,[IOSTBL!LBLEOF,,IODEND] ;DON'T LET THIS GUY SEE EOF OR TROUBLE
JRST STOIOS## ;EXIT IF LABELS EXPECTED
LBLCK2: TLZ S,LBLNED!FSTOP ;ELSE CLEAR THESE FLAGS
MOVEM S,DEVIOS(F) ;...
JRST CPOPJ1## ;SKIP RETURN
>
IFN FTTLAB,<
;ROUTINE TO INVOKE LABELING PROCESS AND SUSPEND JOB
LBLMSG: PUSHJ P,TAPHLD## ;SUSPEND UNIT FOR NOW
TLZ S,LBLNED ;CLEAR THIS NOW
PUSHJ P,LBLSND ;INFORM LBL PCS
TLO S,LBLWAT ;WE ARE NOW WAITING FOR COMPLETION
MOVEM S,DEVIOS(F)
PUSHJ P,LBLSLP ;WAIT FOR LABEL PROCESS
LDB T1,PDVESE## ;GET TERMINATION CODE
JUMPE T1,CPOPJ## ;NONE - CONTINUE
TDO S,LBLETB(T1) ;GET ERROR BITS FROM TABLE
JRST STOIOS## ;SAVE S AND RETURN
;ROUTINE TO SEND IPCF MSG TO LBL PROCESS
LBLSND: MOVE T1,DEVNAM(F) ;YES - BUILD MSG
MOVEM T1,TUBPHY##(U) ;STORE DEVICE NAME
DPB J,TUYJBN ;STORE JOB #
MOVEI T1,%SITLP## ;PID
MOVEI T2,TUBMSG##(U) ;ADDRS OF MSG
HLL T2,TUBMSG##(U) ;MESSAGE MSGE
PJRST SENDSN## ;TRANSMIT MESSAGE AND RETURN
;ROUTINE TO FIX UP S AS IF LABEL PROCESSING HAPPENED
LBLCKS: PUSHJ P,LBLCHK ;FIRST CALL LABEL CHECK
POPJ P, ;NEED LABELLING, DO NOTHING
TLZN S,LBLEOF ;HERE FOR EOF?
JRST CPOPJ1## ;NO, JUST RETURN
TLZ S,IOSTBL ;CLEAR TROUBLE
TDO S,[LBLSTP,,IODEND] ;STOP ON LBL ERR
MOVEM S,DEVIOS(F) ;STORE STATUS
JRST CPOPJ1## ;RETURN
;ROUTINE TO WAIT FOR LABEL PROCESS TO FINISH
LBLSLP: PUSH P,T1 ;SAVE T1
LBLSL1: TLNN S,LBLWAT ;STILL WAITING?
JRST TPOPJ## ;NO, RETURN
MOVEI T1,EV.LBL ;EW CODE FOR LABELS
PUSHJ P,MSLEEP ;GO AWAY
JRST LBLSL1 ;CHECK IF REALLY DONE
;;; STILL IN FTTLAB CONDITIONAL
;ENTER HERE FROM IOSET IF LABEL PROCESSING NEEDED
SETLBL: TLNN S,FSTOP ;FIRST OPERATION?
JRST STLBL1 ;NO - PROCEED
MOVEI T1,LR.FIN ;ASSUME FIRST INPUT
TLNE S,IO ;IS IT REALLY?
SKIPA T1,[LR.FOU] ;NO, FIRST OUTPUT THEN
TLZA S,FINP ;CLEAR FIRST INPUT
TLZ S,FOUT ;CLEAR FIRST OUTPUT
DPB T1,TUYRQT ;SET REQUEST TYPE
MOVEM S,DEVIOS(F)
STLBL1: PUSHJ P,LBLMSG ;INFORM LBL PCS
TLNN S,LBLSTP
JRST IOSET ;NO ERRORS - PROCEED
POPJ P, ;ELSE RETURN UP A LEVEL
;ROUTINE TO CHECK FOR LABEL PCS HNDLING POSITION REQUESTS
LBLPOS: HLRZ U,TDVUDB##(F) ;SET UP U
DPB T1,TUYINF ;SET UP MTAPE CODE
MOVE S,DEVIOS(F) ;SET UP STATUS
LDB J,PJOBN## ;SET UP JOB #
PUSHJ P,LBLCHK ;NEED LABELING?
SKIPA T1,[LR.POS] ;YES - SET POSITION REQ.
JRST CPOPJ1## ;NO - PROCEED
DPB T1,TUYRQT ;SET REQUEST TYPE
PUSHJ P,LBLMSG ;XMIT MSG
TLZ S,LBLSTP ;NEVER NEED THIS BIT ON POSITIONING
LDB T1,PDVESE## ;GET TERMINATION CODE
CAIN T1,LE.CON ;DID HE DO ANYTHING?
AOS (P) ;NO - SKIP RETURN
PJRST STOIOS##
;TABLE TO TRANSLATE LABEL TERM CODE INTO BITS IN IOS
LBLETB: -1 ;0 - ILLEGAL
0 ;1 - CONTINUE POSITIONING
LBLSTP!FSTOP,,IODEND ;2 - RETURN EOF + CALL TAPE LABEL PCS ON NEXT IN/OUT
FSTOP!LBLSTP,,IOERRS ;3 - LABEL TYPE ERROR
FSTOP!LBLSTP,,IOERRS ;4 - HEADER LABEL ERROR
FSTOP!LBLSTP,,IOERRS ;5 - TRAILER LABER ERROR
FSTOP!LBLSTP,,IOERRS ;6 - VOLUME LABEL ERROR
FSTOP!LBLSTP,,IODERR ;7 - DEVICE ERROR
FSTOP!LBLSTP,,IODTER ;10 - DATA ERROR
FSTOP!LBLSTP,,IOERRS ;11 - WRITE LOCKED
FSTOP!LBLSTP,,IOERRS ;12 - POSITIONING ERROR
FSTOP,,IOBOT ;13 - BEGINNING OF TAPE
FSTOP!LBLSTP,,IOERRS ;14 - ILLEGAL OPERATION
FSTOP!LBLSTP,,IOERRS ;15-17 RESERVED
FSTOP!LBLSTP,,IOERRS
FSTOP!LBLSTP,,IOERRS
> ;END IFN FTTLAB
;ROUTINE TO GET CURRENT DENSITY SETTING
;RETURN DENSITY ARG IN T1
GETDEN: LDB T1,PDENS ;SEE IF CHANGED BY SETSTS
JUMPN T1,CPOPJ## ;IF YES - USE IT
LDB T1,TDYDN1 ;SEE IF CHANGED BY SET DENSITY
JUMPN T1,GETDN1 ;IF YES, TRY IT
MOVEI T1,STDENS## ;ELSE USE STANDARD
GETDN1: MOVE T2,TUBCNF##(U) ;PICK UP CONFIGURATION WORD
PUSH P,T1 ;SAVE THE DENSITY FOR A MOMENT
GETDN2: TDNE T2,DENBIT(T1) ;THIS DENSITY OK?
JRST GETDN4 ;YES
SOJG T1,GETDN2 ;NO, TRY A LOWER ONE
MOVE T1,(P) ;NO LOWER ONES ARE ANY GOOD, TRY HIGHER ONES
GETDN3: TDNN T2,DENBIT(T1) ;THIS DENSITY OK?
AOJA T1,GETDN3 ;NO, TRY A HIGHER ONE
GETDN4: POP P,(P) ;GET RID OF ORIGINAL DENSITY
POPJ P, ;AND RETURN
DENBIT=.-1 ;SAVE A WORD
TUCD20##
TUCD55##
TUCD80##
TUCD16##
TUCD62##
IFN FTKL10,<
;ROUTINE CALLED TO SWEEP CACHE UNLESS DEVICE IS A TM10A
;DESTROYS T1
TPMSWP: MOVEI T1,DEPEVM ;DOES THIS DEVICE NEED
TDNE T1,DEVTYP(F) ; EVM (TM10A IF SO)
PUSHJ P,CSDMP## ;NO, WE MUST SWEEP THE CACHE
POPJ P, ;RETURN
>
;SETUP S AND TRANSLATE ERROR BITS FOUND IN IORB
;NON-SKIP RETURN IF ERROR ENCOUNTERED
;SKIP RETURN IF ALL OK - MAYBE EXCEPTION
SETIOS: MOVE S,DEVIOS(F) ;GET STATUS
HLRZ T1,TRBSTS(P1) ;GET IORB STATUS
IFN FTTLAB,< TDZ S,[LBLNED!FSTOP!IOEND!IOSTBL!LBLEOF,,IOBOT!IOTEND!IODEND!IOERRS]>
IFE FTTLAB,< TDZ S,[IOEND!IOSTBL,,IOBOT!IOTEND!IODEND!IOERRS]>
;CLEAR ALL RELATED BITS
SKIPL TRBLNK(P1) ;ANY EXCEPTIONS?
JRST SETIOX ;NO - JUST STORE AND EXIT
TRNE T1,RB.SOL ;CHECK OFF-LINE
PJRST STOIOS## ;YES - HANDLE SPECIAL
TRNN T1,RB.SED ;ANY ERROR
JRST SETS1 ;NO - LOOK FOR OTHER STUFF
TRO S,IODTER ;ASSUME DATA ERROR
TRNN T1,RB.SDE ;IS IT DEVICE?
TRC S,IODTER!IODERR ;YES - CLEAR DATA/SET DEVICE
SETS1: TRNE T1,RB.STM ;TAPE MARK SEEN
IFN FTTLAB,< TDO S,[LBLNED,,IODEND] ;YES - SAY EOF>
IFE FTTLAB,< TRO S,IODEND ;YES - SET EOF>
TRNE T1,RB.SBT ;BOT SEEN
TRO S,IOBOT ;MARK IT
TRNE T1,RB.SET ;TAPE INDICATE
TRO S,IOTEND ;SET EOT
TRNE T1,RB.STL ;READ ENUF?
TRO S,IOBKTL ;SET BLOCK TOO LARGE
TRNE T1,RB.SLK!RB.SIL ;ATTEMPT TO WRITE W/O WRITE RING
TRO S,IOIMPM ;IMPROPER MODE
IFN FTTLAB,<
LDB T1,TUYLTP ;GET LABEL TYPE
SKIPE %SITLP## ;IS THERE A TAPE LABEL PROCESS?
SKIPN T1 ;BYPASS?
TLZ S,LBLNED ;YES - CLEAR BIT
TDNN S,[LBLNED,,IOERRS] ;NON-SKIP IF ANY
>
IFE FTTLAB,<
TRNN S,IOERRS ;NON-SKIP IF ANY
>
SETIOX: AOS 0(P) ;SET FOR SKIP RETURN
PJRST STOIOS## ;STASH IOS AND EXIT
;ROUTINE TO GENERATE I/O XFER LIST FROM IOWD
;CALL: MOVE T2,IOWD
; MOVE T4,NUMBER OF BYTES
; PUSHJ P,MAKLST
; ... RETURN HERE IF NO ROOM
; RETURN HERE IF OK
MAKLST: PUSHJ P,SAVE4## ;SAVE WORLD
MOVE P1,T2 ;COPY UNRELOCATED IOWD
IFN FTKI10!FTKL10,<
PUSHJ P,SVEUF## ;MAKE JOB ADDRESSABLE
MOVEI P2,DEPEVM ;CHECK FOR TM10A
TDNN P2,DEVTYP(F) ;SKIP IF IT IS
JRST MAKLS0
ADDI T2,0(R)
HLL T2,P1
>
MAKLS0: MOVEM P1,TRBRCT(T1) ;SAVE NUMBER OF WORDS, UVA IN IORB (FOR TM2KON)
LDB P4,PRBMOD## ;GET MODE
MOVE P4,TMODTB##(P4) ;CHARS/WD TABLE (4,5,6)
LDB T1,PBUFRM## ;MAX FRAME COUNT USER GAVE
SKIPE T1
CAMLE T1,T4
MOVE T1,T4
HRL P4,T1 ;IN LH (P4)
IFN FTDX10,<
IFN FT5UUO,<
MOVEI T1,DEPDER ;ERROR RETRY ENABLED?
TDNN T1,DEVSTA(F)
>
TDNE S,[MTSNAR,,IONRCK]
TLOA S,IOSRTY ;NO, DON'T LET DX10 RETRY
TLZ S,IOSRTY ;YES, TELL DX TO RETRY
>
HRRZ P3,TKBCDB##(W) ;ADDRS OF CHNCB
HRRZ T1,TUBQUE##(U) ; RESTORE LOC OF IORB
IFN FTKI10!FTKL10,<
MOVEI P2,DEPEVM
TDNN P2,DEVTYP(F) ;SKIP IF OTHER THAN TM10A
JRST MAKLS1 ;TRY KA10 STYLE
MOVEI P1,0 ;INIT CALL TO MAPIOW
PUSHJ P,MAPIO## ;MASSAGE IOWD
POPJ P, ;ERROR - NO FREE SPACE
IFN FTDX10,< ;THIS ONLY WORKS FOR TU70'S
;MAKE MULTI-IOWD LIST IF TU70
MOVEI T4,1 ;AT LEAST ONE RECORD WILL BE DONE
MOVEM T4,TKBCNT##(W)
TRNE S,IOCON ;DISCONTINUOUS MODE?
JRST CHNDON ;YES, DONE
MOVE T4,TKBDSP##(W) ;DOES DEVICE SUPPORT COMMAND CHAINING?
SKIPN TUBCNI##(U) ; AND NO ERRORS DETECTED ON LAST XFER?
SKIPL TPKCMD##(T4)
JRST CHNDON ;NO, ONLY DO 1 RECORD
LDB T4,PRBFCN## ;YES, IS IT BUFFERRED MODE,
LDB T2,PIOMOD## ; AND NOT READ-BACKWARD?
CAIE T4,RB.FRB
CAIL T2,SD
JRST CHNDON ;NO, ONLY 1 RECORD
HRRZ T4,DEVIAD(F) ;YES, GET BUFFER LOC
TLNE S,IO
HRRZ T4,DEVOAD(F)
MOVE T3,T4 ;START AT THAT BUFFERS SUCCESSOR
HRL P2,T1 ;SAVE LOC OF IORB IN P2 (FOR TPKCMD)
;STILL IN FTDX10 CONDITIONAL
CHNLS1: EXCTUX <HRRZ T1,(T3)> ;STEP TO NEXT BUF
CAIN T4,(T1) ;BACK WHERE WE STARTED?
JRST CHNDON ;YES, DONE
PUSHJ P,IADRCK## ;WORD 0 OF BUFFER THERE?
JRST CHNDON ;NO, DONE
EXCTUX <HLL T1,(T1)> ;YES, GET LH OF THE BUFFER
TLNN S,IO ;IF READING,
JUMPL T1,CHNDON ; DONE IF THE USE BIT IS ON
TLNE S,IO ;IF WRITING,
JUMPGE T1,CHNDON ;DONE IF THE USE BIT IS OFF
MOVE T2,TKBDSP##(W) ;WE HAVE A RECORD TO WRITE
PUSHJ P,@TPKCMD##(T2) ;GO SET UP THE DEVICE-COMMAND
JRST CHNDON ;NO ROOM FOR IT IN FREE CORE
TLNE S,IO ;READING?
JRST CHNLS2 ;NO
LDB T2,[POINT 17,T1,17] ;YES, GET MAX SIZE OF BUFFER
MOVNI T2,-1(T2) ;-SIZE
JUMPGE T2,CHNLSX ;DONE IF SIZE WRONG
JRST CHNLS4 ;OK, CONTINUE
CHNLS2: EXCTUX <MOVN T2,1(T1)>;WRITING, GET USERS WRDCNT
JUMPE T2,CHNLSX ;DONE IF 0
LDB T3,PIOMOD##
CAIE T3,BYTMOD
JRST CHNLS4
PUSH P,T1
HRRE T1,TUBQUE##(U)
LDB T3,PRBMOD##
MOVNS T2
LDB T1,PBUFRM##
JUMPE T1,CHNLS3
CAMGE T1,T2
MOVE T2,T1
CHNLS3: HRL P4,T2
POP P,T1
IDIV T2,TMODTB##(T3)
SKIPE T3
ADDI T2,1
MOVNS T2
CHNLS4:
HRRZS T3,T1 ;SAVE START ADR
HRL T3,T2 ; AND WORDCOUNT
IFN FTVM,<
MOVEI T1,-1(T1) ;MAKE SURE ENTIRE BUFFER, PLUS S-WORD
MOVNS T2 ; IS IN CORE
ADDI T2,2(T1) ;TOP OF BUFFER
PUSHJ P,ZRNGE## ;ALL THERE?
JRST CHNLSX ;NO, FORGET ABOUT THIS BUFFER
>
IFE FTVM,<
SUB T1,T2 ;TOP OF BUFFER
PUSHJ P,IADRCK## ;TOP OF BUFFER THERE?
JRST CHNLSX ;NO
>
MOVE T2,T3 ;IOWD
ADDI T2,1(R) ;RELOCATE IT
HLL T2,T3 ;IN CASE OF OVERFLOW OF ADDRESS
PUSH P,P1 ;SAVE CURRENT END
PUSHJ P,MAPIO## ;GO MAP IT
JRST CHNPNT ;NOT ENOUGH FREE CORE
POP P,(P) ;DISCARD PREVIOUS END
AOS TKBCNT##(W) ;ONE MORE RECORD IN THIS XFER
JRST CHNLS1 ;GO TEST NEXT BUFFER
;STILL IN FTDX10 CONDITIONAL
;HERE WHEN MAPIO RAN OUT OF ROOM
CHNPNT: SETZM (P1) ;SO RTNIOW WILL KNOW WHEN TO STOP
POP P,P1 ;RESTORE LOC OF LAST DEVICE COMMAND
;HERE ON BAD WRDCNT, THE DEVICE COMMAND IS ALREADY IN THE LIST
CHNLSX: SUBI P1,1 ;BACK UP OVER DEVICE COMMAND
SETZM (P1) ;CLEAR IT
CHNDON:> ;END FTDX10
MOVE P3,P1 ;SAVE PNTR TO NEXT WORD
> ;END IFN FTKI10!FTKL10
IFN FTKA10,<
JRST MAKLS1
>
MAKLSX:
IFN FTKI10!FTKL10,<
MOVE T1,-6(P)
>
IFE FTKI10!FTKL10,<
MOVE T1,-4(P) ;IORB TO T1
>
HRRM P2,TRBXCW(T1) ;STORE EVA OF IOLIST
HRLM P3,TRBEXL(T1) ;POINT TO LAST WORD OF XFER LIST
IFN FTRDBACK,<
LDB T2,PRBFCN## ;GET FCN
CAIN T2,RB.FRB ;READ BACKWARDS?
JRST INVERT ;YES - INVERT XFER LIST
>
JRST CPOPJ1## ;NO - RETURN
MAKLS1: PUSH P,T2 ;SAVE IOWD
IFN FTKI10!FTKL10,<
PUSHJ P,GCH4WD## ;GET BLOCK OF STORAGE
JRST T2POPJ## ;ERROR RETURN
>
IFN FTKA10,<
MOVEI T2,1 ;GET 4 WORDS
PUSHJ P,GET4WD##
JRST T2POPJ## ;SORRY FOLKS
>
MOVE P2,T1 ;SAVE IN P2
SETZM 3(T1) ;CLEAR LAST WORD
POP P,0(T1) ;STORE IOWD
SETZM 1(T1) ;TERMINATE LIST
MOVEI P3,1(T1) ;ADDRS OF END OF LIST
JRST MAKLSX ;RETURN
IFN FTKI10!FTKL10,<
;HERE WHEN MAPIO LOST - RETURN ANY PARTIAL STUFF
MAKLSF: MOVE P1,-6(P)
HRRZ T1,TRBXCW(P1) ;PARTIAL LIST
PUSHJ P,RTNIOW## ;RETURN IT
MAKLSE: SKIPE T1,P2 ;ANYTHING ALLOCATED
PUSHJ P,RTNIOW## ;YES - RETURN IT
POPJ P, ;GIVE ERROR RETURN
>
;ENTER HERE FOR DUMP MODE IOLISTS
MAKLSD: PUSHJ P,SAVE4## ;SAVE P1-P4
MOVE P1,T2
SUBI P1,(R)
HLL P1,T2
IFN FTKI10!FTKL10,<
PUSHJ P,SVEUF##
>
PJRST MAKLS0 ;CONTINUE PROCESSING
;HERE TO WAIT FOR A KONTROLLER
KSLEEP: SKIPA T3,[FSLEEP##] ;LIKELY THAT EVENT WILL HAPPEN SOON
;HERE TO GO INTO EVENT WAIT
MSLEEP: MOVEI T3,ESLEEP## ;LONG TIME UNTIL THE EVENT
IFN FTKI10!FTKL10,<
MOVEI T2,IOACT ;CHECK FOR IOACTIVE
TDNN T2,DEVIOS(F) ;DON'T RETURN EVM IF SO
PUSHJ P,RTEVM## ;RETURN ANY EVM WHICH WE MAY HAVE
; SINCE WE MIGHT GET SWAPPED
; WHILE SLEEPING
>
PUSHJ P,(T3) ;WAIT FOR EVENT
MOVE S,DEVIOS(F) ;NEW STATE OF UNIT
POPJ P,
IFN FTRDBACK,<
;ROUTINE TO GENERATE XFER LIST FOR READ BACKWARDS
;ENTER WITH P2 := FORWARD XFER LIST
; T1 := IORB ADDRS
; P4 := CHARS/WD
IFN FTKI10!FTKL10,<
INVERT: LDB T2,TUYKTP## ;UNIT TYPE
CAIE T2,K.TX1 ;TX01?
PJRST CPOPJ1## ;NO, LEAVE THE LNT ALONE
MOVEI P3,0 ;INIT CNTR OF IOWDS
MOVE P1,T1 ;IORB ADDRESS
MOVE T2,P2 ;COPY LIST HEAD
INVL1: MOVE T1,0(T2) ;IOWD
JUMPE T1,INVD1 ;DONE IF ZERO
JUMPG T1,[MOVE T2,T1 ;PERFORM XFER
JRST INVL1] ;CONTINUE
ADDI P3,1 ;INCR COUNTER
AOJA T2,INVL1 ;AND LOOK AT NEXT
INVD1: PUSHJ P,GCH4WD## ;GET SOME STORAGE
JRST MAKLSE ;LOSE
HRRM T1,TRBXCW(P1) ;SAVE THIS LIST ADDRS
MOVE P1,T1 ;COPY TO P1
HRLI P1,-3 ;MAKE AOBJN PNTR
SETZM 0(P1) ;GRNTEE ZERO AT END
INVL2: MOVE T2,P2 ;HEAD OF OLD LIST
MOVE T3,P3 ;ITEM # TO FIND
INVL3: SKIPN T1,0(T2) ;LOOK FOR END
STOPCD MAKLSF,DEBUG,BFO, ;++BETTER FIND ONE
JUMPG T1,[MOVE T2,T1 ;LINK TO NEXT
JRST INVL3] ;AND PROCEED
SOJLE T3,INVD2 ;DONE WHEN T3 GOES TO ZERO
AOJA T2,INVL3 ;LOOK FOR MOVE
INVD2: HLRE T3,T1 ;GET LH
ASH T3,-4 ;ADJUST
MOVNS T3 ;POSITIVE
IDIVI T3,(P4) ;MAKE INTO WORDS
ADDI T1,-1(T3) ;ADJUST IOWD TO BUFFER END
MOVEM T1,0(P1) ;STORE IN NEW LIST
SOJLE P3,INVD3 ;DONE IF NO MORE
AOBJN P1,INVL2 ;NO - DO MORE
PUSHJ P,INVMOR ;NEED MORE STORAGE
PJRST MAKLSF ;RETURN TRASH AND LOSE
JRST INVL2 ;TRY AGAIN
INVD3: AOBJN P1,.+1 ;POINT TO END OF LIST
SETZM 0(P1) ;GRNTEE ZERO
IFN FTDX10,<
MOVE T1,-6(P)
>
IFE FTDX10,<
MOVE T1,-4(P) ;RESTORE IORB
>
HRLM P1,TRBEXL(T1) ;SAVE NEW LIST END
MOVE T1,P2 ;NOW RETURN OLD LIST
PUSHJ P,RTNIOW##
PJRST CPOPJ1## ;GIVE GOOD RETURN
>
IFN FTKA10,<
INVERT: MOVEI T2,P2 ;RETURN IOWDS
MOVEI T1,1 ;...
PJRST GIV4WD## ;AND GIVE ERROR
>
INVMOR: PUSH P,U ;SAVE U
MOVEI U,0 ;CAUSE GETMOR TESTS U
PUSHJ P,GETMOR## ; TO SET RH20 GOTO WORDS
SOS -1(P) ;LOSE
JRST UPOPJ1## ;RETURN
> ;;; END IFN FTRDBACK
;ROUTINE TO SET UP CORRECT READ OP
SETRED: MOVEI P2,RB.FRD ;ASSUME NORMAL
MOVE T2,TDVSTS##(F) ;GET FLAGS
TLNE T2,D.NRLT ;LOW THRESHOLD?
MOVEI P2,RB.FRL ;YES - SET FCN
TLNE T2,D.RDBK ;READ BACKWARDS?
MOVEI P2,RB.FRB ;YES - USE THIS
POPJ P, ;RETURN
;ROUTINES TO SETUP ASYNCHRONOUS IORB
ASYNCO: SKIPA T2,[TPMOU1] ;OUTPUT
ASYNCI: MOVEI T2,TPMIN1 ;INPUT
HRRM T2,TRBIVA(T1) ;SAVE IN INT VECTOR
PUSH P,T1 ;SAVE IORB PNTR
PUSHJ P,CKREW ;MAKE SURE NOT REW'D
PUSHJ P,SETACT## ;MAKE (RAD)IOACTIVE
POP P,T1 ;IORB
MOVSI T2,RB.AIO ;SPECIAL IORB
IORM T2,TRBLNK(T1) ;...
CONO PI,PIOFF## ;FIGHT RACE
PUSHJ P,TAPRQT## ;QUEUE IORB, SELECT IF IDLE
MOVE T1,TUBSTS##(U)
CONO PI,PION## ;RESTORE PI
TLNN T1,TKSSEL## ;UNIT SELECTED?
POPJ P, ;NO, IT WILL HAPPEN LATER
HRRZ T1,TUBQUE##(U) ;YES, SET T1=IORB
JRST TAPAGO## ; AND GO DO IO WITH IT
IFN FTWATCH,<
;PROCESS CONTROL-T
TPMCTT::PUSHJ P,SAVE1## ;SAVE P1
HLRZ P1,TDVUDB##(F) ;UDB POINTER
PUSHJ P,INLMES##
ASCIZ " FILE "
MOVE T1,TUBFIL##(P1)
PUSHJ P,PRTDIG##
PUSHJ P,INLMES##
ASCIZ " RECORD "
SKIPL T1,TUBREC##(P1)
PJRST PRTDIG##
PUSHJ P,INLMES##
ASCIZ " ???"
POPJ P,
> ;END FTWATCH
SUBTTL TAPSER CALLED ROUTINES
;ROUTINE CALLED BY TAPSER WHEN KONTROLLER IS GRANTED
;W POINTS TO KDB, U POINTS TO UDB, T1 TO IORB
TPMSIO::HRRZ F,TUBCUR##(U) ;PNTR TO DDB
MOVSI T2,RB.AIO ;CHECK FOR SPECIAL IORBS
TDNE T2,TRBLNK(T1)
JRST TPASIO ;START THESE NOW
PUSH P,T1 ;SAVE IORB PNTR
LDB T1,PJOBN## ;JOB NO. IN T1
JUMPE T1,TPOPJ## ;NO JOB NUM.?
PUSHJ P,EWAKE## ;GET HIM UP
JRST TPOPJ## ;RETURN
;HERE TO START ASYNC I/O REQUEST
TPASIO: PUSHJ P,SVEUF## ;SET UP UPMP
MOVE S,DEVIOS(F) ;SET UP S
;;;; ;FALL INTO TPMDON
;ROUTINE CALLED BY TAPSER WHEN I/O COMPLETE
; U - UDB PNTR , W - KDB PNTR
TPMDON::PUSHJ P,SAVE2## ;SAVE P1,P2
MOVE P1,T1 ;PLACE IORB PNTR IN P1
HRRZ F,TUBCUR##(U) ;PNTR TO DDB
LDB J,PJOBN## ; J = JOB NUMBER
MOVE R,JBTADR##(J) ; R = ADDRS OF JOBDAT
LDB T1,PRBDEN## ;GET SELECTED DENSITY
DPB T1,TDYDN1 ;SAVE FOR ALL TO SEE
HRRZ T1,TRBIVA(P1) ;GET ROUTINE ADDRS
JUMPN T1,0(T1) ;DIPATCH
STOPCD .,STOP,NIV, ;++ NULL INT VECTOR ADDRS
IFN FTTLAB,<
;TAPE LABELING DDB PROTOTYPE
LPROTO:
0 ;(0) DEVNAM
<^D5*HUNGST>,,MTSIZ##+1 ;(1) DEVCHR
0 ;(2) DEVIOS
TPMDSP ;(3) DEVSER
1023,,ASSCON+154403 ;(4) DEVMOD
0 ;(5) DEVLOG
0 ;(6) DEVBUF
R,,0 ;(7) DEVIAD
R,,0 ;(10) DEVOAD
0 ;(11) DEVSTS
.TYMTA!DEPLEN,,0 ;(12) DEVSTA
0 ;(13) DEVXTR
0 ;(14) DEVEVM
0 ;(15) DEVPSI
0 ;(16) DEVJOB (6.02 AND LATER)
PHASE DEVPSI+2
0 ;(17) LH = UDB PNTR
; RH = KDB PNTR
0 ;(20) UNIT STATUS INFO
0 ;(21) IORB TO WAIT FOR
0 ;(22) SAVED USER UPPER LIMIT
0 ;(23) SAVED USER LOWER LIMIT
0 ;(24) SAVED M FOR DUMP MODE
0 ;(25) REMAINDER FOR MODE 16
TDVSVQ:! 0 ;(26) PLACE TO SAVE 'Q' FOR LABELING PCS
DEPHASE
SPROTO==.-LPROTO
>
LIT
TPMEND::! END