Trailing-Edge
-
PDP-10 Archives
-
BB-X140B-BB_1986
-
10,7/703mon/td2kon.mac
There are 11 other files named td2kon.mac in the archive. Click here to see a list.
TITLE TD2KON - DX20/TX02 DEVICE DEPENDENT CODE FOR TAPSER V060
SUBTTL G.M. UHLER/GMU 10 SEP 85
SEARCH F,S,ICHPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1978,1986>
;COPYRIGHT (C) 1978,1979,1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
XP VTD2KN,060 ;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
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
.S6EST==1 ;INDEX INTO THE EST TO GET SENSE BYTE 6
.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 TRANSFER
;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
;BYTE POINTERS INTO THE UDB
DRVNUM: POINT 3,TUBAKA##(U),17 ;POINTER TO DRIVE NUMBER
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 WAIT AWHILE. USED IN RDREG TO GIVE THE MASSBUS TIME TO
;ACCEPT THE DATAO TO SETUP THE PREPARATION REGISTER BEFORE
;DOING THE DATAI TO READ THE REGISTER
DEFINE STALL, <
IMULI T2,1
XLIST
IMULI T2,1
LIST
>
;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 DISPATCH TABLE FOR TAPSER CALLS
TD2DSP::IFIW TD2INI ;00 - INITIALIZE
IFIW TD2RES ;01 - RESET ACTIVE I/O
IFIW TD2SIO ;02 - START I/O
IFIW TD2INT ;03 - INTERRUPT SERVICE
EXP 0 ;04 - SET DEVICE COMMAND
IFIW CPOPJ## ;05 - SET KONTROLLER IDLE
IFIW TD2ONL ;06 - TEST IF CTL ON-LINE
IFIW TD2SCH ;07 - FORCE A SCHEDULE CYCLE
IFIW TD2INX ;10 - RE-INITIALIZATION
IFIW TD2LOD ;11 - LOAD MICROCODE
IFIW TD2EDL ;12 - ENABLE/DISABLE MICROCODE LOADING
IFN FTAUTC,<IFIW TD2CFG> ;13 - AUTOCONFIGURE
SUBTTL AUTO CONFIGURATION
IFN FTAUTC,<
;ENTER WITH P3=CURRENT DRIVE NUMBER
;EXIT P3= NEXT DRIVE NUMBER, LH= TUBSTS IF NOT AN 800/1600 DRIVE
TD2CFG: JUMPGE P3,TD2CF2 ;IF FIRST TIME THROUGH
PUSHJ P,MPRES
PUSHJ P,MPCHK ;MAKE SURE MICROCODE IS OK
SKIPA ;NO GOOD
JRST TD2CF1 ;ONWARD
PUSHJ P,TD2LOD ;LOAD THE MICROCODE
POPJ P, ;GIVE UP
TD2CF1: PUSHJ P,MPSTRT ;START THE MICROCODE
PUSHJ P,CHKDTR ;MAKE SURE IT'S THE RIGHT FLAVOR
POPJ P, ;ITS BAD. DON;T DO ANY MORE
TD2CF2: AOS T2,P3 ;STEP TO NEXT DRIVE
TRZE P3,10 ;DONE?
SOJA P3,CPOPJ## ;YES, RETURN P3=-1
HRLI T2,(.DXGP1) ;SAY WHAT DRIVE WE WANT TO TALK TO
PUSHJ P,WTREG ;TELL THE HARDWARE
MOVE T2,[.DXCTR!CR.SNS] ;DO A SENSE ON THE DRIVE
PUSHJ P,WTREGX ; SO WE CAN READ SENSE BYTES
MOVEI T1,2000 ;LOOP COUNTER
TD2CF3: MOVSI T2,(.DXASR) ;POINT TO ATTENTION SUMMARY REGISTER
PUSHJ P,RDREGX ;READ IT
TRNN T2,377 ;HAVE AN ATTENTION?
SOJG T1,TD2CF3 ;NO, WAIT SOME MORE
JUMPLE T1,TD2CF6 ;DRIVE NOT THERE IF WE TIMED OUT
MOVE T2,[.DXASR!377] ;CLEAR THE ATTENTION WE JUST GOT
PUSHJ P,WTREGX
MOVE T4,[TRNN T2,G0.RES]
TD2CF4: MOVEI T1,100 ;HOW LONG TO WAIT
TD2CF5: MOVSI T2,(.DXGP0) ;POINT TO ENDING STATUS REGISTER
PUSHJ P,RDREGX
XCT T4 ;WAIT FOR CONDITION
SOJG T1,TD2CF5 ;NO, WAIT SOME MORE
TLZE T4,(<TRNN>^!<TRNE>) ;CONVERT TRNN TO TRNE IF NOT ALREADY
JRST TD2CF4 ;WASN'T, WAIT TO CLEAR
JUMPLE T1,TD2CF6 ;NO DRIVE IF WE TIMED OUT
PUSHJ P,REDEST ;READ SENSE BYTES 0-3
TLNN T4,(S1.TUA!S1.TUB) ;DRIVE EXIST?
JRST TD2CF6 ;NO
MOVEI T2,.S6EST ;YES. READ SENSE BYTE 6
PUSHJ P,SETEST ;TELL THE DX WHAT WE WANT TO READ
POPJ P, ;CANT READ IT. ASSUME TU70
PUSHJ P,REDEST ;READ THE SENSE BYTE
TRNE T4,S6.7TK ;7 TRACK DRIVE?
HRLI T3,TUCDR7##+K.DX2 ;YES
TRNE T4,S6.D62 ;6250 DRIVE?
HRLI T3,TUCDR5##+K.DX2 ;YES
MOVSI T2,(.DXERR) ;POINT TO ERROR REGISTER
PUSHJ P,WTREGX ;CLEAR IT AND REURN WITH NEXT DRIVE NUMBER
HLRZS T3 ;POSITION CONFIG INFO
POPJ P,
;HERE IF NO SUCH DRIVE
TD2CF6: MOVSI T2,(.DXERR) ;POINT AT ERROR REGISTER
PUSHJ P,WTREGX ;CLEAR IT
JRST TD2CF2 ;AND TRY NEXT DRIVE
> ;END IFN FTAUTC
SUBTTL INITIALIZATION
;HERE FROM SYSINI AT SYSTEM STARTUP AND TAPUUO OR TAPSER WHEN A
;KONTROLLER COMES BACK ONLINE TO INITIALIZE ALL DX20'S ON THIS
;RH20. TD2INI (TPKINI) IS THE SYSINI ENTRY POINT, TD2INX (TPKINX)
;IS THE TAPUUO OR TAPSER ENTRY POINT. CALL WITH:
; W/KDB ADDRESS, F/MT?DDB IF ENTRY AT TD2INI
;RETURN+1 ALWAYS
DX.FND==1B1 ;SET IN P3 IF WE FOUND A DX20
TD2INI: TDZA T3,T3 ;SET FLAG FOR ENTRY AT TD2INI
TD2INX: MOVSI T3,(1B0) ;DITTO FOR ENTRY AT TD2INX
PUSHJ P,SAVE4## ;SAVE P1-P4
PUSH P,F
MOVEI T2,CO.MBE ;GET BIT TO ENABLE THE MASSBUS
XCT TD2COS##(W) ;DO SO
MOVE P1,TKBIUN##(W) ;GET AOBJN POINTER TO UDB LIST
SKIPN P3,T3 ;MOVE FLAG TO P3, SKIP IF TD2INX ENTRY
HRRI P3,-1 ;RH OF P3 WILL BE THE DX20 NUMBER
TD2IN2: SKIPN U,(P1) ;GET NEXT UDB POINTER
JRST TD2IN6 ;NONE, TRY NEXT
PUSH P,TUBAKA##(U) ;SAVE CURRENT VALUE OF TUBAKA
HRRZ T2,TUBADR##(U) ;GET REAL UNIT NUMBER
HRLM T2,TUBAKA##(U) ;WTREG WANTS UNIT NUMBER HERE
JUMPL P3,TD2IN3 ;DON'T DIDDLE DDB'S IF ENTRY AT TD2INX
DPB T2,PUNIT## ;STORE UNIT NUMBER IN DDB
HLRZ F,DEVSER(F)
MOVEI T2,TUCIRD## ;"INTERRUPT ON REWIND DONE" BIT
IORM T2,TUBCNF##(U) ;TELL TAPUUO WE GET AN INTERRUPT ON REWIND DONE
TD2IN3: HLRZ T2,TKBUNI##(W) ;GET DX20 NUMBER FOR THIS DRIVE
CAIN T2,(P3) ;ALREADY SEEN THIS ONE?
JRST TD2IN4 ;YES, DON'T DIDDLE IT AGAIN
HRRI P3,(T2) ;SAVE NUMBER FOR NEXT TIME
PUSHJ P,CHKDTR ;CHECK DRIVE TYPE REGISTER
JRST TD2IN4 ;BAD, DON'T TOUCH IT FURTHER
PUSHJ P,MPRES ;RESET THE MICROPROCESSOR
PUSHJ P,MPVER ;READ DX20 MICROCODE VERSION NUMBER
HRRZS P4,T2 ;SAVE IN RH OF P4
LSH T3,^D9 ;SHIFT DX20 ADDR INTO LEFT 9 BITS OF RH
HRLI P4,(T3) ;SAVE DX20 ADDRESS_9 IN LH
LSH T2,-D2VLSH ;GET IT
CAIL T2,DX2VER ;UCODE CURRENT?
JRST TD2IN5 ;YES, PROCEED
MOVE T2,[DX2VER,,[ASCIZ/Please reload the DX20 with at least microcode version/]]
PUSHJ P,TAPREV##
JRST TD2IN4 ;DON'T START BAD UCODE
TD2IN5: PUSHJ P,MPCHK ;CHECK INTEGRETY OF MICROSTORE
JRST TD2IN4 ;BAD, DON'T START IT
PUSHJ P,MPSTRT ;START THE DX20 AT THE RESTART ADDRESS
TLO P3,(DX.FND) ;FLAG A DX20 FOUND
;FALL INTO TD2IN4
TD2IN4: POP P,TUBAKA##(U) ;RESTORE INITIAL VALUE OF TUBAKA
MOVEM P4,TD2FST##+.TFVER(U) ;SAVE DX20 ADR,,MICROCODE VER IN FEP BLOCK
MOVSI T2,TUSREW## ;"DRIVE REWINDING" BIT
ANDCAM T2,TUBSTS##(U) ;CLEAR REWINDING IN UDB
TD2IN6: AOBJN P1,TD2IN2 ;LOOP FOR ALL UDB'S
POP P,F
TLNN P3,(DX.FND) ;FIND A LEGAL DX20?
POPJ P, ;NO, DON'T GIVE IT A PIA
PUSHJ P,SETIVO ;SETUP INTERRUPT VECTOR ADDRESS
PJRST CLRALL ;CLEAR RH20 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,SAVE2## ;SAVE P1-P2
PUSH P,U ;SAVE U FOR CALLER
XCT TKBCIS##(W) ;GET CONI IN T2
PUSH P,T2 ;SAVE FOR LATER
PUSHJ P,SETIVO ;SETUP INTERRUPT VECTOR ADDRESS
MOVEI T2,CO.STP ;GET "STOP TRANSFER" BIT AND DEASIGN PI
XCT TD2COS##(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
MOVE P1,TKBIUN##(W) ;GET AOBJN POINTER TO UDB LIST
SETOM P2 ;P2 WILL BE DX20 NUMBER
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,TKBUNI##(W) ;GET DX20 NUMBER FOR THIS DRIVE
CAIN T2,(P2) ;ALREADY SEEN THIS ONE?
JRST TD2RE2 ;YES, DON'T TOUCH IT AGAIN
MOVE P2,T2 ;SAVE NEW DX20 NUMBER
PUSHJ P,MPSTRT ;RESET AND START THE DX20
TD2RE2: AOBJN P1,TD2RE1 ;LOOP FOR ALL UNITS
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
MOVEI T2,CO.MBE ;ENABLE MASSBUS AND DIASSIGN PI
XCT TD2COS##(W) ;DO SO
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, RETURN MODE IN T4
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,WTREG ;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,RH2JMP## ;MAKE IT AN RH20 JUMP WORD
HRRZ T2,TKBICP##(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,TKBUNI##(W) ;GET THE DX20 NUMBER
HRLZM T3,TKBASY(W) ;SAVE FOR QUICK INTERRUPT CHECK
PUSHJ P,WTREGX ;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: LDB T2,DRVNUM ;GET THE 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 AND 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,WTREG ;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,TUBCNF##(U) ;GET TUBSTS, TUBCNF (TUBCNF=TUBSTS)
TLNE P1,(TB.RED) ;IS THIS A READ COMMAND?
TLNN T3,TUSBOT## ;FROM BOT?
CAIA ;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,WTREG ;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,TKBUNI##(W) ;GET DX20 NUMBER
HRLZM T2,TKBASY(W) ;STORE FOR INTERRUPT CHECK
MOVEI T2,CO.STP ;GET STOP TRANSFER BIT
XCT TD2COS##(W) ;SET DONE, CAUSING AND INTERRUPT
PJRST REASPI ;LITE PIA AND RETURN
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
TD2INT: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVE U,TKBCUN##(W) ;POINT AT UNIT WE'RE TALKING TO
MOVE U,(U) ;GET UDB ADDRESS
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
HLRZ T3,TKBASY(W) ;GET DX20 NUMBER
PUSHJ P,MPRUNX ;MICROPROCESSOR RUNNING?
JRST TD2IT1 ;NO, SKIP CHECK FOR GO BIT
MOVSI T2,(.DXCTR) ;POINT AT CONTROL REGISTER
PUSHJ P,RDREGX ;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,RDREG ;READ IT
HRRI P1,(T2) ;CARRY IN RH OF P1
TLNE P1,(TB.ILF) ;HERE BECAUSE OF ILLEGAL FUNCTION?
HLL T1,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/ERROR BITS,,IORB ADDRESS, U/UDB ADDRESS, W/KDB ADDRESS
; P1/LH IOFTBL ENTRY,,DEVICE STATUS BYTE
; P2/SENSE BYTES 0-3
;EXIT THROUGH DONE WITH:
; T1/UPDATED ERROR BITS,,IORB ADDRESS
;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,RDREG ;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 T1,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 T1,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 T1,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?
HRLI T1,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. THIS CODE IS NOT ASSEMBLED
;SINCE TOPS10 DOES NOT USE THIS FUNCTION AT PRESENT.
SFFINT==TAPIFI## ;WHERE TO GO IF NOT ASSEMBLED
REPEAT 0, < ;DON'T ASSEMBLE THIS CODE
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
>;END REPEAT 0
;HERE ON A SPACE BACKWARD FILE INTERRUPT. THIS CODE IS NOT ASSEMBLED
;SINCE TOPS10 DOES NOT USE THIS FUNCTION AT PRESENT.
SBFINT==TAPIFI## ;WHERE TO GO IF NOT ASSEMBLED
REPEAT 0,< ;DON'T ASSEMBLE THIS CODE
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
>;END REPEAT 0
;HERE AT THE COMPLETION OF FUNCTION SPECIFIC INTERRUPT PROCESSING
;OF A COMMAND COMPLETION INTERRUPT (BOTH DATA TRANSFER AND NON-DATA TRANSFER)
;WITH:
; T1/ERROR BITS,,IORB ADDRESS
DONE: TLNN T1,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,WTREG ;DO SO
HLLZ T2,T1 ;GET THE ERROR BITS
IORM T2,TRBSTS(T1) ;SET THEM IN THE IORB
MOVSI T2,TKSOFL## ;GET OFF-LINE BIT
TLNE T1,RB.SOL ;IS IT?
IORM T2,TUBSTS##(U) ;YES, SET THE BIT IN THE UDR
MOVSI T2,RB.EXC ;GET EXCEPTION BIT
TLZE T1,-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: MOVE P3,P1 ;COPY FLAG BITS TO P3
PUSHJ P,CLRATN ;CLEAR ATTN BITS, RETURN IN T2, 0 IN T3
SKIPGE T1,TKBSCH(W) ;INTERRUPT TO FORCE A SCHEDULE?
JRST [SETZM TKBSCH(W) ;YES, CLEAR SCHEDULE FLAG
JRST CLRALL] ;AND RETURN -1 TO TAPSER
MOVEI P1,(T2) ;MOVE TO SAFER PLACE
MOVEI P2,1 ;GET MASK FOR DX20 TO DO
PUSH P,U ;SAVE U
CHKAT1: JUMPE P1,ATNDON ;DONE IF NO MORE BITS UP
TRNN P1,(P2) ;THIS DX20 NEED ATTENTION?
JRST CHKAT2 ;NO, CHECK NEXT
PUSHJ P,MPRUNX ;IS MICROPROCESSOR STILL RUNNING?
JRST [HLRZ T2,TKBASY(W) ;GET DX20 NUMBER FROM POSSIBLE OPERATION
TLNE P3,(TB.DON) ;BEEN THROUGH DONE?
CAIE T2,(T3) ; FOR THIS DX20?
PUSHJ P,LOGUPE ;NO, LOG THE ERROR
JRST CHKAT2] ;TRY NEXT ONE
PUSHJ P,ASYNST ;YES, CHECK FOR ASYNCHRONOUS STATUS
CHKAT2: MOVSI T2,(.DXERR) ;AVOID A POSSIBLE LOOP
PUSHJ P,WTREGX ;BY CLEARING THE ERROR REGISTER HERE
TRZ P1,(P2) ;CLEAR THIS ATTENTION BIT
LSH P2,1 ;STEP TO NEXT BIT POSITION
AOJA T3,CHKAT1 ;BUMP DX20 NUMBER AND LOOP
;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:
; T3/DX20 NUMBER, 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,RDREGX ;READ IT
JUMPE T2,CPOPJ## ;RETURN+1 IF NO STATUS
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,RDREGX ;US A DRIVE WITH NO STATUS, SO READ IT AGAIN
ASYNS1: 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##
MOVSI T2,(.DXGP4) ;SETUP TO CLEAR ASYNC STATUS REGISTER.
PUSHJ P,WTREGX ;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,WTREG ;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,RDREG ;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:
; T3/DX20 NUMBER, W/KDB ADDRESS
;RETURN+1 ALWAYS WITH T4/.DXGP6,,.DXGP7
;ENTER AT REDES3 TO SETUP T3 FROM TKBUNI
REDES3: HLRZ T3,TKBUNI##(W) ;GET THE DX20 NUMBER
REDEST: MOVSI T2,(.DXGP6) ;POINT AT EXTENDED STATUS REGISTER 0
PUSHJ P,RDREGX ;READ IT
HRLZ T4,T2 ;MOVE TO WHERE CALLER EXPECTS IT
MOVSI T2,(.DXGP7) ;POINT AT EXTENDED STATUS REGISTER 1
PUSHJ P,RDREGX ;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, T3/0 (DX20 NUMBER)
CLRATN: MOVSI T2,(.DXASR) ;POINT TO ATTENTION SUMMARY REGISTER
MOVEI T3,0 ;ASR IS NOT DX20 SPECIFIC
PUSHJ P,RDREGX ;READ IT
ANDI T2,AS.ATN ;KEEP ONLY ATTENTION BITS
TDNN T2,TKBUNI##(W) ;ATTEN FOR THIS UNIT?
JRST CLRAT1 ;NO, RETURN 0
HRRZ T2,TKBUNI##(W) ;YES, GET JUST THAT BIT
IORM T2,TKBATN(W) ;UPDATE CORE COPY
HRLI T2,(.DXASR) ;SETUP TO CLEAR THE REGISETER
PUSHJ P,WTREGX ;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/ERROR BITS,,IORB ADDRESS
;RETURN+1 ALWAYS WITH:
; T1/ERROR BITS+RB.STM,,IORB ADDRESS
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 T1,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/ERROR BITS,,IORB ADDRESS
; P1/IOFTBL ENTRY,,DEVICE STATUS BITS
;RETURN+1 ALWAYS WITH:
; T3/+NUMBER IF FORWARD OPERATION, -NUMBER IF REVERSE
NUMOPS: MOVSI T2,(.DXFCR) ;POINT TO FRAME COUNT REGISTER
PUSHJ P,RDREG ;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/ERROR BITS,,IORB ADDRESS
; P2/SENSE BYTES 0-3
;RETURN+1 ALWAYS WITH:
; T1/UPDATED ERROR BITS,,IORB ADDRESS,
; 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 T1,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/ERROR BITS,,IORB ADDRESS
;RETURN+1 ALWAYS WITH:
; T1/ERROR BITS+RB.SBT,,IORB ADDRESS,
; TUBREC, TUBFIL ZEROED, TUBSTS UPDATED
SETBOT: TLO T1,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/ERROR BITS,,IORB ADDRESS, U/UDB ADDRESS, W/KDB ADDRESS,
; P1/IOFTBL BITS,,ENDING STATUS BYTE
;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/UPDATED ERROR BITS,,IORB ADDRESS
CHKERR: MOVEI P2,0 ;ASSUME NO ERRORS AND RETURN ZERO SENSE BYTES
MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
PUSHJ P,RDREG ;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,RDREG ;READ IT
TRNE T2,ER.ERR ;SOME GENERIC HARDWARE FAILURE?
TLO T1,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,REDES3 ;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: EXP FTLERR ;0 - UNKNOWN
EXP ERRXIT ;1 - UNUSUAL DEVICE STATUS
EXP ERRXIT ;2 - SHORT RECORD - NOT AN ERROR
EXP LNGREC ;3 - LONG RECORD
EXP OFLERR ;4 - DRIVE SELECTION ERROR
EXP RTYERR ;5 - RECOVERABLE ERROR (TAPE MOTION)
EXP NOMERR ;6 - RECOVERABLE ERROR (NO TAPE MOTION)
EXP NRTERR ;7 - NON-RECOVERABLE ERROR
EXP FTLERR ;10 - FATAL ERROR
EXP 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 T1,RB.SMO ;FLAG AS SET OFFLINE BY MONITOR
PUSHJ P,MPRES ;MAKE DAMN SURE IT STAYS OFF LINE
MPSERR: TLOA T1,RB.SED!RB.SER!RB.SOL ;SOME ERROR+NO RETRY+SET OFF LINE
NRTER1: TLO T1,RB.SED!RB.SER ;SOME ERROR+NO RETRY
JRST ERRXIT ;JOIN COMMON EXIT
OFLERR: TLO T1,RB.SOL ;SELECT ERROR MEANS DRIVE IS OFF-LINE
NOMERR: TLO T1,RB.SNM ;NO MOTION
RTYERR: TLOA T1,RB.SED ;SOME ERROR
LNGREC: TLO T1,RB.STL!RB.SER ;LONG RECORD+NO RETRY
ERRXIT: TLNE T1,-1 ;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/ERROR BITS,,IORB ADDRESS, U/UDB ADDRESS, W/KDB ADDRESS
; P1/IOFTBL ENTRY,,ENDING STATUS BYTE, P2/SENSE BYTES 0-3 (0 IF NOT READ)
;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,REDES3 ;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,.S6EST ;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,REDES3 ;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/ERROR BITS,,IORB ADDRESS,
; P1/IOFTBL ENTRY,,DEVICE STATUS BYTE, P2/SENSE BYTES 0-3
;RETURN+1 ALWAYS WITH:
; T1/UPDATED ERROR BITS,,IORB ADDRESS
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 T1,RB.SER!RB.SED ;NON-RECOVERABLE + ERROR
IRQERR: TLO T1,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 T1,RB.SNM ;NO, SET NO MOTION
;OVERRUN CAUSES REPOSITION AND RETRY
OVRERR: TLOA T1,RB.SED ;SOME ERROR
;DATA CHECK INVOKES TAPSER'S ERROR RETRY ALGORITHM
DTCERR: TLO T1,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/ERROR BITS,,IORB ADDRESS, P1/IOFTBL ENTRY FOR FUNCTION
; W/KDB ADDRESS
;RETURN+1 ALWAYS WITH:
; T1/UPDATED ERROR BITS,,IORB ADDRESS
CHKCHN: XCT TKBCIS##(W) ;GET CONI INTO T2
MOVE T3,TKBICP##(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,CHNNXM## ;POINT AT RTN TO CALL FOR NXM
MOVSI T4,IOCHNX ;ASSUMING NXM
TLNN T2,(CS.NXM) ;ARE WE CORRECT?
MOVEI T3,CHNMPE## ;NO, USE THIS ONE
TLNN T2,(CS.NXM) ; ...
MOVSI T4,IOCHMP ; ...
HRRZ T1,TKBICP##(W) ;GET ADDRESS OF LOGOUT AREA
HRRZ P1,TKBCDB##(W) ;GET CHANNEL DATA BLOCK ADDRESS
HRRZ 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 T1,RB.SED ;TELL UPPER LEVEL OF ERROR
CHKCH2: TLO T1,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: MOVE T3,TKBSTS##(W) ;ALWAYS ONLINE IF
HRRZ T1,TKBCDB##(W) ;POINTER TO CHANNEL
SKIPGE (T1) ;DON'T DO CONO'S IF CHAN IS IN USE (USER MODE DIAG)
TLNE T3,TKSSEL##!TKSSTD##!TKSSCH## ;THE KONTROLLER
JRST CPOPJ1## ;IS GOING
PUSHJ P,SAVE2## ;SAVE P1-P2
PUSH P,U ;SAVE U FOR TAPSER
MOVE P1,TKBIUN##(W) ;GET AOBJN POINTER TO UNITS
SETOM P2 ;INITIALIZE DX20 NUMBER
TD2ON1: SKIPN U,(P1) ;GET ADDRESS OF NEXT UDB
JRST TD2ON2 ;IGNORE IF ZERO
HLRZ T3,TKBUNI##(W) ;PICK UP DX20 NUMBER
CAIN T3,(P2) ;DONE THIS DX20 ALREADY?
JRST TD2ON2 ;YES, DON'T DO IT AGAIN
MOVE P2,T3 ;SAVE NEW DX20 NUMBER
PUSHJ P,CHEKOK ;IS IT A DX20 WHICH IS RUNNING?
JRST UPOPJ## ;NO, CALL IT OFF-LINE
TD2ON2: AOBJN P1,TD2ON1 ;LOOP FOR ALL UDB'S
IFN FTAUTC,<
JUMPGE P2,UPOPJ1## ;WIN IF ANY DRIVES WERE FOUND
PUSH P,P3 ;NO DRIVES - NO MICROCODE WAS THERE
SETO P3, ;START AT 1ST DRIVE
XCT TKBDIS##(W) ;SAVE PREPERATION REGISTER
PUSHJ P,CHEKOK ;IS IT RUNNING?
JRST TD2ON4 ;NO, DON'T BOTHER TRYING TO START IT
MOVEI T2,CO.MBI ;YES, GET IT INTO A KNOWN STATE
XCT TD2COS##(W)
MOVEI T2,CO.MBE ;MASBUS ENABLE SO WE CAN TALK TO IT
XCT TD2COS##(W)
TD2ON3: PUSHJ P,TD2CFG ;FIND THE NEXT DRIVE
JUMPL P3,TD2ON4 ;DONE IF NO MORE DRIVES
HRRZ T2,P3 ;NEXT DRIVE NUMBER
MOVEI T1,.DTCOD ;TELL AUTCON ITS A DX20/TU7X
PUSHJ P,NEWTAP## ;INFORM THE WORLD THAT A NEW DRIVE APPEARED
JRST TD2ON3 ;AND SEE IF NEXT DRIVE IS THERE
TD2ON4: POP P,P3
>
JRST UPOPJ1## ;RETURN SUCCESSS
;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,CHKDTR ;IS IT REALLY A DX20?
POPJ P, ;NO, ERROR RETURN
MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
TAPOFF ;AVOID RACE WITH INTERRUPT RDREGX
PUSHJ P,RDREGX ;GO READ STATUS REGISTER
TAPON ;TURN PI BACK ON
TRNE T2,SR.RUN ;MP RUNNING?
AOS (P) ;YES. TAKE GOOD RETURN
POPJ P,
;ROUTINE TO READ THE DRIVE TYPE REGISTER TO INSURE THAT THE KONTROLLER
;THAT WE ARE TALKING TO IS REALLY A DX20.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 IF NOT A DX20
;RETURN+2 IF IT IS A DX20
CHKDTR: MOVSI T2,(.DXDTR) ;POINT AT DRIVE TYPE REGISTER
PUSHJ P,RDREG ;READ IT
ANDI T2,DT.COD ;ISOLATE DRIVE TYPE
CAIN T2,.DTCOD ;IS IT A DX20?
AOS 0(P) ;YES, GIVE SKIP RETURN
POPJ P, ;RETURN
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
MOVEI T2,CO.STP ;GET "STOP TRANSFER" BIT
XCT TD2COS##(W) ;STOP THE RH20
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: MOVEI T2,CO.MBE!CO.RAE ;GET MASSBUS ENABLE BIT
XCT TD2COS##(W) ;DO SO
MOVEI T3,TKBVIN##(W) ;SET UP ICWA+3
HRLI T3,(XPCW)
MOVE T2,TKBICP##(W)
MOVEM T3,3(T2)
MOVE T2,TKBIVI##(W) ;GET DATAO WORD TO SETUP INTERRUPT VECTOR
XCT TKBDOS##(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. DESTROYS T2.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
CLRERR: MOVEI T2,CO.CLR ;GET BITS TO CLEAR ERRORS
XCT TD2COS##(W) ;CLEAR THEM
;; PJRST REASPI ;FALL INTO REASPI
;ROUTINE TO REASSIGN THE RH20 PI. DESTROYS T2.
;CALL WITH:
; W/KDB ADDRESS
;RETURN+1 ALWAYS
REASPI: MOVEI T2,CO.AIE!CO.MBE!TAPCHN## ;GET BITS TO ENABLE INTERRUPTS
XCT TD2COS##(W) ;DO SO
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,WTREG ;WRITE THE REGISTER
MOVSI T2,(.DXDR0) ;POINT AT DIAGNOSTIC REGISTER 0
PUSHJ P,RDREG ;READ THE CONTENTS
PUSH P,T2 ;SAVE FOR COMPARE
MOVSI T2,(.DXDTR) ;POINT AT DRIVE TYPE REGISTER
PUSHJ P,RDREG ;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,RDREG ;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,RDREG ;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,RDREG ;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,RDREG ;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,RDREG ;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,WTREG ;TELL MP ITS START ADDRESS
MOVE T2,[.DXMTR!MR.STR] ;SET START BIT IN MAINTENANCE REG
PJRST WTREG ;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 WTREG ;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,WTREG ;TELL THE DX20
MOVSI T2,(.DXDR0) ;ANSWER APPEARS HERE
PJRST RDREG ;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: HLRZ T3,TKBUNI##(W) ;GET DX20 NUMBER
MPRUNX: MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
PUSHJ P,RDREGX ;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, T3/DX20 NUMBER
;RETURN+1 ALWAYS
;PRESERVES U,F,T3
LOGUPE: PUSHJ P,SAVE1## ;SAVE P1
PUSH P,U ; AND U
PUSH P,F ; AND F
PUSH P,T3 ; AND T3
MOVEI T2,(T3) ;COPY DX20 NUMBER TO T2
LSH T2,3 ;CONSTRUCT OFFSET TO DRIVE 0 ON DX20
HLRE T1,TKBIUN##(W) ;GET -VE COUNT OF DRIVES ON THIS KDB
MOVMS T1 ;MAKE IT POSITIVE
CAIGE T2,(T1) ;DOES SUCH A DRIVE EXIST?
PUSHJ P,SETUDB## ;YES, FIND IT'S UDB
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,TUBDDB##(U) ;NO, TRY FOR UNIT 0 DDB
MOVEI F,MT0DDB## ;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
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: XCT TKBCIS##(W) ;GET ERROR CONI
MOVEM T2,TD2FST##+.TFCNI(U) ;SAVE IN UDB
MOVSI T2,(.DIPTC) ;POINT TO PTCR
PUSHJ P,RDREG ;READ IT
MOVEM T2,TD2FST##+.TFD1I(U) ;SAVE IT
MOVSI T2,(.DIPBA) ;POINT TO PBAR
PUSHJ P,RDREG ;READ IT
MOVEM T2,TD2FST##+.TFD2I(U) ;SAVE IT
HRRZ T2,TKBICP##(W) ;GET LOGOUT AREA ADDRESS
HRLI T2,-3 ;MAKE IT AN AOBJN POINTER
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 T3,1 ;BUMP OUTPUT POINTER
AOBJN T2,RDIRE1 ;LOOP FOR ALL
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
HRRZ T2,TKBCDB(W) ;GET ADDRESS OF CHN DB
MOVE T3,.CHMPE(T2) ;GET NUMBER OF MEM PAR ERRORS
MOVEM T3,TD2FST##+.TFMPE(U) ;SAVE IN UDB
MOVE T3,.CHNXM(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,REDES3 ;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: XCT TKBCIS##(W) ;GET FINAL CONI
MOVEM T2,TD2FST##+.TFCIF(U) ;SAVE IN UDB
MOVSI T2,(.DIPTC) ;POINT AT PTCR
PUSHJ P,RDREG ;READ IT
MOVEM T2,TD2FST##+.TFD1F(U) ;SAVE IN UDB
MOVSI T2,(.DIPBA) ;POINT AT PBAR
PUSHJ P,RDREG ;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,RDREG ;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,RDREG ;DO SO
TRZ T2,D1.IRE ;TURN OFF IR ENABLE
HRLI T2,(.DXDR1) ;PUT THE REGISTER NUMBER BACK
PUSHJ P,WTREG ;WRITE OFF IR ENABLE
MOVSI T2,(.DXDR0) ;POINT TO IR REGISTER
PUSHJ P,RDREG ;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 ROUTINES TO ACCESS MASSBUS REGISTERS
;ROUTINE TO READ THE CONTENTS OF A MASSBUS REGISTER. ENTER AT
;RDREGX IF DX20 NUMBER IS ALREADY SETUP IN T3.
;CALL WITH:
; T2/REGISTER TO READ (IN DATAO FORMAT),
; T3/DX20 NUMBER IF ENTRY AT RDREGX
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 ALWAYS WITH C(REGISTER) IN T2
RDREG: HLRZ T3,TKBUNI##(W) ;GET DX20 NUMBER FOR DS
RDREGX: TLO T2,<(DO.DRE)>(T3) ;SET DS AND DISABLE RAE
XCT TKBDOS##(W) ;TELL MBC WHICH REGISTER WE WANT TO READ
STALL ;GIVE IT TIME TO THINK ABOUT IT
XCT TKBDIS##(W) ;READ THE REGISTER
ANDI T2,177777 ;RETURN ONLY 16 BITS
POPJ P, ; AND RETURN
;ROUTINE TO WRITE A MASSBUS REGISTER. ENTER AT WTREGX IF THE DX20
;NUMBER IS ALREADY SETUP IN T3.
;CALL WITH:
; T2/CONTENTS TO SEND TO REGISTER (IN DATAO FORMAT),
; T3/DX20 NUMBER IF ENTRY AT WTREGX,
; W/KDB ADDRESS, U/UDB ADDRESS
;RETURN+1 ALWAYS
WTREG: HLRZ T3,TKBUNI##(W) ;GET DX20 NUMBER FOR DS
WTREGX: TLO T2,<(DO.LDR!DO.DRE)>(T3) ;TELL MBC TO WRITE REG AND DISABLE RAE
XCT TKBDOS##(W) ;WRITE THE REGISTER
POPJ P, ;AND RETURN
SUBTTL TABLES TO CONTROL I/O
;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. NOTE WELL THAT THE SPACE FILE FUNCTIONS ARE MARKED
;AS ILLEGAL SINCE TOPS10 DOES SPACE FILE OPERATIONS VIA MULTIPLE
;SPACE RECORD OPERATIONS. SEE ALSO SFFINT AND SBFINT.
;
;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.ILF+TB.MS7) ;6 - SPACE FORWARD FILE
FCN(CR.SBF,TB.ILF+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: EXP TAPIFI## ;0 - ILLEGAL
EXP RDFINT ;1 - READ FORWARD
EXP WRTINT ;2 - WRITE FORWARD
EXP RDBINT ;3 - READ REVERSE
EXP SFRINT ;4 - SPACE FORWARD RECORD
EXP SBRINT ;5 - SPACE BACKWARD RECORD
EXP SFFINT ;6 - SPACE FORWARD FILE
EXP SBFINT ;7 - SPACE BACKWARD FILE
EXP ERGINT ;10 - ERASE GAP
EXP DSEINT ;11 - DATA SECURITY ERASE
EXP REWINT ;12 - REWIND
EXP UNLINT ;13 - REWIND AND UNLOAD
EXP WTMINT ;14- WRITE TAPE MARK
EXP DONE ;15 - WAIT FOR KONTROLLER IDLE (USED AS A NOOP)
EXP RDFINT ;16 - CORRECTION READ
EXP RDFINT ;17 - READ LOW THRESHOLD
MAXINT==.-INTTBL-1 ;HIGHEST LEGAL FUNCTION
SUBTTL LOAD MICROCODE
; 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
LDB T1,[POINT 7,TD2COS##(W),9] ;GET RH20 DEVICE CODE
LSH T1,2+22 ;MAKE IT FULL 9 BIT DEVICE CODE IN THE LH
HLR T1,TKBUNI##(W) ;GET THE DX20 NUMBER
MOVEM T1,TD2ULB##+.ULDEV(W) ;SAVE IN LOADER BLOCK
XMOVEI T1,TD2ULB##(W) ;POINT TO MICROCODE LOADER BLOCK
PUSHJ P,DXLOAD## ;LOAD AND VERIFY MICROCODE
POPJ P, ;FAILED
PUSHJ P,TD2INI ;INITIALIZE
JRST CPOPJ1## ;AND RETURN
SUBTTL END
END