1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-01 01:19:17 +00:00
Files
Lars Brinkhoff 6e18f5ebef Extract files from tape images.
Some tapes could not be extracted.
2021-01-29 10:47:33 +01:00

1715 lines
55 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE TAPSER - COMMON MAGTAPE PHYSICAL IO DRIVER V1106
SUBTTL L.BOSACK/TAH/TW/DPM 27-SEPTEMBER-88
SEARCH F,S,DEVPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION
; 1974,1975,1976,1977,1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1974,1988>
XP VTAPSR,1106 ;FOR LINKEDIT MAP
SALL
TAPSER::ENTRY TAPSER
;BIT DEFINITIONS
;IN TKBSTS & TUBSTS
TKSOFL==:(1B17) ;OFFLINE
TKSSEL==:(1B16) ;SELECTED
TKSSTD==:(1B15) ;STARTED
TKSSCH==:(1B14) ;REQUESTED SCHED INTERUPT
TKSSIL==:(1B13) ;REQUEST SILENCE ABT OFF-LINE CONDITION
TKSMNT==:(1B12) ;CTL IS IN MAINT MODE
TKSCHE==(1B11) ;JOB HAS SWEPT CACHE FOR QUEUED REQUEST
TKSCHX==:(1B10) ;NOT YET SWEPT FOR (CPU0)
TKSCHA==(77B10) ;TKSCHX BITS FOR ALL CPUS
;IN TUBSTS
TUSNS==:(1B0) ;DO NOT SCHEDULE THIS UNIT (SIGN BIT)
TUSBOT==:(1B1) ;BEGINNING OF TAPE
TUSWTL==:(1B2) ;WRITE LOCKED
TUSREW==:(1B3) ;TAPE REWINDING
TUSFLT==:(1B4) ;TAPE UNIT FAULT (BROKEN DRIVE)
TUSBOF==:TUSBOT!TKSOFL
;IN TKBSTS
TKSNS==:(1B3) ;DON'T SCHEDULE THIS KONTROLLER (DIAG.)
;IN TUBCNF
TUC7TK==:1B18 ;SEVEN TRACK
TUCIRD==:1B19 ;INTERUPTS WHEN REWIND DONE
TUCDMS==:1B20 ;DIAG MODE SET
TUCSNS==:1B21 ;FORCE SENSE
;TUCD??==:1B22 ;THIS BIT LEFT FOR EXPANSION
TUCD62==:1B23 ;DRIVE CAN DO 6250 BPI
TUCD16==:1B24 ;DRIVE CAN DO 1600 BPI
TUCD80==:1B25 ;DRIVE CAN DO 800 BPI
TUCD55==:1B26 ;DRIVE CAN DO 556 BPI
TUCD20==:1B27 ;DRIVE CAN DO 200 BPI
; THE FOLLOWING SYMBOLS ARE FOR THE CONVENIENCE OF MACRO V50
TUCDR8==:TUCD20+TUCD55+TUCD80 ;TM10 9 TRACK DENSITIES
TUCDR7==:TUC7TK+TUCDR8 ;7 TRACK TAPE + DENSITIES
TUCDR6==:TUCD80+TUCD16 ;TM02 AND TU70 DENSITIES
TUCDR5==:TUCD16+TUCD62 ;TU72 DENSITIES
TUCDIG==:1B28 ;DIAG. UUO ON THIS DRIVE
TUCFOI==:1B29 ;FILE OPERATIONS ILLEGAL
;IN TUBERR
NXTLSE==:(1B0) ;NEXT TO LAST ERROR RETRY
;ERROR RECOVERY PARAMETERS
ERPNCS==5 ;NUMBER OF BACKSPACE/SPACE OP IN TAPE CLEANER SEQ.
IOSCP2==:(1B11) ;MUST BE SAME AS TKSCHE
;TAPSBF DETERMINES WHETHER REAL FILE POSITIONING IS DONE OR MULTIPLE
; SKIP/BACKSPACE RECORD OPERATIONS ARE USED TO SIMULATE FILE POSITIONING.
TAPSBF: EXP MTFILE## ;DEFAULT TO MONGEN'ED VALUE
;BYTE POINTERS
;INTO UDB
TUYKTP::POINT 4,TUBCNF(U),35 ;CONTROLLER TYPE
TUYECT: POINT ERCCTS,TUBERR(U),17 ;POINTER TO RETRY COUNTER
TUYEC1: POINT ERCCTS,TUBERR(U),17-ERCCTS ;SECONDARY RETRY COUNTER
;INTO IORB
PRBRQS:: POINT RB.RQS,TRBLNK(T1),RB.RQP ;REQUEST STATUS
PRBMOD:: POINT RB.MDS,TRBLNK(T1),RB.MDP ;REQUEST MODE
PRBMD2:: POINT RB.MDS,TRBLNK(P1),RB.MDP
PRBFCN:: POINT RB.FNS,TRBLNK(T1),RB.FNP ;REQUEST FUNCTION
PRBDEN:: POINT RB.DNS,TRBLNK(T1),RB.DNP ;DENSITY
PRBBYT:: POINT RB.BYS,TRBLNK(T1),RB.BYP ;REQUEST INFO
SUBTTL PROTOTYPE INTERRUPT ROUTINE
TAPICD::PHASE 0
IFN FTKL10,<
CONSO 000,0 ;(00) NEED SERVICE?
JRST . ;(01) TRY NEXT DEVICE ON CHAIN
TAPCNI::!CONI 000,21 ;(02) GET CONI BITS
JSR PIERR## ;(03) SAVE ACS
SKIPA W,.+1 ;(04) SETUP DATA BLOCK POINTER
EXP 0 ;(05) DATA BLOCK ADDRESS
XJRST .+1 ;(06) GO SERVICE INTERRUPT
EXP 0 ;(07) INTERRUPT HANDLER ADDRESS
EXP 0 ;(10) OLD PC FLAGS
EXP 0 ;(11) OLD PC
EXP IC.UOU ;(12) NEW PC FLAGS
EXP .+1 ;(13) NEW PC
XCT 2 ;(14) GET CONI BITS
XCT 3 ;(15) SAVE ACS
DMOVE T1,10 ;(16) COPY OLD PC DOUBLE WORD
DMOVEM T1,-1 ;(17) FAKE UP PI CHANNEL INTERRUPT
JRST 4 ;(20) GO CALL INTERRUPT HANDLER
TAPCII::!EXP -1 ;(21) CONI BITS AT INTTERUPT
> ;END FTKL10
IFN FTKS10,<
CONSO 000,0 ;(00) NEED SERVICE?
JRST . ;(01) TRY NEXT DEVICE ON CHAIN
JSR PIERR## ;(02) SAVE ACS
SKIPA W,.+1 ;(03) SETUP DATA BLOCK POINTER
EXP 0 ;(04) DATA BLOCK ADDRESS
JRST @.+1 ;(05) GO SERVICE INTERRUPT
EXP 0 ;(06) INTERRUPT HANDLER ADDRESS
EXP 0 ;(07) OLD PC FLAGS
EXP 0 ;(10) OLD PC
EXP IC.UOU ;(11) NEW PC FLAGS
EXP .+1 ;(12) NEW PC
XCT 2 ;(13) SAVE ACS
DMOVE T1,7 ;(14) COPY OLD PC DOUBLE WORD
DMOVEM T1,-1 ;(15) FAKE UP PI CHANNEL INTERRUPT
JRST 3 ;(16) GO CALL INTERRUPT HANDLER
> ;END FTKS10
DEPHASE
TAPICL==:.-TAPICD ;LENGTH OF CODE
SUBTTL AUTOCONFIGURATION
;ROUTINE TO SETUP CONI ADDRESS IN CONTROLLER'S CSO (TAPICD) BLOCK
;CALL: MOVE W, KDB ADDRESS
; PUSHJ P,TAPCSA
; <ALWAYS RETURN HERE>
;DESTROYS T1,T2
IFN FTKL10,<
TAPCSA::MOVE T1,KDBCSO(W) ;GET CSO BLOCK ADDRESS
MOVEI T2,TAPCII(T1) ;GET CONI DESTINATION ADDRESS
HRRM T2,TAPCNI(T1) ;PUT ADDRESS IN RH OF INSTRUCTION
SETZM TAPCII(T1) ;CLEAR THE CONI DESTINATION
POPJ P,
>
;ROUTINE TO DO COMMON TAPE DRIVE AUTOCONFIGURATION
;CALL: MOVE T1, PHYSICAL DRIVE #,,UDB TABLE INDEX
; MOVE T2, TUBCNF WORD
; MOVE T3, HUMG TIMER TABLE ADDRESS
; PUSHJ P,TAPDRV
; <NON-SKIP> ;NO CORE FOR UDB OR DDB
; <SKIP> ;DATA STRUCTURES CREATED AND LINKED UP
TAPDRV::PUSH P,T2 ;SAVE TUBCNF BITS
PUSH P,T3 ;SAVE HUNG TIMER TABLE ADDRESS
PUSHJ P,AUTUDB## ;BUILD A UDB
JRST TTPOPJ## ;FAILED
POP P,T1 ;GET HUNG TIMER TABLE ADDRESS
MOVE T2,-1(T1) ;GET MAXIMUM TIMEOUT VALUE
MOVEM T2,TUBMTV(U) ;SAVE INCASE NO ACCESS TO SOME PORT
DMOVE T2,0(T1) ;WORDS 0 & 1
DMOVEM T2,TUBHTT(U) ;SAVE THEM
DMOVE T2,2(T1) ;WORDS 2 & 3
DMOVEM T2,TUBHTT+2(U) ;DITTO
POP P,TUBCNF(U) ;STORE CONFIGURATION WORD
SKIPE F,UDBDDB(U) ;ALREADY HAVE A DDB?
JRST TAPDR1 ;DON'T CREATE ANOTHER
HLLZ T1,KDBNAM(W) ;GENERIC DEVICE NAME,,LOCAL DEVICE
HRR T1,P1 ;GET PHYSICAL DRIVE NUMBER
SETZ T2, ;LOCAL DEVICE
PUSHJ P,AUTDDB## ;CREATE A DDB
SKIPA T1,.CPDRV## ;NO CORE
JRST TAPDR1 ;ONWARD
MOVE T1,DRVULN(T1) ;UDB LENGTH
MOVE T2,U ;UDB ADDRESS
PJRST GIVWDS## ;RELEASE CORE AND RETURN
TAPDR1: MOVEM F,UDBDDB(U) ;LINK UDB TO DDB
MOVEM U,TDVUDB##(F) ;LINK DDB TO UDB
MOVE T1,KDBDSP(W) ;DRIVER DISPATCH
MOVEM T1,DEVDRV(F) ;SO WE CAN FIND IT GIVEN A DDB
MOVSI T1,TUBQUE(U) ;INIT QUEUE HEAD
MOVEM T1,TUBQUE(U) ; TO POINT TO EMPTY QUEUE
MOVE T1,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
MOVEI T2,KDBNUM ;STATE,,MASK WORD OFFSET
PUSHJ P,AUTMSK## ;CLEAR NEW UNIT FOR THIS DRIVE
JFCL ;CAN'T FAIL HERE
MOVE T1,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
MOVEI T2,KDBIUM ;STATE,,MASK WORD OFFSET
PUSHJ P,AUTMSK## ;CLEAR IGNORE UNIT FOR THIS DRIVE
JFCL ;CAN'T FAIL HERE
SYSPIF ;INTERLOCK
MOVSI T1,TKSNS ;DIAG BIT
TDNN T1,TKBSTS(W) ;KONTROLLER STOPPED?
TDZA T1,T1 ;NO DIAG JOB
HLRZ T1,TKBJOB(W) ;GET MAINTENANCE JOB NUMBER
SYSPIN ;RELEASE INTERLOCK
JUMPN T1,TAPDR2 ;CAN'T ATTACH IF DIAG
LDB T1,PJOBN## ;GET DDB OWNER
MOVEI T2,ASSCON ;BIT TO TEST
TDNE T2,DEVMOD(F) ;ASSIGNED TO JOB ZERO?
JUMPN T1,TAPDR2 ;NO, DON'T NEED TO ATTACH IT
PUSHJ P,DDBATT## ;MAKE SURE ATTACHED
POPJ P, ;FAILED
IFN FTMDA,<PUSHJ P,TAPMPA> ;INDICATE TAPE DRIVE ATTACHED
TAPDR2: PUSHJ P,SAVE3## ;SAVE P1-3
PUSH P,W ;SAVE W
HLLZ P1,TUBIEP(U) ;GET INITIAL ERROR POINTER LENGTH
HLLZ P2,TUBFEP(U) ;GET FINAL ERROR POINTER LENGTH
LDB P3,[POINTR KDBSTS(W),KD.MPT] ;GET OUR MAXIMUM PORT COUNT
XMOVEI T1,UDBKDB(U) ;POINT TO KDB TABLE FOR DRIVE
MOVSI T2,-MXPORT ;AOBJN POINTER
TAPDR3: SKIPE W,(T1) ;GET A KDB
CAMN W,(P) ;FOUND OURSELVES?
JRST TAPDR4 ;IGNORE IT
MOVE T3,KDBDSP(W) ;GET DISPATCH
MOVE T3,DRVUDB(T3) ;AND PROTOTYPE UDB
HLLZ T4,TUBIEP(T3) ;GET INITIAL (PROTOTYPE) ERROR POINTER
CAMLE P1,T4 ;CURRENT THE LARGER OF THE TWO?
MOVE P1,T4 ;NO--MAKE IT SO
HLLZ T4,TUBFEP(T3) ;GET FINAL (PROTOTYPE) ERROR POINTER
CAMLE P2,T4 ;CURRENT THE LARGER OF THE TWO?
MOVE P2,T4 ;NO--MAKE IT SO
LDB T3,[POINTR KDBSTS(W),KD.MPT] ;GET THIS KDB'S MAX. PORT COUNT
CAIGE T3,(P3) ;IF HIS IS BETTER,
MOVE P3,T3 ;UPDATE OUR VALUE
DPB P3,[POINTR KDBSTS(W),KD.MPT] ;SAVE POSSIBLY UPDATED VALUE IN KDB
TAPDR4: AOS T1 ;ADVANCE POINTER
AOBJN T2,TAPDR3 ;LOOP FOR ALL KDBS
HLLM P1,TUBIEP(U) ;UPDATE INITIAL ERROR POINTER
HLLM P2,TUBFEP(U) ;UPDATE FINAL ERROR POINTER
POP P,W ;RESTORE OUR KDB ADDRESS
DPB P3,[POINTR KDBSTS(W),KD.MPT] ;SAVE BEST VALUE IN OUR KDB
JRST CPOPJ1## ;RETURN SUCCESS
IFN FTMDA,<
;SEND A DEVICE ATTACHED MESSAGE TO [SYSTEM]MDA
TAPMPA::MOVE T1,UDBNAM(U) ;PRIMARY PORT NAME
SETZ T2, ;NO SECONDARY PORT NAME
PJRST ATTMPA## ;INFORM [SYSTEM]MDA
;SEND A DEVICE DETACHED MESSAGE TO [SYSTEM]MDA
TAPMPD::SETZ T1, ;NO NEW PRIMARY PORT NAME
PJRST DETMPA## ;INFORM [SYSTEM]MDA
> ;END IFN FTMDA
SUBTTL INTERRUPT SERVICE.
;HERE WITH AC'S SAVED AND PDL SETUP.
;C(W) := KDB ADDRESS
;AFTER CALL TO DEVICE DEPENDENT ROUTINE OR ERROR PROCESSOR
;C(T1) := IORB ADDRS IF COMPLETED
; 0 IF ANOTHER INTERUPT COMING - NO FURTHER PROCESSING
; -1 IF SCHED CYCLE REQUESTED
;C(TUBERR) NON-ZERO IF ERROR RECOVERY IN PROGRESS
TAPINT::SKIPG KDBUNI(W) ;MULTIPLE KONTROLLERS ON A SINGLE CHANNEL?
JRST TAPIN3 ;NO
IFN FTKL10,<
MOVE T1,KDBCHN(W) ;GET ADDRESS OF CHANNEL DATA BLOCK
MOVE T1,CHNTYP(T1) ;GET CHANNEL TYPE BITS
TLNE T1,(CP.SAX) ;NON-SA10 CHANNEL?
JRST TAPIN3 ;SA10 DOESN'T HAVE RH10/20 CONI BITS
MOVE T1,KDBCSO(W) ;GET TAPICD BLOCK ADDRESS
MOVE T1,TAPCII(T1) ;GET CONI BITS AT INTERRUPT
TRNE T1,CI.DON ;IS DONE IS ON?
JRST TAPIN3 ;YES, THE INTERRUPT IS FOR THIS KDB
PUSH P,T1 ;SAVE INTERRUPT CONI BITS FOR THE RIGHT KDB
MOVSI T2,(.DIASR) ;ATTEN INTERRUPT. READ ATTN SUMMARY
XCT KDBDTO(W) ; REGISTER
IMULI P,1
IMULI P,1 ;STALL IN CASE AN RH10
XCT KDBDTI(W) ;READ ATTENTION BITS
> ;END IFN FTKL10
IFN FTKS10,<
MOVE T2,KDBDVC(W) ;CSR ADDRESS
RDIO T1,.DOSR(T2) ;READ DRIVE STATUS REGISTER
TRNN T1,DS.ATA ;ATTENTION BITS AVAILABLE?
JRST TAPIN3 ;NO--INTERRUPT FOR INTERRUPTING KDB
RDIO T2,.DOAS(T2) ;READ ATTENTION BITS
> ;END IFN FTKS10
ANDI T2,377 ;GET JUST ATTENTION BITS
MOVE T1,KDBCHN(W) ;POINT TO CHANNEL DATA BLOCK
MOVE T1,CHNTBP(T1) ;AND TO THE TABLE OF KDBS ON THIS CHN
TAPIN1: SKIPN W,(T1) ;GET A KDB ADDRESS
JRST TAPIN2 ;NOTHING THERE??
TDNE T2,KDBUNI(W) ;INTERRUPT FOR THIS KDB?
IFN FTKS10,<JRST TAPIN3> ;YES. HANDLE IT
IFN FTKL10,<
JRST [MOVE T1,KDBCSO(W) ;GET TAPICD BLOCK ADDRESS
POP P,TAPCII(T1) ;PUT IN CORRECT CONI BITS
JRST TAPIN3]
> ;END IFN FTKL10
TAPIN2: AOBJN T1,TAPIN1 ;TRY ANOTHER KDB
IFN FTKL10,<
HRLI T2,(.DIASR!DO.LDR!DO.DRE) ;NOT FOR ANY KDB WE KNOW OF
XCT KDBDTO(W) ; SO CLEAR THE INTERRUPT
POP P,(P) ;SYNCH STACK
> ;END IFN FTKL10
IFN FTKS10,<
MOVE T1,KDBDVC(W) ;GET CSR ADDRESS FOR CONTROLLER
WRIO T2,.DOAS(T1) ;CLEAR ATTENTION BITS
> ;END IFN FTKS10
POPJ P, ;AND GO AWAY
TAPIN3: MOVE T1,KDBDSP(W) ;GET XFER VECTOR
PUSHJ P,@TPKISR(T1) ;CALL DEV DEP INT RTN
TAPAGO: JUMPE T1,CPOPJ## ;IF ZERO, ANOTHER INT IS COMING
JUMPL T1,TAPIN4 ;NO COMPLETION - DO SCHED CYCLE
MOVSI T2,TKSSTD ;CHANNEL NO LONGER STARTED
ANDCAM T2,TKBSTS(W) ;SO CLEAR STATUS
ANDCAM T2,TUBSTS(U) ;AND UNIT STATUS
SKIPE T2,TUBERR(U) ;IS ERP IN PROGRESS?
PUSHJ P,ERPINT ;YES - CALL INTERRUPT PART
JUMPE T1,CPOPJ## ;TERMINATE NOW?
JUMPL T1,TAPIN4 ;NO COMPLETION
MOVEI T2,RB.DUN ;MARK IORB AS DONE
DPB T2,PRBRQS ;...
MOVSI T2,TUSREW ;BIT TO TEST
TDNN T2,TUBSTS(U) ;REWIND OR UNLOAD INTERRUPT PENDING?
PUSHJ P,TAPCTM ;CLEAR HUNG TIMER FOR ALL OTHER OPERATIONS
PUSHJ P,TPMDON## ;YES - NOTIFY UPPER LEVEL
HRRZ T2,TKBSTS(W) ;SEE IF A SCHED CYCLE IS DUE
JUMPG T2,CPOPJ## ;NO - DISMISS
PUSHJ P,TAPDSL ;DE-SELECT KONTROLLER
TAPIN4: SETZB S,F ;MAKE SURE IOSCP2 IS OFF
MOVSI T2,TUSREW ;BIT TO TEST
TDNN T2,TUBSTS(U) ;REWIND OR UNLOAD INTERRUPT PENDING?
PUSHJ P,TAPCTM ;CLEAR HUNG TIMER FOR ALL OTHER OPERATIONS
PUSHJ P,TAPSCH ;SEE IF THERE IS MORE WORK
POPJ P, ;NO MORE TO DO
PJRST TPMSIO## ;START IO
;ROUTINE TO DE-SELECT A KONTROLLER AND CLEAR I/O
TAPDSL::MOVE T1,KDBDSP(W) ;GET XFER VECTOR
PUSHJ P,@TPKIDL(T1) ;MARK IDLE
HLLZS TKBSTS(W) ;SET QUANTUM TO ZERO
MOVSI T1,TKSSEL ;CLEAR SELECTION BITS
ANDCAM T1,TUBSTS(U) ; IN UDB
ANDCAM T1,TKBSTS(W) ; AND KDB
SETOM T1,@KDBCHN(W) ;INDICATE CHANNEL IS IDLE
POPJ P, ;RETURN
;GENERAL INTERUPT ERROR HALT
TAPIFI::STOPCD .,STOP,IFI, ;++ ILLEGAL FUNCTION AT INTERUPT
SUBTTL CHANNEL SCHEDULER
;W/ KDB TO CONTINUE SCANNING.
;SKIP RETURNS WITH W AND U SETUP IF ANOTHER REQUEST IS FOUND
;NON SKIP RETURN IF NOTHING TO DO
TAPSCH: TAPOFF ;TRY TO DEFEND AGAINST RACES
PUSH P,W ;SAVE INITIAL KDB
HRRZS (P) ;SAVING ONLY RIGHT HALF
MOVE T4,KDBCUN(W) ;INDEX INTO UNIT TABLE
PUSH P,T4 ;SAVE START
MOVSI T2,TKSOFL!TKSMNT!TKSNS ;CHECK IF HE IS AMOUNG US
TDNE T2,TKBSTS(W) ;...
JRST TPSCH2 ;NO, DON'T SCHEDULE FOR HIM
CAML T4,KDBFUN(W) ;FINAL UDB?
JRST TPSCH2 ;YES
AOS T4 ;START LOOKINT AT NEXT UDB
TPSCH1: SKIPN U,(T4) ;GET UDB
JRST TPSCHN ;NONE PRESENT
HRRZ T1,TUBQUE(U) ;GET QUEUE POINTER
JUMPE T1,TPSCHN ;GO IF NONE
SKIPL T2,TUBAKA(U) ;GET ACTIVE KDB ADDRESS
CAMN W,T2 ;KONTROLLER ALREADY PICKED?
CAIA ;FOUND RIGHT KDB OR NONE PICKED YET
JRST TPSCHN ;IGNORE THIS TUB
IFE FTMP,<SKIPL T2,TUBSTS(U)> ;NO SCHED?
IFN FTMP,<
SKIPGE T2,TUBSTS(U) ;NO SCHED ON THIS CPU
TLNE T2,TKSCHE
>
TLNE T2,TKSSEL!TKSCHA ;OR SELECTED BY ANOTHER?
JRST TPSCHN ;YES
IFN FTMP,<
MOVE T3,TRBLNK(T1) ;GET IORB FLAGS
TLNN T2,TKSCHE ;QUEUED REQUEST ON UDB?
TLNN T3,RB.PCL ;YES, QUEUED IORB REQUEST?
TDCA T2,S ;CLEAR IOSCP2(=TKSCHE) IF REQUEST TYPES MATCH
JRST TPSCHN ;CANT DO IT IF CHE=0, PCL=1
TLNN T2,IOSCP2 ;CP2=CHE=PCL?
>
JRST TPSCH3 ;FOUND 1 - USE IT
TPSCHN: CAMN T4,(P) ;BACK TO ORIGINAL UNIT?
JRST TPSCHY ;NOTHING TO DO - NON SKIP RETURN
CAMGE T4,KDBFUN(W) ;FINAL UDB?
AOJA T4,TPSCH1 ;LOOP FOR MORE
TPSCH2: MOVSI T2,TKSSCH
ANDCAM T2,TKBSTS(W)
TPSC2A: PUSHJ P,NXTKDB ;ADVANCE TO NEXT KDB ON CHANNEL
JFCL ;IGNORE WRAP AROUND
MOVSI T4,TKSOFL!TKSMNT!TKSNS ;BE SURE HE'S REALLY HERE
TDNE T4,TKBSTS(W) ;IS HE?
JRST [CAMN W,-1(P) ;NO, BACK TO ORIGINAL KDB ALREADY?
JRST TPSCHY ;YES, EXIT
JRST TPSC2A ];NO, STEP ON
IFN FTMP,<
MOVE T1,KDBCAM(W) ;GET ACCESSABILITY BIT
TDNN T1,.CPBIT## ;CAN WE DO I/O FOR THIS KDB?
JRST TPSC2A ;NO, LOOK FOR ANOTHER CANDIDATE
> ;END IFN FTMP
IORM T2,TKBSTS(W)
MOVE T4,KDBIUN(W) ;RESET POINTER
JRST TPSCH1 ;CONTINUE SEARCH
;HERE WHEN A REQUEST IS FOUND
TPSCH3:
IFN FTMP,<
SKIPE T3,CPUTPQ ;ANY QUEUED REQUESTS?
MOVSI T3,TKSCHE ;YES
TDNE T3,TKBSTS(W) ;REQUEST FOR THIS CONTROL?
SOS T3,TKBFCT(W) ;YES, TIME TO BE FAIR?
JUMPL T3,TPSCHY ;YES, LET TAPTIC HAVE IT
>
MOVSI T2,RB.AIO ;IS THIS REQUEST SPECIAL?
TDNE T2,TRBLNK(T1) ;?
PUSHJ P,UUOLVL## ;YES, ARE WE AT UUO LEVEL?
JRST TPSCH4 ;AT INTERRUPT LEVEL OR NOT SPECIAL
PUSH P,F ;SAVE F
MOVE F,TUBCUR(U) ;GET DDB ADDR
LDB T2,PJOBN## ;GET JOB NUMBER
POP P,F ;RESTORE F
CAMN T2,.CPJOB## ;CURRENT JOB (CURRENTLY SWAPPED USER)?
JRST TPSCH4 ;YES, OK TO START IT
MOVE T2,KDBDSP(W) ;CAN'T START NOW, CLANK THE
PUSHJ P,@TPKSCH(T2) ;SCHEDULER TO COME BACK @INTERRUPT LEVEL
JRST TPSCHY ;FIX STACK AND RETURN
TPSCH4: MOVEM T4,KDBCUN(W) ;STORE CURRENT UNIT
MOVSI T2,TKSSEL ;FLAG AS SELECTED
IORM T2,TKBSTS(W) ;IN KDB
IORM T2,TUBSTS(U) ;AND IN UDB
AOS T2,@KDBCHN(W) ;INDICATE CHANNEL IS BUSY
MOVEI T2,MQUANT## ;SET SLICE
HRRM T2,TKBSTS(W) ; ..
MOVE T3,UDBPDN(U) ;GET PHYSICAL DRIVE NUMBER
MOVEM W,TUBAKA(U) ;STORE AS ACTIVE KDB ADDRESS
AOS -2(P) ;SET FOR SKIP RETURN
TPSCHY: POP P,(P)
POP P,(P)
TPSCHX: MOVSI T2,TKSSCH ;CLEAR FACT THAT WE SCHEDULED
ANDCAM T2,TKBSTS(W) ; FOR THIS KDB
JRST TPONPJ ;RESTORE INTERRUPTS AND RETURN
NXTKDB: PUSHJ P,SAVE1## ;SAVE P1
MOVE P1,KDBCHN(W) ;POINT TO THE CHANNEL DATA BLOCK
MOVE P1,CHNTBP(P1) ;AND GET THE AOBJN POINTER TO KDBS
NXTKD1: CAME W,(P1) ;FOUND THE CURRENT KDB YET?
AOBJN P1,.-1 ;KEEP SEARCHING
JUMPGE P1,CPOPJ## ;NOT THERE??
AOBJN P1,NXTKD2 ;ADVANCE TO NEXT SLOT
MOVE P1,KDBCHN(W) ;RAN OUT SO MUST RESET W TO THE
SKIPA P1,CHNTBP(P1) ;FIRST KDB ON THE CHANNEL
NXTKD2: AOS (P) ;FORCE SKIP
MOVE W,(P1) ;PICK UP A KDB ADDRESS
POPJ P, ;AND RETURN
SUBTTL CHECK FILE OPERATIONS
;ROUTINE TO SEE IF IT IS LEGAL TO USE A FILE OPERATION
;CALL: MOVE U, UDB ADDRESS
; PUSHJ P,TAPFOL
; <NON-SKIP> ;LEGAL
; <SKIP> ;ILLEGAL
TAPFOL::PUSH P,T1 ;SAVE T1
MOVE T1,TUBCNF(U) ;GET DRIVE CONFIG WORD
ANDI T1,TUCFOI ;KEEP ONLY "FILE OPERATIONS ILLEGAL" BIT
SKIPE TAPSBF ;TAPSER SAY OK?
JUMPE T1,TPOPJ## ;YES, BUT ONLY IF DRIVER AGREES
JRST TPOPJ1## ;ELSE DO MULTIPLE RECORD OPS
SUBTTL HUNG TIMER CONTROL
;SET HUNG TIMER
;CALL: MOVE U, UDB ADDRESS
; PUSHJ P,TAPSTM
;
;ALL ACS PRESERVED
TAPSTM::PUSH P,T1 ;SAVE T1
MOVE T1,KDBSTS(W) ;GET STATUS WORD
TLNN T1,(KD.APC) ;ALL PORTS CONFIGURED (KNOWN)?
TLNN T1,(KD.MPD) ;NO, BUT IS IT A MULTI-PORTED DEVICE?
JRST TAPST2 ;NORMAL HUNG TIMER WILL DO
PUSH P,T2 ;SAVE T2
XMOVEI T1,UDBKDB(U) ;POINT TO DRIVE'S KDB TABLE
MOVSI T2,-MXPORT ;AOBJN POINTER
PUSH P,[EXP 0] ;INIT A COUNTER
TAPST1: SKIPE (T1) ;HAVE A KDB ADDRESS?
AOS (P) ;COUNT IT
AOS T1 ;ADVANCE POINTER
AOBJN T2,TAPST1 ;LOOP FOR ALL KDBS
POP P,T1 ;GET COUNT
LDB T2,[POINTR (KDBSTS(W),KD.MPT)] ;AND MAXIMUM NUMBER OF PORTS
CAIE T1,(T2) ;ALL PORTS KNOWN?
JRST TAPST3 ;NO, USE MAXIMUM HUNG TIMER
POP P,T2 ;RESTORE T2
MOVSI T1,(KD.APC) ;HERE IF ALL PORTS ARE KNOWN
IORM T1,KDBSTS(W) ;UPDATE TO MINIMIZE OVERHEAD NEXT TIME
TAPST2: HRRZ T1,TUBQUE(U) ;GET CURRENT IORB
LDB T1,PRBFCN ;AND THE FUNCTION CODE
ADJBP T1,[POINT 9,TUBHTT(U),8] ;INDEX TO THE PROPER BYTE
LDB T1,T1 ;GET THE FUNCTION-SPECIFIC TIMER VALUE
JRST TAPST4 ;GO STORE
TAPST3: POP P,T2 ;RESTORE T2
MOVE T1,TUBMTV(U) ;GET MAXIMUM HUNG TIMER VALUE
TAPST4: MOVEM T1,TUBTIM(U) ;STORE IN THE TUB
JRST TPOPJ## ;RESTORE T1 AND RETURN
;CLEAR HUNG TIMER
;CALL: MOVE U, UDB ADDRESS
; PUSHJ P,TAPCTM
;
;ALL ACS PRESERVED
TAPCTM::PUSH P,T1 ;SAVE T1
SETZM TUBTIM(U) ;CLEAR TIMER WORD IN THE TUB
MOVSI T1,(1B0) ;GET A BIT
IORM T1,TUBAKA(U) ;MARK ACTIVE KONTROLLER INVALID
JRST TPOPJ## ;RESTORE ACS AND RETURN
SUBTTL START IO
;HERE WHEN UPPER LEVEL WANTS TO START IO. THE USER JOB IS LOCKED
;AND THE IORB HAS A VALID DATA XFR LIST IF ONE IS NEEDED
TAPSIO::
IFN FTMP,<
MOVE T2,KDBCAM(W) ;GET CPU ACCESSIBILITY MASK FOR KONTROLLER
TDNN T2,.CPBIT## ;ON THE RIGHT CPU?
STOPCD .,STOP,TIO, ;++ TAPE I/O TO WRONG CPU
> ;END IFN FTMP
TAPOFF ;GUARD AGAINST
MOVE T2,TKBSTS(W) ;KONTROLLER STATUS
TLNE T2,TKSOFL ;CONTROLLER INTERRUPTS
JRST TPONPJ ;WHICH SET CONTROLLER OFFLINE
TLOE T2,TKSSEL ;SELECTED?
TLZE T2,TKSSTD ;AND NOT STARTED
STOPCD TAPSI3,INFO,KSW, ;++KONTROLLER STATUS WRONG
TAPSI1: MOVE T2,TUBSTS(U) ;UNIT STATUS
TLOE T2,TKSSEL ;SELECTED?
TLZE T2,TKSSTD ;AND NOT STARTED (ON ANOTHER KONTROL)?
STOPCD TAPSI4,INFO,USW, ;++UNIT STATUS WRONG
TAPSI2: MOVEI T2,RB.ACT ;SET IORB STATUS TO ACTIVE
DPB T2,PRBRQS ; ...
IFN FTMP,<
LDB T2,DEYPCL## ;DON'T SET NON-ZERO IF
JUMPE T2,TPSI2A ;IT WASN'T
SKIPN T2,.CPCPN## ;TELL THW WORLD
MOVEI T2,PCLCP0## ; WHAT CPU IS DOING THE IO
DPB T2,DEYPCL##
TPSI2A:>
PUSHJ P,TAPFLT ;CHECK IF FORCING HUNG DEVICE
JRST TAPSI5 ;WILL HANG, DON'T START THE IORB
;FOR ERROR LOGGING, RECORD SOME DATA IN THE TUB
SKIPGE T2,KDBUNI(W) ;MASSBUS UNIT NUMBER
TDZA T2,T2 ;NOT A MULTI-UNIT DEVICE
HLRZS T2 ;PUT IN RH
ROT T2,-3 ;POSITION IN BITS 0-2
IOR T2,KDBDVC(W) ;INCLUDE THE DEVICE CODE/UNIBUS ADDRESS
MOVEM T2,TUBDVC(U) ;SAVE
MOVE T2,KDBDSP(W) ;DRIVER DISPATCH
LDB T2,[POINTR (DRVCF2(T2),DR.KTY)] ;KONTROLLER TYPE
MOVEM T2,TUBKTY(U)
MOVSI T2,TKSSTD ;MARK AS STARTED
IORM T2,TKBSTS(W) ;IN KDB
IORM T2,TUBSTS(U) ;AND UDB
PUSHJ P,TAPSTM ;SET HUNG TIMER
MOVE T2,KDBDSP(W) ;GET KONTROLLER DISPATCH
PUSHJ P,@TPKSIO(T2) ;CALL START IO
TAPSI5: TAPON ;SAFE NOW
POPJ P,0
;HERE AFTER KSW STOPCD, TRY TO RECOVER
TAPSI3: MOVEM T2,TKBSTS(W) ;STORE REASONABLE STAUS
JRST TAPSI1 ;GO CHECK UNIT STAUS
;HERE AFTER USW STOPCD
TAPSI4: MOVEM T2,TUBSTS(U) ;STORE REASONABLE STATUS
JRST TAPSI2 ;GO START THE IO
;HERE TO SETUP FOR HUNG DEVICE.
;SKIP IF OPERATION OK, NON-SKIP IF FORCING DEVHNG.
TAPFLT::MOVSI T2,TUSFLT ;TU FAULT BIT
TDNN T2,TUBSTS(U) ;IS THE DRIVE BROKEN?
JRST CPOPJ1## ;NO, GIVE OK RETURN
LDB T2,PRBFCN ;GET THE IORB FUNCTION
CAIE T2,RB.FRW ;IS IT REWIND?
CAIN T2,RB.FRU ;OR UNLOAD?
JRST CPOPJ1## ;YES, THIS IS SAFE
MOVEI T2,1 ;A SMALL HUNG TIME LIMIT
MOVEM T2,TUBTIM(U) ;LIMIT FOR TAPSEC
POPJ P, ;GIVE FORCED DEVHNG RETURN
SUBTTL CHECK FOR KONTROLLER BUSY
;THIS IS COMMON CODE TO SUPPORT THOSE KONTROLLERS WHICH ARE INCAPABLE
;OF HANDLING NON-BLOCKING FUNCTION. THAT IS, A GIVEN FUNCTION TIES UP
;THE KONTROLLER UNTIL AN INTERRUPT IS RECEIVED.
;CALL: MOVE W, KDB ADDRESS
; MOVE U, UDB FOR DRIVE TRYING TO SCHEDULE
; PUSHJ P,TX1BSY
; <NON-SKIP> ;BUSY
; <SKIP> ;NOT-BUSY
;
;USES T1 AND T2
TAPBSY::MOVSI T1,TKSOFL!TKSMNT!TKSNS ;INTERESTING BITS
TDNE T1,TKBSTS(W) ;OFFLINE, MAINTENANCE MODE, OR NOT SCHEDULING?
POPJ P, ;RETURN BUSY
MOVE T1,KDBDSP(W) ;POINT TO DRIVER DISPATCH
PUSHJ P,@TPKBSY(T1) ;IS KONTROLLER BUSY?
POPJ P, ;IT IS
JRST CPOPJ1## ;KONTROLLER IS FREE
;HERE IF FOR DUMB KONTROLLERS TO DO TRADITIONAL CHECKING
MOVSI T1,TKSSEL!TKSSTD!TKSSCH ;BITS TO TEST
SKIPGE @KDBCHN(W) ;CHANNEL IN USE (USER MODE DIAG)?
TDNE T1,TKBSTS(W) ;OR CHANNEL ALREADY GOING?
POPJ P, ;THEN IT'S BUSY
JRST CPOPJ1## ;ELSE RETURN CHANNEL FREE
SUBTTL ONLINE CHECK
;HERE ONCE A SECOND/MINUTE.. GROVEL THROUGH THE KDBS AND SEE IF THERE ARE
;ANY OFFLINE. IF SO, COMPLAIN THROUGH TPMOFL. IF ANY CLAIM TO BE OFFLINE
;AND ARE NOW ONLINE, INITIALIZE AND OPERATE A SCHEDULE CYCLE.
CHKKON: SKIPN W,KDBTAB##+.TYMTA ;GET FIRST KDB
JRST CPOPJ1## ;NO TAPES
CHKKO1: MOVSI T1,TKSMNT ;BIT TO TEST
IFN FTMP,<
MOVE T2,KDBCAM(W) ;CPU ACCESSIBILITY MASK
TDNE T2,.CPBIT## ;ON OUR CPU?
>
TDNE T1,TKBSTS(W) ;SEE IF WE SHOULD CHECK
JRST CHKKO7 ; IF HE IS ONLINE
MOVSI T1,TKSSEL!TKSSTD!TKSSCH ;BITS TO TEST
SKIPGE @KDBCHN(W) ;CHANNEL IN USE (USER MODE DIAG)?
TDNE T1,TKBSTS(W) ;OR CHANNEL ALREADY GOING?
JRST CHKKO2 ;THEN IT'S ONLINE
MOVE T1,KDBDSP(W) ;GET XFR VECTOR
PUSHJ P,@TPKONL(T1) ;SEE IF ONLINE
JRST CHKKO4 ;NOT ON LINE - COMPLAIN
CHKKO2: MOVSI T1,TKSOFL ;NOW ONLINE - SEE IF
TDNN T1,TKBSTS(W) ;IF FORMERLY OFFLINE.
JRST CHKKO7 ;NO
TLO T1,TKSSCH!TKSSTD!TKSSEL!TKSSIL!IFN FTMP,<TKSCHE!TKSCHA>
ANDCAM T1,TKBSTS(W) ;CLEAR LOTS OF BITS
MOVSI T2,TKSSTD!TKSSEL!IFN FTMP,<TKSCHE!TKSCHA> ;BITS TO CLEAR IN UDB
MOVE T3,KDBIUN(W) ;POINTER TO UDB TABLE
SETZ U, ;FLAG FOR CALLING TPKRES ROUTINE
;KONTROLLER WAS OFFLINE BEFORE, BUT IT'S ONLINE NOW, SO FIXUP UDBS
CHKKO3: SKIPE 0(T3) ;UNIT PRESENT?
SKIPA U,(T3) ;YES, GET ITS ADDRESS
CAIA ;NO, SKIP THIS ONE
ANDCAM T2,TUBSTS(U) ;YES - CLEAR BITS
CAMGE T3,KDBFUN(W) ;FINAL UDB?
AOJA T3,CHKKO3 ;LOOP FOR MORE
JUMPE U,CHKKO7 ;IF NO UNITS, THEN NO ACTIVE I/O TO RESET
MOVE T1,KDBDSP(W) ;GET XFR VECTOR
PUSHJ P,@TPKRES(T1) ;RESET CONTROLLER
JRST CHKKO7 ;GO FINISH THIS ONE
;KONTROLLER HAS BEEN NOTICED OFFLINE FOR THE FIRST TIME
CHKKO4: MOVE T1,KDBIUN(W) ;IF A KON BUT NO UNITS
CHKKO5: SKIPN (T1) ;HAVE A UDB?
JRST CHKKO6 ;YES
CAMGE T1,KDBFUN(W) ;FINAL UDB?
AOJA T1,CHKKO5 ;LOOP 'TIL A UDB IS FOUND
JRST CHKKO7 ;ONTO THE NEXT KONTROLLER
CHKKO6: PUSHJ P,@0(P) ;CALL CO-ROUTINE
JRST CHKKO7 ;CONTINUE LOOP
;END OF KONTROLLER LOOP
CHKKO7:
IFN FTMP,<
MOVEI T1,TKBICT## ;INITIAL FAIRNESS COUNT
SKIPGE TKBFCT(W) ;FAIRNESS COUNT GONE OFF?
MOVEM T1,TKBFCT(W) ;ABJECT PARANOIA
>
SKIPE W,KDBNXT(W) ;GET NEXT KDB
JRST CHKKO1 ;IF THERE IS ONE, CHECK IT
JRST CPOPJ1## ;ELSE SKIP OVER ARG
;ONCE A SECOND - JUST CHECK AND UPDATE INFO
TAPSEC::MOVSI T1,(CR.ATO) ;BIT TO TEST
TDNE T1,.CPRUN## ;WAITING FOR AUTCON TO RUN?
POPJ P, ;THEN DO NOTHING
PUSHJ P,CHKKON ;CRAWL THROUGH DATA BASE
JRST SETOFL ;WHERE TO GO FOR OFFLINE CTL
SKIPN W,KDBTAB##+.TYMTA ;START AT FIRST KONTROLLER
POPJ P, ;NO TAPES
PUSHJ P,SAVE1## ;SAVE P1
TAPSE1:
IFN FTMP,<
MOVE T1,KDBCAM(W) ;CPU ACCESSIBILITY MASK
TDNN T1,.CPBIT## ;OUR CPU?
JRST TAPSE3 ;NO
> ;END IFN FTMP
MOVE P1,KDBIUN(W) ;GET START ADDR OF DRIVE TABLE
TAPSE2: SKIPE U,(P1) ;GET A TUB
PUSHJ P,UTIMER ;CHECK ITS HUNG TIMER
CAMGE P1,KDBFUN(W) ;LOOKED AT ALL TUBS YET?
AOJA P1,TAPSE2 ;LOOP BACK FOR ANOTHER
TAPSE3: SKIPE W,KDBNXT(W) ;STEP TO NEXT KONTROLLER
JRST TAPSE1 ;GO CHECK IT
POPJ P, ;DONE - RETURN
SETOFL: MOVSI T1,TKSOFL
TDNE T1,TKBSTS(W) ;ON LINE?
POPJ P, ;NO - JUST RETURN
MOVE T1,KDBDSP(W) ;GET DISPATCH TABLE ADDRESS
PUSHJ P,@TPKLOD(T1) ;TRY TO LOAD MICROCODE
SKIPA ;CAN'T OR WON'T LOAD
POPJ P, ;KONTROLLER BACK ON-LINE
MOVSI T1,TKSOFL ;BIT TO SET
IORM T1,TKBSTS(W) ;MARK IT OFF-LINE
PJRST TPMOFL## ;TELL WORLD AND RETURN
;ONCE A MINUTE - SEE IF STILL OFF LINE
TAPMIN::PUSHJ P,CHKKON ;LOOK AT THINGS
JRST TPMOFL## ;JUST COMPLAIN IF OFF LINE
POPJ P, ;RETURN
IFN FTMP,<
;HERE ONCE A TICK
TAPTIC::SKIPN W,KDBTAB##+.TYMTA ;START AT 1ST KDB
POPJ P, ;NO TAPES
SKIPN CPUTPQ ;ANY QUEUED REQUESTS FROM ANY CPU?
JRST TAPTI4 ;NO
TAPTI1: MOVSI T2,TKSCHE ;USE 1 BIT PER CPU
MOVE T1,KDBCAM(W) ;CPU ACCESSIBILITY MASK
TDNE T1,.CPBIT## ;ON THIS CPU?
TDNN T2,TKBSTS(W) ;YES, DOES IT HAVE A QUEUED REQUEST?
JRST TAPTI3 ;NO, TRY NEXT KDB
MOVE T3,.CPQPC## ;YES, CLEAR THE DOORBELL
ANDCAM T3,DOORBL## ; SINCE WE HAVE SERVICED THE REQUEST
TLO S,IOSCP2 ;INDICATE WE ARE LOOKING FOR A QUEUED REQUEST
MOVEI T2,TKBICT## ;IF FAIRNESS HAS GONE OFF
SKIPGE TKBFCT(W)
MOVEM T2,TKBFCT(W) ;RESET IT
PUSHJ P,CKSIO2 ;TRY TO SELECT SOME UNIT ON KDB
MOVSI T1,TKSCHE
MOVE T2,KDBIUN(W) ;POINTER TO UDB TABLE
SYSPIF
TLNN S,IOSCP2 ;DID WE SELECT A UNIT?
ANDCAM T1,TUBSTS(U) ;YES, CLEAR THE QUEUED REQUEST BIT
TAPT1A: SKIPE T3,(T2) ;GET A UDB
TDNN T1,TUBSTS(T3) ;DOES IT HAVE A QUEUED REQUEST?
JRST TAPT1B ;NO, TRY NEXT
HRRZ T4,TUBQUE(T3) ;MAYBE
JUMPN T4,TAPT1C ;IS THERE AN IORB?
ANDCAM T1,TUBSTS(T3) ;NO. IT GOT DESELECTED
TAPT1B: CAMGE T2,KDBFUN(W) ;FINAL UDB?
AOJA T2,TAPT1A ;LOOP FOR MORE
ANDCAM T1,TKBSTS(W) ;NO, CLEAR BIT IN THE KDB
TAPT1C: SYSPIN
TLZN S,IOSCP2 ;DID WE SELECT A UDB?
SOSA CPUTPQ ;YES, DECREMENT NO OF OUTSTANDING REQUESTS
JRST TAPTI3 ;NO, TRY NEXT KDB
HRRZ T1,TUBQUE(U) ;POINT AT IORB
MOVE F,TUBCUR(U) ;SET UP NEEDED ACS
MOVE S,DEVIOS(F)
LDB J,PJOBN## ;JOB WHICH OWNS THE UDB
MOVE T2,TRBLNK(T1) ;GET IORB FLAGS
TLNE T2,RB.PCL ;THERE IS A RACE WITH ^C WHICH COULD GET
JRST TAPTI2 ; US HERE FOR A NON-QUEUED REQUEST
MOVE T1,J ;THE JOB IS WAITING AT KONWAT
PUSHJ P,EWAKE## ;SO JUST TAKE IT OUT OF EW
JRST TAPTI3 ;AND KEEP ON
TAPTI2: PUSHJ P,TAPTIX ;"REGULAR" ROUTE - GO START UP THE IO
TAPTI3: SKIPE W,KDBNXT(W) ;STEP TO NEXT KDB
JRST TAPTI1 ;AND GO TEST IT
;HERE AFTER STARTING WHAT WE COULD
TAPTI4: SKIPN T1,.CPTAP## ;ANY REQUEST FOR THIS CPU
POPJ P, ;NO, GO AWAY
IFN FTKL10,<
SKIPG T1 ;YES, DID FILIO ALREADY SWEEP?
PUSHJ P,CSDMP## ;NO, SWEEP CACHE NOW
>
MOVE W,KDBTAB##+.TYMTA ;START AT BEGINNING
MOVE T1,.CPCHX## ;NEEDS-A-SWEEP BIT
MOVSI T2,TKSCHE ;SWEEP-WAS-DONE BIT
TAPTI5: TDNN T1,TKBSTS(W) ;DOES THIS KDB NEED A SWEEP?
JRST TAPTI8 ;NO
ANDCAM T1,TKBSTS(W) ;YES, CLEAR THAT BIT
SYSPIF
IORM T2,TKBSTS(W) ;AND LIGHT SWEEP-DONE
MOVE T3,KDBIUN(W) ;POINTER TO UDB TABLE
TAPTI6: SKIPE T4,(T3)
TDNN T1,TUBSTS(T4) ;CLEAR SWEEP-NEEDED, SET SWEEP-DONE
JRST TAPTI7
ANDCAM T1,TUBSTS(T4) ; FOR ALL UDBS WHICH NEEDED A SWEEP
IORM T2,TUBSTS(T4)
TAPTI7: CAMGE T3,KDBFUN(W) ;FINAL UDB?
AOJA T3,TAPTI6 ;LOOP FOR MORE
SYSPIN
TAPTI8: SKIPE W,KDBNXT(W) ;STEP TO NEXT KDB
JRST TAPTI5 ;GO SWITCH THE BITS FOR IT TOO
MOVM T1,.CPTAP## ;GET NO OF REQUESTS WE JUST SATISFIED
ADDM T1,CPUTPQ ;AND ADD TO REQUESTS FOR ALL CPUS
SETZM .CPTAP## ;CLEAR THIS-CPU-NEEDS-A-SWEEP
POPJ P, ;AND EXIT
;HERE TO GET A QUEUED REQUEST STARTED
;WILL GET TO START THE IO VIA TPMDON
TAPTIX: PUSHJ P,SVEUB## ;MAKE ADDRESSABLE
PUSHJ P,SPCS## ;AND SET PCS
JRST TAPAGO ;CALL TAPAGO TO GET TO TPMDON TO START IO
>;END IFN FTKL10
SUBTTL CHECK HUNG TIMERS
UTIMER: CAMN W,TUBAKA(U) ;CURRENTLY ACTIVE KDB?
PUSHJ P,CHKIRB ;GET IORB (ONLY REALLY CHECKING ACTIVE STATE)
SKIPA T2,TUBAKA(U) ;NOT ACTIVE, GET KDB
JRST UTIMR1 ;GO CHECK THE TIMER
TLZ T2,(1B0) ;IN CASE KDB WAS INACTIVE
MOVSI T3,TUSREW ;REWIND/UNLOAD BIT
CAMN T2,W ;WAS THIS THE LAST ACTIVE KDB?
TDNN T3,TUBSTS(U) ;AND IS THE DRIVE REWINDING NOW?
POPJ P, ;NO TO EITHER
UTIMR1: DDBSRL ;PREVENT LABEL DDBS FROM BEING DELETED
SKIPN F,TUBCUR(U) ;PICK UP CURRENT DDB
MOVE F,UDBDDB(U) ;OR THE "REAL" DDB IF NONE
JUMPE F,UTIMR6 ;AND PUNT IF IMPOSSIBLE HAPPENS
MOVE S,DEVIOS(F) ;GET I/O STATUS WORD
MOVSI T1,DVOFLN ;BIT TO TEST
HRRZ T2,DEVSER(F) ;UUO-LEVEL DISPATCH TABLE ADDRESS
TDNE T1,DEVCHR(F) ;DRIVE OFFLINE?
PUSHJ P,DOFL(T2) ;YES, SEE IF ITS STILL OFFLINE
JRST UTIMR2 ;IT IS
MOVSI T1,DVOFLN ;GET THE BIT AGAIN
ANDCAM T1,DEVCHR(F) ;CLEAR OFFLINE STATE SINCE IT'S ONLINE NOW
PUSHJ P,PSIONL## ;TELL THE USER ITS ONLINE IF HE'S INTERESTED
UTIMR2: HRRZ T1,TUBQUE(U) ;GET IORB BACK
MOVE T2,TUBTIM(U) ;GET THE TIMER
SOJL T2,UTIMR3 ;ZERO MEANS IGNORE THE DEVICE
MOVEM T2,TUBTIM(U) ;UPDATE COUNTER
JUMPN T2,UTIMR6 ;JUMP IF COUNTER NOT EXPIRED YET
JUMPN T1,UTIMR4 ;ELSE IF AN IORB, THEN SOME OPERATION HUNG
UTIMR3: MOVSI T3,TUSREW ;BIT TO TEST
TDNE T3,TUBSTS(U) ;REWIND OR UNLOAD INTERRUPT PENDING?
JRST [PUSHJ P,REWDON ;MISSED AN INTERRUPT, CLEAR REW/UNL, ETC.
JRST UTIMR6] ;DON'T STOP JOB FOR REWIND OR UNLOAD
JUMPL T2,UTIMR6 ;IGNORE DEVICE IF TIMER WAS ZERO
UTIMR4: JUMPE T1,UTIMR6 ;CAN DO NOTHING WITHOUT AN IORB NOW
MOVSI T2,RB.AIO ;IF ASYNCHRONOUS I/O, THEN THERE'S NO TIMER
TDNE T2,TRBLNK(T1) ; TO COUNT DOWN SINCE THE USER'S PROGRAM IS
JRST UTIMR6 ; TIMING THE I/O (IF IT CARES)
MOVSI T1,TUSFLT ;FAULTY DRIVE BIT
TDNE T1,TUBSTS(U) ;DID THE DRIVE GO BAD?
JRST UTIMR5 ;YES, IGNORE SPECIAL CASE FOR SCHEDULE
MOVSI T1,TKSSCH ;GET SCHEDULER BIT
TDNN T1,TKBSTS(W) ;HUNG TRYING TO FORCE A SCHEDULE?
JRST UTIMR5 ;NO, MUST BE A REAL TAPE OPERATION
PUSHJ P,TAPSTM ;SET HUNG TIMER
MOVE T1,KDBDSP(W) ;TRY AGAIN
PUSHJ P,@TPKSCH(T1) ;BY REQUESTING ANOTHER INTERRUPT
JRST UTIMR6 ;FINISH UP
UTIMR5: PUSH P,U ;SAVE TUB ADDRESS
PUSH P,W ;AND KDB ADDRESS
HRRZ T1,DEVSER(F) ;UUO-LEVEL DISPATCH TABLE
PUSHJ P,DHNG(T1) ;CALL TAPUUO TO UNHANG THE DEVICE
PUSHJ P,DEVHNG## ;PRINT ERROR MESSAGE AND STOP JOB
POP P,W ;RESTORE TKB
POP P,U ;RESTORE TUB ADDRESS
UTIMR6: DDBSRU ;RESUME DDB SCANNING
POPJ P, ;RETURN
SUBTTL HUNG DEVICE
TAPHNG::TAPOFF ;WHO KNOWS WHAT EVIL...
MOVE W,TUBAKA(U) ;GET ACTIVE KDB ADDRESS
TLZ W,(1B0) ;CLEAR POSSIBLY INACTIVE BIT
MOVE T2,KDBDSP(W) ;CALL KON RESET ENTRY
MOVSI T1,TKSSTD
TDNN T1,TUBSTS(U) ;IF TAPE HAS BEEN STARTED
JRST TAPHN1
PUSHJ P,@TPKRES(T2) ; ...
MOVSI T1,(1B2)
IORM T1,TUBTRY(U) ;TELL DAEMON ITS A HUNG
HRRZ P1,TUBQUE(U) ;SETUP FOR TPEMOV
PUSHJ P,TPEMOV## ;PUT STATS IN DAEMON'S PART OF TUB
PUSHJ P,TPELOG## ;AND GO LOG IT
TAPHN1: MOVSI T1,TKSSTD!TUSREW ;CLEAR STARTED AND REWIND
ANDCAM T1,TUBSTS(U) ;IN UDB
TLC T1,TKSSCH^!TUSREW ;ALSO CLEAR SCH AND STARTED
ANDCAM T1,TKBSTS(W) ;IN KDB
IFN FTMP,<
MOVSI T1,TKSCHE ;SWEEP-NEEDED OR SWEEP-DONE
IOR T1,.CPCHX##
TDNE T1,TUBSTS(U) ;IF EITHER IS ON
SOS CPUTPQ ;DECREMENT NO OF OUTSTANDING QUEUED REQUESTS
ANDCAM T1,TUBSTS(U) ;AND CLEAR THE BITS IN THE TUB
> ;END IFN FTMP
CAIA ;PRUNE QUEUE, DESELECT,PION
TAPKIL::TAPOFF ;FIGHT RACE
MOVE W,TUBAKA(U) ;GET ACTIVE KDB ADDRESS
TLZ W,(1B0) ;CLEAR POSSIBLY INACTIVE BIT
HRRZ T1,TUBQUE(U) ;RETURN HEAD OF LIST
MOVSI T2,TUBQUE(U) ;RESET POINTERS
MOVEM T2,TUBQUE(U) ; ...
SETZM TUBERR(U) ;STOP ERROR RECOV
MOVSI T2,TUSNS ;CLEAR HOLD
ANDCAM T2,TUBSTS(U)
PUSH P,T1 ;SAVE PNTR
PUSHJ P,TPCSEL ;DESELECT IF NECESSARY
POP P,T1 ;RESTORE PNTR
PUSHJ P,TAPCTM ;CLEAR HUNG TIMER
PJRST TPONPJ ;TURN ON PI AND EXIT
SUBTTL HOLD/CONTINUE
;HERE TO SET NS BIT ON A UNIT
TAPHLD::MOVSI T1,TUSNS ;SET NO SCHEDULE
IORM T1,TUBSTS(U) ;...
IFN FTMP,<
PUSHJ P,CHKCPI##
JRST [MOVEI T1,1
HRRM T1,TKBSTS(W)
POPJ P,]
>
MOVSI T1,TKSSTD ;SEE IF STARTED
TDNE T1,TUBSTS(U) ;...
JRST [HLLZS TKBSTS(W) ;GRNTEE NO MORE
POPJ P,] ;RETURN
TPCSEL: MOVSI T1,TKSSEL ;SEE IF SELECTED
TDNN T1,TUBSTS(U)
POPJ P, ;NOT SELECTED - EXIT
PUSHJ P,TAPDSL ;YES - DESELECT
PJRST CKSIO1 ;CLANK SCHED IF NECESSARY
;ROUTINE CALLED TO ALLOW UNIT TO SCHEDULE AGAIN
TAPCNT::MOVSI T1,TUSNS
ANDCAM T1,TUBSTS(U) ;CLEAR NS BIT
PUSHJ P,TPMACC## ;KDB/UDB ACCESSIBILE?
SKIPA ;NO
JRST CKSIO2 ;WE CAN DO I/O OURSELVES
CKSIO1: JUMPE W,CPOPJ## ;IF NONE, PUNT
IFN FTMP,<
MOVE T1,KDBCAM(W) ;CPU ACCESSIBILITY MASK
PUSHJ P,CAMCPU## ;FIND ANY (HOPFULLY RUNNING) CPU
CAME T1,.CPCPN## ;IS IT US?
PJRST PCLTAP ;MUST QUEUE THE REQUEST
> ;END IFN FTMP
TLZ S,IOSCP2 ;MAKE SURE IOSCP2 IS OFF
CKSIO2: MOVSI T2,TKSSEL!TKSSCH!TKSOFL
SYSPIF
SKIPGE @KDBCHN(W) ;IS CHANNEL BUSY?
TDNE T2,TKBSTS(W) ; ARE ANY OF THESE ON?
JRST ONPOPJ## ;YES - SOMETHING WILL HAPPEN
MOVSI T2,TKSSCH ;SET SCHED REQUESTED
IORM T2,TKBSTS(W) ;...
AOS @KDBCHN(W) ;INDICATE CHANNEL IS BUSY
SYSPIN
PUSH P,U ;SAVE U
PUSHJ P,TAPSCH ;TRY TO START SOMETHING
JRST CKSIO3 ;NOTHING TO DO, RETURN FOR NOW
IFN FTMP,<
TLZE S,IOSCP2
JRST CKSIO4
>
PUSH P,F ;SAVE F
HRRZ T1,TUBQUE(U) ;CURRENT IORB
PUSHJ P,TPMSIO## ;CRANKUP THE I/O
MOVE U,-1(P) ;WHICH UDB WE WERE USING
PUSHJ P,TAPACC ;RESTORE KDB ADDRESS
JFCL ;IGNORE OFF-CPU RETURN
JRST FUPOPJ## ;RESTORE F,U,AND RETURN
CKSIO3: MOVE U,(P) ;RESTORE U
PUSHJ P,TAPACC ;AND KDB ADDRESS
JFCL ;IGNORE OFF-CPU RETURN
CKSIO4: SOS T1,@KDBCHN(W) ;INDICATE CHANNEL IS NOT BUSY
JRST TPOPJ## ;MAKE STACK RIGHT AND RETURN
;SUPPORT FOR THE TAPOFF MACRO
TAPLOK::CONO PI,PI.OFF ;TURN OFF THE PI SYSTEM WHILE TESTING
AOSE .CPTPN## ;BUMP LEVEL OF NESTING
JRST [CONO PI,PI.ON ;JUST NESTING, RETURN, ALREADY HAVE INTERLOCK
POPJ P,] ;...
CONI PI,.CPTPP## ;SAVE CHANNEL ENABLES
; CONO PI,PI.ON+TAPPIF## ;TURN PI SYSTEM ON LEAVING TAPCHN OFF
CONO PI,PI.ON+TPIOFF## ;TURN TAPCHN AND LOWER CHANNELS OFF
IFN FTMP,<
SKIPGE INTRTP## ;GIVE OTHER CPUS A CHANCE
AOSE INTRTP## ;WAIT FOR THE SYSTEM-WIDE INTERLOCK
JRST .-2 ;WAIT
APRID INTOTP## ;INFORM THE WORLD WHO OWNS THIS
>; END IFN FTMP
POPJ P, ;RETURN
;SUPPORT ROUTINE FOR THE TAPON MACRO
TAPULK::PUSH P,T1 ;SAVE A REGISTER
SOSL T1,.CPTPN## ;DECREMENT LEVEL OF NESTING, SEE IF DONE
PJRST TPOPJ## ;STILL NESTING, JUST RETURN
EXCH T1,.CPTPP## ;GET CHANNEL ENABLE STATES
ANDI T1,177 ;KEEP JUST THE CHANNELS WHICH WERE ON
TRO T1,PI.TNP ;TURN THEM BACK ON
EXCH T1,.CPTPP## ;RESTORE T1 AND SAVE ARGUMENT FOR CONO PI,
IFN FTMP,<
SETOM INTOTP## ;CLEAR INTERLOCK OWNER
EXCH T1,INTRTP## ;RESET THE INTERLOCK
SKIPGE T1 ;MAKE SURE IT WAS OWNED
STOPCD .,CPU,TIU, ;++ TAPE INTERLOCK UNOWNED
>; END IFN FTMP
CONO PI,@.CPTPP## ;PUT THE PI SYSTEM BACK THE WAY IT WAS
PJRST TPOPJ## ;RESTORE T1 AND RETURN
IFN FTMP,<
PCLTAP: HRRZ T1,TUBQUE(U) ;GET IORB ADDRESS
JUMPE T1,CPOPJ## ;NONE??????
MOVE T1,TRBLNK(T1) ;GET IORB FLAGS
TLNE T1,RB.PCL ;IS THIS A QUEUED REQUEST?
JRST PCLTP1 ;YES
PUSHJ P,TSLEE1## ;NO, LET THE NON-QUEUED STUFF FINISH
JRST CKSIO1 ; BEFORE GETTING INTO QUEUED REQUESTS
PCLTP1: MOVE T1,UDBCAM(U) ;GET ACCESSABILITY MASK
PUSHJ P,CPUOK## ;RETURN CDB OFFSET
JRST [PUSHJ P,HNGSTP## ;"PROBLEM ON DEVICE"
JRST PCLTAP] ;TRY AGAIN
IMULI T1,.CPLEN## ;GET CPU OFFSET
MOVE T2,.CPCHX## ;INDICATE WE NEED CACHE SWEEP
SYSPIF
IORM T2,TUBSTS(U) ;DONT SCHED UNIT TILL SWEEP
IORM T2,TKBSTS(W)
SKIPLE .CPTAP## ;COUNT UP A REQUEST
AOSA .CPTAP##
SOS .CPTAP## ; (.CPTAP COULD BE NEGATIVE)
SYSPIN
PJRST SETQP1## ;RING THE DOORBELL ON THE OWNING CPU
;SUBROUTINE TO GET JOB ONTO ANY CPU WHICH CAN ACCESS THE DEVICE
;CALL: MOVE U, UDB ADDRESS
; PUSHJ P,TAPCPU
TAPCPU::PUSHJ P,SAVT## ;SAVE SOME ACS
TAPCP1: PUSHJ P,TAPACC ;FIND CPU--KDB--UDB PATH
JUMPE W,TAPCP2 ;IF NO KDB, THEN HUNG DEVICE
HLRZS T1 ;ELSE GET ACCESSIBILE CPU NUMBER
PUSHJ P,ONCPUS## ;GET US ONTO THAT CPU
JRST TAPCP2 ;CPU DEAD??
POPJ P, ;RETURN
TAPCP2: PUSH P,F ;SAVE F
SKIPN F,TUBCUR(U) ;GET CURRENT DDB
MOVE F,UDBDDB(U) ;POINT AT USER IF NONE
PUSHJ P,HNGSTP## ;CALL IT A HUNG DEVICE
POP P,F ;RESTORE F
JRST TAPCP1 ;TRY AGAIN
> ;END IFN FTMP
;ROUTINE TO CHECK FOR KDB/UDB ACCESSIBILITY ON THE CURRENT CPU
;CALL: MOVE U, UDB ADDRESS
; PUSHJ P,TAPACC
; <NON-SKIP> ;KDB OR UDB INACCESSIBLE
; <SKIP> ;W POINTS TO THE KDB WHICH CAN DO I/O
;
;NOTE: THE NON-SKIP RETURN MIGHT BE TAKEN IF THE KONTROLLER IS OFFLINE
TAPACC::PUSHJ P,SAVE4## ;SAVE SOME ACS
SETZB P3,P4 ;CLEAR OFFLINE KDB AND BEST KDB
MOVSI P1,-1 ;ASSUME ACTIVE KDB
SKIPLE W,TUBAKA(U) ;GET THE KDB
JRST TAPAC2 ;ENTER LOOP WITH ACTIVE KDB SETUP
MOVSI P1,-MXPORT ;ELSE SCAN ALL DRIVE'S KDBS
XMOVEI P2,UDBKDB(U) ;POINT TO KDB TABLE IN UDB
TAPAC1: SKIPN W,(P2) ;GET A KDB
JRST TAPAC3 ;SLOT EMPTY
TAPAC2: MOVE T1,KDBCAM(W) ;GET ASSESSIBILITY BITS
TDNN T1,UDBCAM(U) ;CAN IT TALK TO THE DRIVE IN QUESTION?
JRST TAPAC3 ;NO, MUST TRY ANOTHER KDB
MOVSI T1,TKSOFL ;OFFLINE BIT
TDNE T1,TKBSTS(W) ;IS KONTROLLER OFFLINE?
JRST TAPAC3 ;YES, TRY ANOTHER KDB
IFE FTMP,<HRRZ T1,KDBCAM(W)> ;GET CPU0,,MASK
IFN FTMP,<
MOVE T1,KDBCAM(W) ;GET KONTROLLER'S CPU ACCESSIBILITY MASK
PUSHJ P,CPUOK## ;FIND A RUNNING CPU
JRST TAPAC3 ;CAN'T DO I/O FROM THIS KONTROLLER
HRLZS T1 ;PUT OWNING CPU IN LH
HRR T1,KDBCAM(W) ;GET CPU MASK
TDNN T1,.CPBIT## ;OUR CPU?
JRST TAPAC4 ;NO, KEEP LOOKING
> ;END IFN FTMP
JRST CPOPJ1## ;RETURN WITH USABLE KDB ADDRESS IN W
TAPAC3: SKIPN P3 ;ALREADY HAVE A KDB INCASE ALL OFFLINE?
MOVE P3,W ;NO, SAVE OFFLINE KDB ADDRESS
SKIPA ;THIS ONE'S NOT ONLINE
TAPAC4: MOVE P4,W ;SAVE BEST ONLINE KDB SO FAR
AOS P2 ;ADVANCE POINTER TO NEXT KDB SLOT
AOBJN P1,TAPAC1 ;LOOP BACK AND CHECK IT OUT
SKIPN W,P4 ;SEE IF WE FOUND AN ACCESSIBLE ONLINE KDB
JRST TAPAC5 ;THERE AREN'T ANY
IFE FTMP,<HRRZ T1,KDBCAM(W)> ;GET CPU0,,MASK
IFN FTMP,<
MOVE T1,KDBCAM(W) ;GET KONTROLLER'S CPU ACCESSIBILITY MASK
PUSHJ P,CAMCPU## ;TRANSLATE TO CPU NUMBER
TSO T1,KDBCAM(W) ;ALL IS WELL, PUT MASK IN LH
MOVSS T1 ;SET RETURNED VALUE TO CPU,,MASK
> ;END IFN FTMP
JRST CPOPJ1## ;RETURN GOODNESS
;HERE WHEN THERE ARE NO ONLINE KDBS
TAPAC5: SKIPE W,P3 ;GET OFFLINE KDB
POPJ P, ;TAKE "NO ACCESS" RETURN
MOVSI P1,-MXPORT ;AOBJN POINTER TO FIND ANY KDB
XMOVEI P2,UDBKDB(U) ;POINT TO KDB TABLE IN UDB
TAPAC6: SKIPE W,(P2) ;PICK ANY EXISTANT KONTROLLER
POPJ P, ;TAKE OFFLINE RETURN
AOS P2 ;ADVANCE PONTER
AOBJN P1,TAPAC6 ;LOOP 'TILL WE FIND ONE
POPJ P, ;RETURN
;ROUTINE TO RETURN AN ACCESSIBILITY MASK FOR A GIVEN DDB
;MUST PRESERVE T2, T3, & W!
TAPCPI::SETZ T1, ;JUST IN CASE
SKIPN TDVUDB##(F) ;CHECK FOR PROTOTYPE
POPJ P, ;IT IS
SE1ENT ;ENTER SECTION ONE
PUSH P,U ;SAVE U
PUSH P,T2 ;AND POSSIBLE BUFFER ADDRESS
PUSH P,W ;AND UUOCON'S SAVED IOACT
MOVE U,TDVUDB##(F) ;POINT TO UDB
PUSHJ P,TAPACC ;CAN WE GET TO IT?
JRST TAPPI1 ;NO
MOVE T1,KDBCAM(W) ;GET MASK
TDNE T1,.CPBIT## ;IF WE CAN USE IT,
AOS -3(P) ;SKIP
SKIPA ;RETURN THE MASK
TAPPI1: SETZ T1, ;NOT ACCESSIBLE
POP P,W ;RESTORE FOR UUOCON
POP P,T2 ;RESTORE POSSIBLE BUFFER ADDRESS
POP P,U ;RESTORE U
POPJ P, ;AND RETURN
SUBTTL QUEUE MANIPULATION
;HERE TO INSERT AN IORB AT THE HEAD OF A UNIT QUEUE
;U/ UDB, T1/ IORB
CPURQH::
IFN FTMP,<PUSHJ P,TAPCPU> ;GET ON THE RIGHT CPU
TAPRQH::MOVEI T2,RB.RPN ;SET IORB TO PENDING
DPB T2,PRBRQS ; ...
TAPOFF ;FIGHT RACE
HRRZ T2,TUBQUE(U) ;GET HEAD POINTER
HRRM T2,TRBLNK(T1) ;FORWARD LINK
HRRM T1,TUBQUE(U) ;NEW HEAD
MOVEM F,TUBCUR(U) ;POINT AT THE RIGHT CULPRIT
PUSHJ P,TAPCNT ;POSSIBLY SCHEDULE I/O
PJRST TPONPJ ;RESTORE INTS AND EXIT
;HERE TO INSERT AN IORB AT THE TAIL OF A UNIT QUEUE
;U/UDB, T1/IORB
CPURQT::
IFN FTMP,<PUSHJ P,TAPCPU> ;GET ON THE RIGHT CPU
TAPRQT::MOVEI T2,RB.RPN ;SET IORB AS PENDING
DPB T2,PRBRQS ; ...
TAPOFF ;FIGHT RACE
HLRZ T2,TUBQUE(U) ;GET TAIL POINTER
HRRM T1,TRBLNK(T2) ;FORWARD LINK AT OLD TAIL
HRLM T1,TUBQUE(U) ;NEW TAIL POINTER
CAIN T2,TUBQUE(U) ;IF FIRST IN Q,
MOVEM F,TUBCUR(U) ;TELL TPMSIO WHO WE ARE
PUSHJ P,TAPCNT ;POSSIBLY SCHEDULE I/O
PJRST TPONPJ ;RETURN
;HERE TO REMOVE THE IORB FROM THE HEAD OF A UNIT QUEUE
TAPREM::TAPOFF ;FIGHT RACE
HRRZ T1,TUBQUE(U) ;GET CURRENT HEAD
JUMPE T1,TPONPJ ;EXIT IF NONE
HRRZ T2,TRBLNK(T1) ;FOLLOW FORWARD LINK
HRRM T2,TUBQUE(U) ;NEW HEAD POINTER
HLRZ T3,TUBQUE(U) ;CHECK IF QUEUE ONLY HAD ONE ELEMENT
CAIE T3,(T1) ;...
JRST TAPRM1 ;NO - LEAVE
MOVSI T2,TUBQUE(U) ;MAKE TAIL POINT TO QUEUE HEAD
MOVEM T2,TUBQUE(U) ; ...
SETZM TUBCUR(U) ;NO CURRENT DDB
JRST TPONPJ ;NO DDB TO FIND IF NO NEXT IORB
TAPRM1: SKIPE T3,TUBDDL(U) ;SEE IF HAVE A LABEL DDB
CAME T2,TDVIOR##(T3) ;IS THIS THE RIGHT DDB FOR THIS IORB?
MOVE T3,UDBDDB(U) ;NO, POINT AT USER
CAMN T2,TDVIOR##(T3) ;LAST CHANCE TO GET IT WRONG
MOVEM T3,TUBCUR(U) ;FOR TPMSIO TO FIND THE RIGHT JOB
TPONPJ: TAPON ;ALLOW INTS
POPJ P,
;HERE WHEN UPPER LEVEL DECIDES THAT A SELECTED IORB IS NOT TO
;BE INITIATED AFTER ALL
TAPFLS::PUSHJ P,TAPDSL ;FLUSH HDWRE
PUSHJ P,TAPREM ;AND PRUNE QUEUE
PUSHJ P,UUOLVL## ;IF NOT ON UUO LEVEL (DIAG)
POPJ P, ; RETURN WITHOUT STARTING ANYTHING
PUSH P,T1 ;SAVE T1
PUSHJ P,CKSIO1 ;SEE IF SCHED CYCLE NEEDED
MOVSI T1,TKSSEL
TDNN T1,TUBSTS(U) ;DID THIS UNIT GET SELECTED AGAIN?
TDON T1,TKBSTS(W) ;NO, DID SOME OTHER UNIT GET SEL'D?
JRST TPOPJ## ;NO, RETURN
TLNE T1,TKSSTD ;YES, WAS IT ACTUALLY STARTED?
JRST TPOPJ## ;YES, RETURN
PUSH P,U ;NO, SAVE U
MOVE U,@KDBCUN(W) ;SET U TO RIGHT UNIT
MOVSI T1,TKSSEL ;NO UNIT IS ACTUALLY STARTED
ANDCAM T1,TUBSTS(U) ; NOW
MOVSI T1,TKSSCH ;INDICATE WE'RE REQUESTING A SCHEDULE
IORM T1,TKBSTS(W) ;FOR THIS KONTROLLER
IFN FTMP,<
MOVEI T1,TKBICT## ;CALL BACK ROUTINE
MOVEM T1,TKBFCT(W) ;ENSURE TAPSCH FINDS IT
> ;END IFN FTMP
SETOM @KDBCHN(W) ;MARK CHANNEL AVAILABLE
MOVE T1,KDBDSP(W)
PUSHJ P,@TPKSCH(T1) ;GO CAUSE AN INTERRUPT ON THAT UNIT
POP P,U ;RESTORE U
JRST TPOPJ## ;RESTORE T1 AND EXIT
SUBTTL NOTIFY OPERATOR OF KONTROLLERS WITH DOWN-LEVEL MICROCODE
;HERE TO TYPE OUT MESSAGE FOR WRONG MICROCODE
;CALL WITH T1/ MICROCODE VERSION,,[ASCIZ PREFIX STRING]
;OR WITH T1/ -1,,[ASCIZ TEXT]
TAPREV::PUSHJ P,SAVT## ;SAVE ACS FOR OUR CALLERS
PUSHJ P,SAVE1## ;FREE UP A PRESERVED AC
MOVE P1,T1 ;COPY TEXT POINTER THERE
PUSHJ P,CTYERM## ;SET FOR ERROR MESSAGE TO CTY
PUSHJ P,INLMES## ;TYPE MESSAGE
ASCIZ /
%Tape controller / ;SAY WHAT DEVICE
MOVE T2,KDBNAM(W) ;GET KON NAME
PUSHJ P,PRNAME## ;TELL OPERATOR
PUSHJ P,INLMES## ;FINISH THIS LINE
ASCIZ / is below required microcode revision levels
% / ;AND FLAG THE NEXT LINE
HRRZ T1,P1 ;RETRIEVE CALLER'S TEXT POINTER
PUSHJ P,CONMES## ;TYPE THAT TOO
JUMPL P1,TAPRV1 ;JUMP IF VERSION NOT GIVEN
PUSHJ P,PRSPC## ;SPACE OVER FOR NUMBER
HLRZ T1,P1 ;GET REVISION NUMBER
PUSHJ P,PRTDI8## ;TYPE THE NUMBER (OCTAL)
TAPRV1: PJRST CRLF## ;TYPE THE CRLF AND RETURN
SUBTTL ERROR RECOVERY PROCEDURE.
;CALL HERE FROM TPMDON WHEN ERROR RECOVERY IS TO BE INITIATED
;SELECT MUST BE ON FOR KDB AND UDB. IORB IN T1.
TAPERP::MOVSI T1,(1B0) ;KDB IS NOT INVALID DURING ERROR PROCESSING
ANDCAM T1,TUBAKA(U) ;CLEAR FLAG
MOVEI T1,TKBERB(W) ;ENQUEUE ERP IORB
HLLOS TKBSTS(W) ;SET INFINITE QUANTUM
PUSHJ P,TAPRQH ;THIS IS CHEATING SLIGHTLY
HRRZ T1,TRBLNK+TKBERB(W) ;RECOVER ORIGINAL IORB
LDB T2,PRBFCN ;GET FUNCTION CODE
LDB T3,ERYCNT ;GET INITIAL RETRY COUNT
DPB T3,TUYECT ;SET IN TUBERR
SETZM TUBTRY(U) ;CLEAR ATTEMPT COUNTER
PUSHJ P,ERPCMV ;CHECK IF TAPE MOVED
TDZA T4,T4 ;NO MOVE
MOVNI T4,1 ;MOVED - ADJUST POSITION
SKIPL ERCTAB(T2) ;WAS OP FORWARD MOTION?
MOVNS T4 ;NO - FIX COUNT
ADD T4,TUBREC(U) ;GET CORRECTED COUNT
JUMPL T4,[SETOM TUBPBE(U) ;IF NEG REC COUNT
JRST ERP0] ;THEN WE WON'T POS CHECK RIGHT
HRL T4,TUBFIL(U) ;ALSO COMPARE FILE POSITION
MOVEM T4,TUBPBE(U) ;STORE POSITION BEFORE ERROR
JRST ERP0 ;START ERP
;HERE ON AN INTERRUPT WHILE THE ERP IS RUNNING
ERPINT: CAIE T1,TKBERB(W) ;BE REAL SURE ALL IS WELL
STOPCD .,STOP,ERF, ;++ERP REALLY FOULED UP
HRRZ T2,TUBERR(U) ;GET DISPATCH ADDR
SKIPE T2 ;CODE ZERO IS ILLEGAL
CAIL T2,XERPMX ;SMALLER THAN MAX?
STOPCD .,STOP,RFU, ;++RECOVERY FOULED UP
MOVE F,TUBCUR(U) ;SET UP F AND S
MOVE S,DEVIOS(F)
JRST @ERPSTB(T2) ;THE LEAP OF FAITH
;HERE TO SEE IF ANYTHING OFFENSIVE HAS HAPPENED TO
;THE IORB IN T1
ANYERR: SKIPL TRBLNK(T1) ;IS EXCEPTION UP?
POPJ P, ;NO - ALL IS WELL.
MOVE T2,TRBSTS(T1) ;GET STATUS WORD
TLNN T2,RB.SER!RB.SED!RB.SLK!RB.SOL!RB.STL ;...
POPJ P, ;NOTHING TO OFFEND
JRST CPOPJ1## ;LOSE
;HERE TO COPY NEEDED THINGS TO THE ERP IORB
SETERB: HRRZ T1,TRBLNK+TKBERB(W) ;GET OLD IORB
HLLZ T3,TRBLNK(T1) ;GET MODE ETC
TLZ T3,RB.EXC ;CLEAR EXCEPTION BIT
HLLM T3,TRBLNK+TKBERB(W) ;STORE IN NEW IORB
HRRZ T3,TRBXCW(T1) ;GET XFR LIST ADDR
MOVEM T3,TRBXCW+TKBERB(W) ;STORE
MOVE T3,TRBRCT(T1) ;COPY WORDCOUNT (FOR TM02)
MOVEM T3,TRBRCT+TKBERB(W)
HLLZ T3,TRBEXL(T1) ;GET END OF XFR LIST
MOVEM T3,TRBEXL+TKBERB(W) ;STORE
POPJ P,
;HERE TO SETUP ERP IORB FOR A NON DATA XFR OP
STERBS: PUSHJ P,SETERB ;SETUP ERB
MOVEI T1,1 ;SET OP COUNT
HRRM T1,TRBXCW+TKBERB(W) ;...
HRRZS TRBEXL+TKBERB(W) ;ALSO CLEAR END OF LIST
MOVEI T1,TKBERB(W) ;ERR REC IORB
POPJ P,
;HERE TO CLEAN UP WHEN LEAVING THE ERP FOR THE LAST TIME
ERPDON: HRRZ T2,TRBLNK+TKBERB(W) ;PNTR TO ACTUAL IORB
MOVE T3,TRBRCT+TKBERB(W) ;LAST BYTE COUNT
MOVEM T3,TRBRCT(T2) ;INTO IORB
PUSHJ P,TAPREM ;REMOVE ERP IORB
MOVE T2,TUBERR(U) ;SAVE STATE WORD AT TERMINATION
MOVEM T2,TUBFES(U) ;AS FINAL ERROR STATE
SETZM TUBERR(U) ;CLEAR STATE INFO
HLLZS TKBSTS(W) ;CLEAR CHANNEL QUANTUM
POPJ P,
;ERP ACTION 0 - REPOSITION IF NEEDED. IORB IN T1
;FCN CODE IN T2
ERP0: PUSHJ P,ERPCMV ;CHECK MOVEMENT
JRST ERP2 ;NO - NO NEED TO REPOSITION
MOVSI T3,(ERCRPS) ;SHOULD REPOSITIONING BE DONE?
TDNN T3,ERCTAB(T2) ; ...
JRST ERP2 ;NO - GO RETRY
PUSHJ P,STERBS ;YES - SETUP ERP IORB
MOVEI T4,RB.FBR ;ASSUME FORWARD MOTION, REPOS W/ BS
SKIPL ERCTAB(T2) ;WAS OP FORWARD MOTION?
MOVEI T4,RB.FSR ;NO-REPOS WITH FWD SPACE
DPB T4,PRBFCN ;STORE FUNCTION CODE
MOVEI T2,XERP1 ;SET NEXT STATE
;HERE TO EXIT AND START IO ON ERP IORB
ERPX0: HRRM T2,TUBERR(U) ;STORE NEXT STATE
MOVEI T1,TKBERB(W) ;GET ERP IORB
PUSHJ P,TAPSIO ;GO INITIATE OP
SETZ T1, ;RETURN ZERO
POPJ P,
;HERE AT TERMINATION OF A REPOSITION
ERP1: MOVSI T2,RB.SNM!RB.SOL ;MOVED OR OFF-LINE?
TDNN T2,TRBSTS(T1)
JRST ERP1A ;SEE IF SPECIAL ACTION
;HERE WHEN RECOVERY HAS FAILED
ERP4: HRRZ T3,TRBLNK+TKBERB(W) ;ORIG IORB
MOVSI T2,RB.SOL ;OFFLINE BIT
TDNE T2,TRBSTS(T1) ;CHECK STATUS
IORM T2,TRBSTS(T3) ;COPY BIT TO ORIG. IORB
PUSHJ P,ERPDON ;CLEAN UP
HRRZ T1,TUBQUE(U) ;GET FORMER IORB
MOVSI T2,RB.SER ;FLAG NON REC ERROR
IORM T2,TRBSTS(T1) ;IN IORB
POPJ P, ;RETURN FAILING IORB
;SEE IF THE LAST OP SHOULD BE ERASED.
ERP1A: HRRZ T1,TRBLNK+TKBERB(W) ;GET ORIGINAL OP
LDB T2,PRBFCN ; ...
CAIE T2,RB.FWT ;WRITE?
CAIN T2,RB.FTM ;OR WRITE TAPE MARK?
JRST ERP5 ;YES
JRST ERP2 ;NO - DO RETRY NOW.
;MORE ERROR RECOVERY PROCEDURE
;HERE TO RETRY A FAILING OPERATION. THE TAPE HAS BEEN
;REPOSITIONED IF NECESSARY
ERP2: MOVE T3,TUBPBE(U) ;GET POSITION BEFORE ERROR
JUMPL T3,ERP2A ;SKIP CHECK IF NEG.
MOVE T2,TUBREC(U) ;CHECK THAT REPOSITIONING
HRL T2,TUBFIL(U) ;HAS BROUGHT US
CAME T2,T3 ;BACK TO BEFORE THE ERROR
JRST ERP4
ERP2A: PUSHJ P,SETERB ;COPY NEEDED GOODIES
HRRZ T1,TRBLNK+TKBERB(W) ;GET OLD IORB
LDB T2,PRBFCN ;GET FUNCTION
LDB T3,ERYFCN ;GET FUNCTION TO RETRY
MOVEI T1,TKBERB(W) ;GET ERP IORB
DPB T3,PRBFCN ;STORE NEW OP.
AOS TUBTRY(U) ;INCREMENT ATTEMPT COUNT
MOVEI T2,XERP3 ;SET NEXT STATE
JRST ERPX0
;HERE ON THE TERMINATION OF A RETRY OPERATION
ERP3: PUSHJ P,ANYERR ;ANY ERRORS TO SPEAK OF?
JRST ERP3B ;NO - WIN WIN WIN
MOVSI T2,RB.SOL!RB.SER ;OFFLINE OR NON-RECOVERABLE
TDNE T2,TRBSTS(T1) ;???
JRST ERP4 ;YES - LOSAGE
LDB T2,TUYECT ;GET RETRY COUNTER
SUBI T2,1 ;DECREMENT
JUMPLE T2,ERP4 ;SIGH - LOSE
DPB T2,TUYECT ;RESTORE COUNT
MOVSI T1,NXTLSE ;GET NEXT TO LAST RETRY BIT
ANDCAM T1,TUBERR(U) ;CLEAR IT
CAIN T2,2 ;IS THIS NEXT TO LAST RETRY?
IORM T1,TUBERR(U) ;YES--THEN SET IT
HRRZ T1,TRBLNK+TKBERB(W) ;GET OLD IORB
LDB T2,PRBFCN ;GET FUNCTION
MOVE T4,TUBTRY(U) ;RE-TRY COUNTER
MOVSI T3,(ERCTCS) ;THIS OP USE TCS?
TDNE T3,ERCTAB(T2) ;??
TRNE T4,3 ;TCS EVERY 4 RE-TRIES
JRST ERP3A ;NO TCS NOW
JRST ERP7 ;TCS TIME NOW
;HERE TO PERFORM REPOS/RETRY
ERP3A: MOVEI T1,TKBERB(W) ;SET UP ERROR IORB
LDB T2,PRBFCN ;AND FUNCTION
JRST ERP0 ;AND TRY THE WHOLE THING AGAIN
;HERE WHEN THE ERROR IS RECOVERED. THE WORLD IS AMAZED.
ERP3B: MOVSI T2,RB.SNM ;CHECK MOVEMENT
TDNE T2,TRBSTS(T1) ;DID IT?
JRST ERP3C ;NO - TRY AGAIN
PUSHJ P,ERPDON ;GO CLEAN UP
HRRZ T1,TUBQUE(U) ;GET OLD IORB
MOVSI T2,RB.SRE ;RECOVERY SUCCEEDED
IORM T2,TRBSTS(T1) ;SET IN IORB
POPJ P, ;RETURN AND REJOICE
;HERE WHEN RETRY DIDN'T MOVE TAPE TRY AGAIN
ERP3C: LDB T2,TUYECT ;GET COUNTER
SUBI T2,1 ;DECREMENT
JUMPLE T2,ERP4 ;ALL THROUGH IF ZERO
DPB T2,TUYECT ;PUT COUNT BACK
JRST ERP2 ;AND RETRY OP
;HERE TO DO AN ERG BEFORE RETRY
ERP5: PUSHJ P,STERBS ;SETUP ERB
MOVEI T2,RB.FLG ;GET ERG FUNCTION
DPB T2,PRBFCN ;STORE IN ERP IORB
MOVEI T2,XERP6 ;NEXT STATE
JRST ERPX0 ;EXIT AND SET STATE
;HERE AT THE TERMINATION OF AN OP BEFORE RETRY.
ERP6: PUSHJ P,ANYERR ;ERRORS?
JRST ERP2 ;NO - DO RETRY
JRST ERP4 ;YES - FAIL
;ERROR RECOVERY TAPE CLEANER SEQUENCE (TCS)
;FCN CODE IN T2
;HERE TO STARTUP TCS
ERP7: MOVEI T1,TKBERB(W) ;GET RETRY IORB
MOVSI T3,RB.SBT!RB.SAP ;AT BOT OR ALREADY REPOSITIONED?
TDNE T3,TRBSTS(T1) ; ???
JRST ERP3A ;YES - NO TCS
MOVEI T4,ERPNCS ;NUMBER OF SPACE OPS IN TCS
SKIPL ERCTAB(T2) ;WAS OP FORWARD MOTION?
SUBI T4,1 ;NO - USE ONE LESS BACKSPACE
DPB T4,TUYEC1 ;STORE IN SECONDARY COUNTER
;HERE TO DO A BACKSPACE AS PART OF A TAPE CLEANER SEQ
ERP8: PUSHJ P,STERBS ;SETUP IORB
MOVEI T2,RB.FBR ;BACKSPACE FUNCTION
DPB T2,PRBFCN ;STORE
MOVEI T2,XERP9 ;NEXT STATE
JRST ERPX0 ;LEAVE
;HERE WHEN A TCS BACKSPACE HAS COMPLETED
ERP9: LDB T2,TUYEC1 ;GET COUNT
SOSL T2 ;DECREMENT
DPB T2,TUYEC1 ;SAVE NEW VALUE
HLRZ T3,TRBSTS(T1) ;GET STATUS
TRNE T3,RB.SBT ;DONE?
JRST ERP9B ;YES - RECOMPUTE SPACE COUNT
TRNE T3,RB.SNM ;DID IT MOVE AT ALL
JRST ERP4 ;NO -******SHOULD FIX POSITION****
JUMPG T2,ERP8 ;TRY AGAIN IF STILL MORE TO GO
MOVEI T4,ERPNCS-1 ;NUMBER OF SPACE OPS
JRST ERP9C
ERP9B: MOVEI T4,ERPNCS-2 ;COMPUTE NUMBER OF SPACE OPS
LDB T2,TUYEC1 ; ...
SUB T4,T2 ; ...
ERP9C: HRRZ T1,TRBLNK+TKBERB(W) ;GET ORIG IORB
LDB T2,PRBFCN ;ORIG FCN
MOVEI T1,TKBERB(W) ;RESTORE ERROR IORB
SKIPL ERCTAB(T2) ;WAS OP FORWARD MOTION?
ADDI T4,1 ;NO - ONE MORE THEN
DPB T4,TUYEC1 ;STORE COUNT
JUMPLE T4,ERP2 ;NONE - GO TRY AGAIN
;FALL THROUGH INTO ERP10.
;FALL THROUGH HERE FROM ERP9C.
;HERE TO DO A SPACE RECORD AS PART OF A TCS
ERP10: PUSHJ P,STERBS ;SETUP IORB
MOVEI T2,RB.FSR ;SPACE OP
DPB T2,PRBFCN ;STORE
MOVEI T2,XERP11 ;NEXT STATE
JRST ERPX0 ;START IO AND EXIT
;HERE ON THE TERMINATION OF A TCS SPACE OP
ERP11: HLRZ T2,TRBSTS(T1) ;GET STATUS
TRNE T2,RB.SNM ;MOVED?
JRST ERP4 ;NO ****SHOULD FIX POSN****
LDB T2,TUYEC1 ;GET COUNT
SUBI T2,1 ;DECREMENT
DPB T2,TUYEC1 ;RESTORE
JUMPLE T2,ERP2 ;CONTINUE RETRY
JRST ERP10 ;MORE SPACES TO DO
;TABLE RELATING STATE CODES TO ROUTINE ADDRS.
ERPSTB: PHASE 0
XWD 0,-1 ;ILLEGAL
XERP1:! IFIW ERP1 ;REPOSITION TERMINATION
XERP3:! IFIW ERP3 ;RETRY TERMINATION
XERP6:! IFIW ERP6 ;ERASE GAP TERMINATION
XERP9:! IFIW ERP9 ;TCS BACKSPACE TERMINATION
XERP11:!IFIW ERP11 ;TCS SPACE TERMINATION
XERPMX:! ;HIGHEST STATE
DEPHASE
;TABLE USED TO GUIDE THE ERROR RECOVERY PROCEDURE
;BITS
ERCFWD==1B0 ;OPERATION MOVES TAPE FOREWARD
ERCRPS==1B1 ;OPERATION NEEDS REPOSITION BEFORE RETRY
ERCCSZ==1B2 ;THIS OP IGNORE "NOISE" RECORDS
ERCTCS==1B3 ;THIS OP USES TCS
;BYTES AND BYTE POINTERS
ERCCTP==^D17 ;INITIAL RETRY COUNT POSITION
ERCCTS==6 ;INITIAL RETRY COUNT SIZE
ERYCNT: POINT ERCCTS,ERCTAB(T2),ERCCTP
ERCFNP==^D35 ;RETRY FUNCTION POSITION
ERCFNS==5 ;RETRY FUNCTION SIZE
ERYFCN: POINT ERCFNS,ERCTAB(T2),ERCFNP
;MACRO TO BUILD ERCTAB ENTRY
DEFINE X(FLGS,CNT,FCN) <
EXP FLGS+<CNT>B<ERCCTP>+<FCN>B<ERCFNP>
>
;THE TABLE
ERCTAB: EXP -1 ;ILLEGAL
X(ERCFWD+ERCRPS+ERCCSZ+ERCTCS,^D40,RB.FCR) ;READ FORWARD
X(ERCFWD+ERCRPS,^D14,RB.FWT) ;WRITE
X(ERCRPS+ERCCSZ+ERCTCS,^D40,RB.FRB) ;READ BACKWARDS
X(ERCFWD+ERCRPS,6,RB.FSR) ;SKIP RECORD
X(ERCRPS,6,RB.FBR) ;BACKSPACE RECORD
X(ERCFWD+ERCRPS,6,RB.FSF) ;SKIP FILE
X(ERCRPS,6,RB.FBF) ;BACKSPACE FILE
X(ERCFWD,6,RB.FLG) ;ERASE GAP
X(ERCFWD,6,RB.FSE) ;DATA SECURITY ERASE
X(0,6,RB.FRW) ;REWIND
X(0,6,RB.FRU) ;REWIND AND UNLOAD
X(ERCFWD+ERCRPS,^D14,RB.FTM) ;TAPE MARK
X(ERCFWD,1,RB.FYB) ;YELLOW BALL
X(ERCFWD+ERCRPS+ERCCSZ,6,RB.FCR) ;CORRECTION READ (ONLY IF USER REQD)
X(ERCFWD+ERCRPS+ERCCSZ+ERCTCS,^D40,RB.FCR) ;READ LOW THRESHOLD
;ROUTINE CHECK IF TAPE MOVED OR ERROR ON NOISE RECORD
;CALL: MOVE T1,IORB
; MOVE T2,FCN
; PUSHJ P,ERPCMV
; RETURN IF NO MOVEMENT
; RETURN IF MOVEMENT
ERPCMV: MOVE T4,TRBRCT(T1) ;GET BYTE COUNT
MOVSI T3,(ERCCSZ) ;SIZE CHECK?
TDNN T3,ERCTAB(T2) ;...
JRST ERPCM1 ;NO - PROCEED
CAIGE T4,NOISE## ;IS THIS A NOISE RECORD
JUMPGE T4,CPOPJ## ;NOISE IF NOT AN IOWD - DIDN'T MOVE
ERPCM1: MOVSI T3,RB.SNM!RB.SAP ;NO - CHECK PHYSICAL MOVEMENT
TDNN T3,TRBSTS(T1) ;...
AOS 0(P) ;OK
POPJ P, ;RETURN
SUBTTL COMMON ROUTINES
;ROUTINES COMMON TO ALL KONTROLLER DEPENDENT CODE
;HERE ON REWIND DONE
REWDON::MOVSI T2,TUSREW!TUSFLT ;NO LONGER REWINDING
ANDCAM T2,TUBSTS(U) ;...
UNIBOT::MOVSI T2,TUSBOT ;ALSO NOW AT BOT
IORM T2,TUBSTS(U) ; ...
SETZM TUBREC(U) ; ...
SETZM TUBFIL(U) ; ...
PJRST TAPCTM ;CLEAR HUNG TIMER AND RETURN
;HERE TO VERIFY THAT TUBQUE POINTS TO A REASONABLE IORB
CHKIRB::HRRZ T1,TUBQUE(U) ;GET HEAD IORB
JUMPE T1,CPOPJ## ;EXIT IF NOT REQUEST BLOCK
LDB T2,PRBRQS ;GET REQUEST STATUS
CAIN T2,RB.ACT ;ACTIVE?
AOS (P) ;YES - GIVE GOOD RETURN
POPJ P,
;ROUTINE TO HANDLE SPURIOUS INTERRUPTS
TAPDIS::MOVE T1,KDBDSP(W) ;GET DISPATCH
PUSHJ P,@TPKIDL(T1) ;SET CTRL IDLE (USER WILL GET HUNG DEVICE)
MOVSI T2,TKSSCH ;TEST SCHED REG. BIT
MOVEI T1,0 ;ASSUME IGNORE INT.
TDNE T2,TKBSTS(W) ;WANT SCHED. CYCLE?
MOVNI T1,1 ;YES- INFORM WORLD
POPJ P, ; AND EXIT
;ROUTINE TO SET UP U TO POINT TO UDB MENTIONED IN T2
;C(T2) = UNIT # , C(W) = KDB ADDRS
;NON-SKIP RETURN IF NON-EX UNIT
;SKIP RETURN IF UNIT IS OK
SETUDB::MOVE U,KDBIUN(W) ;POINTER TO UDB TABLE
ADD U,T2 ;PLUS OFFSET
SKIPN U,0(U) ;SEE IF ONE EXISTS
POPJ P,
PJRST CPOPJ1##
;TABLE USED TO CONVERT IORB MODE TO CHARS/WORD
TMODTB::0 ;0 - ILLEGAL
5 ;1 - 9-TK CORE DUMP
4 ;2 - 9-TK INDUSTRY COMPAT.
6 ;3 - TU70 SIXBIT
5 ;4 - TU70 MARVELOUS ASCII
6 ;5 - 7-TK CORE DUMP
;TABLE TO CONVERT IORB MODE TO FRAME SIZE
TMODFS::0 ;0 - ILLEGAL
0 ;1 - CORE DUMP (N/A)
8 ;2 - 9 TK INDUSTRY COMPATIBLE
6 ;3 - SIXBIT
7 ;4 - ASCII
0 ;5 - 7 TK CORE DUMP (N/A)
LIT
$LOW
IFN FTMP,<
CPUTPQ::BLOCK 1 ;COUNT OF CPUS WAITING FOR SWEEP
>
TPSEND: END