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

1134 lines
39 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
TITLE T78KON - RH20/TM78/TU78/TX79 DRIVER FOR TAPSER V126
SUBTTL T WACHS/TW/DPM/RJF 04-OCTOBER-88
SEARCH F,S,DEVPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1980,1981,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1980,1988>
XP VT78KN,126
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
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,TRBXCW(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,TRBXCW(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,TRBXCW(T1)
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,.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,.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,TRBXCW(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,TRBLNK(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
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
SKIPN F,TUBCUR(U) ;IF DDB USE IT
CLRIN1: XMOVEI F,TDVDDB## ;NO - USE PROTOTYPE
MOVEI T1,.ERTAP ;ERROR TYPE TO DAEMON
HRL T1,F ;DDB
PUSHJ P,DAEERR## ;TELL DAEMON
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