Trailing-Edge
-
PDP-10 Archives
-
bb-jr93j-bb
-
7,6/ap023/t78kon.x23
There is 1 other file named t78kon.x23 in the archive. Click here to see a list.
TITLE T78KON - RH20/TM78/TU78/TX79 DRIVER FOR TAPSER V132
SUBTTL T WACHS/TW/DPM/RJF 16-MAY-89
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 1980,1981,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1980,1988>
XP VT78KN,132
SALL
T78KON::ENTRY T78KON
;OFFSETS INTO TKBCCL
TKBSCW==TKBCCL+1 ;SAVED CHANNEL WORD
TKBFLG==TKBCCL+2 ;FLAGS FROM FNCTBL
TKBCHR==TKBCCL+3 ;CHARACTER (FRAME) COUNT
TKBSCH==TKBCCL+4 ;-1 IF A SCHEDULE CYCLE
T78DMX==4 ;MAXIMUM DRIVES PER KONTROLLER
T78HDN==T78DMX-1 ;HIGHEST DRIVE NUMBER ON KONTROLLER
T78AMX==^D10 ;MAX ASYNCH INTERRUPTS BEFORE
; SHUTTING DOWN THE TM78
T78IRE==INSVL.(.CCFTH,CC.OPC)!INSVL.(17,CC.WDC)!INSVL.(T78REG+30,CC.ADR)
;IOWD TO READ ERROR LOG INFO
;DRIVER CHARARCTERISTICS
; T78 = T78CNF
; MTA = MAGTAPE
; 0 = MAXIMUM DEVICES IN SYSTEM (NO LIMIT)
; K.T78 = KONTROLLER TYPE
; T78DMX = MAXIMUM DRIVES PER KONTROLLER
; T78HDN = HIGHEST DRIVE NUMBER ON KONTROLLER
; MDSEC0 = SECTION FOR KDB/UDB
; MDSEC0 = SECTION FOR DDB
DRVCHR (T78,MTA,0,K.T78,T78DMX,T78HDN,MDSEC0,MDSEC0,<DR.XAD!DR.MCD!DR.DPU!DR.GCC!DR.DDN>)
.ORG TKBUDB ;START OF TM78 SPECIFIC DATA
T78UTB:! BLOCK T78DMX ;TABLE OF POINTERS TO UDBS
T78UVA:! BLOCK 1 ;USER IOWD
T78RRO:! BLOCK 1 ;IOWD FOR RETRY OPPOSITE OR ZERO
T78ACT:! BLOCK 1 ;COUNT OF CONTINUOUS ASYNC INTERRUPTS
T78XIW:! BLOCK 1 ;IOWD TO READ ERROR LOG INFO
T78ROM:! BLOCK 2 ;ROM REV LEVELS
T78IUM:! BLOCK T78DMW ;IGNORE DRIVE MASK
T78NUM:! BLOCK T78DMW ;NEW DRIVE MASK
T78KLN:! ;LENGTH OF KDB
.ORG
.ORG TUBLEN
T78ICS:! BLOCK 47
T78ISE:! BLOCK 1 ;LAST WORD IN INITIAL STATISTICS
T78REG:! BLOCK 50
T78ESD:! BLOCK 1 ;TEMP USED DURING ERROR SENSE
T78SNS:! BLOCK 1 ;INDICATES A SENSE IS IN PROGRESS
T78ULN:! ;LENGTH OF UDB
.ORG
T78KDB: KDBBEG (T78,T78KLN)
SETWRD (KDBNAM,<SIXBIT/MT/>) ;KONTROLLER NAME
SETWRD (KDBIUN,<TKBUDB>) ;INITIAL POINTER TO UNITS
SETWRD (KDBCUN,<TKBUDB>) ;CURRENT POINTER TO UNITS
SETWRD (KDBPCC,<TKWCCL,,TKBCCL>) ;PHYSICALLY CONTIGUOUS CORE
SETWRD (KDBIUM,<T78IUM>) ;OFFSET TO IGNORE UNIT MASK
SETWRD (KDBNUM,<T78NUM>) ;OFFSET TO NEW UNIT MASK
SETWRD (KDBSTS,<INSVL.(1,KD.MPT)>) ;INITIALLY ONE PATH
IFN FTMP,<SETWRD (TKBFCT,<TKBICT##>)> ;FAIRNESS COUNTER FOR QUEUED I/O
SETWRD (T78XIW,<T78IRE>) ;IOWD TO READ ERROR LOG INFO
KDBEND
T78UDB: UDBBEG (T78,T78ULN)
SETWRD (UDBNAM,<SIXBIT/MT/>) ;DRIVE NAME
SETWRD (UDBPCC,<20,,T78REG+30>);PHYSICALLY CONTIGUOUS CORE
SETWRD (TUBIEP,<-50,,T78ICS>) ;INITIAL ERROR POINTER
SETWRD (TUBFEP,<-50,,T78REG>) ;FINAL ERROR POINTER
UDBEND
EQUATE (LOCAL,0,<T78ULP,T78ULB>)
EQUATE (LOCAL,CPOPJ##,<T78CMD,T78EDL,T78IDL,T78LOD>)
T78ICD==TAPICD## ;PROTOTYPE INTERRUPT CODE ADDRESS
T78ICL==TAPICL## ;PROTOTYPE INTERRUPT CODE LENGTH
T78INT==TAPINT## ;INTERRUPT SERVICE
T78ELG==TPELGX## ;MAKE AN ERROR LOG ENTRY
T78DSP: DRVDSP (T78,TAPCHN##,TDVDDB##,TDVLEN##,TPMDIA##)
TPK (T78,NO,16K) ;SERVICE DEPENDENT DISPATCH
T78CKT: EXP K.T78,0 ;COMPATIBLE KONTROLLER TABLE
T78NBF: TPNBF (<SR,BR,SF,BF,RW,RU>) ;NON-BLOCKING FUNCTION MASK
SUBTTL PARAMETERS
;DRIVE REGISTERS USED IN DATAO'S
.DOCR==0B5 ;DRIVE CONTROL REGISTER
.DOICD==1B5 ;INTERRUPT CODE (DATA XFER)
DO.ICD==77 ;INTERRUPT CODE
DI.FCD==176000 ;FAILURE CODE
.DOFMT==2B5 ;RECORD COUNT/FORMAT
DO.SER==100000 ;SUPRESS ERROR RETRY
DO.RC1==4 ;RECORD COUNT RIGHTMOST BIT
.DOER==3B5 ;ERROR REGISTER
.DOAS==4B5 ;ATTENTION SUMMARY
.DOBC==5B5 ;BYTE COUNT
.DODT==6B5 ;DRIVE TYPE
.DOSR==7B5 ;STATUS REGISTER
DI.RDY==100000 ;READY
DI.PRS==40000 ;PRESENT
DI.PE==4000 ;PHASE ENCODED
DI.BOT==2000 ;BOT
DI.FPT==400 ;FILE PROTECTED
DI.AVL==200 ;AVAILABLE
DI.MNT==40 ;IN MAINTENANCE MODE
.DOSN==10B5 ;SERIAL NUMBER
.DODG==11B5 ;DIAGNOSTIC
.DODG2==12B5 ;DIAGNOSTIC
ICNREG==13
.DOICN==13B5 ;INTERRUPT CODE (NON DATA-XFER)
DI.DRV==1400 ;DRIVE NUMBER
.DOND0==14B5 ;NON DATA-XFER COMMAND, UNIT 0
DO.NDC==177400 ;COUNT FIELD
DO.NDF==77 ;FUNCTION CODE
NDCSHF==^D8 ;SHIFT VALUE FOR COUNT
.DOND1==15B5 ;COMMAND, UNIT 1
.DOND2==16B5 ;COMMAND, UNIT 2
.DOND3==17B5 ;COMMAND, UNIT 3
.DOIA==20B5 ;INTERNAL ADDRESS
.DOTMS==21B5 ;TM STATUS
DI.TMR==1B20 ;TM READY
DO.TMC==1B21 ;TM CLEAR
DO.HLA==1B26 ;HOLD ACKNOWLEDGED
DO.HLD==1B27 ;HOLD
;DRIVE FUNCTIONS
DF.NOP==3 ;NO-OP
DF.UNL==5 ;UNLOAD
DF.REW==7 ;REWIND
DF.SNS==11 ;SENSE
DF.DSE==13 ;DATA SECURITY ERASE
DF.WTM==15 ;WRITE TAPE MARK (PE)
DF.SPF==21 ;SPACE FORWARD RECORD
DF.SPR==23 ;SPACE REVERSE RECORD
DF.SFF==25 ;SPACE FORWARD FILE
DF.SRF==27 ;SPACE REVERSE FILE
DF.SFE==31 ;SPACE FORWARD RECORD OR FILE
DF.SRE==33 ;SPACE REVERSE RECORD OR FILE
DF.ERG==35 ;ERASE 3 INCHES OF TAPE (PE)
DF.CLF==41 ;CLOSE FILE (PE) - 2 EOFS, BACKSP 1
DF.LET==45 ;SKIP TO LOGICAL EOT
DF.WRT==61 ;WRITE (PE)
DF.RED==71 ;READ
DF.RRV==77 ;READ REVERSE
DF.XSN==73 ;EXTENDED SENSE
;BYTE POINTER TO FAILURE CODE IN EXTENDED SENSE DATA
TUYECD: POINT 8,T78REG+30(U),35
SUBTTL START IO
;HERE TO START IO
T78SIO: PUSHJ P,CHKIRB## ;GET IORB FOR THIS OP
JRST TAPDIS## ;NONE, GO AWAY
PUSHJ P,SAVE1## ;SAVE P1
LDB T4,PRBFCN## ;FUNCTION
SKIPN T78RRO(W) ;ARE WE IN RETRY OPPOSITE?
JRST T78SI1 ;NO
CAIN T4,RB.FRB ;YES, TRYING TO DO A REVERSE READ?
MOVEI T4,RB.FRD ;YES, RETRY FORWARD
CAIN T4,RB.FCR ;DOING A CORRECTIVE READ?
MOVEI T4,RB.FRB ;YES, READ BACKWARDS
T78SI1: SKIPN P1,FNCTBL(T4) ;LEGAL?
JRST ILLFNC ;NO
SKIPGE T2,TRBRCT(T1) ;IF POSITIVE IN ERROR RECOVERY
MOVEM T2,T78UVA(W) ;REAL IOWD - SAVE IT
SKIPGE T78ACT(W) ;DID WE SHUT OFF TM TO PREVENT EXCESSIVE INTERRUPTS?
PUSHJ P,CLRHLD ;YES, CLEAR HOLD SO WE CAN TALK TO IT AGAIN
SETZM T78ACT(W) ;CLEAR ASYNC INTERRUPT COUNT
LDB T4,PRBDEN## ;GET DENSITY
CAIGE T4,RB.D16 ;TOO LOW?
MOVEI T4,RB.D16
CAILE T4,RB.D62 ;TOO HIGH?
MOVEI T4,RB.D62
DPB T4,PRBDEN## ;TELL THE REST OF THE WORLD
CAIN T4,RB.D62 ;6250?
TLNN P1,(TB.WRT) ;YES, WRITE?
JRST T78SI2 ;NO
TROA P1,WT.GCR ;YES, SET 6250 IN FUNCTION
ILLFNC: MOVE P1,FNCNOP ;ILLEGAL FNCN - JUST GET AN INTERRUPT
JRST T78SI2 ;GO START THE OPERATOIN
SENSE: MOVEM P1,T78SNS(U) ;TELL INTERRUPT SERVICE WE ARE DOING A SENSE
T78SI2: PUSH P,T1 ;SAVE T1
MOVEI T1,CO.MBE ;ENABLE THE MASSBUS, DISABLE INTERRUPTS
XCT KDBCNO(W)
POP P,T1 ;RESTORE T1
MOVE T3,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
SKIPE T78SNS(U) ;SENSE?
JRST [MOVEI T2,DF.SNS ;YES, DO IT
JRST T78SI3]
JUMPL P1,T78SI4 ;NO, GO IF A DATA OP
MOVE T2,@IRBACC(T1) ;SENSE OR NON-DATA. GET COUNT
LSH T2,NDCSHF ;POSITION IT
ANDI T2,DO.NDC ;MASK OUT GARBAGE
TRO T2,(P1) ;SET FUNCTION FROM TABLE
T78SI3: ADDI T3,<(.DOND0)>_-14 ;GET RIGHT REGISTER (14=DRIVE 0, 15=DRIVE 1,...)
DPB T3,[POINT 4,T2,5] ;SAVE REGISTER IN FUNCTION
JRST T78SI6 ;GO START UP THE WORLD
;HERE TO START A DATA OPERATION
T78SI4: LDB T4,PRBMOD## ;GET MODE
SKIPGE T4,MODTBL(T4) ;LEGAL?
JRST ILLFNC ;NO
MOVEI T2,(T4) ;YES. SET MODE IN COMMAND
TRO T2,DO.RC1(T3) ;RECORD COUNT=1, SET UNIT
TLNE S,IOSRTY## ;IF NOT DOING RETRIES
TRO T2,DO.SER ;INFORM THE HARDWARE
HRLI T2,(.DOFMT) ;TELL MODE, COUNT, UNIT
PUSHJ P,WTMBR##
MOVS T2,T78UVA(W) ;GET WORD COUNT
HLRZS T4 ;NO OF FRAMES PER WORD
TLOE T2,-1 ;DO WE ALREADY HAVE FRAME COUNT ?
IMULI T2,(T4) ;COMPUTE FRAME COUNT
MOVNM T2,TKBCHR(W) ;SAVE IN KDB
MOVNS T2 ;+FRAME COUNT
ANDI T2,DO.ERD ;ONLY 16 BITS WORTH
HRLI T2,(.DOBC)
PUSHJ P,WTMBR## ;TELL BYTE COUNT REGISTER
MOVE T2,KDBICP(W) ;INITIAL CNTRL WORD ADDRESS
HRRZ T3,@IRBACC(T1) ;LOC OF FIRST IOWD
TLO T3,(INSVL.(.CCJMP,CC.OPC)) ;MAKE A JUMP TO IT
MOVEM T3,(T2) ;STORE IN ICWA
HRRZ T2,P1 ;FUNCTION (READ/WRITE, PE/GCR)
T78SI5: TDO T2,[.DOSTC!DO.RCP!DO.SCS!DO.CNT]
T78SI6: SKIPN T78SNS(U) ;IF NOT DOING A SENSE
MOVEM T2,T78REG+5(U) ;SAVE FUNCTION IN UDB FOR SYSERR
MOVE T3,T2 ;COPY FUNCTION WORD
ANDI T3,77 ;MASK TO FUNCTION BYTE
CAIE T3,DF.SNS ;IF NOT DOING A SENSE,
MOVEM P1,TKBFLG(W) ;SAVE WHAT THE KONTROLLER IS DOING
PUSHJ P,WTMBR## ;START UP THE WORLD
SKIPGE P1 ;DATA OP?
PUSHJ P,SETIVI ;YES, RESET INTERRUPT VECTOR ADDR
PUSH P,T1 ;SAVE T1
XCT KDBCNI(W) ;CONI
MOVE T2,T1 ;COPY RESULTS
MOVEI T1,TAPCHN##+CO.AIE+CO.MBE
TRNE T2,CI.RAE ;REGISTER ACCESS ERROR?
MOVEI T1,TAPCHN##+CO.MBE+CO.STP ;YES, GET TO INTERRUPT LEVEL NOW
XCT KDBCNO(W) ;NO, ENABLE FOR INTERRUPTS
POP P,T1 ;RESTORE
SKIPE T78SNS(U) ;SENSE?
RTZER: SETZ T1, ;YES, ANOTHER INTERRUPT COMING
POPJ P, ;RETURN TO TAPSER
SUBTTL CHECK FOR KONTROLLER BUSY
;CHECK FOR KONTROLLER BUSY
;CALL: MOVE W, KDB ADDRESS
; MOVE U, UDB FOR DRIVE TRYING TO SCHEDULE
; PUSHJ P,T78BSY
; <RETURN 1> ;BUSY
; <RETURN 2> ;NOT-BUSY
; <RETURN 3> ;DON'T KNOW
;
;USES T1 AND T2
T78BSY: MOVE T1,KDBCHN(W) ;LOOK AT THE CHANNEL DATA BLOCK
MOVE T1,CHNTBP##(T1) ;SEE IF MORE THAN ONE KONT ON THE RH20
AOBJN T1,CPOPJ2## ;IF SO, THEN AVOID OVERHEAD & SAY "DON'T KNOW"
PUSHJ P,SAVE1## ;SAVE P1
PUSH P,U ;SAVE U
MOVE P1,KDBIUN(W) ;POINT TO START OF DRIVE TABLE
T78BS1: SKIPE U,(P1) ;GET A TUB ADDRESS
PUSHJ P,CHKIRB## ;SEE IF IT HAS A VALID IORB
JRST T78BS2 ;TRY ANOTHER DRIVE
LDB T2,PRBFCN## ;GET FUNCTION CODE
MOVE T2,BITTBL## ;NOT PICK UP THE ASSOCIATED BIT
TDNN T2,T78NBF ;NON-BLOCKING FUNCTION?
POPJ P, ;NO--KONT IS BUSY
T78BS2: CAMGE P1,KDBFUN(W) ;CHECKED ALL DRIVES?
AOJA P1,T78BS1 ;LOOP BACK FOR ANOTHER
JRST UPOPJ1## ;RESTORE U AND RETURN KONT NOT BUSY
SUBTTL INTERRUPT PROCESSING
T78ISR: PUSHJ P,SAVE4## ;SAVE SOME ACS
PUSHJ P,SVMBR## ;SAVE CURRENT MBR FOR UUO LEVEL
SETZ P4, ;CLEAR TO GET TRBSTS FLAGS
MOVE P1,TKBFLG(W) ;GET COMMUNICATION/FLAGS WORD
MOVE P2,KDBCSO(W) ;GET TAPICD BLOCK ADDRESS
MOVE P2,TAPCII##(P2) ;GET CONI BITS AT INTERRUPT
TRNE P2,CI.RAE ;REGISTER ACCESS ERROR?
JRST NOATT1 ;YES, HANDLE IT
MOVSI T2,(.DOAS) ;NO, READ ATTEN SUMMARY
PUSHJ P,RDMBR##
ANDI T2,377 ;JUST REAL ATTENTIONS
TDNN T2,KDBUNI(W) ;ATTENTION FOR THIS KDB?
JRST NOATTN ;NO
PUSHJ P,ATTEN ;GO HANDLE IT
POPJ P, ;ASYNC EVENT - RETURN 0 OR -1 TO TAPSER
JUMPE T1,INTREW ;REW COMPLETE IF T1=0
SKIPN T78SNS(U) ;COMPLETE A SENSE?
TLNN P1,(TB.DAT) ;NO, DATA OPERATION IN PROGRESS?
JRST CHEKIT ;SENSE OR NON-DATA
TLO P4,RB.SDE ;DATA OPERATION + ATTENTION - CANT HAPPEN
JRST DONE ;SO LIGHT AN ERROR AND RETURN
;HERE IF NO ATTENTIONS
NOATTN: TRNN P2,CI.DON ;DONE?
JRST RTZER ;NO, ERROR (NO ATTEN, NOT DONE = RH20 GOOFED)
NOATT1: SKIPE T1,TKBSCH(W) ;SCHEDULE CYCLE?
JRST SCHDON ;YES, TELL TAPSER ABOUT IT
PUSH P,T1 ;SAVE T1
MOVEI T1,CO.CCD!CO.MBE;NO, CLEAR DONE
XCT KDBCNO(W)
MOVEI T1,CI.DON ;CLEAR IN INTERRUPT CONI WORD ALSO
MOVE T2,KDBCSO(W)
ANDCAM T1,TAPCII##(T2)
POP P,T1 ;RESTORE T1
MOVE U,@KDBCUN(W) ;UNIT WE ARE TALKING TO
SKIPE T78SNS(U) ;DOING A SENSE?
TLNN P1,(TB.XSN) ;YES, AN EXTENDED SENSE?
JRST NOATT2 ;NO
MOVE T2,TKBSCW(W) ;YES, RESTORE REAL CHAN GOTO WORD
MOVEM T2,@KDBICP(W)
SETZM TKBSCW(W) ;INDICATE WE DON'T HAVE A REAL IOWD ANY MORE
PUSHJ P,ATTEN3 ;FINISH UP INTERRUPT PROCESSING
JRST CLRCTL ;ASYNC
JRST CHEKIT ;KEEP ON TRUCKIN
NOATT2: MOVSI T2,(.DOICD) ;GET INTERRUPT CODE
PUSHJ P,RDMBR##
MOVE P3,T2 ;WHERE ATTEN6 WANT IT
PUSHJ P,ATTEN6 ;CHECK IT FOR GOODNESS
PJRST CLRCTL ;ASYNC EVENT (!)
TLNE T4,RB.SER!RB.SED ;IF AN ERROR,
JRST CHEKIT ; DON'T BOTHER CHECKING CHANNEL FOR ERRORS
MOVE T3,KDBICP(W) ;GET LOC OF LOGOUT AREA
HLL P2,1(T3) ;GET RH20 LH FLAGS
TLC P2,(CS.NAE)
TLNE P2,(CS.SWC) ;IF SHORT WORDCOUNT (RECORD TOO LONG)
TRZ P2,CI.OVR ;THEN OVERRUN CAME UP ERRONEOUSLY
TDNE P2,[CS.ERR!CI.ERR] ;CHANNEL ERROR?
JRST CHNERR ;TOO BAD
CHEKIT: LDB T4,[POINT 4,P1,17] ;GET INDEX INTO FUNCTION TABLE
HLLZ P4,TRBSTS(T1) ;GET ERROR BITS
TLNN P1,(TB.ERA!TB.REW) ;ERASE OR REWIND?
TLNE P4,RB.SNM!RB.SAP ;NO, ANY TAPE MOTION
JRST NOTM ;DON'T UPDATE TUBREC/FIL
MOVEI T2,1 ;ASSUME FORWARD
TLNE P1,(TB.REV) ;IS IT?
MOVNI T2,1 ;NO
ADDM T2,TUBREC(U) ;UPDATE TUBREC
LDB T3,PRBFCN## ;GET IORB FUNCTION
CAIE T3,RB.FSF ;SKIP FILE?
CAIN T3,RB.FBF ;BACKSPACE FILE?
TLO P4,RB.STM ;SUCCESSFUL COMPLETION HERE NOT AN EXCEPTION
HLLM P4,TRBSTS(T1) ;POSSIBLY UPDATE IORB STATUS
TLNN P1,(TB.WTM) ;JUST WRITE AN EOF?
TLNE P4,RB.STM ; OR JUST SEE AN EOF?
CAIA ;YES
JRST NOTM ;NO
ADDM T2,TUBFIL(U) ;UPDATE TUBFIL
SETZM TUBREC(U) ;AT 0TH RECORD
NOTM: MOVSI T2,TUSBOT ;ASSUME NOT AT BOT
ANDCAM T2,TUBSTS(U)
TLNE P4,RB.SBT ;ARE WE?
IORM T2,TUBSTS(U) ;YES, TELL THE REST OF THE WORLD
PJRST @INTABL(T4) ;THE LEAP OF FAITH
;SUBROUTINE TO HANDLE ATTENTION INTERRUPTS
;EXIT T1=IORB OR T1=0 IF REWIND JUST FINISHED
;NON-SKIP IF ASYNCHRONOUS EVENT, SKIP-RETURN NORMALLY
ATTEN: MOVSI T2,(.DOICN) ;READ THE INTERRUPT CODE
PUSHJ P,RDMBR##
MOVE P3,T2 ;SAVE IT (DISAPPEARS AFTER CLEARING ATTENTION)
HRRZ T2,KDBUNI(W) ;GET BIT FOR ATTENTIONS ON THIS UNIT
HRLI T2,(.DOAS)
PUSHJ P,WTMBR## ;CLEAR THIS ATTENTION, LEAVE ANY OTHERS ALONE
LDB T1,[POINT 2,P3,27] ;GET UNIT
ADD T1,KDBIUN(W) ;POINT AT RIGHT UDB
SKIPE U,(T1) ;SET UP U TO UDB
JRST ATTEN2 ;INTERRUPT FROM UNKNOWN DRIVE
;HERE IF NO UDB IS FOUND FOR THE INTERRUPT ADDRESS
LDB T1,[POINT 5,P3,35] ;GET INTERRUPT CODE
CAIE T1,ICDND1 ;IS IT ONE FOR WHICH THE ADDRESS ISNT VALID?
CAIN T1,ICDND2
SKIPA T1,KDBCUN(W) ;YES, BLAME IT ON THE CURRENT UNIT
JRST ATTE15 ;NO,NEW UNIT
SKIPN U,(T1) ;SET U TO CURRENT UDB
JRST CLRINT
ATTEN2: SKIPN T78SNS(U) ;DOING A SENSE?
JRST ATTEN6 ;NO
MOVE P1,T78SNS(U) ;SET P1 FOR THIS FUNCTION
TLZN P1,(TB.RRG) ;SENSE WHILE READING REGISTERS?
JRST ATTEN4 ;NO, CARRY ON
PUSHJ P,RDREG2 ;YES, READ REGS 7, 10, 11
SKIPGE T78ESD(U) ;SENSE AFTER AN RH20 ERROR?
JRST ATTEN3 ;NO
MOVE T4,[IC.BST!RB.SED] ;YES, CAUSE AN ERROR BIT TO GET LIT IN IORB
JRST ATTEN9
ATTEN3: MOVE T4,T78ESD(U) ;RESTORE ERROR BITS
TLNE T4,(IC.XSN) ;NEED EXTENDED SENSE INFO?
TLOE P1,(TB.XSN) ;YES, HAVE WE DONE IT ALREADY?
JRST ATTEN9 ;FINISH UP INTERRUPT
JRST ATTE14 ;GO CRANK UP EXTENDED SENSE
ATTEN4: MOVSI T2,(.DOSR) ;READ THE STATUS REGISTER
PUSHJ P,RDMBR##
JUMPL P1,ATTEN6 ;GO IF A DATA OP
MOVSI T4,TUSWTL##!TUSBOT## ;NON-DATA, CLEAR WRITE-LOCK BIT, BOT
ANDCAM T4,TUBSTS(U)
TRNN T2,DI.FPT ;SET IT AGAIN IF TAPE REALLY IS WRITE LOCKED
TLZ T4,TUSWTL## ;NOT WRITE-LOCKED
TRNN T2,DI.BOT
TLZ T4,TUSBOT## ;NOT AT LOAD-POINT
IORM T4,TUBSTS(U)
; JRST ATTEN6 ;PUSH ON
;HERE ON NORMAL ATTENTION INTERRUPT
ATTEN6: LDB T2,[POINT 5,P3,35] ;GET INTERRUPT CODE
CAIE T2,ICDND1 ;ASYNC INTERRUPT WHERE REGS NOT READ?
CAIN T2,ICDND2
JRST [MOVEI T1,T78REG+7(U) ;YES. CLEAR OUT OLD INFO
SETZM -1(T1) ; SO AS NOT TO CONFUSE FIELD-SERVICE
HRLI T1,-1(T1) ; SINCE WE CAN'T GET ANY OTHER INFORMATION
BLT T1,T78REG+47(U)
MOVEM P3,T78REG+6+ICNREG(U) ;SAVE INTERRUPT CODE
JRST .+1]
CAILE T2,MAXICD ;LEGAL?
MOVEI T2,0 ;NO
SKIPN P3,T78RRO(W) ;DOING RETRY OPPOSITE?
JRST ATTEN8 ;NO
TLC P1,(TB.REV) ;YES, THE OPERATION IS REALLY IN THE OTHER DIRECTION
SETZM T78RRO(W) ;EITHER WIN OR RETRY IN ORIGINAL DIRECTION - CLEAN UP
PUSH P,T2
PUSHJ P,CHKIRB## ;GET IORB
JRST ATTEN7 ;NONE (!)
LDB T3,PRBFCN## ;GET FUNCTION
HLRZ T2,TUBCHR(U) ;GET WORDCOUNT OF RECORD
SKIPL FNCTBL(T3) ;IF A DATA OPERATION
JRST ATTEN7 ;NOT A DATA OP!
HRRZ T3,@IRBACC(T1) ;GET CHANNEL COMMAND
PUSHJ P,REVCCW## ;RE-REVERSE THE IO LIST
HLLM P3,(P3) ;RESTORE ORIGINAL LH OF CHANGED IOWD
ATTEN7: POP P,T2
ATTEN8: SKIPL T4,ICDTBL(T2) ;GET BITS/DISPATCH ADDRESS
JRST ATTEN9 ;NO ERROR, KEEP ON
SKIPE TUBERR(U) ;ERROR. FIRST TIME WE'VE SEEN IT?
TRNN T4,RB.SAP ;YES. DOES TM REPOSITION ON THIS ERROR?
JRST ATTE13 ;1ST TIME OR NO REPOS, READ REGISTERS
ATTEN9: TLNN T4,(IC.RRG) ;WIN WITH NO ERRORS?
SKIPN TUBERR(U) ;YES, IN ERROR RETRY?
CAIA
PUSHJ P,RDREG3 ;GOOD RETRY - READ WINNING REGISTERS
TLNN T4,(IC.ASY) ;ASYNC INTERRUPT?
AOS (P) ;NON ASYNC - SKIP RETURN
TLNE T4,(IC.DSP) ;DISPATCH ON THIS CONDITION?
PJRST (T4) ;YES, GO TO SUBROUTINE
ATTE10: TLNN T4,(IC.BST) ;NO, SET A BIT?
TDZA T4,T4 ;NO
HRLZS T4 ;YES
PUSHJ P,CHKIRB## ;NO, POINT T1 AT IORB
SETZ T1, ;NO IORB
MOVE T2,TUBSTS(U) ;GET STATUS
TLNE T2,TUSREW## ;WAS IT REWINDING?
JRST ATTE11 ;YES, PROBABLY ASYNC INTERRUPT AT BOT
JUMPE T1,ATTE12 ;GO IF NO IORB
IORM T4,TRBSTS(T1) ;LIGHT BIT IN IORB
POPJ P, ;AND RETURN
;HERE IF TUSREW IS ON IN TUB
ATTE11: JUMPE T1,CPOPJ## ;AT BOT IF NO IORB
LDB T2,PRBFCN## ;IORB - IS IT THE REWIND?
CAIE T2,RB.FRU
CAIN T2,RB.FRW
POPJ P, ;YES. REW WHEN WE'RE AT BOT (IMMEDIATE DONE INTERRUPT)
JRST RTZER ;NO, ANOTHER IORB HAS BEEN QUEUED. WE'RE AT BOT
;HERE WITH NO IORB, TAPE WAS NOT REWINDING
ATTE12: SOS (P) ;NON-SKIP RETURN
SETZB T1,T78SNS(U) ;PROBABLY SENSE AFTER ON-LINE
POPJ P, ;RETURN WITH T1=0
;HERE ON AN ERROR WHICH REQUIRES READING THE DRIVE REGISTERS
ATTE13: SETZM T78RRO(W) ;CLEAN UP FLAGS
PUSHJ P,RDREGS ;READ REGS (7-10 AREN'T CORRECT)
TLO P1,(TB.RRG) ;INDICATE WHY WE'RE DOING THE SENSE
MOVEM T4,T78ESD(U) ;SAVE ERROR BITS FOR WHEN SENSE FINISHES
PJRST SENSE ;DO A SENSE SO WE CAN READ REGS 7-10
;HERE WHEN WE NEED TO START AN EXTENDED SENSE OPERATION TO READ ERROR INFO
ATTE14: MOVEM P1,T78SNS(U) ;UPDATED FLAGS WORD
XMOVEI T2,TKBCCL(W) ;WHERE TO DO THE SENSE
MAP T2,(T2) ;CONVERT TO PHYSICAL ADDRESS
TLZ T2,(MP.NAD)
TLO T2,(INSVL.(.CCJMP,CC.OPC)) ;MAKE AN RH20 JUMP WORD
EXCH T2,@KDBICP(W) ;SAVE CURRENT ICWA, SET UP JUMP TO TEMP
MOVEM T2,TKBSCW(W)
MOVE T2,T78XIW(W) ;IOWD TO READ SENSE BYTES INTO TUB
ADDI T2,(U) ;POINT AT RIGHT TUB
HLLZM T2,TKBCCL(W) ;SAVE WHERE ICWA POINTS
MAP T2,(T2) ;COMPUTE PHYSICAL ADDRESS
TLZ T2,(MP.NAD) ;CLEAR EXTRANEOUS BITS
IORM T2,TKBCCL(W) ;COMPLETE THE IOWD
MOVE T2,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
TRO T2,DO.RC1 ;SET UP FORMAT REGISTER
HRLI T2,(.DOFMT) ; ONLY NEEDS UNIT NUMBER
PUSHJ P,WTMBR##
MOVEI T2,DF.XSN ;FUNCTION IS EXTENDED SENSE
PJRST T78SI5 ;GO CRANK IT UP AND RETURN 0 TO TAPSER
;HERE ON AN INTERRUPT OF A NEW (UNKNOWN) UNIT
ATTE15: LDB T1,[POINT 2,P3,27] ;DRIVE NUMBER
MOVE T1,BITTBL##(T1) ;TRANSLATE TO BIT REPRESENTATION
IORM T1,T78NUM(W) ;REMEMBER TO CONFIGURE LATER
HRROS KDBNUM(W) ;FLAG IT FOR THE REST OF THE WORLD TO SEE
JRST RTZER ;AND CHUCK THE INTERRUPT
;HERE ON READ INTERRUPT
INTRD: MOVE T2,TUBREC(U) ;SET MODE/DENSITY IF FILE 0, RECORD 1
SKIPE TUBFIL(U) ;IN THE FIRST FILE?
JRST INTRD2 ;NO, DON'T WORRY ABOUT MODE/DENSITY
SOJG T2,INTRD2 ;YES, JUMP IF PAST 1ST RECORD
SKIPN T78SNS(U) ;SENSE DONE ALREADY?
SKIPE P4
JRST INTRD1 ;YES, GO READ STATUS REGISTER
TLO P4,RB.SNM ;NO, LITE "NO MOTION" BIT SO CHEKIT
IORM P4,TRBSTS(T1) ; WON'T INCREMENT TUBREC AGAIN
PJRST SENSE ;GO DO THE SENSE
INTRD1: TLZ P4,RB.SNM ;CLEAR "NO MOTION" SO STATS ARE CORRECT
MOVSI T2,(.DOSR) ;SENSE ALREADY DONE, READ STATUS REGISTER
PUSHJ P,RDMBR##
MOVEI T3,RB.D16 ;SET TAPE'S DENSITY IN IORB
TRNN T2,DI.PE
MOVEI T3,RB.D62
DPB T3,PRBDEN##
INTRD2: MOVSI T2,(.DOBC) ;READ BYTE COUNT
PUSHJ P,RDMBR##
MOVEM T2,TRBRCT(T1) ;SAVE BYTE COUNT IN IORB
MOVEM T2,TUBCCR(U) ; AND IN TUB
TLZ T2,-1 ;CLEAR POSSIBLE FLAG
SKIPN P4 ;IF NO ERROR
ADDM T2,TUBCRD(U) ; UPDATE TOTAL STATS
ADDM T2,TKBCRD(W)
ADDM T2,.CPTFI##
CAMLE T2,TKBCHR(W) ;TOO LARGE A RECORD?
TLO P4,RB.STL!RB.SER ;YES, TELL TAPUUO
LDB T3,PRBMOD## ;MODE
IDIV T2,TMODTB##(T3) ;COMPUTE NUMBER OF WORDS XFERRED
HRLM T2,TUBCHR(U) ;SAVE WORDS
DPB T3,PMTNCR## ;SAVE RESIDUE
JRST DONE
;HERE ON WRITE INTERRUPT
INTWRT: MOVE T2,TKBCHR(W) ;NO OF FRAMES WE WROTE
ADDM T2,TUBCWR(U) ;UPDATE STATS
ADDM T2,TKBCWR(W)
ADDM T2,.CPTFO##
JRST DONE ;AND FINISH UP
;HERE ON A REREAD OPPOSITE INTERRUPT
INTRRO: PUSHJ P,CHKIRB## ;SET T1 TO IORB
JRST INTRR1 ;NONE(!) CALL IT A HARD ERROR
MOVSI T2,(.DOBC) ;READ THE BYTE COUNT REGISTER
PUSHJ P,RDMBR##
JUMPE T2,INTRR1 ;THE TM78 BLEW IT IF BYTE COUNT IS 0
MOVN T3,T2 ;-VE BYTE COUNT
HRLZM T3,T78UVA(W) ;TO TELL THE TM78 THE RIGHT BYTE COUNT
LDB T3,PRBMOD## ;MODE
IDIV T2,TMODTB##(T3) ;CONVERT BYTES TO WORDS
JUMPN T3,INTRR1 ;LOSE IF A NON-INTEGRAL NUMBER OF WORDS
HRRZ T3,@IRBACC(T1) ;POINT TO CHANNEL COMMAND
PUSHJ P,REVCCW## ;GOODNESS. REVERSE THE IO LIST
MOVEM T2,T78RRO(W) ;SAVE ORIGINAL IOWD ADDR AND LH
MOVE T4,[IC.BST!RB.SED!RB.SDE!RB.SAP] ;SOME ERROR BITS TO SET
JRST ATTE10 ;AND KEEP GOING WITH ANALYSIS (WILL EVENTUALLY RETRY)
INTRR1: MOVE T4,NRTERD ;CANT RETRY OPPOSITE
JRST ATTEN9 ;READ REGISTERS AND GIVE NON-RECOVERABLE ERROR
INTRWP: MOVSI T2,TUSREW## ;SAY WE'RE REWINDING
IORM T2,TUBSTS(U)
HRRZ T1,TUBQUE(U) ;SET T1 TO IORB (OR 0)
TLZ P1,17 ;SO WE DON'T GO TO INTREW NOW
JRST CPOPJ1## ;SKIP RETURN TO T78INT
INTUNL: MOVSI T2,TKSOFL## ;LET REST OF WORLD KNOW
IORM T2,TUBSTS(U) ; THAT THE DRIVE IS OFF-LINE
TLO P4,RB.SOL ;SAY DRIVE IS OFF-LINE
INTREW: PUSHJ P,REWDON## ;TELL WORLD WE'RE THROUGH REWINDING
SETZM TUBREC(U) ;CLEAR STATS
SETZM TUBFIL(U)
JUMPE T1,CLRCTY ;JUST RETURN TO TAPSER IF WE WEREN'T AT BOT ALREADY
JRST DONE ;AND FINISH UP
;HERE ON ANY FLAVOR OF OFF-LINE/NOT AVAILABLE TO THIS MASSBUS INTERRUPT
INTOFL: PUSHJ P,CHKIRB## ;DOING AN OPERATION?
JRST OFLUNI ;NO, ASYNC. RETURN 0 TO TAPSER
MOVSI T2,RB.SOL!RB.SER!RB.SNM ;YES, TELL WORLD NOTHING HAPPENED
IORM T2,TRBSTS(T1)
OFLUNI: MOVSI T2,TKSOFL## ;LET REST OF WORLD KNOW
IORM T2,TUBSTS(U) ; THAT THE DRIVE IS OFF-LINE
POPJ P,
;HERE ON BAD TAPE INTERRUPT
BADTAP: LDB T1,TUYECD ;PICK UP FAILURE CODE
MOVE T4,NRTERD ;LOAD BAD DATA ERROR
CAIN T1,14 ;BAD TAPE AT OR BEYOND EOT?
TRO T4,RB.SET ;YES, NOTE NEED TO SET EOT AS WELL
PJRST ATTE10 ;AND GO HANDLE SETTING THE BITS
;HERE ON TU FAULT A INTERRUPT
TUFLTA: MOVE T4,NRTERV ;GET BAD DRIVE ERROR BITS
LDB T1,TUYECD ;GET ERROR CODE
CAIE T1,44 ;31/44 (PREVIOUS RECORD DESTROYED)?
JRST ATTEN9 ;NO, JUST SET BITS AS REQUESTED
MOVSI T1,TUSFLT## ;YES, LOAD NEW ERROR BIT
IORM T1,TUBSTS(U) ;TELL WORLD THAT TU IS BAD
PJRST RTZER ;AND PITCH THE INTERRUPT (USER GETS HUNG DEV)
;HERE ON ON-LINE INTERRUPT
INTONL: MOVSI T2,TKSOFL## ;CLEAR OFF-LINE BIT
ANDCAM T2,TUBSTS(U)
PUSHJ P,TPMONL## ;TELL MDA A DRIVE JUST CAME UP
MOVEI P1,DF.SNS ;NON-DATA TYPE SENSE
SETZ T1, ;TELL TAPSER THIS IS ASYNC
PJRST SENSE ;GO START A SENSE AND RETURN
SCHDON: SETZM TKBSCH(W)
JRST CLRCTL
;HERE AFTER AN OPERATION IS THROUGH
DONE: IORB P4,TRBSTS(T1) ;FLAGS BEFORE AND AFTER ATTEN6
MOVSI T2,RB.EXC
SKIPE P4 ;ANY FUNNY THINGS?
IORM T2,TRBFNC(T1) ;YES, AN EXCEPTION HAS OCCURRED
SETZM T78SNS(U)
CLRCTL: PUSH P,T1 ;SAVE IORB
MOVEI T1,CO.CLR
MOVE T2,KDBCSO(W) ;GET CONI BITS AT INTERRUPT
MOVE T3,TAPCII##(T2)
TRZE T3,CI.DON ;DONE LIT?
TRO T1,CO.CCD ;YES, CLEAR IT ALSO
MOVEM T3,TAPCII##(T2)
XCT KDBCNO(W)
XCT KDBCNI(W) ;SOMETIMES RAE WON'T CLEAR
MOVE T3,T1 ;COPY RESULTS
MOVEI T1,CO.MBI ;MASSBUS INIT
TRNE T3,CI.RAE ;IS IT STILL UP?
XCT KDBCNO(W) ;YES - ZAP IT
SETZM TKBFLG(W) ;NOTHING HAPPENING NOW
SKIPA ;ONWARD
CLRCTY: PUSH P,T1 ;SAVE T1
MOVEI T1,TAPCHN##+CO.AIE+CO.MBE ;ENABLE FOR INTERRUPTS
XCT KDBCNO(W)
POP P,T1 ;RESTORE T1
POPJ P, ;AND RETURN
;HERE TO CLEAR THE TM78
CLRTMI: PUSH P,T1 ;SAVE T1
MOVEI T1,CO.CLR!CO.MBE;CLEAR THE RH20 OF ALL ERRORS
XCT KDBCNO(W)
POP P,T1 ;RESTORE T1
CAIA
CLRTMO: TAPON
CLRTM: MOVE T2,[.DOTMS!DO.TMC] ;DO AN INIT OF THE TM78
PUSHJ P,WTMBR##
MOVEI T4,40000 ;HOW LONG TO WAIT
CLRTM1: MOVSI T2,(.DOTMS) ;READ TM78 STATUS
PUSHJ P,RDMBR##
TRNN T2,DI.TMR ;TM READY?
SOJG T4,CLRTM1 ;NO, TRY AGAIN
PJRST RTZER ;YES (OR TIMEOUT) RETURN
;HERE ON CONI ERROR BIT
CHNERR: TRNN P2,CI.RAE ;REGISTER ACCESS ERROR?
JRST NORAE ;NO
TLO P4,RB.SNM!RB.SED ;YES, NO TAPE MOTION+ERROR
JRST DONE
NORAE: TLNN P2,(CS.MPE!CS.NXM)
JRST CHNRTY ;NO, JUST RETRY
MOVEI T3,CHENXM## ;SET TO CALL RIGHT ROUTINE
MOVSI T4,IOCHNX ;ASSUMING NXM
TLNN P2,(CS.NXM) ;NXM?
PUSHJ P,[MOVEI T3,CHEMPE## ;NO--SET FOR MEMORY PARITY
MOVSI T4,IOCHMP ; ...
POPJ P,]
MOVE F,TUBCUR(U) ;POINT TO CURRENT DDB
MOVE T1,KDBICP(W) ;T1=ICWA
MOVE P1,KDBCHN(W) ;P1=CDB
IORM T4,CHNNUM(P1) ;MARK MEMORY ERROR FOR LATER SWEEP
SKIPN TUBERR(U) ;CALL ERRCON ON FIRST ERROR ONLY
PUSHJ P,(T3) ;GO CALL ERRCON
CHNRTY: MOVEI T4,-1 ;SET T78ESD=0,,-1 AS A FLAG
JRST ATTE13 ;AND GO CRANK UP A SENSE
;SUBROUTINE TO SET HOLD IN THE TM78
;RETURNS CPOPJ IF HOLD DIDN'T SET, CPOPJ1 NORMALLY
SETHLD: PUSH P,T1 ;SAVE T1
MOVE T2,[.DOIA!3776] ;POINT INTERNAL ADDR AT A READ-ONLY LOCATION
PUSHJ P,WTMBR## ;IN CASE TM78 DECIDES TO WRITE WHEN HOLD SETS
MOVE T2,[.DOTMS!DO.HLD]
PUSHJ P,WTMBR## ;SET HOLD
MOVEI T1,40000 ;HOW LONG TO WAIT
SETHL1: MOVSI T2,(.DOTMS) ;READ STATUS
PUSHJ P,RDMBR##
TRNN T2,DO.HLA ;HOLD ACKNOWLEDGED?
SOJG T1,SETHL1 ;NO, WAIT SOME MORE
JUMPN T1,TPOPJ1## ;SKIP-RETURN IF HOLD ACKNOWLEDGED
JRST TPOPJ## ;COULDN'T SET HOLD
;SUBROUTINE TO CLEAR HOLD
CLRHLD: MOVSI T2,(.DOTMS)
PUSHJ P,WTMBR## ;CLEAR HOLD
MOVE T2,[.DOTMS!DO.TMC]
PUSHJ P,WTMBR## ;CLEAR POSSIBLE ERROR
POPJ P, ;AND RETURN
;ROUTINE TO DO A SENSE TO SEE IF A SLAVE IS PRESENT
;ENTER WITH T2 = DRIVE NUMBER
;RETURNS CPOPJ IF NOT THERE, CPOPJ1 IF IT IS
INISNS: ADDI T2,<(.DOND0)>_-14 ;SET RIGHT DRIVE
ROT T2,-6
HRRI T2,DF.SNS ;DO A SENSE ON THAT DRIVE
PUSHJ P,WTMBR##
MOVEI T1,40000 ;HOW LONG TO WAIT
INISN1: MOVSI T2,(.DOAS)
PUSHJ P,RDMBR## ;READ ATTEN SUMMARY
TRNN T2,377 ;SENSE OP COMPLETE?
SOJG T1,INISN1 ;NO, WAIT SOME MORE
JUMPE T1,CPOPJ## ;GO IF WE TIMED OUT
MOVSI T2,(.DOSR) ;READ STATUS REGISTER
PUSHJ P,RDMBR##
TRNE T2,DI.AVL+DI.MNT ;IS IT THERE?
AOS (P) ;YES
POPJ P, ;RETURN
;ROUTINE TO DETERMINE WHAT SLAVES ARE PRESENT
T78CFG: CAIL T1,FSTICD/4 ;AN RH20?
CAILE T1,LSTICD/4 ;...
JRST CPOPJ1## ;WRONG DRIVER
TLNE T2,(CI.PPT) ;IPA CHANNEL?
JRST CPOPJ1## ;YES
MOVSI T1,CP.RH2 ;RH20 CHANNEL
PUSHJ P,AUTCHN## ;BUILD A CHANNEL DATA BLOCK
POPJ P, ;NO CORE
PUSHJ P,SAVE1## ;SAVE P1
SETZ P1, ;MASSBUS UNIT NUMBER 0, DRIVE 0
T78CF1: PUSHJ P,T78UNI ;AUTOCONFIGURE A SINGLE MASSBUS UNIT
HLLOS P1 ;RESET DRIVE NUMBER
AOBJN P1,.+1 ;ADVANCE TO NEXT MASSBUS UNIT
TLNN P1,10 ;CHECKED ALL UNITS?
JRST T78CF1 ;LOOP BACK FOR ANOTHER
JRST CPOPJ1## ;TRY ANOTHER DEVICE ON SAME CHANNEL
;AUTOCONFIGURE A SINGLE MASSBUS UNIT
T78UNI: PUSHJ P,RDDTR## ;READ DRIVE TYPE REGISTER
CAIE T2,TY.T78 ;TU78?
POPJ P, ;NOT ON THIS MASSBUS UNIT
HLRZ T1,P1 ;GET MASSBUS UNIT NUMBER
PUSHJ P,AUTKDB## ;BUILD A KDB
POPJ P, ;GIVE UP IF NO CORE
PUSHJ P,TAPCSA## ;SET UP CSO CONI ADDRESS
SETZB T1,T2 ;NO KONTROLLER SERIAL NUMBER
PUSHJ P,AUTKSN## ;DUMMY ONE UP AND STORE IT
PUSHJ P,CLRTMI ;RESET THE TM78
PUSHJ P,T78ONL ;IS THE TM78 ALIVE?
POPJ P, ;DO NO MORE
PUSHJ P,T78UN3 ;PUT THE CONTROLLER IN A KNOWN STATE
PUSHJ P,T78MRL ;CHECK MICROCODE ROM LEVELS
POPJ P, ;OLD ROMS
HRRZ T2,KDBUNI(W) ;GET BIT FOR ATTENTIONS ON THIS UNIT
HRLI T2,(.DIDTR) ;REGISTER TO READ
PUSHJ P,WTMBR## ;GET DRIVE TYPE REGISTER
TRNN T2,TR.DRQ ;DRIVE REQUEST REQUIRED (DUAL PORTED)?
JRST T78UN1 ;NO
MOVEI T2,2 ;THERE CAN BE TWO PATHS
DPB T2,[POINTR (KDBSTS(W),KD.MPT)] ;STORE COUNT
MOVSI T2,(KD.MPD) ;GET MULTI-PORTED BIT
IORM T2,KDBSTS(W) ;LITE FOR FUTURE REFERENCE
T78UN1: MOVNI P3,1 ;INIT DRIVE NUMBER
T78UN2: PUSHJ P,T78DRV ;AUTOCONFIGURE A SINGLE DRIVE
JFCL ;IGNORE ERRORS
HRRZ T1,P1 ;GET DRIVE NUMBER
CAIGE T1,T78DMX-1 ;DONE ALL DRIVES?
AOJA P1,T78UN2 ;LOOP BACK FOR MORE
PJRST CLRCTY ;YES, ENABLE FOR INTERRUPTS AND RETURN
T78UN3: MOVE T2,[.DOAS!377] ;CLEAR GARBAGE FROM ATTEN SUMMARY REG
PUSHJ P,WTMBR## ;DATAO
MOVEI T1,CO.MBI ;MASSBUS INIT
XCT KDBCNO(W) ;...
MOVEI T1,CO.MBE ;MASSSBUS ENABLE
XCT KDBCNO(W) ;...
POPJ P, ;RETURN
;AUTOCONFIGURE A SINGLE DRIVE
T78DRV: PUSHJ P,CLRTMI ;CLEAR ERRORS, ETC.
HRRZ T1,P1 ;GET UNIT
MOVE T1,BITTBL##(T1) ;AND IT'S BIT
TDNE T1,T78IUM(W) ;WANT TO IGNORE THIS DRIVE?
POPJ P, ;SAY IT DOESN'T EXIST
HRRZ T2,P1 ;DRIVE NUMBER
PUSHJ P,INISNS ;SEE IF THE NEXT SLAVE IS THERE
PJRST CLRTMI ;NO THERE SO RESET THINGS AND RETURN
HRRZ T1,P1 ;DRIVE NUMBER
SETCM T1,BITTBL##(T1) ;GET MASK OF ALL BUT THIS DRIVE
SETZ T2, ;ASSUME NO OTHER NEW DRIVES
SYSPIF ;AVOID RACE WITH INTERRUPT LEVEL
ANDB T1,T78NUM(W) ;CLEAR SINCE DRIVE IS NO LONGER "NEW"
SKIPE T1 ;WORK PENDING FOR OTHER DRIVES?
MOVNI T2,1 ;YES
HLLM T2,KDBNUM(W) ;UPDATE FLAG
SYSPIN ;RELEASE INTERLOCK
MOVE T2,[.DOAS!377] ;CLEAR THE ATTENTION
PUSHJ P,WTMBR## ;...
MOVSI T2,(.DOSN) ;MASSBUS REGISTER
PUSHJ P,RDMBR## ;READ DRIVE SERIAL NUMBER
SETZ T1, ;REALLY A ONE WORD QUANTITY
HRRZ T3,P1 ;GET PHYSICAL DRIVE NUMBER
PUSHJ P,AUTDSN## ;FAKE UP IF A ZERO & SAVE TEMPORARILY
HRRZ T3,P1 ;GET PHYSICAL DRIVE NUMBER
PUSHJ P,AUTDPU## ;LINK UP DUAL PORTED DRIVES
JFCL ;MUST PROCEED EVEN IF DUAL PORTED
HRLZ T1,P1 ;PHYSICAL DRIVE NUMBER
HRR T1,P1 ;UDB TABLE INDEX
MOVEI T2,TUCIRD##+TUCD62##+TUCD16##+K.T78
XMOVEI T3,HNGTBL ;POINT TO HUNG TIMER TABLE
MOVE T4,['TU78/9'] ;DRIVE MODEL
PUSHJ P,TAPDRV## ;BUILD AND LINK UP UDB AND DDB
JFCL ;FAILED
DMOVE T1,.CPTSN## ;RETRIEVE DRIVE SERIAL NUMBER
DMOVEM T1,UDBDSN(U) ;SAVE IN UDB
MOVEM T2,T78REG+14(U) ;SAVE FOR DIAGNOSTICS
DMOVE T1,T78ROM(W) ;GET ROM LEVELS
DMOVEM T1,T78REG(U) ;SAVE FOR ERROR LOGGING
MOVSI T2,(.DOSR) ;READ STATUS REG
PUSHJ P,RDMBR## ;DATAO
MOVSI T3,TKSOFL## ;BIT TO SET
TRNN T2,DI.RDY ;IF NOT READY
IORM T3,TUBSTS(U) ; THE DRIVE IS OFF-LINE
MOVSI T3,TUSWTL## ;BIT TO CLEAR
ANDCAM T3,TUBSTS(U) ;ASSUME TAPE IS NOT WRITE-LOCKED
TRNE T2,DI.FPT ;CHECK WRITE ENABLED STATE
IORM T3,TUBSTS(U) ;WRONG - IT IS WRITE LOCKED
MOVE T2,[.DOAS!377] ;CLEAR THE ATTEN BIT WE JUST LIT
PUSHJ P,WTMBR## ;DATAO
JRST CPOPJ1## ;RETURN
;CHECK MICROCODE ROM LEVELS
T78MRL: PUSHJ P,SETHLD ;SET HOLD IN TM SO WE CAN READ REV LEVELS
JRST T78MR4 ;LOSE IF IT DIDNT SET
XMOVEI T3,T78ROM(W) ;POINT TO STORAGE
HRLI T3,(POINT 9,) ;MAKE A BYTE POINTER
MOVE T4,[.DOIA!3776] ;POINT AT LOC FOR 1ST ROM REV LEVEL
T78MR1: MOVE T2,T4
PUSHJ P,WTMBR## ;LOC WE WANT TO READ
MOVSI T2,(.DOTMS)
PUSHJ P,RDMBR## ;READ THE LOCATION
ANDI T2,377 ;ONLY 8 BITS ARE OF INTEREST
IDPB T2,T3 ;SAVE IN KDB
ADDI T4,4000 ;STEP TO NEXT REV LEVEL LOC
TRNN T4,40000
JRST T78MR1 ;GO READ IT
DMOVE T3,[POINT 9,T78ROM(W) ;POINT TO WHAT WE GOT
POINT 9,T78REV] ;AND WHAT WE EXPECT FOR EACH ROM
PUSH P,P1 ;SAVE P1
MOVSI P1,-^D8 ;NUMBER OF ROMS TO CHECK
T78MR2: ILDB T1,T3 ;GET NEXT ROM WE GOT
ILDB T2,T4 ;AND WHAT WE EXPECT
CAML T1,T2 ;SEE IF AT LEAST WHAT WE EXPECT
AOBJN P1,T78MR2 ;OK, CONTINUE
JUMPGE P1,T78MR3 ;JUMP IF ALL OK
HRROI T1,[ASCIZ /Ask field service to install the new TM78 microcode ROMs/]
PUSHJ P,TAPREV## ;LET TAPSER TYPE A MESSAGE
SKIPA ;TAKE FAILING RETURN
T78MR3: AOS -1(P) ;SKIP
POP P,P1 ;RESTORE P1
PUSHJ P,CLRHLD ;CLEAR HOLD
T78MR4: MOVEI T1,CO.MBE!CO.RAE ;CLEAR POSSIBLE REG ACCESS ERROR
XCT KDBCNO(W) ; (ON IF NON-EX DRIVE)
PUSHJ P,SETIVI ;SET UP INTERRUPT VECTOR
JRST CLRCTL ;CLEAR RH20 AND RETURN
;TWO WORDS FOR PATCHING IN NEW TM78 ROM REV LEVELS
T78REV: BYTE (9) 6,5,6,4
BYTE (9) 2,3,8,3
;HERE TO CHECK IF ON-LINE
T78ONL: MOVSI T2,(<DO.DRE>!.DOTMS)
TAPOFF ;PREVENT INTERRUPT CODE FROM CHANGING
; PREPERATION REGISTER
PUSHJ P,RDMBR## ;IS THE TM78 ALIVE?
TRNE T2,DO.HLA ;DID WE STOP IT?
JRST T78ON2 ;YES, OFF-LINE
TRNE T2,DI.TMR
JRST T78ON1 ;YES
XCT KDBCNI(W) ;NO, IS THE UNIT THERE AT ALL?
TRNN T1,CI.RAE
PJRST CLRTMO ;YES, TRY TO GET IT GOING AGAIN
MOVEI T1,CO.RAE+CO.MBE+CO.AIE+TAPCHN## ;NO, CLEAR THE RAE
XCT KDBCNO(W) ; (NON-EX UNIT)
MOVSI T1,TKSOFL## ;BIT TO SET
IORM T1,TKBSTS(W) ; MARK CONTROLLER OFFLINE
CAIA
T78ON1: AOS (P)
T78ON2: TAPON
SKIPE T1,T78NUM(W) ;GET BIT MASK
JFFO T1,T78ON3 ;FIND FIRST UNIT NUMBER
HRRZS KDBNUM(W) ;INDICATE NO DRIVES TO CONFIGURE
PJRST CLRCTY ;RETURN ENABLING INTERRUPTS
T78ON3: PUSHJ P,AUTLOK## ;GET AUTCON INTERLOCK
POPJ P, ;TRY AGAIN NEXT TIME
MOVEI P1,(T2) ;GET PHYSICAL DRIVE NUMBER
HLL P1,KDBUNI(W) ;INCLUDE MASSBUS UNIT
MOVE T1,KDBDVC(W) ;DEVICE CODE
XMOVEI T2,T78DSP ;DISPATCH
MOVE T3,KDBCHN(W) ;CHANNEL DATA BLOCK
PUSHJ P,AUTSET## ;SET UP CPU VARIABLES
PUSHJ P,T78DRV ;TRY TO CONFIGRE A DRIVE
JFCL ;IGNORE ERRORS
PUSHJ P,AUTULK## ;RELEASE AUTCON INTERLOCK
POPJ P, ;TELL TAPSER CONTROLLER IS ALIVE
;HERE TO CAUSE A SCHEDULE CYCLE
T78SCH: SETOM TKBSCH(W) ;SET FLAG
;HERE TO RESET AN ACTIVE DRIVE (HUNG)
T78RES: SKIPE T2,TKBSCW(W) ;LOSE DURING AN EXTENDED SENSE?
MOVEM T2,@KDBICP(W) ;YES, RESET ICWA TO WHAT IT SHOULD BE
SETZM TKBSCW(W)
SETZM T78RRO(W) ;NO LONGER IN READ-OPPOSITE
PUSH P,T1 ;SAVE T1
MOVEI T1,CO.MBE ;MAKE SURE THE
XCT KDBCNO(W) ; RH IS LISTENING
PUSHJ P,SETIVI ;SET UP INTERRUPT VECTOR
MOVEI T1,CO.STP!CO.MBE ;CLEAR BUSY, SET DONE
XCT KDBCNO(W) ;DO IT
POP P,T1 ;RESTORE T1
SKIPE TKBSCH(W) ;SCHEDULING?
JRST CLRCTY ;YES, JUST ENABLE INTERRUPTS
MOVE T1,KDBCSO(W) ;NO, CLEAR CONI BITS SO AS NOT
SETZM TAPCII##(T1) ; TO CONFUSE CLRCTL
JRST CLRCTL ;CLEAR RH20 AND RETURN
;HERE ON AN INTERRUPT WHICH REQUIRES RESETING THE TM78
CLRINT: PUSHJ P,CLRTM ;RESET THE CONTROLLER
JUMPE U,CLRIN1
MOVSI T1,(1B1) ;MARK AS A HARD ERROR FOR DAEMON
IORM T1,TUBTRY(U)
MOVSI T1,T78REG(U) ;COPY FROM "AT END"
HRRI T1,T78ICS(U) ; TO "AT ERROR"
BLT T1,T78ISE(U) ; FOR SYSERR
PUSHJ P,TPELOG## ;LOG THE ERROR
CLRIN1: SKIPN P1,TKBFLG(W) ;WAS ANYTHING HAPPENING?
JRST CLRIN2 ;NO, RETURN A ZERO
HRRZ T1,TUBQUE(U) ;POINT T1 AT IORB
JUMPE T1,CLRIN2 ;NONE????
JUMPL P1,T78SI1 ;RETRY THE COMMAND IF IT WAS A DATA OPERATION
MOVE T4,NRTERV ;POSITIONING OP - CALL IT A HARD DEVICE ERROR
JRST ATTEN9 ;FINISH UP PROCESSING
;HERE IF NOTHING WAS HAPPENING
CLRIN2: AOS T1,T78ACT(W) ;BUMP ASYNC INTERRUPT COUNT
CAIG T1,T78AMX ;GONE OVER THE THRESHOLD?
JRST RTZER ;NO, RETURN A ZERO
PUSHJ P,SETHLD ;YES. SET HOLD IN THE TM (STOP THE MICROCODE)
JFCL ; TO STOP THESE INTERRUPTS FROM CLOGGING THE SYSTEM
SETOM T78ACT(W) ;INDICATE HOLD IS SET
JRST RTZER ;AND KEEP ON GOING (RETURN 0 TO TAPSER)
;ROUTINE TO READ REGISTERS ON ERROR
RDREGS: MOVEM P2,T78REG+2(U) ;SAVE CONI
MOVSI T2,(.DOPTC)
PUSHJ P,RDMBR##
MOVEM T2,T78REG+3(U) ;DATAI PRIMARY TRANSFER CONTROL REG
MOVSI T2,(.DOPBA)
PUSHJ P,RDMBR##
MOVEM T2,T78REG+4(U) ;DATAI PRIMARY BLOCK ADDR REG
PUSH P,T1
MOVEI T1,T78REG+6(U) ;(REG+5 = LAST COMMAND)
HRLI T1,-22 ;READ ALL REGISTERS
SETZ T2, ; STARTING AT 0
RDREG1: PUSH P,T2
PUSHJ P,RDMBR##
MOVEM T2,(T1) ;STORE DATA IN UDB
POP P,T2
ADD T2,[010000,,0] ;SET FOR NEXT REGISTER
AOBJN T1,RDREG1
JRST TPOPJ##
;ROUTINE TO SET UP INTERRUPT VECTOR, JSR
SETIVI: MOVE T2,KDBVIN(W) ;SET UP JSR IN ICWA+3
HRLI T2,(XPCW)
MOVE T3,KDBICP(W)
MOVEM T2,3(T3) ;FOR VECTORED INTERRUPTS
MOVE T2,KDBIVI(W) ;RESET INTERRUPT VECTOR ADDRESS
XCT KDBDTO(W)
POPJ P, ;AND RETURN
;HERE AFTER SENSE COMPLETES WHICH WAS DONE TO READ REGS 7-10
RDREG2: MOVSI T1,T78REG+6+22(U) ;ZERO THE EXTENDED SENSE AREA
HRRI T1,T78REG+6+23(U) ; IN CASE WE DONT DO AN EXTENDED SENSE
SETZM T78REG+6+22(U) ; OR WE DO ONE AND IT FAILS
BLT T1,T78REG+6+22+16(U)
MOVEI T1,T78REG+6+7(U)
HRLI T1,-3 ;WHAT TO READ
MOVSI T2,070000
PUSH P,T1 ;RDREG1 EXITS TPOPJ
PJRST RDREG1
;HERE TO READ REGS ON SUCCESSFUL READ
RDREG3: PUSH P,T2
PUSHJ P,RDREGS ;READ (MOST) REGISTERS
MOVSI T2,T78ICS+6+7(U) ;COPY REGS 7-10 FROM WHERE WE READ THEM
HRRI T2,T78REG+6+7(U) ; TO THE FEP AREA (ELSE HAVE TO SENSE AGAIN)
BLT T2,T78REG+6+11(U) ; AND THESE REGISTERS DON'T CHANGE
JRST T2POPJ##
;TABLES TO CONTROL IO
TB.DAT==1B0
TB.WRT==1B1
TB.REV==1B2
TB.SPC==1B3
TB.RD==1B4
TB.ERA==1B5
TB.WTM==1B6
TB.REW==1B7
TB.RRG==1B8 ;NOT IN TABLE, LIGHTS ON SENSE FROM RDMBR
TB.XSN==1B9 ;NOT IN TABLE, LIGHTS AFTER SENSE IF WE DO EXTENDED SENSE
FNCTBL: 0 ;0 - ILLEGAL
TB.DAT!TB.RD!DF.RED!1B17 ;1 - READ FORWARD
TB.WRT!TB.DAT!DF.WRT!2B17 ;2 - WRITE
TB.DAT!TB.RD!TB.REV!DF.RRV!3B17 ;3 - READ REVERSE
TB.SPC!DF.SPF!4B17 ;4 - SKIP RECORD
TB.SPC!TB.REV!DF.SPR!5B17 ;5 - BACKSPACE RECORD
TB.SPC!DF.SFF!6B17 ;6 - SKIP FILE
TB.SPC!TB.REV!DF.SRF!7B17 ;7 - BACKSPACE FILE
TB.WRT!TB.ERA!DF.ERG!10B17 ;10 - ERASE
TB.WRT!DF.DSE!11B17 ;11 - DATA SECURITY ERASE
TB.REW!TB.REV!DF.REW!12B17 ;12 - REWIND
DF.UNL!13B17 ;13 - REW, UNLOAD
TB.WRT!TB.WTM!DF.WTM!14B17 ;14 - WRITE TAPE MARK
FNCNOP: TB.SPC!DF.NOP!15B17 ;15 - YELLOW BALL
TB.DAT!TB.RD!DF.RED!16B17 ;16 - CORRECTION READ
TB.DAT!TB.RD!DF.RED!17B17 ;17 - LOW THRESHOLD READ
WT.GCR==2 ;TURN WRITE PE INTO WRITE GCR
;HUNG TIMER TABLE
EXP ^D320 ;MAXIMUM TIMEOUT VALUE
HNGTBL: BYTE(9) ^D000,^D031,^D031,^D031 ;IL,RD,WT,RB
BYTE(9) ^D031,^D031,^D320,^D320 ;SR,BR,SF,BF
BYTE(9) ^D031,^D320,^D150,^D150 ;LG,SE,RW,RU
BYTE(9) ^D031,^D031,^D031,^D031 ;TM,YB,CR,RL
;FRAMES/WORD,,MODE BITS
MODTBL: -1 ;0 - ILLEGAL
5,,30000 ;1 - CORE DUMP
4,,20000 ;2 - INDUSTRY COMPAT
-1 ;3 - SIXBIT
-1 ;4 - 7 BIT (ASCII)
-1 ;5 - 7-TRACK CORE DUMP
;MISC BIT DEFINITIONS
;RH20 COMPOSITE BITS
CI.ERR==CI.DBP!CI.LWC!CI.DRE!CI.RAE!CI.OVR ;CONI ERROR BITS
CO.CLR==CO.RAE!CO.TEC ;CONO BITS TO CLEAR ERRORS
CS.ERR==CS.MPE!CS.NAE!CS.NXM!CS.RHE!CS.OVR ;LOGOUT-AREA ERROR BITS
IC.RRG==1B0 ;READ REGISTERS
IC.BST==1B1 ;SET A BIT IN TKBSTS
IC.DSP==1B2 ;DISPATCH TO AN ADDRESS
IC.ASY==1B3 ;ASYNCH EVENT (RETURN 0 TO TAPSER)
IC.XSN==1B4 ;DO AN EXTENDED SENSE TO GET MORE INFO
ICDTBL: IC.BST!RB.SER!RB.SED ;0 - UNDEFINED
0 ;1 - DONE
IC.BST!RB.STM ;2 - UNEXPECTED TAPE MARK
IC.BST!RB.SBT!RB.SNM ;3 - UNEXPECTED BOT
IC.BST!RB.SET ;4 - END OF TAPE
IC.BST!RB.STM ;5 - UNEXPECTED LOGICAL EOT
IC.BST!RB.SER!RB.SIL ;6 - NO OP COMPLETED
IC.ASY!IC.DSP!INTRWP ;7 - REWIND IN PROGRESS
IC.BST!RB.SLK!RB.SER!RB.SNM ;10 - WRITE TO A WRITE-LOCKED TAPE
IC.DSP!INTOFL!IC.RRG ;11 - NOT READY
IC.DSP!INTOFL!IC.RRG ;12 - DRIVE NOT AVAILABLE (ON OTHER PORT)
IC.DSP!INTOFL!IC.RRG ;13 - OFF LINE
IC.DSP!INTOFL!IC.RRG ;14 - NON-EXISTENT DRIVE
IC.BST!RB.SER!RB.SED!IC.RRG ;15 - NOT CAPABLE
IC.BST!RB.SER!RB.SED!IC.RRG ;16 - UNDEFINED
IC.ASY!IC.DSP!INTONL ;17 - DRIVE HAS COME ON LINE
IC.BST!RB.STL!RB.SER!IC.RRG ;20 - LONG RECORD
0 ;21 - SHORT RECORD
IC.BST!IC.RRG!IC.XSN!RB.SDE!RB.SED!RB.SAP ;22 - RETRY THE INITIAL OPERATION
IC.DSP!INTRRO ;23 - REREAD IN OPPOSITE DIRECTION
NRTERD: IC.BST!RB.SER!RB.SED!RB.SDE!IC.RRG!IC.XSN ;24 - UNREADABLE
NRTERV: IC.BST!RB.SER!RB.SED!IC.RRG!IC.XSN ;25 - ERROR, SER IS SET
IC.BST!RB.SET!RB.SER!RB.SED!IC.RRG!IC.XSN ;26 - ERROR AFTER EOT, SER IS SET
IC.DSP!IC.BST!BADTAP!IC.RRG!IC.XSN ;27 - BAD TAPE
IC.BST!RB.SED!RB.SNM!IC.RRG!IC.XSN ;30 - TM FAULT A
IC.DSP!IC.ASY!TUFLTA!IC.RRG!IC.XSN ;31 - TU FAULT A
IC.ASY!IC.DSP!CLRINT ;32 - TM FAULT B
ICDND1==.-ICDTBL-1
IC.ASY!IC.DSP!CLRINT!IC.RRG!IC.XSN ;33 - TU FAULT B
IC.ASY!IC.DSP!CLRINT ;34 - MASSBUS FAULT
ICDND2==.-ICDTBL-1
MAXICD==.-ICDTBL-1
REVERR==23
INTABL: IFIW DONE ;(00) ILLEGAL
IFIW INTRD ;(01) READ FORWARD
IFIW INTWRT ;(02) WRITE
IFIW INTRD ;(03) READ BACKWARDS
IFIW DONE ;(04) SKIP RECORD
IFIW DONE ;(05) BACKSPACE RECORD
IFIW DONE ;(06) SKIP FILE
IFIW DONE ;(07) BACKSPACE FILE
IFIW DONE ;(10) ERASE GAP
IFIW DONE ;(11) DATA SECURITY ERASE
IFIW INTREW ;(12) REWIND
IFIW INTUNL ;(13) UNLOAD
IFIW DONE ;(14) WRITE TAPE MARK
IFIW DONE ;(15) YELLOW BALL/ILLEGAL FUNCTIONS
IFIW INTRD ;(16) CORRECTION READ
IFIW INTRD ;(17) LOW-THRESHOLD READ
T78END: END