1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-02 09:37:06 +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

2023 lines
69 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 TD2KON - DX20/TX03 DEVICE DEPENDENT CODE FOR TAPSER V121
SUBTTL G.M. UHLER/GMU/DPM 9-AUGUST-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 1978,1979,1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1978,1988>
XP VTD2KN,121 ;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
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
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,TRBXCW(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,TRBXCW(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,TRBLNK(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,.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,.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,TRBLNK(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 TRBXCW 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,TRBXCW(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 LOGUP2 ;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
SKIPE F,TUBCUR(U) ;ANY DDB IN USE?
JRST LOGUP1 ;YES, USE IT
SKIPN F,UDBDDB(U) ;NO, TRY FOR UNIT 0 DDB
XMOVEI F,TDVDDB## ;CAN'T FIND ONE, USE SOMETHING
LOGUP1: MOVEI T1,.ERDXE ;DX20 DEVICE ERROR
HRL T1,F ;PUT DDB ADDRESS IN LH OF F
PUSHJ P,DAEERR## ;LOG THIS ERROR
LOGUP2: 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,TRBXCW(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 END
END