Trailing-Edge
-
PDP-10 Archives
-
bb-bt99h-bb
-
tapser.x14
There are 3 other files named tapser.x14 in the archive. Click here to see a list.
TITLE TAPSER - COMMON MAGTAPE PHYSICAL IO DRIVER V1040
SUBTTL L.BOSACK/TAH/TW 27 MAY 86
SEARCH F,S
IFE FTKS10,<SEARCH ICHPRM>
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1974,1986>
;COPYRIGHT (C) 1974,1975,1976,1977,1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
;
XP VTAPSR,1040 ;FOR LINKEDIT MAP
SALL
TAPSER:: ENTRY TAPSER
;BIT DEFINITIONS
;IN TKBSTS
;BITS 0-2 = CPU NUMBER WHICH "OWNS" CONTROL
;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==(17B10) ;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
;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
TPKINI==:0 ;INITIALIZATION CODE
TPKRES==:1 ;RESET ACTIVE TRANSFER
TPKSIO==:2 ;START IO
TPKINT==:3 ;INTERRUPT ROUTINE
TPKCMD==:4 ;SET DEVICE COMMAND IN LIST (DX10 ONLY)
TPKIDL==:5 ;SET DEVICE IDLE
TPKONL==:6 ;SKIP IF KON ONLINE
TPKSCH==:7 ;CAUSE SCHEDULE CYCLE
TPKINX==:10 ;INITIALIZATION CODE AFTER SYSTEM STARTUP
;(WHEN KONTROLLER COMES ONLINE, ETC.)
TPKLOD==:11 ;LOAD MICROCODE
TPKEDL==:12 ;ENABLE/DISABLE MICROCODE LOADING
TPKCFG==:13 ;AUTO-CONFIG. ONLY NEEDED FOR TAPES WITH SUBUNITS
;EG TM02, TM78
;BYTE POINTERS
;INTO KDB
TKYCPU:: POINT 3,TKBSTS##(W),2
;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 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::
IFE FTKS10,<
SKIPG TKBUNI##(W) ;MULTI UNITS ON AN RH?
JRST TAPIN2 ;NO, CARRY ON
XCT TKBCIS##(W) ;YES. CONI
TRNE T2,CI.DON ;IF DONE IS ON
JRST TAPIN2 ; THE INTERRUPT IS FROM THIS KDB
MOVSI T2,(.DIASR) ;ATTEN INTERRUPT. READ ATTN SUMMARY
XCT TKBDOS##(W) ; REGISTER
IMULI P,1
IMULI P,1 ;STALL IN CASE AN RH10
XCT TKBDIS##(W) ;READ ATTENTION BITS
ANDI T2,377 ;GET JUST ATTENTION BITS
MOVE T1,W ;SAVE STARTING KDB ADDR
TAPIN1: TDNE T2,TKBUNI##(W) ;INTERRUPT FOR THIS KDB?
JRST TAPIN2 ;YES. HANDLE IT
HLR W,TKBCDB##(W) ;NO, STEP TO NEXT KDB ON CONTROLLER
CAME T1,W ;BACK WHERE WE STARTED?
JRST TAPIN1 ;NO, SEE IF INTERRUPT FOR THIS KDB
HRLI T2,(.DIASR!DO.LDR!DO.DRE) ;YES, NOT FOR ANY KDB WE KNOW OF
XCT TKBDOS##(W) ; SO CLEAR THE INTERRUPT
POPJ P, ;AND GO AWAY
>
TAPIN2: HRRZ T1,TKBDSP##(W) ;GET XFER VECTOR
PUSHJ P,@TPKINT(T1) ;CALL DEV DEP INT RTN
TAPAGO::JUMPE T1,CPOPJ## ;IF ZERO, ANOTHER INT IS COMING
JUMPL T1,TPINT1 ;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,TPINT1 ;NO COMPLETION
MOVEI T2,RB.DUN ;MARK IORB AS DONE
DPB T2,PRBRQS ;...
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
TPINT1: SETZB S,F ;MAKE SURE IOSCP2 IS OFF
SETZM TKBTIM##(W) ;CLEAR HUNG TIMER
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::
HRRZ T1,TKBDSP##(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
HRRZ T1,TKBCDB##(W) ;LOC OF CHANNEL DATA BLOCK
SETOM (T1) ;INDICATE THAT CHAN 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: PUSH P,W ;SAVE INITIAL KDB
HRRZS (P) ;SAVING ONLY RIGHT HALF
MOVE T4,TKBCUN##(W) ;GET CURRENT AOBJN POINTER
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
AOBJP T4,TPSCH2 ;AND START LOOKING AT NEXT UNIT
TPSCH1: SKIPN U,(T4) ;GET UDB
JRST TPSCHN ;NONE PRESENT
HRRZ T1,TUBQUE##(U) ;GET QUEUE POINTER
JUMPE T1,TPSCHN ;GO IF NONE
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 ;NO. 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
AOBJN T4,TPSCH1 ;NEXT UNIT
TPSCH2: MOVSI T2,TKSSCH
ANDCAM T2,TKBSTS##(W)
TPSC2A: HLRZ W,TKBCDB##(W) ;STEP TO NEXT KDB ON THIS CHANNEL
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
IORM T2,TKBSTS##(W)
MOVE T4,TKBIUN##(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
HRRZ 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
HRRZ T2,TKBDSP##(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,TKBCUN##(W) ;STORE CURRENT UNIT
MOVSI T2,TKSSEL ;FLAG AS SELECTED
IORM T2,TKBSTS##(W) ;IN KDB
IORM T2,TUBSTS##(U) ;AND IN UDB
HRRZ T2,TKBCDB##(W) ;LOC OF CHAN DATA BLOCK
AOS (T2) ;INDICATE THAT CHAN IS BUSY
MOVEI T2,MQUANT## ;SET SLICE
HRRM T2,TKBSTS##(W) ; ..
HLRZ T3,TUBADR##(U) ;GET KON1 ADR
HLRZ T2,TUBKDB##(U) ;SETUP CURRENT KON AND ADR
CAIE T2,(W) ; ...
HRRZ T3,TUBADR##(U) ; ...
HRLM T3,TUBAKA##(U) ;STORE UNIT ADDR
HRRM W,TUBAKA##(U) ;STORE 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
POPJ P, ;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::MOVE T2,TKBSTS##(W) ;KONTROLLER STATUS
TAPOFF ;GUARD AGAINST
TLNE T2,TKSOFL ;CONTROLLER INTERRUPTS
JRST TPONPJ ;WHICH SET CONTROLLER OFFLINE
TLOE T2,TKSSEL ;SELECTED?
TLZE T2,TKSSTD ;AND NOT STARTED
STOPCD TAPSI3,DEBUG,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,DEBUG,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
MOVSI T2,TKSSTD ;MARK AS STARTED
IORM T2,TKBSTS##(W) ;IN KDB
IORM T2,TUBSTS##(U) ;AND UDB
MOVE T2,TUBITM##(U) ;SET UP TIMER
MOVEM T2,TUBTIM##(U) ; FOR MISSED REWIND-DONE INTERRUPT
HRRZ T2,TKBDSP##(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
DPB T2,TDYHNG## ;ONLY TRY ONCE
MOVEM T2,TKBTIM##(W) ;LIMIT FOR TAPSEC
POPJ P, ;GIVE FORCED DEVHNG RETURN
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. (IT IS UNLIKELY ANYTHING WILL
; BE THERE, BUT IN CASE..)
CHKKON: SKIPN W,CNFMTK## ;GET FIRST KDB
JRST CPOPJ1## ;NO TAPES
CHKKNL: MOVSI T1,TKSMNT ;BIT TO TEST
IFN FTMP,<
LDB T2,TKYCPU ;IF ON DIFFERENT CPU
CAMN T2,.CPCPN## ; DONT CHECK ON THIS ONE
>
TDNE T1,TKBSTS##(W) ; TOO SEE IF WE SHOULD CHECK
JRST CHKNXT ; IF HE IS ONLINE
HRRZ T1,TKBDSP##(W) ;GET XFR VECTOR
PUSHJ P,@TPKONL(T1) ;SEE IF ONLINE
JRST CHKOFL ;NOT ON LINE - COMPLAIN
MOVSI T1,TKSOFL ;NOW ONLINE - SEE IF
TDNN T1,TKBSTS##(W) ;IF FORMERLY OFFLINE.
JRST CHKNXT ;NO
TLO T1,TKSSCH!TKSSTD!TKSSEL!TKSSIL!IFN FTMP,<TKSCHE!TKSCHA>
;CLR THESE ALSO
ANDCAM T1,TKBSTS##(W) ;CLEAR OFFLINE
MOVSI T2,TKSSTD!TKSSEL!IFN FTMP,<TKSCHE!TKSCHA> ;BITS TO CLEAR IN UDB
MOVE T3,TKBIUN##(W) ;GET AOBJN PNTR TO LIST
CHKUNL: SKIPE U,0(T3) ;UNIT PRESENT?
ANDCAM T2,TUBSTS##(U) ;YES - CLEAR BITS
AOBJN T3,CHKUNL ;LOOP TILL DONE
HRRZ T1,TKBDSP##(W) ;YES - GET XFR VECTOR
PUSHJ P,@TPKINX(T1) ;CALL TO INITIALIZE
IFN FTMP,<
SETZB S,F
>
PUSHJ P,CKSIO2 ;CLANK SCHED FOR THIS KON.
CHKNXT:
IFN FTMP,<
MOVEI T1,TKBICT##
SKIPGE TKBFCT##(W)
MOVEM T1,TKBFCT##(W) ;ABJECT PARANOIA
>
HRRZ W,TKBKDB##(W) ;GET NEXT KDB
JUMPN W,CHKKNL ;IF THE IS ONE, CHECK IT.
PJRST CPOPJ1## ;ELSE SKIP OVER ARG
CHKOFL:
IFN FTAUTC,<
MOVE T1,TKBIUN##(W) ;IF A KON BUT NO UNITS
SKIPN (T1)
AOBJP T1,CHKNXT ;DON'T COMPLAIN ABOUT IT
>
PUSHJ P,@0(P) ;CALL CO-ROUTINE
JRST CHKNXT ;CONTINUE LOOP
;ONCE A SECOND - JUST CHECK AND UPDATE INFO
TAPSEC::PUSHJ P,CHKKON ;CRAWL THROUGH DATA BASE
JRST SETOFL ;WHERE TO GO FOR OFF-LINE CTL
SKIPN W,CNFMTK## ;START AT FIRST KONTROLLER
POPJ P, ;NO TAPES
TAPSE1:
IFN FTMP,<
LDB T1,TKYCPU ;IF ON DIFFERENT CPU
CAME T1,.CPCPN## ; DONT DECR. TIMER ON THIS ONE
JRST TAPSE5
>
SOSE TKBTIM##(W) ;HUNG MTAPE?
JRST TAPSE3 ;NO
MOVE U,TKBCUN##(W) ;GET RIGHT UNIT
MOVE U,(U)
MOVSI T1,TUSFLT ;FAULTY DRIVE BIT
TDNE T1,TUBSTS##(U) ;DID THE DRIVE GO BAD?
JRST TAPSE2 ;YES, IGNORE SPECIAL CASE FOR SCHEDULE
MOVSI T1,TKSSCH ;HUNG TRYING TO FORCE A SCHEDULE?
TDNN T1,TKBSTS##(W) ;...
JRST TAPSE2 ;NO, MUST BE A REAL TAPE OPERATION
HRRZ T1,TKBDSP##(W) ;YES, TRY AGAIN
PUSHJ P,@TPKSCH(T1) ;BY REQUESTING ANOTHER INTERRUPT
JRST TAPSE5 ;LOOK TO NEXT KONTROLLER
TAPSE2: MOVE T1,TUBSTS##(U)
TLNN T1,TKSSEL ;IS UNIT SELECTED?
JRST TAPSE5 ;NO, BETTER HUNG THAN STOPCD
MOVE F,TUBCUR##(U) ;YES, SET SO DEVCHK WILL CATCH IT
MOVEI T1,1
DPB T1,PDVCNT##
MOVEI S,IOACT
IORM S,DEVIOS(F)
TAPSE3: MOVE T1,TKBIUN##(W) ;SET TO LOOK AT ALL UNITS ON KDB
MOVSI T2,TUSREW ;BITS TO CLEAR
TAPSE4: SKIPE U,(T1) ;UDB EXIST?
SOSE TUBTIM##(U) ;YES, TIMER GONE TO 0?
CAIA ;NO
ANDCAM T2,TUBSTS##(U) ;YES, CLEAR UNIT-IS-REWINDING (MISSED AN INTERRUPT)
AOBJN T1,TAPSE4 ;LOOP FOR ALL UNITS ON KDB
TAPSE5: HRRZ W,TKBKDB##(W) ;STEP TO NEXT KONTROLLER
JUMPN W,TAPSE1
POPJ P, ;DONE - RETURN
SETOFL: MOVSI T1,TKSOFL
TDNE T1,TKBSTS##(W) ;ON LINE?
POPJ P, ;NO - JUST RETURN
HRRZ T1,TKBDSP##(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,CNFMTK## ;YES, 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
LDB T1,TKYCPU ;IS THE KDB ON THIS CPU?
CAMN T1,.CPCPN##
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,TKBIUN##(W) ;START AT THE BEGINNING
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: AOBJN T2,TAPT1A ;YES, TRY NEXT
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: HRRZ W,TKBKDB##(W) ;STEP TO NEXT KDB
JUMPN W,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,CNFMTK## ;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,TKBIUN##(W) ;START AT 1ST UDB
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: AOBJN T3,TAPTI6
SYSPIN
TAPTI8: HRRZ W,TKBKDB##(W) ;STEP TO NEXT KDB
JUMPN W,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 HUNG DEVICE
TAPHNG::TAPOFF ;WHO KNOWS WHAT EVIL...
HRRZ W,TUBAKA##(U) ;GET CURRENT KDB
HRRZ T2,TKBDSP##(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 ;CLEAR STARTED
ANDCAM T1,TUBSTS##(U) ;IN UDB
TLO T1,TKSSCH ;ALSO CLEAR SCH
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
>
;PRUNE QUEUE, DESELECT,PION
TAPKIL::TAPOFF ;FIGHT RACE
HRRZ W,TUBAKA##(U) ;GET KONTROLLER
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
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
HLRZ W,TUBKDB##(U) ;CHECK ONE KONT
PUSHJ P,CKSIO1 ; ...
JUMPN W,CPOPJ##
HRRZ W,TUBKDB##(U) ;AND THEN THE OTHER
;FALL INTO CKSIO1
CKSIO1: JUMPE W,CPOPJ## ;IF NONE, PUNT
IFN FTMP,<
LDB T2,TKYCPU ;CPU WHICH OWNS CONTROL
DPB T2,DEYCPF## ;LET REST OF WORLD KNOW
PUSHJ P,CHKCPI## ;ARE WE ON THAT CPU?
PJRST PCLTAP ;NO, QUEUE THE REQUEST
>
TLZ S,IOSCP2 ;MAKE SURE IOSCP2 IS OFF
CKSIO2: HRRZ T3,TKBCDB##(W) ;POINT AT CHAN DATA BLOCK
MOVSI T2,TKSSEL!TKSSCH!TKSOFL
SYSPIF
SKIPGE (T3) ;IS CHAN 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 (T3) ;INDICATE THAT CHAN 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
JRST FUPOPJ## ;RESTORE F,U,AND RETURN
CKSIO3: MOVE U,(P) ;RESTORE U
CKSIO4: HRRZ T1,TKBCDB##(W)
SOS (T1) ;INDICATE CHAN IS NOT BUSY
JRST TPOPJ## ;MAKE STACK RIGHT 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: PUSHJ P,CPUOFS## ;GET CPU WHICH OWNS THE DEVICE
SKIPG .C0OK##(T1) ;IS THAT CPU ALIVE AND WELL?
JRST PCLTP2 ;YES
PUSHJ P,HNGSTP## ;NO, "PROBLEM ON DEVICE"
JRST PCLTAP ;AND TRY, TRY AGAIN
PCLTP2: 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 SETQPB## ;RING THE DOORBELL ON THE OWNING CPU
;SUBROUTINE TO GET JOB ONTO THE CPU WHICH OWNS THE DEVICE
TOCPU:: HLRZ W,TUBKDB##(U)
SKIPN W
HRRZ W,TUBKDB##(U)
PUSH P,T1
TOCPU1::LDB T1,TKYCPU ;CPU WHICH OWNS THE DEVICE
PUSHJ P,ONCPUS## ;GET US ONTO THAT CPU
JRST [PUSHJ P,HNGSTP##
JRST TOCPU1]
JRST TPOPJ## ;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,TOCPU
>
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
PUSHJ P,TAPCNT ;SEE IF THE CHANNEL NEEDED TO BE POKED
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,TOCPU
>
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
PUSHJ P,TAPCNT
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 TPONPJ ;NO - LEAVE
MOVSI T2,TUBQUE##(U) ;MAKE TAIL POINT TO QUEUE HEAD
MOVEM T2,TUBQUE##(U) ; ...
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,TKBCUN##(W)
MOVE U,(U) ;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
MOVE T1,[TKBICT##,,TAPTIM##]
HRRZM T1,TKBTIM##(W) ;SET TIMER TO CATCH LOST INTERRUPT
IFN FTMP,<
HLRZM T1,TKBFCT##(W) ;ENSURE TAPSCH FINDS IT
>
MOVE T1,TKBCDB##(W) ;MARK CHAN AVAILABLE
SETOM (T1)
HRRZ T1,TKBDSP##(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,TKBNAM##(W) ;GET KON NAME
ADD T2,['A'-'0',,0] ;EXTERNALIZE IT
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::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
0,,-1 ;ILLEGAL
XERP1:! ERP1 ;REPOSITION TERMINATION
XERP3:! ERP3 ;RETRY TERMINATION
XERP6:! ERP6 ;ERASE GAP TERMINATION
XERP9:! ERP9 ;TCS BACKSPACE TERMINATION
XERP11:! 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) ; ...
POPJ P,
;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::HRRZ T1,TKBDSP##(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 LF NON-EX UNIT
;SKIP RETURN IF UNIT IS OK
SETUDB::MOVEI U,TKBUDB##(W) ;BASE ADDRS
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)
TPSEND: END