mirror of
https://github.com/PDP-10/stacken.git
synced 2026-03-01 01:19:17 +00:00
1715 lines
55 KiB
Plaintext
1715 lines
55 KiB
Plaintext
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
|