Trailing-Edge
-
PDP-10 Archives
-
dec-10-omona-u-mc9
-
tapser.mac
There are 11 other files named tapser.mac in the archive. Click here to see a list.
TITLE TAPSER - COMMON MAGTAPE PHYSICAL IO DRIVER V032
SUBTTL L.BOSACK/TAH/TW 08 MAR 77
SEARCH F,S
$RELOC
$HIGH
;***COPYRIGHT 1974,1975,1976,1977 DIGITAL EQUIPMENT CORP., MAYNARD, MASS.***
XP VTAPSR,032 ;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
;IN TUBSTS
TUSNS==:(1B0) ;DO NOT SCHEDULE THIS UNIT (SIGN BIT)
TUSBOT==:(1B1) ;BEGINNING OF TAPE
TUSWTL==:(1B2) ;WRITE LOCKED
TUSREW==:(1B3) ;TAPE REWINDING
TUSBOF==:TUSBOT!TKSOFL
;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
;PI SYSTEM DEFINITIONS
TPIOFF==:PI.TFP+TAPBIT## ;TURN OFF TAPE CHL
TPION==:PI.TNP+TAPBIT## ;TURN ON TAPE CHL
;ERROR RECOVERY PARAMETERS
ERPNCS==5 ;NUMBER OF BACKSPACE/SPACE OP IN TAPE CLEANER SEQ.
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
;BYTE POINTERS
;INTO KDB
;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::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 SCHEC 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: 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
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: MOVSI T2,TKSOFL!TKSMNT ;CHECK IF HE IS AMOUNG US
TDNE T2,TKBSTS##(W) ;...
JRST TPSCHX ;NO - JUST EXIT
MOVE T4,TKBCUN##(W) ;GET CURRENT AOBJN POINTER
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
SKIPL T2,TUBSTS##(U) ;NO SCHED?
TLNE T2,TKSSEL ;OR SELECTED BY ANOTHER?
JRST TPSCHN ;YES
JRST TPSCH3 ;FOUND 1 - USE IT
TPSCHN: CAMN T4,TKBCUN##(W) ;BACK TO ORIGINAL UNIT?
JRST TPSCHX ;NOTHING TO DO - NON SKIP RETURN
AOBJN T4,TPSCH1 ;NEXT UNIT
TPSCH2: MOVE T4,TKBIUN##(W) ;RESET POINTER
JRST TPSCH1 ;CONTINUE SEARCH
;HERE WHEN A REQUEST IS FOUND
TPSCH3: 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
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 0(P) ;SET FOR SKIP RETURN
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
TLOE T2,TKSSEL ;SELECTED?
TLZE T2,TKSSTD!TKSOFL ;AND NEITHER STARTED NOR OFF-LINE?
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 ; ...
MOVSI T2,TKSSTD ;MARK AS STARTED
IORM T2,TKBSTS##(W) ;IN KDB
IORM T2,TUBSTS##(U) ;AND UDB
HRRZ T2,TKBDSP##(W) ;GET KONTROLLER DISPATCH
PJRST TPKSIO(T2) ;CALL START I/O
;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
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: MOVEI W,MT0KDB## ;GET FIRST KDB
CHKKNL: MOVSI T1,TKSMNT ;BIT TO TEST
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 ;CLR THESE ALSO
ANDCAM T1,TKBSTS##(W) ;CLEAR OFFLINE
MOVSI T2,TKSSTD!TKSSEL ;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,TPKINI(T1) ;CALL TO INITIALIZE
PUSHJ P,CKSIO1 ;CLANK SCHED FOR THIS KON.
CHKNXT: HRRZ W,TKBKDB##(W) ;GET NEXT KDB
JUMPN W,CHKKNL ;IF THE IS ONE, CHECK IT.
PJRST CPOPJ1## ;ELSE SKIP OVER ARG
CHKOFL: 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
MOVEI W,MT0KDB## ;START AT FIRST KONTROLLER
TAPSE1: SOSE TKBTIM##(W) ;HUNG MTAPE?
JRST TAPSE2 ;NO
MOVE U,TKBCUN##(W) ;YES, GET RIGHT UNIT
MOVE U,(U)
MOVE T1,TUBSTS##(U)
TLNN T1,TKSSEL ;IS UNIT SELECTED?
JRST TAPSE2 ;NO, BETTER HUNG THAN STOPCD
MOVE F,TUBCUR##(U) ;YES, SET SO DEVCHK WILL CATCH IT
LDB J,PJOBN## ;JOB OWNING TAPE
MOVE T2,JBTSTS##(J)
TLNE T2,SWP ;CANT CALL HNGSTP IF SWAPPED
JRST TAPSE2 ; SO HAVE TO GIVE UP
MOVEI T1,1
DPB T1,PDVCNT##
MOVEI S,IOACT
IORM S,DEVIOS(F)
TAPSE2: 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
IORM T1,TKBSTS##(W) ;YES - ITS OFF NOW
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
SUBTTL HUNG DEVICE
TAPHNG::TAPOFF ;WHO KNOWS WHAT EVIL...
HRRZ W,TUBAKA##(U) ;GET CURRENT KDB
HRRZ T2,TKBDSP##(W) ;CALL KON RESET ENTRY
PUSHJ P,TPKRES(T2) ; ...
MOVSI T1,TKSSTD ;CLEAR STARTED
ANDCAM T1,TUBSTS##(U) ;IN UDB
TLO T1,TKSSCH ;ALSO CLEAR SCH
ANDCAM T1,TKBSTS##(W) ;IN KDB
;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) ; ...
HLLZS TKBSTS##(W) ;ZERO QUANTUM
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) ;...
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 ; ...
HRRZ W,TUBKDB##(U) ;AND THEN THE OTHER
;FALL INTO CKSIO1
CKSIO1: JUMPE W,CPOPJ ;IF NONE, PUNT
MOVSI T2,TKSSEL!TKSSCH!TKSOFL
TDNE T2,TKBSTS##(W) ; ARE ANY OF THESE ON?
POPJ P, ;YES - SOMETHING WILL HAPPEN
MOVSI T2,TKSSCH ;SET SCHED REQUESTED
IORM T2,TKBSTS##(W) ;...
PUSH P,U ;SAVE U
PUSHJ P,TAPSCH ;TRY TO START SOMETHING
JRST UPOPJ## ;NOTHING TO DO, RETURN FOR NOW
MOVE T1,F ;STARTED, SAVE F
MOVE F,TUBCUR##(U) ;CURRENT DDB
LDB F,PJOBN## ;JOB NUMBER
EXCH T1,F ;T1=JOB, RESTORE F
PUSHJ P,EWAKE## ;RESTART THE JOB, HE HAS THE KONTROLLER NOW
JRST UPOPJ## ;RESTORE U AND RETURN
SUBTTL QUEUE MANIPULATION
;HERE TO INSERT AN IORB AT THE HEAD OF A UNIT QUEUE
;U/ UDB, T1/ IORB
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
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
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
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 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
CAILE 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
ERPX: 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 ;OFFLINE
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
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 ;AT BOT?
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
POPJ P, ;YES - NO MOVEMENT
ERPCM1: MOVSI T3,RB.SNM ;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 ;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
TPSEND: END