Trailing-Edge
-
PDP-10 Archives
-
bb-bt99q-bb
-
td2kon.x23
There is 1 other file named td2kon.x23 in the archive. Click here to see a list.
TITLE TD2KON - DX20/TX03 DEVICE DEPENDENT CODE FOR TAPSER V126
SUBTTL G.M. UHLER/GMU/DPM 23-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 1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1978,1988>
XP VTD2KN,126 ;VERSION NUMBER FOR LINK MAP
SALL
TD2KON::ENTRY TD2KON
;TECHNICAL INFORMATION AND TECHNIQUES FOR PROGRAMMING THE DX20 ARE
;AVAILABLE IN THE FOLLOWING DOCUMENTS:
;
; FUNCTIONAL SPECIFICATION FOR DX20-V100 MICRO CODE,
; DOCUMENT NUMBER 105-220-001-00, MAR 78
; DX20 PROGRAMMED DEVICE ADAPTER TECHNICAL MANUAL,
; DOCUMENT NUMBER EK-0DX20-TM-001, FEB 78
; RH20 MASSBUS CONTROLLER UNIT DESCRIPTION,
; DOCUMENT NUMBER EK-RH20-UD-001, AUG 76
; DX10 DATA CHANNEL MAINTENANCE MANUAL ADDENDUM, CHAPTERS 4-6,
; DOCUMENT NUMBER EK-DX10-AD-001, JUN 77
; DX20-V100 MAGNETIC TAPE SUBSYSTEM MICRO-CODE,
; DOCUMENT NUMBER MAINDEC-10-DXMCA-A-D, SEP 77
;TD2KON TUBIEP/TUBFEP BLOCK SIZES
.TD2MC==25 ;MISCELLANEOUS VALUES
.TD2ES==24 ;DX20 EXTENDED STATUS REGISTERS
.TD2MR==27 ;MASSBUS REGISTERS
TD2ELN==.TD2MC+.TD2ES+.TD2MR ;SIZE OF FEP TABLE
TD2DMX==20 ;MAXIMUM DRIVES PER KONTROLLER
TD2HDN==TD2DMX-1 ;HIGHEST DRIVE NUMBER ON KONTROLLER
;DRIVER CHARARCTERISTICS
; TD2 = TD2CNF
; MTA = MAGTAPE
; 0 = MAXIMUM DEVICES IN SYSTEM
; K.DX2 = KONTROLLER TYPE
; TD2DMX = MAXIMUM DRIVES PER KONTROLLER
; TD2HDN = HIGHEST DRIVE NUMBER ON KONTROLLER
; MDSEC0 = SECTION FOR KDB/UDB
; MDSEC0 = SECTION FOR DDB
DRVCHR (TD2,MTA,0,K.DX2,TD2DMX,TD2HDN,MDSEC0,MDSEC0,<DR.XAD!DR.MCD!DR.DPU!DR.GCC!DR.DDN>)
.ORG TKBUDB ;START OF TX02 SPECIFIC DATA
TD2UTB:! BLOCK TD2DMX ;TABLE OF POINTERS TO UDBS
TD2ULB:! BLOCK .ULLEN ;MICROCODE LOADER BLOCK
TD2SUN:! BLOCK 1 ;NON-EXISTANT DRIVE BEING SENSED
TD2IUM:! BLOCK TD2DMW ;IGNORE DRIVE MASK
TD2NUM:! BLOCK TD2DMW ;NEW DRIVE MASK
TD2KLN:! ;LENGTH OF KDB
.ORG
.ORG TUBLEN
TD2DID:!BLOCK 1 ;DEVICE IDENTIFIER FOR ERROR LOGGING
TD2IST:!BLOCK 1 ;INITIAL ERROR POINTER (NOT USED)
TD2FST:!BLOCK TD2ELN ;LAST ERROR FINAL STATUS
TD2ULN:! ;LENGTH OF UDB
.ORG
TD2KDB: KDBBEG (TD2,TD2KLN)
SETWRD (KDBNAM,<SIXBIT/MT/>) ;KONTROLLER NAME
SETWRD (KDBIUN,<TKBUDB>) ;INITIAL POINTER TO UDBS
SETWRD (KDBCUN,<TKBUDB>) ;CURRENT POINTER TO UDBS
SETWRD (KDBIUM,<TD2IUM>) ;OFFSET TO IGNORE UNIT MASK
SETWRD (KDBNUM,<TD2NUM>) ;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
KDBEND
TD2UDB: UDBBEG (TD2,TD2ULN)
SETWRD (UDBNAM,<SIXBIT/MT/>) ;DRIVE NAME
SETWRD (TUBIEP,<-1,,TD2IST>) ;INITIAL ERROR POINTER
SETWRD (TUBFEP,<-TD2ELN,,TD2FST>) ;FINAL ERROR POINTER
UDBEND
EQUATE (LOCAL,CPOPJ##,<TD2CMD,TD2IDL>)
TD2ICD==TAPICD## ;PROTOTYPE INTERRUPT CODE ADDRESS
TD2ICL==TAPICL## ;PROTOTYPE INTERRUPT CODE ADDRESS
TD2INT==TAPINT## ;INTERRUPT SERVICE
TD2DSP: DRVDSP (TD2,TAPCHN##,TDVDDB##,TDVLEN##,TPMDIA##)
TPK (TD2,NO,16K) ;SERVICE DEPENDENT DISPATCH
TD2CKT: EXP K.TX1,K.DX2,K.TS1,0 ;COMPATIBLE KONTROLLER TABLE
TD2NBF: TPNBF (RW,RU) ;NON-BLOCKING FUNCTION MASK
;PROTOTYPE MICROCODE LOADER BLOCK
TD2ULP: EXP .BTTX2## ;MICROCODE INDEX
XWD 000,0 ;DEVICE CODE,,MASSBUS UNIT NUMBER
SIXBIT /TX02/ ;INTERFACE NAME
SIXBIT /DX20/ ;CHANNEL NAME
EXP TD2MVR ;MINIMUM MICROCODE VERSION
EXP 0 ;DATE/TIME OF LOAD SUCCESS OR FAILURE
EXP 0 ;MICROCODE VERSION
EXP TD2MAG ;POINTER TO MAGIC TABLE
EXP 0 ;MICROCODE LENGTH
EXP 0 ;MICROCODE ADDRESS
SUBTTL BIT AND REGISTER DEFINITIONS
;DX20 MASSBUS REGISTER AND BIT DEFINITIONS
.DXCTR==0B5 ;CONTROL REGISTER
CR.NOP==0!CR.CGO ;NO-OP
CR.UNL==2!CR.CGO ;REWIND AND UNLOAD
CR.REW==6!CR.CGO ;REWIND
CR.ERA==24!CR.CGO ;ERASE GAP
CR.WTM==26!CR.CGO ;WRITE TAPE MARK
CR.SFR==30!CR.CGO ;SPACE FORWARD RECORD
CR.SBR==32!CR.CGO ;SPACE BACKWARD RECORD
CR.SFF==34!CR.CGO ;SPACE FORWARD FILE
CR.SBF==36!CR.CGO ;SPACE BACKWARD FILE
CR.DSE==42!CR.CGO ;DATA SECURITY ERASE
CR.SNS==44!CR.CGO ;SENSE
CR.WTF==60!CR.CGO ;WRITE DATA
CR.RDF==70!CR.CGO ;READ DATA
CR.RDR==76!CR.CGO ;READ REVERSE
CR.CGO==1B35 ;GO BIT (INCLUDED IN ABOVE FUNCTIONS)
.DXSTR==1B5 ;STATUS REGISTER
SR.CER==1B21 ;COMPOSITE ERROR
SR.RUN==1B23 ;MICROPROCESSOR RUNNING
.DXERR==2B5 ;ERROR REGISTER
ER.ESC==17B23 ;ERROR SUB-CLASS CODE
.ERRTT==4 ;READ TRANSFER TIMEOUT (ERROR CODE=7)
ER.ECC==17B27 ;ERROR CLASS CODE
ER.UPE==1B28 ;MICROPROCESSOR ERROR
ER.STP==1B29 ;MICROPROCESSOR STOPPED
ER.MPE==1B30 ;MICROBUS PARITY ERROR
ER.DPE==1B31 ;DATA BUFFER PARITY ERROR
ER.CPE==1B32 ;CONTROLLER BUS PARITY ERROR
ER.RMR==1B33 ;REGISTER MODIFICATION REFUSED
ER.ILR==1B34 ;ILLEGAL REGISTER ACCESSED
ER.ILF==1B35 ;ILLEGAL FUNCTION ATTEMPTED
ER.ERR==ER.MPE!ER.DPE!ER.CPE!ER.RMR!ER.ILR!ER.ILF
.DXMTR==3B5 ;MAINTENANCE REGISTER
MR.STR==1B33 ;MICROPROCESSOR START
MR.RES==1B34 ;MICROPROCESSOR RESET
.DXASR==4B5 ;ATTENTION SUMMARY REGISTER
AS.ATN==377 ;ATTENTION BITS
.DXFCR==5B5 ;FRAME COUNT REGISTER (IDENTICAL WITH .GXGP5)
.DXDTR==6B5 ;DRIVE TYPE REGISTER
DT.COD==777 ;MASK FOR DRIVE TYPE
.DTCOD==060 ;DRIVE TYPE FOR DX20
.DXGP0==20B5 ;STATUS INDEX/ENDING STATUS REGISTER
G0.ATN==1B20 ;ATTENTION
G0.STM==1B21 ;STATUS MODIFIER
G0.CUE==1B22 ;CONTROL UNIT END
G0.BSY==1B23 ;BUSY
G0.CHE==1B24 ;CHANNEL END
G0.DVE==1B25 ;DEVICE END
G0.UCK==1B26 ;UNIT CHECK
G0.UEX==1B27 ;UNIT EXCEPTION
G0.RES==1B28 ;SET BIT TO REQUEST EXTENDED STATUS
G0.IDX==177B35 ;INDEX INTO THE STATUS TABLE
.SB00==0 ;EST INDEX TO SENSE BYTES 0 - 3
.SB06==1 ;EST INDEX TO SENSE BYTES 4 - 7
.SB08==2 ;EST INDEX TO SENSE BYTES 8 - 11
.SB12==3 ;EST INDEX TO SENSE BYTES 12 - 15
.SB16==4 ;EST INDEX TO SENSE BYTES 16 - 19
.SB20==5 ;EST INDEX TO SENSE BYTES 20 - 23
.DXGP1==21B5 ;DRIVE NUMBER/MODE REGISTER
G1.DTM==17B23 ;DATA MODE
G1.DVM==17B27 ;DRIVE MODE
G1.DRV==377B35 ;DRIVE NUMBER
.DXGP2==22B5 ;EXTENDED STATUS TABLE SIZE REGISTER
.DXGP3==23B5 ;TRACK IN ERROR/FLAGS REGISTER
G3.SAS==1B25 ;SUPPRESS AUTO SENSE ON UNIT CHECK
G3.RSO==1B26 ;REQUEST SENSE OPERATION
G3.TER==1B27 ;REQUEST TIE ERROR RECOVERY
G3.TIE==377B35 ;TIE BYTE FOR ERROR RECOVERY
G3.ALL==G3.SAS!G3.RSO!G3.TER!G3.TIE ;MASK OF ALL BITS
.DXGP4==24B5 ;ASYNCHRONOUS STATUS REGISTER
G4.DVS==377B27 ;DEVICE STATUS BYTE FOR ASYNC STATUS
G4.DRV==377B35 ;DEVICE NUMBER GIVING ASYNC STATUS
G4.ATN==1B20 ;ATTENTION
G4.STM==1B21 ;STATUS MODIFIER
.DXGP5==25B5 ;FRAME COUNT REGISTER (IDENTICAL WITH .DXFCR)
.DXGP6==26B5 ;EXTENDED STATUS REGISTER 0
.DXGP7==27B5 ;EXTENDED STATUS REGISTER 1
.DXDR0==30B5 ;DIAGNOSTIC REGISTER 0
.DXDR1==31B5 ;DIAGNOSTIC REGISTER 1
D1.IRE==1B20 ;INSTRUCTION REGISTER ENABLE
D1.MSE==1B21 ;MICROSTORE ENABLE
D1.PCE==1B22 ;PC ENABLE
D1.PCI==1B23 ;PC AUTO INCREMENT
D1.MPC==7777B35 ;MICRO PROCESSOR PC
.DXDR7==37B5 ;DIAGNOSTIC REGISTER 7
D7.IRP==1B22 ;INSTRUCTION REGISTER PARITY ERROR
;FOLLOWING ARE SENSE BYTE BIT DEFINITIONS FOR BYTES 0-3.
;THESE DEFINITIONS ASSUME THAT THE BYTES ARE STORED IN
;ONE WORD IN THE FORMAT 0(2-9), 1(10-17), 2(20-27), 3(28-35)
S0.CRJ==1B2 ;COMMAND REJECT
S0.IRQ==1B3 ;INTERVENTION REQUIRED
S0.BOC==1B4 ;BUS OUT CHECK
S0.EQC==1B5 ;EQUIPMENT CHECK
S0.DTC==1B6 ;DATA CHECK
S0.OVR==1B7 ;OVERRUN
S0.WCZ==1B8 ;WORD COUNT ZERO
S0.DCC==1B9 ;DATA CONVERTER CHECK
S0.ALL==377B9 ;ALL OF SENSE BYTE ZERO
S1.NSE==1B10 ;NOISE
S1.TUA==1B11 ;TU STATUS A
S1.TUB==1B12 ;TU STATUS B
S1.7TK==1B13 ;7 TRACK FEATURE
S1.BOT==1B14 ;BOT - LOAD POINT
S1.WTS==1B15 ;WRITE STATUS
S1.FPR==1B16 ;FILE PROTECTED
S1.NTC==1B17 ;NOT CAPABLE
S2.TIE==377B27 ;TRACK IN ERROR BYTE
S3.VRC==1B28 ;READ/WRITE VRC
S3.MTE==1B29 ;LRC/MTE
S3.SKW==1B30 ;SKEW ERROR
S3.CRC==1B31 ;EDC/CRC ERROR
S3.ENV==1B32 ;ENV/ECC ERROR
S3.D16==1B33 ;1600 BPI
S3.BKW==1B34 ;BACKWARD STATUS
S3.CPC==1B35 ;C/P COMPARE
SB.UCE==S0.ALL!S1.TUB!S1.NTC ;BAD ERRORS ON UNIT CHECK
;OTHER SENSE BYTE DEFINTITIONS
S6.7TK==1B20 ;7-TRACK DRIVE
S6.D62==1B22 ;6250 BPI IF S3.D16 IS OFF
;RH20 CONI/CONO/LOGOUT AREA BIT DEFINITIONS
CI.ERR==CI.DBP!CI.LWC!CI.DRE!CI.RAE ;CONI ERROR BITS
CO.CLR==CO.RAE!CO.TEC!CO.CCD ;CONO BITS TO CLEAR ERRORS
CS.ERR==CS.MPE!CS.NAE!CS.NXM!CS.RHE!CS.OVR
;ALL CHANNEL LOGOUT ERRORS
;OFFSETS IN TUBFEP FOR COMMUNICATION WITH DAEMON. IF THESE
;DEFINITIONS CHANGE CHECK DAEMON FOR A CORRESPONDING CHANGE.
.TFZRO==0 ;ZERO WORD; ALL UNDEFINED ENTRIES MAP TO HERE
.TFCNI==1 ;CONI INITIAL
.TFCIF==2 ;CONI FINAL
.TFRED==3 ;NUMBER OF FRAMES READ
.TFWRT==4 ;NUMBER OF FRAMES WRITTEN
.TFD1I==5 ;DATAI PTCR INITIAL
.TFD1F==6 ;DATAI PTCR FINAL
.TFD2I==7 ;DATAI PBAR INITIAL
.TFD2F==10 ;DATAI PBAR FINAL
.TFCS0==11 ;CHANNEL LOGOUT 0
.TFCS1==12 ;CHANNEL LOGOUT 1
.TFCS2==13 ;CHANNEL LOGOUT 2
.TFCC1==14 ;FIRST CCW
.TFCC2==15 ;SECOND CCW
.TFMPE==16 ;COUNT OF MPE
.TFNXM==17 ;COUNT OF NXM
.TFOVR==20 ;COUNT OF OVERRUNS
.TFICR==21 ;CONTENTS OF INITIAL CONTROL REG
.TFVER==22 ;BYTE (9)DX20 ADDRESS(9)0(18)MICROCODE VER
.TFMBR==23 ;# OF MASSBUS REGS,,OFFSET TO FIRST
.TFDVL==24 ;# OF DEVICE REGS,,OFFSET TO FIRST
.TFMBX==25 ;START OF NUMBER MASSBUS REGISTERS
.TFD2R==.TFMBX+.TD2MR ;START OF DX20 REGISTERS
.TFTIE==.TFD2R ;TIE BYTE STORED HERE ON ERROR
.TFEND==.TFD2R+.TD2ES-1 ;LAST ENTRY IN TUBFEP
IFN <.TD2MC-<.TFDVL+1>>, <
PRINTX ?.TD2MC INCORRECT; CHECK VALUE IN S
PASS2
END
>
;MISCELLANEOUS DEFINITIONS
TD2MVR==1000,,34 ;MINIMUM MICROCODE VERSION ALLOWED
.DXSAD==6 ;DX20 MONITOR RESTART ADDRESS
.CRM10==100 ;CORRECT CONTENTS OF CRAM LOCATION 10
.CRM11==042562 ;CORRECT CONTENTS OF CRAM LOCATION 11
DX2VER==10 ;MINIMUM ALLOWABLE MICROCODE VERSION
D2VLSH==^D10 ;# BITS TO LSH TO RIGHT-JUSTIFY VERSION
;OFFSETS IN TKBCCL FOR OUR USE
TKBWCT==TKBCCL+0 ;UNUSED,,-BYTE COUNT FOR LAST NON-ERROR XFER
;SIGN BIT MUST BE ZERO FOR THIS TO BE VALID
TKBSCH==TKBCCL+1 ;-1 IF SCHEDULE CYCLE REQUESTED
TKBFLG==TKBCCL+2 ;FLAGS FROM IOFTBL
TKBASY==TKBCCL+3 ;DX20 NUMBER,,ASYNCHRONOUS STATUS
;DURING FORCED SENSE OPERATION
TKBATN==TKBCCL+4 ;IORB ADDRESS,,ATTENTION BITS DURING
;ASYNCHRONOUS STATUS PROCESSING
SUBTTL MACRO DEFINITIONS
;MACRO TO COMPUTE THE WIDTH OF A MASK
; "WID" RETURNS THE LENGTH OF THE LEFTMOST STRING OF
; CONSECUTIVE ONES IN THE WORD.
DEFINE WID(MASK),<<^L<-<<MASK>_<^L<MASK>>>-1>>>
;MACRO TO COMPUTE THE POSITION OF A MASK
DEFINE POS(MASK),<<^L<MASK>+^L<-<<MASK>_<^L<MASK>>>-1>-1>>
;MACRO TO BUILD A POINTER TO A MASKED QUANTITY
; POINTR LOCATION,MASK
DEFINE POINTR(LOC,MASK),<<POINT WID(MASK),LOC,POS(MASK)>>
;MACRO TO DEFINE THE MASSBUS REGISTERS TO SAVE IN THE UDB WHEN AN
;ERROR IS DETECTED. ARGUMENT IS A LIST OF THE OCTAL MASSBUS REGISTER
;NUMBERS TO SAVE. THE TOTAL NUMBER OF REGISTERS MUST NOT EXCEED ^D36.
DEFINE MBRLST (LST), <
..CNT==0 ;START WITH 0 REGISTERS
MBRTBL==0 ;AND WITH NO BITS
IRP LST, <
IFE <LST-0>,<.TFM00==.TFMBX+..CNT>
IFE <LST-30>,<.TFM30==.TFMBX+..CNT>
..CNT==..CNT+1 ;BUMP NUMBER BY 1
MBRTBL==MBRTBL!<1_<^D35-LST>> ;SET BIT IN TABLE
> ;END IRP LST
IFN <.TD2MR-..CNT>, <
PRINTX ?.TD2MR IS INCORRECT; CHECK VALUE IN S
PASS2
END
> ;END IFN
>
MBRLST <0,1,2,3,4,5,6,20,21,22,23,24,25,26,27,30,31,32,33,34,35,36,37>
SUBTTL AUTO CONFIGURATION
TD2CFG: CAIL T1,FSTICD/4 ;AN RH20?
CAILE T1,LSTICD/4 ;...
JRST CPOPJ1## ;WRONG DRIVER
TLNE T2,(CI.PPT) ;IPA CHANNEL?
JRST CPOPJ1## ;YES
PUSHJ P,SAVE2## ;SAVE P1-2
SETZ P1, ;MASSBUS UNIT NUMBER 0, DRIVE 0
TD2CF1: PUSHJ P,TD2UNI ;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 TD2CF1 ;LOOP BACK FOR ANOTHER
JRST CPOPJ1## ;TRY ANOTHER DEVICE ON SAME CHANNEL
;AUTOCONFIGURE A SINGLE MASSBUS UNIT
TD2UNI: PUSHJ P,RDDTR## ;READ DRIVE TYPE REGISTER
CAIE T2,TY.DXA ;IS IT A DX20/TAPE?
POPJ P, ;NO--GIVE UP
MOVSI T1,CP.RH2 ;RH20 CHANNEL
PUSHJ P,AUTCHN## ;BUILD A CHANNEL DATA BLOCK
POPJ P, ;NO CORE
XMOVEI T1,TD2MDT## ;POINT TO MONGEN'ED DEVICE TABLE
SETZ T2, ;THE DEFAULT IS IMPLICIT (RH20 TEST)
HLLO T3,P1 ;MASSBUSS UNIT,,NO DRIVE INFORMATION
MOVEI T4,MD.KON ;SEARCH FOR A KONTROLLER DEFINITION
PUSHJ P,AUTMDT## ;SEE IF WE HAVE ANY DATA
SETZ T1, ;NO DATA IF NO SPECIAL ENTRY
TRNN T1,-1 ;ANY MAX. UNIT INFO?
HRRI T1,-1 ;NO, JUST TRUST THE TX
MOVE P2,T1 ;SAVE THE DATA WORD
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
MOVEI T1,CO.MBE ;GET BIT TO ENABLE THE MASSBUS
XCT KDBCNO(W) ;DO SO
PUSHJ P,MPRES ;RESET MICROPROCESSOR
PUSHJ P,TD2LOD ;LOAD THE MICROCODE
POPJ P, ;GIVE UP
SETOM TD2SUN(W) ;NOT SENSING NON-EXISTANT UNITS
MOVNI P3,1 ;INIT DRIVE NUMBER
TD2UN2: PUSHJ P,TD2DRV ;AUTOCONFIGURE A SINGLE DRIVE
JFCL ;IGNORE ERRORS
HRRZ T1,P1 ;GET DRIVE NUMBER
CAIGE T1,TD2DMX-1 ;DONE ALL DRIVES?
AOJA P1,TD2UN2 ;LOOP BACK FOR MORE
POPJ P, ;ALL DONE
;AUTOCONFIGURE A SINGLE DRIVE
TD2DRV: PUSHJ P,TD2DCK ;CHECK FOR DRIVE EXISTANCE
JRST TD2DR5 ;NOT THERE
MOVEI T2,.SB12 ;SENSE BYTE 12
PUSHJ P,SETEST ;SET UP READ
JRST TD2DR5 ;SHOULDN'T FAIL
PUSHJ P,REDEST ;READ SENSE BYTES 12 - 15
PUSH P,T4 ;SAVE RESULTS
MOVEI T2,.SB16 ;SENSE BYTE 16
PUSHJ P,SETEST ;SET UP READ
JRST TD2DR4 ;SHOULDN'T FAIL
PUSHJ P,REDEST ;READ SENSE BYTES 16 - 19
MOVE T1,(P) ;COPY SENSE BYTES 12-15
TLZ T1,777600 ;ISOLATE BYTE 13 (HIGH BYTE OF TX UNIT S/N)
LSH T1,-14 ;ISOLATE BYTE 14 (LOW BYTE OF TX UNIT S/N)
SKIPN T1 ;HAVE A NON-ZERO S/N?
HRRZ T1,.CPDVC## ;USE DEVICE CODE
TRNN P1,TD2DMX/2 ;CU FOR LOW NUMBERED DRIVES?
MOVEM T1,KDBSER(W) ;YES
TRNE P1,TD2DMX/2 ;CU FOR HIGH NUMBERED DRIVES?
MOVEM T1,KDBSER+1(W) ;YES
TLNN T4,(S172CH_2) ;TWO CHANNEL SWITCH CAPABILITY?
TLZ T4,(S17SWF_2) ;MAKE SURE NO PORTS
LDB T1,[POINTR (T4,S17SWF_2)] ;GET SWITCH FEATURES
ANDI T1,3 ;STRIP OFF HI/LO UNIT BIT
AOS T1 ;GET MAXIMUM NUMBER OF PORTS
LSH T1,1 ;ACCOUNT FOR A/B PATHS PER TCU
CAILE T1,(P2) ;IF MDT KNOWS BETTER THAN WE DO,
HRRZ T1,P2 ;USE ITS MAXIMUM
DPB T1,[POINTR (KDBSTS(W),KD.MPT)] ;SAVE
MOVSI T2,(KD.MPD) ;GET A BIT
CAIE T1,1 ;IF MORE THAN ONE POSSIBLE PATH,
IORM T2,KDBSTS(W) ;THEN SAY MULTI-PORTED DEVICE
TD2DR1: MOVE T3,(P) ;COPY SENSE BYTES 12 - 15
MOVE T1,T3 ;SAVE INCASE NO S/N
ANDI T3,377 ;ISOLATE HIGH ORDER S/N BITS
LSH T4,2 ;POSITION LOW ORDER S/N BITS
LSHC T3,-34 ;MERGE HIGH AND LOW BITS
DMOVE T1,T3 ;COPY RESULTS
JUMPN T2,TD2DR2 ;HAVE A SERIAL NUMBER?
MOVE T1,(P) ;GET SENSE BYTES 12 - 15 AGAIN
TLZ T1,777740 ;ISOLATE HIGH BYTE OF TX UNIT S/N
LSHC T1,-20 ;SHIFT OUT LOW BYTE OF TX UNIT S/N
LSH T1,-2 ;RIGHT JUSTIFY HIGH BYTE IN RH(T1)
LSHC T1,10 ;FORM FULL TX UNIT S/N
HRRZ T2,P1 ;MAKE WORD 2 = DRIVE NUMBER
TD2DR2: POP P,(P) ;KEEP STACK IN PHASE
HRR T3,P1 ;GET PHYSICAL DRIVE NUMBER
PUSHJ P,AUTDSN## ;FAKE UP S/N IF A ZERO & SAVE TEMPORARILY
HRR T3,P1 ;GET PHYSICAL DRIVE NUMBER
PUSHJ P,AUTDPU## ;LINK UP DUAL PORTED DRIVES
JFCL ;MUST PROCEED EVEN IF DUAL PORTED
MOVEI T2,.SB06 ;SENSE BYTE 6
PUSHJ P,SETEST ;TELL THE DX20 WHAT WE WANT TO READ
JRST TD2DR5 ;CAN'T TALK TO THE DX20
MOVEI T1,TUCD80##+TUCD16## ;ASSUME TU70 TO START
PUSHJ P,REDEST ;READ THE SENSE BYTE
TRNE T4,S6.7TK ;7 TRACK DRIVE?
MOVEI T1,TUCD20##+TUCD55##+TUCD80##+TUC7TK##
TRNE T4,S6.D62 ;6250 DRIVE?
MOVEI T1,TUCD16##+TUCD62##
TRO T1,TUCIRD##+K.DX2 ;INCLUDE REWIND INTERRUPT AND KONT TYPE
MOVE T2,T1 ;COPY DRIVE INFO
HRLZ T1,P1 ;PHYSICAL DRIVE NUMBER
HRR T1,P1 ;UDB TABLE INDEX
LDB T3,[POINT 4,T4,27] ;GET TU MODEL BITS
SETZ T4, ;INCASE WE CAN'T FIGURE IT OUT
CAIN T3,5 ;TU70/71?
MOVE T4,['TU70 '] ;YES
TRNE T2,TUC7TK## ;BUT IS IT 7-TK?
TRO T4,10000 ;MAKE IT A TU71
CAIN T3,14 ;TU72?
MOVE T4,['TU72 '] ;YES
CAIN T3,15 ;TU73?
MOVE T4,['TU73 '] ;YES
XMOVEI T3,HNGTBL ;POINT TO HUNG TIMER TABLE
PUSHJ P,TAPDRV## ;BUILD AND LINK UP UDB AND DDB
JFCL ;FAILED
TD2DR3: DMOVE T1,.CPTSN## ;RETRIEVE DRIVE SERIAL NUMBER
DMOVEM T1,UDBDSN(U) ;SAVE IN UDB
AOSA (P) ;ONWARD
TD2DR4: POP P,(P) ;PHASE STACK
TD2DR5: MOVSI T2,(.DXERR) ;POINT TO ERROR REGISTER
PJRST WTMBR## ;CLEAR IT AND RETURN
;CHECK FOR DRIVE EXISTANCE
TD2DCK: HRRZ T1,P1 ;GET UNIT
MOVE T1,BITTBL##(T1) ;AND IT'S BIT
TDNE T1,TD2IUM(W) ;WANT TO IGNORE THIS DRIVE?
POPJ P, ;SAY IT DOESN'T EXIST
SKIPL T1,TD2SUN(W) ;FULL AUTOCONFIGURE?
JRST TD2DC0 ;NO
HRRZS T1 ;ISOLATE POSSIBLE DRIVE NUMBER
HRRZ T2,P1 ;AND THE ONE BEING CONFIGURED NOW
CAIN T1,(T2) ;MATCH?
JRST CPOPJ1## ;THEN INTERRUPT LEVEL TOLD US IT EXISTED
TD2DC0: HRRZ T2,P1 ;GET DRIVE NUMBER
HLLZ T3,P1 ;AND MASSBUS UNIT NUMBER
HRLI T2,(.DXGP1) ;SAY WHAT DRIVE WE WANT TO TALK TO
PUSHJ P,WTMBR## ;TELL THE HARDWARE
MOVE T2,[.DXCTR!CR.SNS] ;DO A SENSE ON THE DRIVE
PUSHJ P,WTMBR## ; SO WE CAN READ SENSE BYTES
SKIPL TD2SUN(W) ;DOING FULL AUTOCONFIGURE?
PJRST REASPI ;NO--JUST LITE PIA AND RETURN
MOVEI T1,2000 ;LOOP COUNTER
TD2DC1: MOVSI T2,(.DXASR) ;POINT TO ATTENTION SUMMARY REGISTER
PUSHJ P,RDMBR## ;READ IT
TRNN T2,377 ;HAVE AN ATTENTION?
SOJG T1,TD2DC1 ;NO, WAIT SOME MORE
JUMPLE T1,TD2DC4 ;DRIVE NOT THERE IF WE TIMED OUT
MOVE T2,[.DXASR!377] ;CLEAR THE ATTENTION WE JUST GOT
PUSHJ P,WTMBR##
MOVE T4,[TRNN T2,G0.RES]
TD2DC2: MOVEI T1,100 ;HOW LONG TO WAIT
TD2DC3: MOVSI T2,(.DXGP0) ;POINT TO ENDING STATUS REGISTER
PUSHJ P,RDMBR##
XCT T4 ;WAIT FOR CONDITION
SOJG T1,TD2DC3 ;NO, WAIT SOME MORE
TLZE T4,(<TRNN>^!<TRNE>) ;CONVERT TRNN TO TRNE IF NOT ALREADY
JRST TD2DC2 ;WASN'T, WAIT TO CLEAR
JUMPLE T1,TD2DC4 ;NO DRIVE IF WE TIMED OUT
PUSHJ P,REDEST ;READ SENSE BYTES 0-3
TLNE T4,(S1.TUA!S1.TUB) ;DRIVE EXIST?
JRST CPOPJ1## ;YES
TD2DC4: MOVSI T2,(.DXERR) ;POINT AT ERROR REGISTER
PJRST WTMBR## ;CLEAR IT AND RETURN
SUBTTL RESET I/O ON HUNG DEVICE
;HERE TO RESET I/O ON A HUNG DEVICE. STOP THE RH20 AND RESET
;AND RESTART ALL DX20'S.
;CALL WITH:
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 ALWAYS
TD2RES: MOVSI T2,TKSOFL## ;GET OFFLINE BIT
TDNE T2,TKBSTS(W) ;IS KON OFFLINE?
POPJ P, ;YES, JUST RETURN
PUSHJ P,SAVE1## ;SAVE P1
PUSH P,U ;SAVE U FOR CALLER
XCT KDBCNI(W) ;GET CONI IN T2
PUSH P,T1 ;SAVE FOR LATER
PUSHJ P,SETIVO ;SETUP INTERRUPT VECTOR ADDRESS
MOVEI T1,CO.STP ;GET "STOP TRANSFER" BIT AND DEASIGN PI
XCT KDBCNO(W) ;STOP ANY TRANSFER
MOVE P1,TKBFLG(W) ;SETUP FLAGS FOR OPERATION
PUSHJ P,RDAREG ;READ INITIAL AND FINAL REGISTERS
POP P,TD2FST+.TFCNI(U) ;STORE CONI IN BLOCK
PUSHJ P,MPSTRT ;RESET AND START THE DX20
MOVE P1,KDBIUN(W) ;POINTER TO UDB TABLE
TD2RE1: SKIPN U,(P1) ;GET NEXT UDB ADDRESS
JRST TD2RE2 ;NONE, SKIP IT
MOVSI T2,TUSREW## ;GET UNIT IS REWINDING BIT
ANDCAM T2,TUBSTS(U) ;CLEAR IN UDB
HLRZ T2,KDBUNI(W) ;GET DX20 NUMBER FOR THIS DRIVE
TD2RE2: CAMGE P1,KDBFUN(W) ;FINAL UDB?
AOJA P1,TD2RE1 ;LOOP FOR MORE
POP P,U ;RESTORE U
PUSHJ P,CLRFLG ;CLEAR KDB FLAGS
PJRST REASPI ;REASSIGN PI AND RETURN
SUBTTL START I/O
;HERE FROM TAPSER TO START AN OPERATION GOING ON A DRIVE. IF THE
;OPERATION IS ILLEGAL FOR SOME REASON, WE SET THE APPROPRIATE BITS
;IN THE IORB AND DO A NO-OP TO GET TO INTERRUPT LEVEL WHERE IT WILL
;BE SEEN. CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS
;RETURN+1 ALWAYS WITH OPERATION STARTED
TD2SIO: PUSHJ P,CHKIRB## ;GET IORB, RETURN ADDR IN T1
JRST TAPDIS## ;NONE, FORGET IT
PUSHJ P,SETIVO ;SET INTERRUPT VECTOR
PUSHJ P,SAVE2## ;SAVE P1-P2
SKIPGE T2,TRBRCT(T1) ;IN ERROR RECOVERY? (IOWD SETUP BY MAKLST)
MOVEM T2,TKBWCT(W) ;NO, SAVE -WORD COUNT FOR LATER
LDB P2,PRBFCN## ;GET FUNCTION FROM IORB
PUSH P,T1 ;SAVE IORB
MOVEI T1,CO.MBE ;ENABLE MASSBUS AND DIASSIGN PI
XCT KDBCNO(W) ;DO SO
POP P,T1 ;RESTORE IORB
PUSHJ P,MPRUN ;IS MICROPROCESSOR STILL RUNNING
JRST [MOVSI T2,RB.SED!RB.SER!RB.SOL ;GET ERROR BITS
JRST GENINT] ;GO CAUSE AN INTERRUPT
SKIPL P1,IOFTBL(P2) ;IS FUNCTION LEGAL?
PUSHJ P,SETMOD ;YES, SETUP DRV #, DENS, MODE
JRST [MOVSI T2,RB.SED!RB.SER!RB.SIL ;GET ERROR BITS
JRST GENINT] ;GO CAUSE AN INTERRUPT
TLNN P1,(TB.DAT) ;DATA OPERATION?
JRST TD2SI2 ;NO
SKIPL T2,TKBWCT(W) ;IN ERROR RECOVERY ? (FROM ABOVE)
JRST TD2SI4 ;YES, USE PREVIOUS FRAME COUNT
MOVSS T2 ;MAKE IT FLAG,,-WORD(BYTE) COUNT
TLOE T2,-1 ;SKIP MULTIPLYIF ALREADY -BYTE COUNT
IMUL T2,TMODTB##(T4) ;CONVERT -WORD COUNT TO -BYTE COUNT
HRRZM T2,TKBWCT(W) ;SAVE FOR RECOVERY ATTEMPT
JRST TD2SI4 ; AND JOIN COMMON CODE
TD2SI2: MOVEI T2,0 ;ASSUME NO FRAME COUNT NEEDED
TRNE P1,TB.ZFC ;ARE WE CORRECT?
JRST TD2SI4 ;YES
TRNE P1,TB.OFC ;-1 FRAME COUNT NEEDED?
SOJA T2,TD2SI4 ;YES, MAKE IT -1 AND JOIN COMMON CODE
HRRZ T2,@IRBACC(T1) ;GET NUMBER OF OPS FROM IORB
MOVNS T2 ;MAKE IT NEGATIVE
TD2SI4: ANDI T2,177777 ;MAKE IT 16 BITS ONLY
HRLI T2,(.DXFCR) ;POINT TO FRAME COUNT REGISTER
PUSHJ P,WTMBR## ;TELL THE DX20 HOW MANY FRAMES
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
HRRZ T3,@IRBACC(T1) ;GET EXEC VIRTUAL ADDR OF CMD LIST
HRLI T3,(INSVL.(.CCJMP,CC.OPC)) ;MAKE IT AN RH20 JUMP WORD
MOVE T2,KDBICP(W) ;GET ADDRESS OF RH20 LOGOUT AREA
MOVEM T3,.CSICW(T2) ;STORE JUMP WORD IN LOGOUT AREA
HRRZI T2,(P1) ;GET HDW FCN AND SET REGISTER (.DXCTR==0)
TRZ T2,-1-TB.FCN ;CLEAR ALL BUT FUNCTION BITS
TLNE P1,(TB.DAT) ;DATA OPERATION?
TDO T2,[.DOSTC!DO.RCP!DO.SCS!177700] ;YES, TALK TO RH20
SKIPGE TUBERR(U) ;IF NEXT TO LAST ERROR RETRY
TRO T2,DO.DTE ; LITE DXES
SKIPN TUBERR(U) ;IF NOT IN ERROR RECOVERY,
MOVEM T2,TD2FST+.TFICR(U) ;SAVE LAST COMMAND
IORM P1,TKBFLG(W) ;REMEMBER WHAT WE WERE DOING
HLRZ T3,KDBUNI(W) ;GET THE DX20 NUMBER
HRLZM T3,TKBASY(W) ;SAVE FOR QUICK INTERRUPT CHECK
PUSHJ P,WTMBR## ;START THE TRANSFER
PJRST REASPI ;LITE PIA AND RETURN
;ROUTINE TO TELL THE DX20 THE DRIVE NUMBER, DENSITY, PARITY, DATA
;MODE, AND RECOVERY PROCEDURES FOR THE CURRENT OPERATION. CALL WITH:
; T1/IORB ADDRESS, P1/IOFTBL ENTRY, P2/FUNCTION,
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 IF DENSITY OR MODE IS ILLEGAL
;RETURN+2 IF ALL IS OK WITH:
; T1/UNCHANGED, T4/MODE FROM IORB
SETMOD: MOVE T2,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
LDB T4,PRBDEN## ;GET DENSITY FROM IORB
MOVEI T3,TUC7TK## ;GET "DRIVE IS A 7 TRACK" BIT
TDNN T3,TUBCNF(U) ;IS IT?
JRST SETMO1 ;NO, DO 9 TRACK SET
;
;HERE TO SETUP THE DENSITY AND PARITY FOR A 7 TRACK DRIVE. WE NEED
;ONLY DO THIS IF TB.MS7 IS SET IN P1.
;
TRNN P1,TB.MS7 ;NEED A MODE SET FOR THIS FUNCTION?
JRST SETMO2 ;NO, SKIP IT
CAIL T4,RB.D2 ;DENSITY LESS THAN 200?
CAILE T4,RB.D8 ;GREATER THAN 800?
POPJ P, ;YES, ERROR
LSH T4,1 ;DEN7TB ENTRIES ARE 2 WORDS (ODD & EVEN PARITY)
MOVSI T3,RB.PAR ;GET EVEN PARITY BIT
TDNE T3,TRBFNC(T1) ;THIS FUNCTION EVEN PARITY?
IORI T4,1 ;YES, BUMP THE POINTER TO THE NEXT WORD
IOR T2,DEN7TB(T4) ;OR IN THE APPROPRIATE HARDWARE DENSITY
JRST SETMO2 ;AND JOIN COMMON CODE
;
;HERE TO SETUP THE DENSITY FOR A 9 TRACK DRIVE. WE NEED ONLY DO THIS
;IF TB.MS9 IS SET IN P1 AND THE DRIVE IS AT BOT.
;
SETMO1: MOVSI T3,TUSBOT## ;GET BOT BIT
TRNE P1,TB.MS9 ;NEED TO DO A MODE SET?
TDNN T3,TUBSTS(U) ; AND DRIVE IS AT BOT?
JRST SETMO2 ;NO, SKIP IT
CAIL T4,RB.D8 ;DENSITY LESS THAN 800?
CAILE T4,RB.D62 ;GREATER THAN 6250?
POPJ P, ;YES, ERROR
IOR T2,DEN9TB(T4) ;OR IN THE APPROPRIATE HARDWARE DENSTIY
;
;HERE TO SETUP THE MODE FOR THIS FUNCTION. CALLER WANTS MODE IN T4.
;
SETMO2: LDB T4,PRBMOD## ;GET MODE FROM IORB
SKIPGE T3,MODTBL(T4) ;GET HARDWARE MODE, SKIP IF LEGAL
POPJ P, ;IT'S NOT, ILLEGAL
IORI T2,(T3) ;SET THE MODE INTO THE WORD
HRLI T2,(.DXGP1) ;POINT AT REGISTER TO SET
PUSHJ P,WTMBR## ;TELL THE DX20
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;HERE TO SETUP ANY ERROR RECOVERY PROCEDURES FOR THIS OPERATION.
;WE ALSO FORCE A SENSE ON THIS OPERATION IF IT IS A READ FROM BOT
;SO THAT WE CAN TELL THE USER THE REAL DENSITY OF THE TAPE.
MOVSI T2,(.DXGP3) ;POINT AT TIE,FLAGS REGISTER
MOVE T3,TUBSTS(U) ;GET TUBSTS
TLNE P1,(TB.RED) ;IS THIS A READ COMMAND?
TLNN T3,TUSBOT## ;FROM BOT?
SKIPA T3,TUBCNF(U) ;NOT A READ OR NOT AT BOT
JRST [TLO P1,(TB.FSN) ;TELL INTERRUPT LEVEL THAT WE FORCED A SENSE
JRST SETMO4] ;JOIN COMMON CODE
TRNN P1,TB.REW ;IS THIS A REWIND OR UNLOAD?
TRNN T3,TUCSNS## ;NO, WAS A SENSE REQUESTED BY THE USER?
JRST SETMO5 ;NO SENSE REQUIRED
SETMO4: TRO T2,G3.RSO ;SET REQUEST SENSE BIT
SETMO5: LDB T3,[POINTR TD2FST+.TFTIE(U),S2.TIE] ;GET TIE BYTE FROM LAST ERROR
CAIN P2,RB.FCR ;THIS A CORRECTION READ?
TRO T2,G3.TER(T3) ;YES, SET TIE BYTE AND REQUEST TIE RECOVERY
TRNE T2,G3.ALL ;NEED TO DO THIS?
PUSHJ P,WTMBR## ;YES, DO SO
JRST CPOPJ1## ;RETURN SUCCESS
;HERE TO SETUP THE APPROPRIATE FLAGS AND GENERATE AN INTERRUPT SO
;THAT WE CAN GET TO INTERRUPT LEVEL TO REPORT AN ERROR NOTICED WHEN
;WE WERE TRYING TO START AN OPERATION.
;CALL WITH:
; T1/IORB ADDRESS, T2/ERROR BITS TO SET IN IORB
;RETURN+1 ALWAYS
GENINT: IORM T2,TRBSTS(T1) ;SET ERROR BITS IN IORB
MOVE T2,IOFTBL+RB.FYB ;GET DUMMY FUNCTION
IORM T2,TKBFLG(W) ;STORE IN KDB FOR INTERRUPT LEVEL
HLRZ T2,KDBUNI(W) ;GET DX20 NUMBER
HRLZM T2,TKBASY(W) ;STORE FOR INTERRUPT CHECK
PUSH P,T1 ;SAVE IORB
MOVEI T1,CO.STP ;GET STOP TRANSFER BIT
XCT KDBCNO(W) ;SET DONE, CAUSING AND INTERRUPT
POP P,T1 ;RESTORE IORB
PJRST REASPI ;LITE PIA AND RETURN
SUBTTL CHECK FOR KONTROLLER BUSY
;CHECK FOR KONTROLLER BUSY
;CALL: MOVE W, KDB ADDRESS
; MOVE U, UDB FOR DRIVE TRYING TO SCHEDULE
; PUSHJ P,TD2BSY
; <RETURN 1> ;BUSY
; <RETURN 2> ;NOT-BUSY
; <RETURN 3> ;DON'T KNOW
;
;USES T1 AND T2
TD2BSY: 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,SAVE2## ;SAVE P1 AND P2
PUSH P,U ;SAVE U
MOVE P1,KDBIUN(W) ;POINT TO START OF DRIVE TABLE
MOVSI P2,-<TD2DMX/2> ;ACTUAL RANGE OF DRIVES PER KONT
MOVE T1,UDBPDN(U) ;GET PHYSICAL DRIVE NUMBER
TRZ T1,<TD2DMX/2>-1 ;MASK OUT DRIVE LEAVING KONTROLLER OFFSET
ADDI P1,(T1) ;ADJUST STARTING TABLE INDEX
TD2BS1: SKIPE U,(P1) ;GET A TUB ADDRESS
PUSHJ P,CHKIRB## ;SEE IF IT HAS A VALID IORB
JRST TD2BS2 ;TRY ANOTHER DRIVE
LDB T2,PRBFCN## ;GET FUNCTION CODE
MOVE T2,BITTBL## ;NOT PICK UP THE ASSOCIATED BIT
TDNN T2,TD2NBF ;NON-BLOCKING FUNCTION?
POPJ P, ;NO--KONT IS BUSY
TD2BS2: AOBJN P2,TD2BS1 ;LOOP BACK IF MORE DRIVES TO CHECK
JRST UPOPJ1## ;RESTORE U AND RETURN KONT NOT BUSY
SUBTTL INTERRUPT SERVICE
;HERE ON AN INTERRUPT FOR THIS KONTROLLER WITH:
; W/KDB ADDRESS
;RETURNS+1 ALWAYS TO TAPINT TO DISMISS THE INTERRUPT AND MAYBE
;START MORE I/O WITH
; T1/IORB ADDRESS IF FUNCTION COMPLETED,
; 0 IF ANOTHER INTERRUPT COMING
; -1 IF SCHEDULE CYCLE REQUESTED
TD2ISR: PUSHJ P,SAVE4## ;SAVE P1-P4
PUSHJ P,SVMBR## ;SAVE CURRENT MBR FOR UUO LEVEL
SETZ P4, ;CLEAR ERROR FLAGS
MOVE U,@KDBCUN(W) ;POINT AT UDB WE'RE TALKING TO
SKIPE P1,TKBFLG(W) ;OPERATION OR SENSE IN PROGRESS?
TLNN P1,-1 ;CHECK ONLY LEFT HALF
JRST CHKATN ; GO CHECK ATTENTIONS
PUSHJ P,CLRATN ;CLEAR ATTNS TO AVOID RACE IN GO BIT CHECK
PUSHJ P,MPRUN ;MICROPROCESSOR RUNNING?
JRST TD2IT1 ;NO, SKIP CHECK FOR GO BIT
MOVSI T2,(.DXCTR) ;POINT AT CONTROL REGISTER
PUSHJ P,RDMBR## ;READ IT
TRNN T2,CR.CGO ;GO BIT STILL UP FOR THIS DX20?
TD2IT1: PUSHJ P,CHKIRB## ;CHECK IORB, RETURN ADDRESS IN T1
JRST CHKATN ;NONE, CHECK ATTENTIONS
MOVSI T2,(.DXGP0) ;POINT AT ENDING STATUS REGISTER
PUSHJ P,RDMBR## ;READ IT
HRRI P1,(T2) ;CARRY IN RH OF P1
TLNE P1,(TB.ILF) ;HERE BECAUSE OF ILLEGAL FUNCTION?
HLLZ P4,TRBSTS(T1) ;YES, SETUP BITS STORED BY GENINT
MOVSI T2,TUSBOF## ;GET BOT AND OFFLINE BITS
ANDCAM T2,TUBSTS(U) ;AND CLEAR THEM IN THE UDB
SETZM TD2FST+.TFRED(U) ;ZERO FRAMES READ AND
SETZM TD2FST+.TFWRT(U) ; FRAMES WRITTEN
PUSHJ P,CHKERR ;CHECK ON ERRORS IN LAST OP
JRST DONE ;FATAL ERRORS FOUND, GIVE UP
LDB T2,[POINTR P1,TB.SFC] ;GET SOFTWARE FUNCTION FOR THIS OP
CAILE T2,MAXINT ;GREATER THAN MAX FUNCTION?
JRST TAPIFI## ;YES, ERROR
JRST @INTTBL(T2) ;DISPATCH TO SPECIFIC INTERRUPT HANDLER
SUBTTL FUNCTION SPECIFIC INTERRUPT HANDLERS
;DISPATCH HERE THROUGH INTTBL TO DO FUNCTION SPECIFIC INTERRUPT
;HANDLING. ENTER WITH:
; T1/IORB ADDRESS, U/UDB ADDRESS, W/KDB ADDRESS
; P1/LH IOFTBL ENTRY,,DEVICE STATUS BYTE
; P2/SENSE BYTES 0-3
; P4/ERROR BITS
;EXIT THROUGH DONE WITH:
; T1/IORB ADDRESS
; P4/UPDATED ERROR BITS
;HERE ON A READ BACKWARD INTERRUPT
RDBINT: SOS TUBREC(U) ;DECREMENT RECORD COUNT
TRNE P1,G0.UEX ;UNIT EXCEPTION?
PUSHJ P,LSTFIL ;YES, JUST SAW TAPE MARK
TRNN P1,G0.UCK ;UNIT CHECK?
JRST RDXINT ;NO, JOIN COMMON READ CODE
TLNE P2,(SB.UCE) ;UNIT CHECK DUE TO ERRORS?
PUSHJ P,SNSANL ;YES, ANALYZE SENSE BYTES
PUSHJ P,CHKBOT ;CHECK FOR BOT
JRST RDXINT ;JOIN COMMON READ CODE
;HERE ON A READ FORWARD/CORRECTION READ/READ LOW THRESHOLD INTERRUPT
RDFINT: AOS TUBREC(U) ;INCREMENT RECORD COUNT
TRNE P1,G0.UEX ;UNIT EXCEPTION?
PUSHJ P,NXTFIL ;YES, JUST SAW TAPE MARK
TRNE P1,G0.UCK ;UNIT CHECK?
PUSHJ P,SNSANL ;YES, ANALYZE SENSE BYTES
;; JRST RDXINT ;FALL INTO RDXINT
;HERE TO DO PROCESSING COMMON TO ALL READ INTERRUPTS
RDXINT: MOVSI T2,(.DXFCR) ;POINT AT FRAME COUNT REGISTER
PUSHJ P,RDMBR## ;READ IT
MOVEM T2,TRBRCT(T1) ;SAVE CHARACTERS READ IN IORB
MOVEM T2,TUBCCR(U) ; AND IN UDB
MOVEM T2,TD2FST+.TFRED(U) ; AND FOR DAEMON
ADDM T2,TUBCRD(U) ;BUMP CHARACTERS READ SINCE UNLOAD
ADDM T2,TKBCRD(W)
ADDM T2,.CPTFI##
LDB T3,PRBMOD## ;GET DATA MODE FROM IORB
IDIV T2,TMODTB##(T3) ;COMPUTE NUMBER OF WORDS AND RESIDUE
HRLM T2,TUBCHR(U) ;STORE WORD COUNT IN UDB
DPB T3,PMTNCR## ; AND RESIDUE
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON A WRITE INTERRUPT
WRTINT: AOS TUBREC(U) ;INCREMENT RECORD COUNT
TRNE P1,G0.UEX ;UNIT EXCEPTION?
TLO P4,RB.SET ;YES, SAW END-OF-TAPE
TRNE P1,G0.UCK ;UNIT CHECK?
JRST CHKWLK ;YES, CHECK FOR WRITE LOCK ERROR
HRRE T2,TKBWCT(W) ;GET -NUMBER OF BYTES WRITTEN
MOVNS T2 ;MAKE IT POSITIVE
MOVEM T2,TD2FST+.TFWRT(U) ;SAVE FOR DAEMON
ADDM T2,TUBCWR(U) ;BUMP CHARACTERS WRITTEN SINCE UNLOAD
ADDM T2,TKBCWR(W)
ADDM T2,.CPTFO##
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON WRITE TAPE MARK INTERRUPT
WTMINT: TRNE P1,G0.UEX ;UNIT EXCEPTION?
TLO P4,RB.SET ;YES, SAW END-OF-TAPE
TRNE P1,G0.UCK ;UNIT CHECK?
JRST CHKWLK ;YES, CHECK FOR WRITE LOCKED TAPE
AOS TUBFIL(U) ;ADJUST FILE AND RECORD COUNT (DON'T
SETZM TUBREC(U) ; CALL NXTFIL CAUSE IT SET RB.STM)
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON AN ERASE GAP INTERRUPT
ERGINT: TRNE P1,G0.UEX ;UNIT EXCEPTION?
TLO P4,RB.SET ;YES, SAW END-OF-TAPE
TRNE P1,G0.UCK ;UNIT CHECK?
JRST CHKWLK ;YES, CHECK FOR WRITE LOCKED TAPE
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON A DATA SECURITY ERASE INTERRUPT
DSEINT: TRNN P1,G0.UCK ;UNIT CHECK?
JRST DONE ;NO, EXIT THROUGH COMMON CODE
;; JRST CHKWLK ;FALL INTO CHKWLK
;HERE ON UNIT CHECKS ON WRITE TYPE OPERATIONS TO CHECK FOR A
;WRITE LOCKED TAPE
CHKWLK: PUSHJ P,SNSANL ;ANALYZE SENSE BYTES
TLNE P2,(S1.FPR) ;IS UNIT WRITE PROTECTED?
MOVSI P4,RB.SLK ;YES, TELL TAPUUO
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON A REWIND AND UNLOAD INTERRUPT
UNLINT: MOVSI T2,TKSOFL## ;GET "UNIT IS OFFLINE" BIT
IORM T2,TUBSTS(U) ;SET IT IN THE UDB
MOVSI T2,TUSBOT##!TUSREW## ;GET BOT BIT & REW
ANDCAM T2,TUBSTS(U) ;AND CLEAR IT IN THE UDB
JRST REWIN1 ;DO MOST OF REWIND CODE ALSO
;HERE ON A REWIND INTERRUPT
REWINT: MOVSI T2,TUSREW## ;GET "UNIT IS REWINDING" BIT
IORM T2,TUBSTS(U) ;SET IN UDB
REWIN1: TRNE P1,G0.UCK ;UNIT CHECK? (PROBABLY OFF-LINE)
PUSHJ P,SNSANL ;YES, ANALYZE SENSE BYTES
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON A SPACE FORWARD RECORD INTERRUPT
SFRINT: PUSHJ P,ADJREC ;ADJUST TUBREC AS APPROPRIATE
TRNE P1,G0.UEX ;UNIT EXCEPTION?
PUSHJ P,NXTFIL ;YES, SAW A TAPE MARK
TRNE P1,G0.UCK ;UNIT CHECK?
PUSHJ P,SNSANL ;YES, ANALYZE SENSE BYTES
PUSHJ P,CHKBOT ;CHECK FOR BOT
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON A SPACE BACKWARD RECORD INTERRUPT
SBRINT: PUSHJ P,ADJREC ;ADJUST TUBREC AS APPROPRIATE
TRNN P1,G0.UEX ;UNIT EXCEPTION?
JRST SBRIN1 ;NO
PUSHJ P,LSTFIL ;BACKED INTO A TAPE MARK
SETOM TUBREC(U) ;AT AN EOF
SBRIN1: TRNN P1,G0.UCK ;UNIT CHECK?
JRST DONE ;NO, EXIT THROUGH COMMON CODE
TLNE P2,(SB.UCE) ;UNIT CHECK DUE TO ERRORS?
PUSHJ P,SNSANL ;YES, ANALYZE SENSE BYTES
PUSHJ P,CHKBOT ;CHECK FOR BOT
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON A SPACE FORWARD FILE INTERRUPT
SFFINT: TRNE P1,G0.UCK ;UNIT CHECK?
PUSHJ P,SNSANL ;YES, ANALYZE SENSE BYTES
PUSHJ P,ADJFIL ;ADJUST TUBFIL, TUBREC
PUSHJ P,CHKBOT ;CHECK FOR BOT
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE ON A SPACE BACKWARD FILE INTERRUPT.
SBFINT: TRNN P1,G0.UCK ;UNIT CHECK?
JRST SBFIN1 ;NO
TLNE P2,(SB.UCE) ;UNIT CHECK DUE TO ERRORS?
PUSHJ P,SNSANL ;YES, ANALYZE SENSE BYTES
PUSHJ P,CHKBOT ;CHECK FOR BOT
SBFIN1: PUSHJ P,ADJFIL ;ADJUST TUBFIL, TUBREC
JRST DONE ;EXIT THROUGH COMMON CODE
;HERE AT THE COMPLETION OF FUNCTION SPECIFIC INTERRUPT PROCESSING
;OF A COMMAND COMPLETION INTERRUPT (BOTH DATA TRANSFER AND NON-DATA TRANSFER)
;WITH:
; T1/IORB ADDRESS
; P4/ERROR BITS
DONE: TLNN P4,RB.SLK ;CHANNEL ERRS MEANINGLESS ON WLK ERRS
PUSHJ P,CHKCHN ;CHECK FOR CHANNEL ERRORS
PUSHJ P,TSTERR ;READ ERROR REGISTERS IF NECESSARY
MOVSI T2,(.DXERR) ;SETUP TO CLEAR ERROR REGISTER
PUSHJ P,WTMBR## ;DO SO
IORM P4,TRBSTS(T1) ;SET ERROR BITS IN THE IORB
MOVSI T2,TKSOFL## ;GET OFF-LINE BIT
TLNE P4,RB.SOL ;IS IT?
IORM T2,TUBSTS(U) ;YES, SET THE BIT IN THE UDR
MOVSI T2,RB.EXC ;GET EXCEPTION BIT
TLZE P4,-1 ;ANY BITS SET?
IORM T2,TRBFNC(T1) ;YES, SET EXCEPTION ALSO
HRLM T1,TKBATN(W) ;SAVE IORB ADDRESS FOR LATER
TLO P1,(TB.DON) ;TELL CHKATN WE'VE BEEN THROUGH DONE
PUSHJ P,CHKATN ;CHECK FOR ASYNCHRONOUS STATUS
PJRST CLRALL ;RETURN
SUBTTL ANSYNCHRONOUS EVENT PROCESSING
;HERE TO CHECK FOR ANY ASYNCHRONOUS STATUS PRESENTED BY THE DX20
;AS A RESULT OF REWIND-DONE OR DRIVE ONLINE. IF ANY SUCH STATUS
;IS PRESENTED, WE START A FORCED SENSE FUNCTION ON THAT DRIVE AND
;GO AWAY, TELLING TAPSER THAT ANOTHER INTERRUPT WILL FOLLOW. WHEN
;ALL ASYNCHRONOUS STATUS IS PROCESSED, WE RETURN THE IORB FOR THE
;OPERATION THAT WAS IN PROGRESS TO TAPSER.
CHKATN: PUSHJ P,CLRATN ;CLEAR ATTENTION BITS
SKIPL T1,TKBSCH(W) ;INTERRUPT TO FORCE A SCHEDULE?
JRST CHKAT1 ;NO
SETZM TKBSCH(W) ;CLEAR SCHEDULE FLAG
JRST CLRALL ;AND RETURN -1 TO TAPSER
CHKAT1: PUSH P,U ;SAVE U
PUSHJ P,MPRUN ;IS MICROPROCESSOR STILL RUNNING?
SKIPA T2,[LOGUPE] ;NO--MUST LOG THE ERROR
MOVEI T2,ASYNST ;ELSE CHECK FOR ASYNCHRONOUS STATUS
PUSHJ P,(T2) ;DO SOMETHING
MOVSI T2,(.DXERR) ;DX20 REGISTER
PUSHJ P,WTMBR## ;CLEAR THE ERROR REGISTER
;HERE WHEN ALL ASYNCHRONOUS STATUS HAS BEEN PROCESSED. CLEAR ALL
;ASYNCHRONOUS STATUS FLAGS AND RETURN ANY IORB TO TAPSER.
ATNDON: HLRZ T1,TKBATN(W) ;GET SAVED IORB ADDRESS, IF ANY
SETZM TKBATN(W) ;NO ATTENTIONS TO WORRY ABOUT
SETZM TKBASY(W) ;NO ASYNCH
POP P,U ;RESTORE U
PJRST CLRERR ;CLEAR ERROR AND RETURN
;HERE TO RETURN A ZERO TO TAPSER TO TELL IT THAT ANOTHER INTERRUPT
;IS COMING.
RTNZRO: MOVEI T1,0 ;RETURN TO TAPSER.
POPJ P, ;AND RETURN.
SUBTTL INTERRUPT LEVEL SUPPORT SUBROUTINES
;ROUTINE TO CHECK FOR ANY ASYNCHRONOUS STATUS PRESENTED BY A
;DRIVE AT THE COMPLETION OF REWIND DONE, COMING ONLINE, ETC.
;CALL WITH:
; W/KDB ADDRESS, P1/ATTENTION BITS
;RETURN+1 IF NO STATUS PRESENTED
;RETURN+2 IF STATUS READ AND SENSE FUNCTION STARTED ON THAT DRIVE
; WITH TKBASY(W)/DX20 NUMBER,,ENDING STATUS OF DRIVE
;BOTH RETURN WITH:
; T3/UNCHANGED
ASYNST: MOVSI T2,(.DXGP4) ;POINT AT ASYNCHRONOUS STATUS REGISTER
PUSHJ P,RDMBR## ;READ IT
JUMPE T2,ASYNS2 ;MAYBE POLLING FOR NEW DRIVES
TRNE T2,G4.DVS ;ANY STATUS BITS SET?
JRST ASYNS1 ;YES, CONTINUE
MOVSI T2,(.DXGP4) ;THERE'S A UCODE RACE WHICH CAUSES IT TO GIVE
PUSHJ P,RDMBR## ;US A DRIVE WITH NO STATUS, SO READ IT AGAIN
ASYNS1: HLRZ T3,KDBUNI(W) ;GET DX20 NUMBER
HRLM T3,TKBASY(W) ;SAVE DX20 NUMBER
HRRM T2,TKBASY(W) ; AND STATUS FOR INTERRUPT
HRRM P1,TKBATN(W) ;SAVE CURRENT STATE OF ATTENTIONS
LDB T2,[POINTR TKBASY(W),G4.DRV] ;GET DRIVE #
PUSHJ P,SETUDB## ;SETUP U TO UDB ADDRESS IF ANY
POPJ P, ;NONE, JUST TRY NEXT
MOVE T2,TKBASY(W) ;GET ASSYNC AND DRIVE STATUS.
MOVE T4,TUBSTS(U) ;GET OLD STATUS
TRNN T2,G4.STM ;WRITE LOCK?
TLZA T4,TUSWTL## ;NO
TLO T4,TUSWTL## ;YES
TRNE T2,G4.ATN ;AT BOT?
TLOA T4,TUSBOT## ;YES
TLZA T4,TUSBOT## ;NO
TLZ T4,TUSREW## ;NOT REWINDING IF SO
TLZE T4,TKSOFL## ;NOT OFF-LINE NOW, WAS IT?
PUSHJ P,NOWONL ;YES, TELL MDA
MOVSI T2,TUSREW##!TKSOFL##!TUSWTL##!TUSBOT##
ANDCAM T2,TUBSTS(U) ;CLEAR IN TUB
IORM T4,TUBSTS(U) ;SO CAN SET OUR VALUES
TLNE T4,TUSBOT##
PUSHJ P,UNIBOT##
JRST ASYNS4 ;GO FINISH UP
ASYNS2: MOVSI T2,(.DXGP1) ;NEED TO KNOW WHICH DRIVE RAISED INTERRUPTED
PUSHJ P,RDMBR## ;ASK DX20
ANDI T2,G1.DRV ;KEEP ONLY DRIVE NUMBER
MOVE T1,KDBIUN(W) ;GET POINTER TO UDB TABLE
ADDI T1,(T2) ;INDEX TO TARGET UDB
SKIPN (T1) ;ALREADY KNOWN TO US?
CAILE T2,TD2HDN ;OR OUT OF RANGE?
JRST ASYNS4 ;GIVE UP
MOVE T1,BITTBL##(T2) ;GET ASSOCIATED BIT
TDNE T1,TD2IUM(W) ;WANT TO IGNORE THIS DRIVE?
JRST ASYNS3 ;YES
PUSHJ P,REDEST ;FETCH SENSE BYTES OUT OF DX20 REGISTERS
TLNE T4,(S1.TUA+S1.TUB) ;DRIVE EXIST?
IORM T1,TD2NUM(W) ;REMEMBER WHICH NEW DRIVE TO CONFIGURE
HRROS KDBNUM(W) ;FLAG IT FOR THE ONCE-A-SECOND CODE
ASYNS3: HRROS TD2SUN(W) ;OK TO CHECK ANOTHER DRIVE NOW
ASYNS4: MOVSI T2,(.DXGP4) ;SETUP TO CLEAR ASYNC STATUS REGISTER.
PUSHJ P,WTMBR## ;DO IT!!!
PJRST CLRERR
;ROUTINE TO REQUEST THAT THE DX20 STORE A PARTICULAR LOCATION
;FROM ITS EXTENDED STATUS TABLE INTO MASSBUS REGISTERS 26 AND 27.
;CALL WITH:
; T2/EST OFFSET REQUESTED, U/UDB ADDRESS, W/KDB ADDRESS
;RETURN+1 IF THE DX20 TIMED OUT ON THE REQUEST
;RETURN+2 IF SUCCESSFUL
SETEST: HRLI T2,(.DXGP0) ;POINT TO EST REGISTER
TRO T2,G0.RES ;SET THE REQUEST EST BIT
PUSHJ P,WTMBR## ;TELL THE DX20
PUSH P,T1 ;SAVE T1
MOVEI T1,100 ;MAX LOOP COUNT TO WAIT FOR BIT TO CLEAR
SETES1: MOVSI T2,(.DXGP0) ;POINT AT EST REGISTER AGAIN
PUSHJ P,RDMBR## ;READ IT
TRNE T2,G0.RES ;DX20 DONE WHAT WE WANT?
SOJG T1,SETES1 ;NO, LOOP
JUMPLE T1,TPOPJ## ;IF WE TIMED OUT, QUIT
JRST TPOPJ1## ;GOT IT, GIVE SKIP RETURN
;ROUTINE TO READ THE INFORMATION FROM THE TWO EXTENDED STATUS
;REGISTERS. THE EXACT INFORMATION READ DEPENDS UPON THE VALUE
;OF THE STATUS INDEX IN .DXGP0.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS WITH T4/.DXGP6,,.DXGP7
REDEST: MOVSI T2,(.DXGP6) ;POINT AT EXTENDED STATUS REGISTER 0
PUSHJ P,RDMBR## ;READ IT
HRLZ T4,T2 ;MOVE TO WHERE CALLER EXPECTS IT
MOVSI T2,(.DXGP7) ;POINT AT EXTENDED STATUS REGISTER 1
PUSHJ P,RDMBR## ;READ IT
HRR T4,T2 ;MOVE TO WHERE CALLER EXPECTS IT
POPJ P, ;AND RETURN
;ROUTINE TO CLEAR ALL ATTENTION BITS IN THE ATTENTION SUMMARY REGISTER
;AND UPDATE THE ATTENTION BITS IN TKBATN.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS WITH:
; T2/UPDATED ATTENTION BITS
CLRATN: MOVSI T2,(.DXASR) ;POINT TO ATTENTION SUMMARY REGISTER
MOVEI T3,0 ;ASR IS NOT DX20 SPECIFIC
PUSHJ P,RDMBR## ;READ IT
ANDI T2,AS.ATN ;KEEP ONLY ATTENTION BITS
TDNN T2,KDBUNI(W) ;ATTEN FOR THIS UNIT?
JRST CLRAT1 ;NO, RETURN 0
HRRZ T2,KDBUNI(W) ;YES, GET JUST THAT BIT
IORM T2,TKBATN(W) ;UPDATE CORE COPY
HRLI T2,(.DXASR) ;SETUP TO CLEAR THE REGISETER
PUSHJ P,WTMBR## ;DO SO
CLRAT1: HRRZ T2,TKBATN(W) ;RETURN UPDATED BITS TO CALLER
POPJ P, ;RETURN
;ROUTINES TO SET RB.STM, ZERO TUBREC AND ADJUST TUBFIL
;TO REFLECT THE ENDING STATE OF THE LAST OPERATION. ENTRY POINTS ARE:
; NXTFIL - ADD 1 TO TUBFIL
; LSTFIL - SUBTRACT 1 FROM TUBFIL
; ADJFIL - ADJUST TUBFIL BY NUMBER OF FILES DONE (+ OR -)
;CALL WITH:
; W/KDB ADDRESS, U/UDB ADDRESS, T1/IORB ADDRESS, P4/ERROR BITS
;RETURN+1 ALWAYS WITH:
; T1/IORB ADDRESS, P4/ERROR BITS+RB.STM
LSTFIL: SOSA TUBFIL(U) ;AT LAST FILE
NXTFIL: AOS TUBFIL(U) ;AT NEXT FILE
JRST ADJFI1 ;JOIN COMMON CODE
ADJFIL: PUSHJ P,NUMOPS ;COMPUTE NUMBER OF FILES MOVED
ADDM T3,TUBFIL(U) ;ADJUST TUBFIL BY THAT AMOUNT
JUMPE T3,ADJFI2 ;DON'T SET RB.STM IF NO MOTION
ADJFI1: TLO P4,RB.STM ;SAW TAPE MARK
ADJFI2: SETZM TUBREC(U) ;AT FIRST RECORD OF FILE
POPJ P, ;RETURN
;ROUTINE TO ADJUST TUBREC BY THE NUMBER OF RECORDS MOVED IN THE
;LAST OPERATION. CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS
;RETURN+1 ALWAYS
ADJREC: PUSHJ P,NUMOPS ;COMPUTE NUMBER OF RECORDS MOVED
ADDM T3,TUBREC(U) ;ADJUST TUBREC ACCORDINGLY
POPJ P, ;AND RETURN
;ROUTINE TO COMPUTE THE NUMBER OF OPERATIONS PERFORMED AS A RESULT
;OF THE LAST NON DATA TRANSFER REQUEST. DEPENDS ON THE FACT THAT
;TAPUUO SETS UP IRBCCW TO THE CORRECT NUMBER OF OPERATIONS FOR ANY
;REQUEST ON WHICH NUMOPS IS TO BE CALLED. CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS, T1/IORB ADDRESS
; P1/IOFTBL ENTRY,,DEVICE STATUS BITS
; P4/ERROR BITS
;RETURN+1 ALWAYS WITH:
; T3/+NUMBER IF FORWARD OPERATION, -NUMBER IF REVERSE
NUMOPS: MOVSI T2,(.DXFCR) ;POINT TO FRAME COUNT REGISTER
PUSHJ P,RDMBR## ;READ -NUMBER OF OPS NOT PERFORMED
HRRZ T3,@IRBACC(T1) ;GET +NUMBER REQUESTED BY TAPUUO
JUMPE T2,NUMOP1 ;IF ALL WERE DONE, TAKE QUICK PATH
IOR T2,[-1,,600000] ;MAKE IT 36 BIT NEGATIVE NUMBER
MOVNS T2 ;MAKE IT POSITIVE
SUB T3,T2 ;COMPUTE NUMBER ACTUALLY DONE
NUMOP1: TLNE P1,(TB.REV) ;THIS A REVERSE OPERATION?
MOVNS T3 ;YES, MAKE IT NEGATIVE
POPJ P, ;RETURN TO CALLER
;ROUTINE TO SEE IF THE UNIT IS CURRENTLY AT BOT AND ADJUST THE UNIT
;AND IORB STATUS TO REFLECT THIS. CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS, T1/IORB ADDRESS
; P2/SENSE BYTES 0-3
; P4/ERROR BITS
;RETURN+1 ALWAYS WITH:
; T1/IORB ADDRESS,
; P4/UPDATED ERROR BITS
; TUBFIL AND TUBREC ZEROED IF AT BOT, TUBSTS UPDATED
CHKBOT: TLNN P2,(S1.BOT) ;NOW AT BOT?
POPJ P, ;NO, RETURN
SKIPN TUBREC(U) ;IF NOT PREVIOUSLY
SKIPE TUBFIL(U) ; AT BOT,
PJRST SETBOT ; SET IT NOW
TLO P4,RB.SNM ;OTHERWISE, NO MOTION
;; PJRST SETBOT ;AND FALL INTO BOT
;ROUTINE TO ADJUST UDB AND IORB STATUS TO SHOW THAT THE UNIT IS
;AT BOT. CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS, T1/IORB ADDRESS, P4/ERROR BITS
;RETURN+1 ALWAYS WITH:
; T1/IORB ADDRESS, P4/ERROR BITS+RB.SBT,
; TUBREC, TUBFIL ZEROED, TUBSTS UPDATED
SETBOT: TLO P4,RB.SBT ;NOW AT BOT
PJRST UNIBOT## ;LET TAPSER DO THE REST
;ROUTINE TO CHECK FOR ANY ERRORS IN THE LAST OPERATION.
;CALL WITH:
; T1/IORB ADDRESS, U/UDB ADDRESS, W/KDB ADDRESS,
; P1/IOFTBL BITS,,ENDING STATUS BYTE
; P4/ERROR BITS
;RETURN+1 IF HARD ERROR
;RETURN+2 IF NO ERRORS (OR A RECOVERABLE ERROR) DETECTED
;BOTH RETURN WITH:
; P2/0 IF NO ERRORS
; SENSE BYTES 0-3 IF ERROR
; T1/IORB ADDRESS
; P4/UPDATED ERROR BITS
CHKERR: MOVEI P2,0 ;ASSUME NO ERRORS AND RETURN ZERO SENSE BYTES
MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
PUSHJ P,RDMBR## ;READ IT
TRNN T2,SR.RUN ;MICROPROCESSOR STILL RUNNING?
JRST MPSERR ;NO
AOS 0(P) ;ASSUME NO ERROR OR RECOVERABLE ERROR
TRNN T2,SR.CER ;COMPOSITE ERROR?
PJRST CHKDEN ;NO, CHECK FOR SENSE DATA FOR DENSITY DETECT
MOVSI T2,(.DXERR) ;POINT AT ERROR REGISTER
PUSHJ P,RDMBR## ;READ IT
TRNE T2,ER.ERR ;SOME GENERIC HARDWARE FAILURE?
TLO P4,RB.SED ;YES, JUST TRY RECOVERY
TDNN P1,[TB.FSN!G0.UCK] ;FORCED A SENSE OR HAVE A UNIT CHECK?
JRST CHKER1 ;NO, NO SENSE BYTES WERE READ
PUSH P,T2 ;SAVE ERROR REGISTER
PUSHJ P,REDEST ;GET SENSE BYTES FOR THIS DRIVE
MOVE P2,T4 ;MOVE SENSE BYTES TO CORRECT PLACE
PUSHJ P,CHKDEN ;CHECK FOR DENSITY DETECT EVEN IF ERRORS
POP P,T2 ;RESTORE ERROR REGISTER
CHKER1: TRNN T2,ER.UPE ;MICROPROCESSOR ERROR?
JRST ERRXIT ;NO, THEN CODE IS MEANINGLESS
LDB T3,[POINTR T2,ER.ECC] ;GET ERROR CLASS CODE
CAILE T3,ECCMAX ;BIGGER THAN WE KNOW ABOUT
JRST FTLERR ;YES, FATAL
JRST @ECCTBL(T3) ;DISPATCH TO ERROR HANDLER
;DISPATCH TABLE OF ROUTINES TO HANDLE SPECIFIC ERROR CONDITIONS
;DETECTED BY THE DX20. THE TABLE IS INDEXED BY THE ERROR CLASS
;CODE IN THE ERROR REGISTER.
ECCTBL: IFIW FTLERR ;0 - UNKNOWN
IFIW ERRXIT ;1 - UNUSUAL DEVICE STATUS
IFIW ERRXIT ;2 - SHORT RECORD - NOT AN ERROR
IFIW LNGREC ;3 - LONG RECORD
IFIW OFLERR ;4 - DRIVE SELECTION ERROR
IFIW RTYERR ;5 - RECOVERABLE ERROR (TAPE MOTION)
IFIW NOMERR ;6 - RECOVERABLE ERROR (NO TAPE MOTION)
IFIW NRTERR ;7 - NON-RECOVERABLE ERROR
IFIW FTLERR ;10 - FATAL ERROR
IFIW FTLERR ;11 - MICRODIAGNOSTICS FAILURE
ECCMAX==.-ECCTBL-1 ;MAXIMUM ERROR CODE WE KNOW ABOUT
NRTERR: LDB T3,[POINTR T2,ER.ESC] ;GET SUB-CLASS CODE FOR THIS ERROR
CAIE T3,.ERRTT ;READ TRANSFER TIMEOUT (BLANK TAPE)?
JRST NRTER1 ;NO
JRST MPSERR ;YES, SET OFF-LINE ALSO
FTLERR: SOS 0(P) ;GIVE NON-SKIP RETURN FOR HARD BAD ERROR
TLO P4,RB.SMO ;FLAG AS SET OFFLINE BY MONITOR
PUSHJ P,MPRES ;MAKE DAMN SURE IT STAYS OFF LINE
MPSERR: TLOA P4,RB.SED!RB.SER!RB.SOL ;SOME ERROR+NO RETRY+SET OFF LINE
NRTER1: TLO P4,RB.SED!RB.SER ;SOME ERROR+NO RETRY
JRST ERRXIT ;JOIN COMMON EXIT
OFLERR: TLO P4,RB.SOL ;SELECT ERROR MEANS DRIVE IS OFF-LINE
NOMERR: TLO P4,RB.SNM ;NO MOTION
RTYERR: TLOA P4,RB.SED ;SOME ERROR
LNGREC: TLO P4,RB.STL!RB.SER ;LONG RECORD+NO RETRY
ERRXIT: SKIPE P4 ;SEE ANY ERRORS AT ALL?
TLO P1,(TB.ERR) ;YES, SET FLAG FOR QUICK CHECK
POPJ P, ;RETURN
;ROUTINE TO CHECK TO SEE IF WE FORCED A SENSE ON A READ OPERATION SO
;THAT WE CAN TELL THE USER THE REAL DENSITY THAT THE TAPE IS WRITTEN
;AT.
;CALL WITH:
; T1/IORB ADDRESS, U/UDB ADDRESS, W/KDB ADDRESS
; P1/IOFTBL ENTRY,,ENDING STATUS BYTE, P2/SENSE BYTES 0-3(0 IF NOT READ)
; P4/ERROR BITS
;RETURN+1 ALWAYS WITH DENSITY UPDATED IN THE IORB
CHKDEN: MOVEI T2,TUC7TK## ;GET 7 TRACK BIT
TDNN T2,TUBCNF(U) ;NO SENSE BYTE INFO IF A 7 TRACK DRIVE
TLNN P1,(TB.FSN) ;FORCED SENSE DONE?
POPJ P, ;NEITHER, RETURN NOW
JUMPN P2,CHKDE1 ;GO IF ALREADY HAVE THE SENSE BYTES
PUSHJ P,REDEST ;READ SENSE BYTES 0-3 NOW
JUMPE T4,CPOPJ## ;DIDN'T GET THEM IF ALL ZERO
MOVE P2,T4 ;MOVE THEM TO WHERE WE WANT THEM
CHKDE1: TRNE P2,S3.D16 ;IS THE TAPE AT 1600?
JRST [MOVEI T2,RB.D16 ;YES, SET 1600 BPI
JRST CHKDE2] ;AND STORE IT
MOVEI T2,.SB06 ;GET OFFSET INTO EST TO READ SENSE BYTE 6
PUSHJ P,SETEST ;ASK THE DX20 FOR THE INFORMATION
POPJ P, ;CAN'T GET IT, GIVE UP
PUSHJ P,REDEST ;READ SENSE BYTES 4-7 INTO T4
MOVEI T2,RB.D8 ;ASSUME 800 BPI
TRNE T4,S6.D62 ;WAS IT A 6250 BPI TAPE?
MOVEI T2,RB.D62 ;YES, USE THAT INSTEAD
CHKDE2: DPB T2,PRBDEN## ;STORE THAT IN THE IORB FOR THE WORLD
POPJ P, ;RETURN
;ROUTINE TO ANALYZE THE SENSE BYTES FOR A DRIVE ON WHICH AN ERROR
;OCCURRED AND SET THE APPROPRIATE ERROR BITS.
;CALL WITH:
; T1/IORB ADDRESS,
; P1/IOFTBL ENTRY,,DEVICE STATUS BYTE, P2/SENSE BYTES 0-3
; P4/ERROR BITS
;RETURN+1 ALWAYS WITH:
; T1/IORB ADDRESS
; P4/UPDATED ERROR BITS
SNSANL: TLO P1,(TB.ERR) ;SET ERROR
TLNE P2,(S0.EQC) ;EQUIPMENT CHECK?
JRST EQCERR ;YES, GO ANALYZE IT
TLNE P2,(S0.BOC) ;BUS-OUT CHECK?
JRST BOCERR ;YES
TLNE P2,(S0.IRQ) ;INTERVENTION REQUIRED WITHOUT
TRNE P1,G0.DVE ; DEVICE END MEANS
JRST SNSAN1 ; DEVICE IS OFFLINE OR
JRST IRQERR ; NON-EXISTENT
SNSAN1: TLNE P2,(S0.CRJ!S1.NTC) ;COMMAND REJECT OR NOT CAPABLE?
JRST CMRERR ;YES
TLNE P2,(S0.OVR) ;OVERRUN?
JRST OVRERR ;YES
TLNE P2,(S0.DTC) ;DATA CHECK?
JRST DTCERR ;YES
;COMMAND REJECT AND EQUIPMENT CHECK ARE CONSIDERED FATAL ERRORS
CMRERR:
EQCERR: TLOA P4,RB.SER!RB.SED ;NON-RECOVERABLE + ERROR
IRQERR: TLO P4,RB.SED!RB.SOL!RB.SNM ;IRQ GETS OFFLINE + NO MOTION
POPJ P, ;RETURN
;BUS OUT CHECK WITHOUT DEVICE END MEANS NO MOTION, ELSE RETRY
BOCERR: TRNN P1,G0.DVE ;DEVICE END UP?
TLO P4,RB.SNM ;NO, SET NO MOTION
;OVERRUN CAUSES REPOSITION AND RETRY
OVRERR: TLOA P4,RB.SED ;SOME ERROR
;DATA CHECK INVOKES TAPSER'S ERROR RETRY ALGORITHM
DTCERR: TLO P4,RB.SDE!RB.SED ;DATA ERROR + ERROR
POPJ P, ;RETURN
;ROUTINE TO CHECK FOR AND HANDLE ANY CHANNEL ERRORS THAT OCCURRED
;ON THE LAST OPERATION. CALL WITH:
; T1/IORB ADDRESS, P1/IOFTBL ENTRY FOR FUNCTION, P4/ERROR BITS
; W/KDB ADDRESS
;RETURN+1 ALWAYS WITH:
; T1/IORB ADDRESS
; P4/UPDATED ERROR BITS
CHKCHN: PUSH P,T1 ;SAVE IORB
XCT KDBCNI(W) ;GET CONI INTO T1
MOVE T2,T1 ;COPY RESULTS
POP P,T1 ;RESTORE IORB
MOVE T3,KDBICP(W) ;GET ADDRESS OF CHANNEL LOGOUT AREA
HLL T2,.CSCLP(T3) ;LOGOUT AREA ERROR BITS IN LH
TLNN P1,(TB.DAT) ;THIS A DATA OPERATION?
TLZA T2,-1 ;NO, CLEAR THE STATUS BITS; THEY'RE USELESS
TLC T2,(CS.NAE) ;MAKE BIT EQUAL 1 IF ADDRESS PARITY ERROR
TDNN T2,[CS.ERR!CI.ERR] ;ANY ERROR DETECTED?
POPJ P, ;NO, RETURN
TRNE T2,CI.RAE ;REGISTER ACCESS ERROR?
JRST CHKCH2 ;YES, GO SET THE APPROPRIATE BITS AND RETRY
TLNN T2,(CS.MPE!CS.NXM) ;MEM PAR ERROR OR NXM?
JRST CHKCH1 ;NO
PUSHJ P,SAVE1## ;GET A REGISTER TO USE
PUSH P,T1 ;AND SAVE OUR T1
MOVEI T3,CHENXM## ;POINT AT RTN TO CALL FOR NXM
MOVSI T4,IOCHNX ;ASSUMING NXM
TLNN T2,(CS.NXM) ;ARE WE CORRECT?
MOVEI T3,CHEMPE## ;NO, USE THIS ONE
TLNN T2,(CS.NXM) ; ...
MOVSI T4,IOCHMP ; ...
MOVE T1,KDBICP(W) ;GET ADDRESS OF LOGOUT AREA
MOVE P1,KDBCHN(W) ;GET CHANNEL DATA BLOCK ADDRESS
MOVE F,TUBCUR(U) ;GET DDB ADDRESS
IORM T4,CHNNUM(P1) ;MARK MEMORY ERROR FOR LATER SWEEP
SKIPN TUBERR(U) ;CALL ERRCON ON FIRST ERROR ONLY
PUSHJ P,(T3) ;LET COMMON HANDLE THE ERROR
POP P,T1 ;RESTORE T1
CHKCH1: TLOA P4,RB.SED ;TELL UPPER LEVEL OF ERROR
CHKCH2: TLO P4,RB.SNM!RB.SED ;NO MOTION, SOME ERROR FOR RAE
TLO P1,(TB.ERR) ;ALSO SET ERROR
POPJ P, ;AND RETURN
SUBTTL CHECK FOR KONTROLLER ONLINE
;HERE TO SEE IF A KONTROLLER IS ONLINE. WHAT WE REALLY DO IS
;CHECK TO SEE THAT ALL DX20'S ON THIS KONTROLLER ARE RUNNING.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 IF ANY DX20 IS NOT RUNNING
;RETURN+2 IF ALL DX20'S ARE RUNNING
TD2ONL: MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
TAPOFF ;AVOID RACE WITH INTERRUPT RDMBR
PUSHJ P,RDMBR## ;GO READ STATUS REGISTER
TAPON ;TURN PI BACK ON
TRNN T2,SR.RUN ;MP RUNNING?
POPJ P, ;REPORT CONTROLLER OFFLINE
SKIPL @KDBCHN(W) ;CHANNEL BUSY?
JRST CPOPJ1## ;LEAVE IT ALONE
SKIPE T1,TD2NUM(W) ;GET BIT MASK
JFFO T1,TD2ON3 ;FIND FIRST UNIT NUMBER
HRRZS KDBNUM(W) ;INDICATE NO DRIVES TO CONFIGURE
SKIPL T1,TD2SUN(W) ;GET NON-EXISTANT UNIT BEING SENSED
JRST CPOPJ1## ;DO NOTHING IF SENSE IN PROGRESS
PUSHJ P,SAVE1## ;SAVE P1
AOS T1 ;ADVANCE TO NEXT UNIT
HRRZS T1 ;CLEAR LH FLAG
CAILE T1,TD2HDN ;OVERFLOW?
MOVEI T1,0 ;START WITH DRIVE ZERO
ADD T1,KDBIUN(W) ;INDEX INTO TABLE
TD2ON1: SKIPN (T1) ;KNOWN UNIT?
JRST TD2ON2 ;NO
CAMGE T1,KDBFUN(W) ;END OF TABLE?
AOJA T1,TD2ON1 ;TRY ANOTHER
SETOM TD2SUN(W) ;RESET COUNTER
JRST CPOPJ1## ;AND INDICATE CONTROLLER ONLINE
TD2ON2: SUB T1,KDBIUN(W) ;REDUCE TO A DRIVE NUMBER
MOVEM T1,TD2SUN(W) ;SAVE FOR NEXT TIME
MOVE P1,T1 ;COPY PHYSICAL DRIVE NUMBER
HLL P1,KDBUNI(W) ;INCLUDE MASSBUS UNIT
PUSHJ P,TD2DCK ;QUEUE UP SENSE REQUEST
JFCL ;SHOULD NEVER SKIP
JRST CPOPJ1## ;RETURN
TD2ON3: PUSHJ P,AUTLOK## ;GET AUTCON INTERLOCK
JRST CPOPJ1## ;TRY AGAIN NEXT TIME
MOVE P1,T2 ;COPY PHYSICAL DRIVE NUMBER
HLL P1,KDBUNI(W) ;INCLUDE MASSBUS UNIT
MOVE T1,KDBDVC(W) ;DEVICE CODE
XMOVEI T2,TD2DSP ;DISPATCH
MOVE T3,KDBCHN(W) ;CHANNEL DATA BLOCK
PUSHJ P,AUTSET## ;SET UP CPU VARIABLES
PUSHJ P,TD2DRV ;TRY TO CONFIGURE A DRIVE
JFCL ;IGNORE ERRORS
PUSHJ P,AUTULK## ;RELEASE AUTCON INTERLOCK
JRST CPOPJ1## ;TELL TAPSER THE CONTROLLER IS ALIVE
;ROUTINE TO CHECK THAT THE DX20 IS ALIVE AND WELL
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 IF NOT OK
;RETURN+2 IF OK
CHEKOK: PUSHJ P,RDDTR## ;IS IT REALLY A DX20?
CAIE T2,.DTCOD ;DX20?
POPJ P, ;NO, ERROR RETURN
MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
TAPOFF ;AVOID RACE WITH INTERRUPT RDMBR
PUSHJ P,RDMBR## ;GO READ STATUS REGISTER
TAPON ;TURN PI BACK ON
TRNE T2,SR.RUN ;MP RUNNING?
AOS (P) ;YES. TAKE GOOD RETURN
POPJ P,
SUBTTL CAUSE A SCHEDULE CYCLE
;HERE TO FORCE A SCHEDULE CYCLE. WE SET A FLAG FOR LATER
;AND SET THE STOP BIT IN THE RH20 WHICH CAUSES AN INTERRUPT.
;AT INTERRUPT LEVEL, WE CHECK THE FLAG AND RETURN T1=-1 TO
;TAPSER TO FORCE A SCHEDULE CYCLE.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
TD2SCH: SETOM TKBSCH(W) ;SET FLAG FOR SCHEDULE CYCLE
PUSHJ P,SETIVO ;SETUP INTERRUPT VECTOR ADDRESS
PUSH P,T1 ;SAVE T1
MOVEI T1,CO.STP ;GET "STOP TRANSFER" BIT
XCT KDBCNO(W) ;STOP THE RH20
POP P,T1 ;RESTORE T1
PUSHJ P,CLRFLG ;CLEAR KDB FLAGS
PJRST REASPI ;REASSIGN PI AND RETURN
;ROUTINE TO ENABLE THE MASSBUS AND SETUP THE RH20
;INTERRUPT VECTOR ADDRESS
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
SETIVO: PUSH P,T1 ;SAVE T1
MOVEI T1,CO.MBE!CO.RAE ;GET MASSBUS ENABLE BIT
XCT KDBCNO(W) ;DO SO
POP P,T1 ;RESTORE T1
MOVE T3,KDBVIN(W) ;SET UP ICWA+3
HRLI T3,(XPCW)
MOVE T2,KDBICP(W)
MOVEM T3,3(T2)
MOVE T2,KDBIVI(W) ;GET DATAO WORD TO SETUP INTERRUPT VECTOR
XCT KDBDTO(W) ;WE GET INTERRUPTS AT 40+2N
POPJ P, ;RETURN
SUBTTL ASSORTED SMALL ROUTINES
;ROUTINE TO CLEAR ALL ERRORS, THE KDB FLAGS AND REASSIGN THE RH20
;PI. CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
CLRALL: PUSHJ P,CLRFLG ;CLEAR KDB FLAGS
;; PJRST CLRERR ;FALL INTO CLRERR
;ROUTINE TO CLEAR THE ERROR BITS IN THE RH20 CONI WORD AND REASSIGN
;THE PI ASSIGNMENT
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
CLRERR: PUSH P,T1 ;SAVE T1
MOVEI T1,CO.CLR ;GET BITS TO CLEAR ERRORS
XCT KDBCNO(W) ;CLEAR THEM
SKIPA ;FALL INTO REASPI
;ROUTINE TO REASSIGN THE RH20 PI
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
REASPI: PUSH P,T1 ;SAVE T1
MOVEI T1,CO.AIE!CO.MBE!TAPCHN## ;GET BITS TO ENABLE INTERRUPTS
XCT KDBCNO(W) ;DO SO
POP P,T1 ;RESTORE T1
POPJ P, ;RETURN
;ROUTINE TO CLEAR ALL KDB FLAGS.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
CLRFLG: HRRZS TKBATN(W) ;CLEAR ALL BUT ATTENTION BITS
SETZM TKBASY(W) ;PLUS ASYNCHRONOUS STATUS
SETZM TKBFLG(W) ;AND OPERATION FLAGS
POPJ P, ;RETURN
;ROUTINE TO TELL THE MOUNTABLE DEVICE ALLOCATOR THAT A TAPE
;DRIVE JUST CAME ONLINE. PRESERVES T1-T4.
;RETURN+1 ALWAYS
NOWONL: PUSHJ P,SAVT## ;SAVE T1-T4
PJRST TPMONL## ;TELL MDA AND RETURN
SUBTTL MICROPROCESSOR HANDLING ROUTINES
;ROUTINE TO CHECK THE VALIDITY OF THE MICROPROCESSOR CONTROL STORE.
;THIS INVOLVES CHECKING FOUR THINGS AS FOLLOWS:
;
; 1. CRAM LOCATION 7 MUST CONTAIN A COPY OF THE DRIVE TYPE REGISTER
; 2. CRAM LOCATION 10 MUST CONTAIN AN OCTAL 100 (.CRM10)
; 3. CRAM LOCATION 11 MUST CONTAIN THE MAGIC VALUE 042562 (.CRM11)
; 4. D7.IRP MUST NOT COME UP WHILE READING ANY OF THE ABOVE
;
;CALL WITH:
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 IF AN ERROR IS DETECTED
;RETURN+2 IF ALL OK
MPCHK: MOVE T2,[.DXDR1!D1.IRE!D1.PCE!D1.PCI!7] ;REGISTER TO WRITE+
; IR ENABLE+PC ENABLE+PC AUTO INCR+PC TO READ
PUSHJ P,WTMBR## ;WRITE THE REGISTER
MOVSI T2,(.DXDR0) ;POINT AT DIAGNOSTIC REGISTER 0
PUSHJ P,RDMBR## ;READ THE CONTENTS
PUSH P,T2 ;SAVE FOR COMPARE
MOVSI T2,(.DXDTR) ;POINT AT DRIVE TYPE REGISTER
PUSHJ P,RDMBR## ;READ THAT
POP P,T3 ;RESTORE CRAM LOCATION 7
CAME T2,T3 ;HAVE TO BE THE SAME
POPJ P, ;ERROR IF NOT
MOVSI T2,(.DXDR7) ;POINT AT DIAGNOSTIC REGISTER 7
PUSHJ P,RDMBR## ;READ IT
TRNE T2,D7.IRP ;IR PARITY ERROR ON LAST READ?
POPJ P, ;YES, THAT'S AN ERROR
MOVSI T2,(.DXDR0) ;POINT AT DIAGNOSTIC REGISTER 0 AGAIN
PUSHJ P,RDMBR## ;READ CRAM LOC 10 (PC AUTO INCR SET)
CAIE T2,.CRM10 ;MUST BE THIS VALUE
POPJ P, ;NOT, ERROR
MOVSI T2,(.DXDR7) ;POINT AT DIAGNOSTIC REGISTER 7
PUSHJ P,RDMBR## ;READ IT
TRNE T2,D7.IRP ;IR PARITY ERROR ON LAST READ?
POPJ P, ;YES, ERROR
MOVSI T2,(.DXDR0) ;POINT AT DIAGNOSTIC REGISTER 0 ONCE MORE
PUSHJ P,RDMBR## ;READ CRAM LOCATION 11
CAIE T2,.CRM11 ;MUST BE THIS VALUE
POPJ P, ;NOT, ERROR
MOVSI T2,(.DXDR7) ;POINT AT DIAGNOSTIC REGISTER 7
PUSHJ P,RDMBR## ;READ IT
TRNN T2,D7.IRP ;IR PARITY ERROR ON LAST READ?
AOS (P) ;NO, GIVE SKIP RETURN
POPJ P, ; AND RETURN
;ROUTINE TO START THE MICROPROCESSOR AT A SPECIFIED LOCATION
;CALL WITH:
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 ALWAYS
MPSTRT: PUSHJ P,MPRES ;RESET THE MICROPROCESSOR
MOVE T2,[.DXDR1!D1.IRE!D1.PCE!D1.PCI!.DXSAD] ;POINT TO REGISTER AND SET BITS
PUSHJ P,WTMBR## ;TELL MP ITS START ADDRESS
MOVE T2,[.DXMTR!MR.STR] ;SET START BIT IN MAINTENANCE REG
PJRST WTMBR## ;START IT AND RETURN
;ROUTINE TO RESET THE MICRO PROCESSOR
;CALL WITH:
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 ALWAYS
MPRES: MOVE T2,[.DXMTR!MR.RES] ;SET RESET BIT IN MAINT REG
PJRST WTMBR## ;WRITE REGISTER AND RETURN
;ROUTINE TO READ THE DX20 MICROCODE VERSION NUMBER FROM CRAM
;LOCATION 0.
;CALL WITH:
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 ALWAYS WITH:
; T2/MICROCODE VERSION NUMBER, T3/DX20 ADDRESS
MPVER: MOVE T2,[.DXDR1!D1.IRE!D1.PCE!0] ;SET TO READ CRAM LOC 0
PUSHJ P,WTMBR## ;TELL THE DX20
MOVSI T2,(.DXDR0) ;ANSWER APPEARS HERE
PJRST RDMBR## ;READ VERSION NUMBER AND RETURN
;ROUTINE TO SEE IF THE MICROPROCESSOR IS STILL RUNNING?
;CALL WITH:
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 IF NOT RUNNING
;RETURN+2 IF RUNNING
MPRUN: MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
PUSHJ P,RDMBR## ;READ IT
TRNE T2,SR.RUN ;IS IT RUNNING?
AOS 0(P) ;YES, GIVE SKIP RETURN
POPJ P, ;RETURN
;ROUTINE TO MAKE AN ERROR ENTRY FOR A DX20 THAT HAS HALTED.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
;PRESERVES U,F
LOGUPE: PUSHJ P,SAVE1## ;SAVE P1
PUSH P,U ; AND U
PUSH P,F ; AND F
PUSH P,T3 ;SAVE T3
HLRZ T2,KDBUNI(W) ;GET DX20 NUMBER
LSH T2,3 ;CONSTRUCT OFFSET TO DRIVE 0 ON DX20
ADD T2,KDBIUN(W) ;INDEX INTO UDB TABLE
CAMG T2,KDBFUN(W) ;REASONABLE OFFSET?
SKIPN U,(T2) ;FETCH UDB ADDRESS
JRST LOGUP1 ;NONE???
MOVSI T2,(1B1) ;FLAG THIS A HARD
IORM T2,TUBTRY(U) ; ERROR FOR DAEMON
MOVEI P1,0 ;SET NO FLAGS
PUSHJ P,RDAREG ;READ INITIAL AND FINAL REGISTERS
PUSHJ P,TPELOG## ;LOG THIS ERROR
LOGUP1: POP P,T3 ;RESTORE T3
POP P,F ; AND F
JRST UPOPJ## ; AND U AND RETURN
SUBTTL ROUTINES TO SAVE ERROR INFORMATION IN TUBFEP
;ROUTINE TO READ THE ERROR INFORMATION INTO THE UDB IF AN ERROR
;WAS DETECTED OR AS THE RESULT OF A RECOVERED ERROR.
;CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS
;RETURN+1 ALWAYS
TSTERR: SKIPE TUBERR(U) ;IN ERROR RECOVERY?
PJRST RDFREG ;YES, READ FINAL REGISTERS
MOVEI T2,TUCSNS## ;GET "REQUEST FORCED SENSE" BIT
TLZN P1,(TB.ERR) ;ERROR SEEN ON THIS OPERATION?
TDNE T2,TUBCNF(U) ; OR USER FORCE A SENSE?
PJRST RDIREG ;YES, READ INITIAL REGISTERS
POPJ P, ;NO, JUST RETURN
;ROUTINE TO READ BOTH THE INITIAL AND FINAL "REGISTERS" INTO THE
;UDB.
;CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS
; P1/IOFTBL ENTRY,,DEVICE STATUS BYTE
;RETURN+1 ALWAYS
RDAREG: PUSH P,TUBERR(U) ;SAVE VALUE OF TUBERR
SETZM TUBERR(U) ;FORCE READ OF INITIAL REGISTERS
PUSHJ P,RDIREG ;READ "INITIAL" REGISTERS
SETOM TUBERR(U) ;FORCE READ OF FINAL REGISTERS
PUSHJ P,RDFREG ;READ "FINAL" REGISTERS
POP P,TUBERR(U) ;RESTORE VALUE OF TUBERR
MOVE T1,TD2ULP+.ULVER ;GET UCODE VERSION
HLL T1,KDBUNI(W) ;INCLUDE MASSBUS UNIT NUMBER
MOVEM T1,TD2FST+.TFVER(U) ;SAVE IN FEP BLOCK
POPJ P, ;RETURN
;ROUTINE TO SAVE INFORMATION IN THE UDB AT THE TIME OF THE ERROR.
;CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS,
; P1/IOFTBL ENTRY,,DEVICE STATUS BYTE
;RETURN+1 ALWAYS
RDIREG: PUSH P,T1 ;SAVE T1
XCT KDBCNI(W) ;GET ERROR CONI
MOVEM T1,TD2FST+.TFCNI(U) ;SAVE IN UDB
POP P,T1 ;RESTORE
MOVSI T2,(.DIPTC) ;POINT TO PTCR
PUSHJ P,RDMBR## ;READ IT
MOVEM T2,TD2FST+.TFD1I(U) ;SAVE IT
MOVSI T2,(.DIPBA) ;POINT TO PBAR
PUSHJ P,RDMBR## ;READ IT
PUSH P,T1 ;SAVE IORB ADDRESS
MOVSI T1,-3 ;AOBJN POINTER
MOVEM T2,TD2FST+.TFD2I(U) ;SAVE IT
MOVE T2,KDBICP(W) ;GET LOGOUT AREA ADDRESS
MOVEI T3,TD2FST+.TFCS0(U) ;WHERE TO PUT THEM
RDIRE1: MOVE T4,(T2) ;GET NEXT WORD OF LOGOUT AREA
MOVEM T4,(T3) ;STORE IN UDB
ADDI T2,1 ;BUMP LOGOUT AREA POINTER
ADDI T3,1 ;BUMP OUTPUT POINTER
AOBJN T1,RDIRE1 ;LOOP FOR ALL
POP P,T1 ;RESTORE IORB ADDRESS
HRRZ T2,@IRBACC(T1) ;GET ADDRESS OF CHANNEL COMMAND LIST
TLNN P1,(TB.DAT) ;THIS A DATA OPERATION?
TDZA T3,T3 ;NO, NO COMMAND LIST
MOVE T3,(T2) ;GET FIRST CCW
MOVEM T3,TD2FST+.TFCC1(U) ;SAVE IN UDB
TLNE P1,(TB.DAT) ;DATA OP?
MOVE T3,1(T2) ;YES, GET NEXT CCW
MOVEM T3,TD2FST+.TFCC2(U) ;SAVE IN UDB
MOVE T2,KDBCHN(W) ;GET ADDRESS OF CHN DB
MOVE T3,CHNMPE(T2) ;GET NUMBER OF MEM PAR ERRORS
MOVEM T3,TD2FST+.TFMPE(U) ;SAVE IN UDB
MOVE T3,CHNNXM(T2) ;GET NUMBER OF NXM'S
MOVEM T3,TD2FST+.TFNXM(U) ;SAVE IN UDB
PUSHJ P,REDMBR ;READ INITIAL MASSBUS REGISTERS
;; PJRST REDD2R ;READ DX20 REGISTERS AND RETURN
;ROUTINE TO READ THE DX20 REGISTERS INTO THE UDB WHEN AN ERROR IS
;DETECTED.
;CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS
;RETURN+1 ALWAYS
REDD2R: PUSHJ P,MPRUN ;IS MICROPROCESSOR RUNNING?
JRST REDD24 ;NO, ZERO COUNT AND RETURN
PUSHJ P,SAVE2## ;SAVE P1-P2
MOVSI P1,-.TD2ES ;BUILD AOBJN POINTER FOR NUMBER OF REGS
REDD21: MOVEI T2,(P1) ;GET EST INDEX THAT WE WANT
PUSHJ P,SETEST ;GET THE DX20 TO LOAD THE VALUES
JRST REDD23 ;GO IF WE TIMED OUT
PUSHJ P,REDEST ;READ THE INFORMATION, RETURN IN T4
MOVEI T2,TD2FST+.TFD2R(U) ;GET BASE OF REGISTER BLOCK
ADDI T2,(P1) ;OFFSET TO THIS REGISTER
MOVEM T4,(T2) ;STORE IN CORRECT PLACE
AOBJN P1,REDD21 ;LOOP FOR ALL REGISTERS
REDD23: MOVSS P1 ;PUT NUMBER OF REGISTERS IN LH
HRRI P1,.TFD2R-.TFDVL ;OFFSET TO FIRST IN RH
TLNN P1,-1 ;IF COUNT IS ZERO,
REDD24: MOVEI P1,0 ;ZERO THE WHOLE WORD
MOVEM P1,TD2FST+.TFDVL(U) ;STORE IN UDB
POPJ P, ;RETURN
;ROUTINE TO SAVE INFORMATION IN THE UDB ON SUBSEQUENT ERRORS DURING
;ERROR RECOVERY OR WHEN THE ERROR IS RECOVERED.
;CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS
;RETURN+1 ALWAYS
RDFREG: PUSH P,T1 ;SAVE T1
XCT KDBCNI(W) ;GET FINAL CONI
MOVEM T1,TD2FST+.TFCIF(U) ;SAVE IN UDB
POP P,T1 ;RESTORE
MOVSI T2,(.DIPTC) ;POINT AT PTCR
PUSHJ P,RDMBR## ;READ IT
MOVEM T2,TD2FST+.TFD1F(U) ;SAVE IN UDB
MOVSI T2,(.DIPBA) ;POINT AT PBAR
PUSHJ P,RDMBR## ;READ IT
MOVEM T2,TD2FST+.TFD2F(U) ;SAVE IN UDB
;; PJRST REDMBR ;READ FINAL MASSBUS REGISTERS AND RETURN
;ROUTINE TO READ THE MASSBUS REGISTERS SPECIFIED BY THE BIT TABLE
;MBRTBL AND STORE THEM IN THE UDB.
;CALL WITH:
; U/UDB ADDRESS, W/KDB ADDRESS
;RETURN+1 ALWAYS
REDMBR: PUSHJ P,SAVE2## ;SAVE P1-P2
MOVE P1,[.TD2MR,,.TFMBX-.TFMBR] ;# OF MBR,,OFFSET TO FIRST
MOVEM P1,TD2FST+.TFMBR(U) ;SAVE IN UDB
MOVEI P1,TD2FST+.TFMBX(U) ;POINT TO PLACE TO STORE REGS
MOVE P2,[MBRTBL] ;GET BIT TABLE OF REGISTERS TO SAVE
REDMB1: JUMPGE P2,REDMB2 ;IF SIGN BIT NOT SET, DON'T SAVE THIS ONE
HLLZ T2,P1 ;GET REGISTER ADDRESS
CAMN T2,[.DXDR0] ;READING THE IR?
TDZA T2,T2 ;YES, READ IT LATER
PUSHJ P,RDMBR## ;READ THE REGISTER
SKIPN TUBERR(U) ;IN ERROR RECOVERY?
HRRZM T2,(P1) ;NO, SAVE INITIAL VALUE
SKIPE TUBERR(U) ;OTHERWISE
HRLM T2,(P1) ;SAVE FINAL VALUE
HRRI P1,1(P1) ;BUMP BLOCK POINTER BY 1
REDMB2: ADD P1,[1B5] ;PLUS REGISTER ADDRESS BY 1
LSH P2,1 ;SHIFT BIT TABLE BY 1
JUMPN P2,REDMB1 ;IF MORE TO READ, LOOP
;; PJRST REDMIR ;FALL INTO REDMIR
;ROUTINE TO CONDITIONALLY READ THE MICROPROCESSOR INSTRUCTION
;REGISTER. WE DON'T DO THIS UNLESS THE MICROPROCESSOR IS STOPPED
;BECAUSE READING THE IR WITH IR ENABLE SET CAUSES IT TO BE LOADED
;FROM THE MICROSTORE LOCATION CURRENTLY POINTED TO BY THE PC. THIS
;SOMETIMES CAUSES IR PARITY ERRORS.
;CALL WITH:
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 ALWAYS
REDMIR: DMOVE T2,TD2FST+.TFM00(U) ;GET CONTROL AND STATUS REGS
SKIPN TUBERR(U) ;IN ERROR RECOVERY?
JRST REDMI1 ;NO, CONTINUE
MOVSS T2 ;YES, BITS ARE IN THE
MOVSS T3 ; LEFT HALF OF THE WORD
REDMI1: TRNN T2,CR.CGO ;IS GO STILL UP?
TRNE T3,SR.RUN ;NO, IS THE UCODE STILL RUNNING?
POPJ P, ;YES, DON'T READ THE REGISTER
MOVSI T2,(.DXDR1) ;SETUP TO READ THE PC REGISTER
PUSHJ P,RDMBR## ;DO SO
TRZ T2,D1.IRE ;TURN OFF IR ENABLE
HRLI T2,(.DXDR1) ;PUT THE REGISTER NUMBER BACK
PUSHJ P,WTMBR## ;WRITE OFF IR ENABLE
MOVSI T2,(.DXDR0) ;POINT TO IR REGISTER
PUSHJ P,RDMBR## ;READ IT
SKIPN TUBERR(U) ;IN ERROR RECOVERY?
HRRZM T2,TD2FST+.TFM30(U) ;NO, SAVE INITIAL VALUE
SKIPE TUBERR(U) ;OTHERWISE
HRLM T2,TD2FST+.TFM30(U) ;SAVE FINAL VALUE
POPJ P, ;RETURN
SUBTTL TABLES TO CONTROL I/O
;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,^D090,^D090 ;LG,SE,RW,RU
BYTE(9) ^D031,^D031,^D031,^D031 ;TM,YB,CR,RL
;THE FOLLOWING TABLE CONVERTS FROM THE SOFTWARE DATA MODES TO
;THOSE NEEDED BY THE HARDWARE. -1 IS ILLEGAL.
MODTBL: EXP -1 ;SOFTWARE MODE 0 IS ILLEGAL
EXP 1B<POS(G1.DTM)> ;CORE DUMP
EXP 2B<POS(G1.DTM)> ;INDUSTRY COMPATIBLE BYTE MODE
EXP 3B<POS(G1.DTM)> ;SIXBIT
EXP 4B<POS(G1.DTM)> ;ASCII
EXP 3B<POS(G1.DTM)> ;7 TRACK CORE DUMP (SIXBIT)
;THE FOLLOWING TWO TABLES CONVERT FROM THE SOFTWARE DENSITY
;SETTINGS TO THOSE NEEDED BY THE HARDWARE. FOR THE 7 TRACK
;TABLE, EACH ENTRY CONSISTS OF TWO WORDS-ONE FOR EACH PARITY
;SETTING.
DEN7TB==.-<RB.D2*2> ;MAKE TABLE START AT CORRECT OFFSET
EXP 1B<POS(G1.DVM)> ;7 TRACK, 200 BPI, ODD PARITY
EXP 5B<POS(G1.DVM)> ;7 TRACK, 200 BPI, EVEN PARITY
EXP 2B<POS(G1.DVM)> ;7 TRACK, 556 BPI, ODD PARITY
EXP 6B<POS(G1.DVM)> ;7 TRACK, 556 BPI, EVEN PARITY
EXP 3B<POS(G1.DVM)> ;7 TRACK, 800 BPI, ODD PARITY
EXP 7B<POS(G1.DVM)> ;7 TRACK, 800 BPI, EVEN PARITY
DEN9TB==.-RB.D8 ;MAKE TABLE START AT CORRECT OFFSET
EXP 13B<POS(G1.DVM)> ;9 TRACK, 800 BPI
EXP 14B<POS(G1.DVM)> ;9 TRACK, 1600 BPI
EXP 15B<POS(G1.DVM)> ;9 TRACK, 6250 BPI
;THE FOLLOWING TABLE CONVERTS FROM THE SOFTWARE FUNCTION IN THE IORB
;TO THAT REQUIRED BY THE HARDWARE. IT ALSO HOLDS FLAG BITS FOR
;THE FUNCTION.
;
;IT IS ALSO IMPORTANT TO NOTE THE PLACEMENT OF THE FLAG BITS WITHIN
;THE FUNCTION WORD. FLAG BITS THAT ARE ONLY USED DURING THE START
;OPERATION SEQUENCE (TD2SIO AND FRIENDS) ARE PLACED IN THE RIGHT
;HALF OF THE WORD WITH THE HARDWARE FUNCTION CODE. FLAG BITS THAT
;MUST BE PASSED TO THE INTERRUPT LEVEL ROUTINES MUST BE PLACED IN THE
;LEFT HALF OF THE WORD BECAUSE ONLY THE LEFT HALF IS PRESERVED AT
;INTERRUPT LEVEL.
TB.ILF==1B0 ;ILLEGAL FUNCTION (MUST BE SIGN BIT)
TB.DAT==1B1 ;TALK TO RH20 REG INSTEAD OF DX20
TB.RED==1B2 ;OPERATION PERFORMS A READ
;1B7 FORMERLY TB.SNS, NOT NEEDED WITH VERSION 10 UCODE
TB.REV==1B8 ;OPERATION MOVES TAPE BACKWARDS
TB.ERR==1B9 ;OPERATION DETECTED AN ERROR
;1B10 FORMERLY TB.SIO, NOT NEEDED WITH VERSION 10 UCODE
TB.DON==1B11 ;BEEN THROUGH DONE BEFORE GOING TO CHKATN
TB.FSN==1B12 ;FORCED SENSE DONE ON THIS COMMAND
TB.SFC==37B17 ;SOFTWARE FUNCTION CODE, I.E. INDEX IN TABLE
TB.ZFC==1B18 ;USE ZERO IN FRAME COUNT REGISTER
TB.OFC==1B19 ;USE -1 IN FRAME COUNT REGISTER
TB.REW==1B20 ;FUNCTION DOES A REWIND
TB.MS7==1B21 ;MODE SET ON 7 TRACK NEEDED
TB.MS9==1B22 ;MODE SET ON 9 TRACK NEEDED
TB.FCN==77B<POS(CR.CGO)> ;HARDWARE FUNCTION CODE
DEFINE FCN (CODE,FLAGS), <
EXP <FLAGS>+<.-IOFTBL>B<POS(TB.SFC)>+<CODE>B<POS(TB.FCN)>
>
IOFTBL: FCN(0,TB.ILF) ;0 - ILLEGAL
FCN(CR.RDF,TB.DAT+TB.RED+TB.MS7) ;1 - READ FORWARD
FCN(CR.WTF,TB.DAT+TB.MS7+TB.MS9) ;2 - WRITE FORWARD
FCN(CR.RDR,TB.DAT+TB.RED+TB.MS7+TB.REV) ;3 - READ REVERSE
FCN(CR.SFR,TB.MS7) ;4 - SPACE FORWARD RECORD
FCN(CR.SBR,TB.MS7+TB.REV) ;5 - SPACE BACKWARD RECORD
FCN(CR.SFF,TB.MS7) ;6 - SPACE FORWARD FILE
FCN(CR.SBF,TB.MS7+TB.REV) ;7 - SPACE BACKWARD FILE
FCN(CR.ERA,TB.MS7+TB.MS9) ;10 - ERASE GAP
FCN(CR.DSE,TB.ZFC) ;11 - DATA SECURITY ERASE
FCN(CR.REW,TB.ZFC+TB.REW) ;12 - REWIND
FCN(CR.UNL,TB.ZFC+TB.REW) ;13 - REWIND AND UNLOAD
FCN(CR.WTM,TB.MS7+TB.MS9) ;14 - WRITE TAPE MARK
FCN(CR.NOP,TB.ILF) ;15 - WAIT FOR KONTROLLER IDLE
FCN(CR.RDF,TB.DAT+TB.RED+TB.MS7) ;16 - CORRECTION READ
FCN(CR.RDF,TB.DAT+TB.RED+TB.MS7) ;17 - READ LOW THRESHOLD
;THE FOLLOWING TABLE GIVES THE ADDRESSES OF THE SPECIFIC INTERRUPT
;HANDLER FOR EACH FUNCTION.
INTTBL: IFIW TAPIFI## ;(00) ILLEGAL
IFIW RDFINT ;(01) READ FORWARD
IFIW WRTINT ;(02) WRITE FORWARD
IFIW RDBINT ;(03) READ REVERSE
IFIW SFRINT ;(04) SPACE FORWARD RECORD
IFIW SBRINT ;(05) SPACE BACKWARD RECORD
IFIW SFFINT ;(06) SPACE FORWARD FILE
IFIW SBFINT ;(07) SPACE BACKWARD FILE
IFIW ERGINT ;(10) ERASE GAP
IFIW DSEINT ;(11) DATA SECURITY ERASE
IFIW REWINT ;(12) REWIND
IFIW UNLINT ;(13) REWIND AND UNLOAD
IFIW WTMINT ;(14) WRITE TAPE MARK
IFIW DONE ;(15) WAIT FOR KONTROLLER IDLE (USED AS A NOOP)
IFIW RDFINT ;(16) CORRECTION READ
IFIW RDFINT ;(17) READ LOW THRESHOLD
MAXINT==.-INTTBL-1 ;HIGHEST LEGAL FUNCTION
SUBTTL LOADABLE MICROCODE CONTROL
; MAGIC NUMBER TRANSLATION TABLE
TD2MAG: XWD .CRM10,000010 ;LOCATION 10
XWD .CRM11,000011 ;LOCATION 11
EXP -1 ;TERMINATE TABLE
;ENABLE/DISABLE MICROCODE LOADING
TD2EDL: SE1ENT ;ENTER SECTION ONE
HRRZS W ;REMOVE JUNK IN LH
MOVE T2,T1 ;COPY BIT
XMOVEI T1,TD2ULB(W) ;POINT TO UCODE LOADER BLOCK IN KDB
PJRST BTUEDL## ;ENABLE OR DISABLE
;LOAD MICROCODE
TD2LOD: SE1ENT ;ENTER SECTION ONE
XMOVEI T1,TD2ULB(W) ;POINT TO MICROCODE LOADER BLOCK
PUSHJ P,DXLOAD## ;LOAD AND VERIFY MICROCODE
POPJ P, ;FAILED
PUSHJ P,SETIVO ;SETUP INTERRUPT VECTOR ADDRESS
JRST CPOPJ1## ;AND RETURN
SUBTTL ERROR LOGGING
TD2ELG: HLLZ T1,ELGTBL+.EXFLG ;GET -VE LENGTH OF XFER TABLE
ADD T1,TUBFEP(U) ;PLUS -VE FEP LENGTH
MOVMS T1 ;MAKE POSITIVE
ADD T1,TD2MBR(U) ;PLUS NUMBER OF MASSBUS REGISTERS
ADD T1,TD2DVL(U) ;PLUS NUMBER OF DX20 REGISTERS
HLRZS T1 ;PUT IN RH
PUSHJ P,ALCSEB## ;ALLOCATE A SYSTEM ERROR BLOCK
POPJ P, ;NO CORE
HRLZ T2,KDBDSP(W) ;GET DEVICE CODE
IOR T2,TD2VER(U) ;INCLUDE UCODE VERSION
HRRI T2,001001 ;PLUS RH20 MAGTAPE FLAGS
MOVEM T2,TD2DID(U) ;SAVE AS DEVICE IDENTIFIER
XMOVEI T2,ELGTBL ;POINT TO TRANSFER TABLE
PUSHJ P,XFRSEB## ;LOAD UP THE ERROR RECORD
JFCL ;CAN'T FAIL HERE
MOVEI T2,43 ;OFFSET WITHIN RECORD
SKIPE .EBHDR+43(T1) ;MASSBUS REGISTERS SUB-BLOCK POINTER?
ADDM T2,.EBHDR+43(T1) ;RELOCATE (R43)
MOVEI T2,44 ;OFFSET WITHIN RECORD
SKIPE .EBHDR+44(T1) ;DX20 REGISTER SUB-BLOCK POINTER?
ADDM T2,.EBHDR+44(T1) ;RELOCATE (R44)
SKIPN T2,.EBHDR+43(T1);ANY MASSBUS REGISTERS?
JRST CPOPJ1## ;NO
ADDI T2,.EBHDR(T1) ;POINT TO STORAGE
HLRZ T3,T2 ;GET COUNT
MOVNS T3 ;MAKE NEGATIVE
HRL T2,T3 ;MAKE AN AOBJN POINTER TO STORAGE
HRRZ T3,TD2MBR(U) ;GET OFFSET TO MBR BLOCK
ADDI T3,TD2MBR ;INDEX INTO FEP BLOCK
ADD T3,U ;RELOCATE
TD2EL1: MOVE T4,(T3) ;GET A WORD
MOVEM T4,(T2) ;PUT A WORD
AOS T3 ;ADVANCE SOURCE POINTER
AOBJN T2,TD2EL1 ;LOOP FOR ALL MASSBUS REGISTERS
SKIPN T3,.EBHDR+44(T1) ;GET POINTER TO DX20 REGISTER SUB-BLOCK
JRST CPOPJ1## ;NONE THERE
HLRZ T4,T3 ;GET REGISTER COUNT
MOVNS T4 ;NEGATE
HRL T2,T4 ;MAKE AN AOBJN POINTER TO STORAGE
HRRZ T3,TD2DVL(U) ;GET OFFSET TO DX20 REG BLOCK
ADDI T3,TD2DVL ;INDEX INTO FEP BLOCK
ADD T3,U ;RELOCATE
TD2EL2: MOVE T4,(T3) ;GET A WORD
MOVEM T4,(T2) ;PUT A WORD
AOS T3 ;ADVANCE SOURCE POINTER
AOBJN T2,TD2EL2 ;LOOP FOR ALL DX20 REGISTERS
JRST CPOPJ1## ;RETURN AND LOG ERROR
;OFFSETS WITHIN THE FEP BLOCK
.ORG TD2FST ;DEFINED RELATIVE TO START OF FEP BLOCK
TD2ZRO:! BLOCK 1 ;ZERO WORD (UNDEFINED ENTRIES MAP HERE)
TD2CNI:! BLOCK 1 ;CONI INITIAL
TD2CIF:! BLOCK 1 ;CONI FINAL
TD2RED:! BLOCK 1 ;NUMBER OF FRAMES READ
TD2WRT:! BLOCK 1 ;NUMBER OF FRAMES WRITTEN
TD2D1I:! BLOCK 1 ;DATAI PTCR INITIAL
TD2D1F:! BLOCK 1 ;DATAI PTCR FINAL
TD2D2I:! BLOCK 1 ;DATAI PBAR INITIAL
TD2D2F:! BLOCK 1 ;DATAI PBAR FINAL
TD2CS0:! BLOCK 1 ;CHANNEL LOGOUT 0
TD2CS1:! BLOCK 1 ;CHANNEL LOGOUT 1
TD2CS2:! BLOCK 1 ;CHANNEL LOGOUT 2
TD2CC1:! BLOCK 1 ;FIRST CCW
TD2CC2:! BLOCK 1 ;SECOND CCW
TD2MPE:! BLOCK 1 ;COUNT OF MPE
TD2NXM:! BLOCK 1 ;COUNT OF NXM
TD2OVR:! BLOCK 1 ;NUMBER OF OVERRUNS
TD2ICR:! BLOCK 1 ;CONTENTS OF INITIAL CONTROL REG
TD2VER:! BLOCK 1 ;BYTE (9)DX20 ADDRESS(9)0(18)UCODE VERSION
TD2MBR:! BLOCK 1 ;# OF MASSBUS REGS,,OFFSET TO FIRST
TD2DVL:! BLOCK 1 ;# OF DEVICE REGS,,OFFSET TO FIRST
.ORG
ELGTBL: SEBTBL (.ERDXE,ELGEND,)
MOVE UDBNAM(U) ;(R00) DEVICE NAME
MOVE TUBRID(U) ;(R01) REELID
MOVE TD2DID(U) ;(R02) DEVICE IDENTIFIER
MOVE TUBPBE(U) ;(R03) POSITION BEFORE ERROR
MOVE TUBFES(U) ;(R04) FINAL ERROR STATE
MOVE TD2CNI(U) ;(R05) CONI INITIAL
MOVE TD2CIF(U) ;(R06) CONI FINAL
MOVE TD2ZRO(U) ;(R07) NUMBER OF SEEKS (0 FOR MAGTAP)
MOVE TD2RED(U) ;(R10) NUMBER OF FRAMES READ
MOVE TD2WRT(U) ;(R11) NUMBER OF FRAMES WRITTEN
MOVE TD2ZRO(U) ;(R12) SIXBIT FILENAME
MOVE TUBUID(U) ;(R13) PPN OF USER
MOVE TUBPGM(U) ;(R14) SIXBIT PROGRAM NAME
MOVE TD2D1I(U) ;(R15) DATAI PTCR INITIAL
MOVE TD2D1F(U) ;(R16) DATAI PTCR FINAL
MOVE TD2D2I(U) ;(R17) DATAI PBAR INITIAL
MOVE TD2D2F(U) ;(R20) DATAI PBAR FINAL
MOVE TUBSRE(U) ;(R21) SOFT READ ERRORS
MOVE TUBSWE(U) ;(R22) SOFT WRITE ERRORS
MOVE TUBHRE(U) ;(R23) HARD READ ERRORS
MOVE TUBHWE(U) ;(R24) HARD WRITE ERRORS
MOVE TUBFIL(U) ;(R25) FILE POSITION
MOVE TUBREC(U) ;(R26) RECORD POSITION
MOVE TD2CS0(U) ;(R27) CHANNEL LOGOUT 0
MOVE TD2CS1(U) ;(R30) CHANNEL LOGOUT 1
MOVE TD2CS2(U) ;(R31) CHANNEL LOGOUT 2
MOVE TD2CC1(U) ;(R32) FIRST CCW
MOVE TD2CC2(U) ;(R33) SECOND CONTROL WORD
MOVE TD2MPE(U) ;(R34) COUNT OF MPE
MOVE TD2NXM(U) ;(R35) COUNT OF NXM
MOVE TD2ZRO(U) ;(R36) SOFT POSITIONING ERRORS
MOVE TD2ZRO(U) ;(R37) HARD POSITIONING ERRORS
MOVE TD2OVR(U) ;(R40) NUMBER OF OVERRUNS
MOVE TD2ICR(U) ;(R41) CONTENTS OF INITIAL CONTROL REG
MOVE TD2VER(U) ;(R42) DX20 MICRO-CODE VERSION #
MOVE TD2MBR(U) ;(R43) # OF MASSBUS REGS,,OFFSET TO FIRST
MOVE TD2DVL(U) ;(R44) # OF DEVICE REGS,,OFFSET TO FIRST
ELGEND:! ;END OF TABLE
SUBTTL END
END