1
0
mirror of https://github.com/PDP-10/stacken.git synced 2026-03-07 03:15:54 +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

2095 lines
71 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 RNXKON -- DRIVER FOR RP20'S V073
SUBTTL G.M. UHLER/GMU 23-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 1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1980,1988>
XP VRNKON,073
SALL
RNXKON::ENTRY RNXKON
;NOTE THAT LABELS OF THE FORM RNXBP? ARE USED BY THE RP20 TRACE
;PROGRAM FOR SNOOP. BREAKPOINTS. DO NOT REMOVE THESE LABELS.
;TECHNICAL INFORMATION AND TECHNIQUES FOR PROGRAMMING THE
;RH20/DX20/RP20 ARE AVAILABLE IN THE FOLLOWING DOCUMENTS:
;
; FUNCTIONAL SPECIFICATION FOR DX20-V210 MICRO CODE,
; AUG 79
; 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
; DX20-V210 RP20 DISK SUBSYSTEM MICRO-CODE,
; DOCUMENT NUMBER MAINDEC-10-DXMCD-A, AUG 79
SUBTTL RH20/DX20 DEVICE DEPENDENT REGISTER/BIT DEFINITIONS
.DXCTR==00B5 ;CONTROL REGISTER
CR.IGN==1B14 ;BIT SET IN UNILAS TO INDICATE THAT THIS
; COMMAND WAS TOSSED
CR.FNC==76B35 ;FUNCTION CODE
.CRNOP==01 ;NO-OP
.CRRCL==07 ;RECALIBRATE
.CRSRC==31 ;SEARCH
.CRWRT==61 ;WRITE DATA
.CRWTF==63 ;WRITE FORMAT
.CRRED==71 ;READ DATA
.CRRDF==73 ;READ FORMAT
CR.IOP==40B35 ;BITS TELLING THAT THIS OPERATION WAS
; AN I/O FUNCTION
CR.RED==10B35 ;BIT TELLING THAT THIS I/O OPERATION WAS
; A READ
CR.GO==1B35 ;GO BIT
.DXSTR==01B5 ;STATUS REGISTER
ST.CER==1B21 ;COMPOSITE ERROR
ST.RUN==1B23 ;MICROPROCESSOR RUNNING
.DXERR==02B5 ;ERROR REGISTER
ER.SCC==17B23 ;ERROR SUB CLASS CODE
ER.ECC==17B27 ;ERROR CLASS CODE
.ERSEL==3 ;DEVICE SELECT ERROR
ER.UPE==1B28 ;MICROPROCESSOR ERROR
ER.STP==1B29 ;MICROPROCESSOR STOPPED
ER.MPE==1B30 ;MICRO BUS PARITY ERROR
ER.DPE==1B31 ;DATA BUS PARITY ERROR
ER.CPE==1B32 ;CONTROL BUS PARITY ERROR
ER.RMR==1B33 ;REGISTER MODIFICATION REFUSED
ER.ILR==1B34 ;ILLEGAL REGISTER
ER.ILF==1B35 ;ILLEGAL FUNCTION
ER.ERR==ER.MPE!ER.DPE!ER.CPE!ER.RMR!ER.ILR!ER.ILF
.DXMTR==03B5 ;MAINTENANCE REGISTER
MR.SCY==1B31 ;MICROPROCESSOR SINGLE CYCLE
MR.STR==1B33 ;MICROPROCESSOR START
MR.RES==1B34 ;MICROPROCESSOR RESET
.DXASR==04B5 ;ATTENTION SUMMARY REGISTER
AT.ATN==377B35 ;THE ATTENTION BITS
.DXDAR==05B5 ;DESIRED ADDRESS REGISTER (TRACK/SECTOR)
DA.TRK==377B27 ;TRACK
DA.SEC==377B35 ;SECTOR
.DXDTR==06B5 ;DRIVE TYPE REGISTER
DT.COD==777B35 ;DRIVE TYPE
.DTCOD==061 ;CODE FOR DX20
.DXESR==20B5 ;ENDING STATUS REGISTER
ES.STM==1B21 ;STATUS MODIFIER
ES.CUE==1B22 ;CONTROL UNIT END
ES.BSY==1B23 ;BUSY
ES.CHE==1B24 ;CHANNEL END
ES.DVE==1B25 ;DEVICE END
ES.UCK==1B26 ;UNIT CHECK
ES.UEX==1B27 ;UNIT EXCEPTION
ES.SUI==1B28 ;STATUS UPDATE INTERLOCK
ES.IDX==177B35 ;STATUS INDEX
.ESSB0==0 ;INDEX TO GET SENSE BYTE 0(-3)
.ESSB7==1 ;INDEX TO GET SENSE BYTE (4-)7
.DXASY==21B5 ;ASYNCHRONOUS STATUS REGISTER
AS.DVS==377B27 ;DRIVE STATUS
AS.DRV==377B35 ;DRIVE NUMBER
AS.UNF==17B35 ;UNIT NUMBER
.DXFLG==22B5 ;FLAGS/ARGUMENT
FA.RTY==1B23 ;COMMAND RETRY
FA.FNC==377B35 ;FUNCTION FOR SENSE/NOOP
.FATIO==0 ;CODE FOR TEST I/O
.DXDNM==23B5 ;DRIVE NUMBER REGISTER
DN.CUA==17B31 ;CONTROL UNIT ADDRESS
DN.DRV==17B35 ;DRIVE NUMBER
.DXDCR==24B5 ;DESIRED CYLINDER REGISTER
.DXES1==26B5 ;EXTENDED STATUS REGISTER 1
.DXES2==27B5 ;EXTENDED STATUS REGISTER 2
.DXMIR==30B5 ;MICROCONTROLLER INSTRUCTION REGISTER
.DXPCR==31B5 ;MICROPROCESSOR PC REGISTER
PC.IRE==1B20 ;INSTRUCTION REGISTER ENABLE
PC.MSE==1B21 ;MICROSTORE ENABLE
PC.PCE==1B22 ;PC ENABLE
PC.PCI==1B23 ;PC AUTO INCREMENT
PC.MPC==7777B35 ;MICROPROCESSOR PC
.DXIPE==37B5 ;DIAGNOSTIC REGISTER 7
DX.IPE==1B22 ;INSTRUCTION REGISTER PARITY ERROR
;SENSE BYTE DEFINITIONS
S0.CRJ==1B2 ;COMMAND REJECT
S0.IRQ==1B3 ;INTERVENTION REQUIRED
S0.BOP==1B4 ;CHANNEL BUS OUT PARITY
S0.EQC==1B5 ;EQUIPMENT CHECK
S0.DTC==1B6 ;DATA CHECK
S0.OVR==1B7 ;OVERRUN
S1.PER==1B10 ;PERMANENT ERROR
S1.ITF==1B11 ;INVALID TRACK FORMAT
S1.ECY==1B12 ;END OF CYLINDER
S1.NRF==1B14 ;NO RECORD FOUND
S1.FPR==1B15 ;FILE PROTECTED
S1.WRI==1B16 ;WRITE INHIBITED
S1.OPI==1B17 ;OPERATION INCOMPLETE
DEFINE HEX(SYM,VAL),<
SYM==0
IRPC VAL,<
SYM==SYM*^D16
IFLE <"VAL"-"9">,<SYM==SYM+"VAL"-"0">
IFG <"VAL"-"9">,<SYM==SYM+"VAL"-"A"+^D10>
>
>
HEX(.S7ECC,53) ;SENSE BYTE 7 CODE INDICATING ECC RECOVERABLE ERROR
;RH20 CONI/CONO/LOGOUT AREA BIT DEFINITIONS
CI.ERR==CI.DBP!CI.LWC!CI.DRE!CI.RAE!CI.OVR
;ALL 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.LWC!CS.SWC!CS.OVR
;ALL CHANNEL LOGOUT AREA ERROR BITS
SUBTTL RNXEBK/UNIEBK BLOCK OFFSETS
;OFFSETS IN THE RNXEBK AND UNIEBK BLOCKS FOR THE RP20. DAEMON KNOWS
;ABOUT THESE OFFSETS SO IF YOU CHANGE THEM, BE SURE TO CHANGE DAEMON
;ALSO. IF YOU CHANGE THE LENGTH OF THIS BLOCK, YOU MUST ALSO MAKE
;THE CORRESPONDING CHANGE IN THE DATA BLOCK GENERATION MACROS IN COMMOD.
;
;FIRST DEFINE THE SYMBOLS USED IN RNXKON FOR THE OFFSETS.
.EBNMR==RNVNMR ;NUMBER OF MASSBUS REGISTERS (DEFINED BY MBRLST)
.EBNDR==^D24 ;NUMBER OF DRIVE REGISTERS
.EBTYP==0 ;BYTE (9) DX20 ADDR(9)0(18) MICROCODE VERSION
.EBCS0==1 ;CHANNEL LOGOUT 0
.EBCS1==2 ;CHANNEL LOGOUT 1
.EBCS2==3 ;CHANNEL LOGOUT 2
.EBCC1==4 ;FIRST CCW
.EBCC2==5 ;SECOND CCW
.EBMPE==6 ;COUNT OF MPE
.EBNXM==7 ;COUNT OF NXM
.EBMBR==10 ;+LEN,,OFFSET FROM . OF MASSBUS REGISTERS
.EBDVL==11 ;+LEN,,OFFSET FROM . OF DEVICE REGISTERS
.EBSMR==12 ;START OF MASSBUS REGISTER BLOCK
.EBSTR==.EBSMR+1 ;WHERE STATUS REGISTER IS STORED
.EBERR==.EBSMR+2 ;WHERE ERROR REGISTER IS STORED
.EBESR==.EBSMR+7 ;WHERE ENDING STATUS REGISTER IS STORED
.EBSDR==.EBSMR+.EBNMR ;START OF DEVICE REGISTER BLOCK
.EBS07==.EBSDR+1 ;WORD CONTAINING SENSE BYTE 7
EB.S07==377B35 ;POSITION OF SENSE BYTE 7
.EBS18==.EBSDR+4 ;WORD CONTAINING SENSE BYTES 18 AND 19
EB.S18==177777B35 ;POSITION OF SENSE BYTES 18 AND 19
.EBS20==.EBSDR+5 ;WORD CONTAINING SENSE BYTES 20 AND 21
EB.S20==177777B17 ;POSITION OF SENSE BYTES 20 AND 21
.EBICR==.EBSDR+.EBNDR ;CONTENTS OF INITIAL CONTROL REGISTER
;NOW DEFINE THE VALUES THAT THE REST OF THE MONITOR USES TO INTERFACE
;TO THIS BLOCK.
RNVEBK==.EBICR ;LENGTH OF THE ???EBK BLOCK
RNVSMR==:.EBSMR ;OFFSET OF START OF MASSBUS REGISTERS IN RNXEBK/UNIEBK
SUBTTL DATA STRUCTURE FIELD AND BYTE POINTER DEFINITIONS
RNXMVR==300,,1 ;MINIMUM MICROCODE VERSION ALLOWED
;FIELDS IN RNXFLG(J)
RN.UPA==1B1 ;BEEN THROUGH RNXUPA ONCE FOR THIS CONTROLLER
RN.FTL==1B3 ;LAST TRANSFER ERROR WAS FATAL
RN.CLR==RN.FTL ;BITS TO CLEAR IN CONECT
RN.DCA==17B31 ;4 BITS OF DCU ADDRESS (SUBFIELD OF RN.CUA)
;BYTE POINTERS TO ABOVE FIELDS
RNYDCA: POINTR RNXFLG(J),RN.DCA ;DCU ADDRESS
;FIELDS IN RNXCMD(J)
CM.FNC==77B5 ;FUNCTION ISSUED TO DRIVE (I.E., BITS 30-35
; OF DATAO TO CONTROL REGISTER OR STCR)
CM.XFR==1B0 ;THIS FUNCTION CAUSES A DATA TRANSFER
CM.IO==1B2 ;1=READ, 0=WRITE
CM.HNG==1B6 ;THIS INTERRUPT CAME THROUGH RNXSTP
CM.DVA==377B35 ;DEVICE ADDRESS FOR THIS OPERATION
CM.UNF==17B35 ;4 BIT UNIT NUMBER
;MISCELLANEOUS PARAMETER DEFINITIONS
.CRM10==210 ;CONTENTS OF CRAM LOCATION 10
.DXSAD==5 ;DX20 RESTART ADDRESS
MAXRSC==^D8 ;NUMBER OF TIMES TO SIMPLY RESTART THE
; DX20 WHEN WE DISCOVER THAT IT STOPPED
; BEFORE SIMPLY CALLING IT DEAD
RTYNUM==^D24 ;NUMBER OF RETRIES TO DO IN ERROR RECOVERY
ATNRTY==^D10 ;NUMBER OF TIMES TO RETRY CLEARING AN
; ATTENTION BIT FOR A DX20 THAT WE KNOW
; ABOUT BEFORE RESORTING TO A MASSBUS
; INIT TO CLEAR IT
ALLERR==777770B35 ;ALL POSSIBLE ERROR BITS SET BY INTERRUPT
;SERVICE IN THE COMMUNICATIONS WORD
MAXDCU==^D16 ;MAXIMUM NUMBER OF DCU ADDRESSES WE
; CAN HAVE ON A DX20
MAXSPD==^D16 ;MAXIMUM NUMBER OF SPINDLES WE CAN HAVE
; ON A DCU
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 LOAD AN ARBITRARY BYTE FROM A LOCATION INTO AN AC.
; LOAD AC,LOC,MASK
DEFINE LOAD(A,B,C),<.LDST.(A,B,C,HRRZ,HLRZ,LDB,MOVE)>
;MACRO TO STORE AN ARBITRARY BYTE FROM AN AC INTO A LOCATION
; STORE AC,LOC,MASK
DEFINE STORE(A,B,C),<.LDST.(A,B,C,HRRM,HRLM,DPB,MOVEM)>
;UTILITY MACRO USED BY LOAD AND STORE
DEFINE .LDST.(A,B,C,D,E,F,G),<
IFNB <C>,<..T==0
IFE C-777777,<..T==1
D A,B>
IFE C-777777000000,<..T==1
E A,B>
IFE ..T,<F A,[POINTR(B,C)]>>
IFB <C>,<G A,B>
> ;END OF DEFINE .LDST.
;MACRO TO INSERT A VALUE IN A MASKED FIELD
; INSVL.(VALUE,MASK)
DEFINE INSVL.(VALUE,MASK),<<<<VALUE>B<POS(<MASK>)>>&<MASK>>>
;MACRO TO WAIT AWHILE. USED IN DODTI TO GIVE THE DRIVE TIME TO
;RESPOND WITH THE VALUE OF THE EXTERNAL REGISTER.
DEFINE STALL, <
IMULI T2,1
XLIST
IMULI T2,1
LIST
>
;MACRO TO DEFINE THE MASSBUS REGISTERS TO SAVE IN THE KDB 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>,<.EBM00==..CNT>
IFE <LST-30>,<.EBM30==..CNT>
..CNT==..CNT+1 ;BUMP NUMBER BY 1
MBRTBL==MBRTBL!<1_<^D35-LST>> ;SET BIT IN TABLE
> ;END IRP LST
RNVNMR==:..CNT ;DEFINE THE NUMBER OF REGISTERS
>
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 AUTOCONFIGURATION
RNFIX==0 ;NOT FIXED HEAD, CANNOT SEEK WHILE XFERRING
RNOFS==0 ;DRIVE CAN OFFSET. IT CAN'T REALLY BUT WE HAVE
;TO GET FILIO TO CALL US (VIA RNXERR) TO DIRECT
;ERROR RECOVERY.
RNRDC==400000 ;NO 10/11 COMPATABLILITY MODE
RNUNL==400000 ;DRIVE CANNOT BE UNLOADED
RNCPY==KOPIDL ;KONTROL MUST BE IDLE FOR RNXCPY
RNMX==0 ;CANNOT DO MULTIPLE TRANSFERS
RNDRB==0 ;DOESN'T USE DISK I/O REQUEST BLOCKS
RNBMX==0 ;NOT A BLOCK MULTIPLEX KONTROLLER
RNECA==0 ;TRY OFFSET/RECAL BEFORE TRYING ECC
RNERNO==^D57 ;NUMBER OF MASSBUS REGISTERS TO SAVE
RNXDMX==20 ;MAXIMUM DRIVES PER KONTROLLER
RNXHDN==RNXDMX-1 ;HIGHEST DRIVE NUMBER ON KONTROLLER
;DRIVER CHARACTERISTICS
; RNX = RNXCNF
; DSK = DISK
; 0 = MAXIMUM DEVICES IN SYSTEM (NO LIMIT)
; TYPRN = KONTROLLER TYPE
; RNXDMX = MAXIMUM DRIVES PER KONTROLLER
; RNXHDN = HIGHEST DRIVE NUMBER ON KONTROLLER
; MDSEC0 = SECTION FOR KDB/UDB
; MDSEC0 = SECTION FOR DDB
DRVCHR (RNX,DSK,0,TYPRN,RNXDMX,RNXHDN,MDSEC0,MDSEC0,DR.MCD)
.ORG KONUDB ;START OF RP20 SPECIFIC DATA
RNXUTB:!BLOCK RNXDMX ;UDB TABLE
RNXULB:!BLOCK .ULLEN ;MICROCODE LOADER BLOCK
RNXEBK:!BLOCK RNERNO ;STORAGE FOR MASSBUS REGISTERS
RNXIOB:! ;START OF SPECIAL I/O INSTRUCTIONS
RNXCO2:!BLOCK 1
RNXCO4:!BLOCK 1
RNXCI2:!BLOCK 1
RNXDO2:!BLOCK 1
RNXDO1:!BLOCK 1
RNXDI2:!BLOCK 1
RNXRAE:!BLOCK 1 ;SKIP IF NO RAE
RNXIOE:! ;END OF SPECIAL I/O INSTRUCTIONS
RNXRAC:!BLOCK 1 ;LH=COUNT OF RAE'S CAUSED BY OTHER THAN
; NON-EXISTENT DRIVES
;RH=COUNT OF RAE'S CAUSED BY NON-EXISTENT
; DRIVES
RNXAEC:!BLOCK 1 ;RH=COUNT OF THE NUMBER OF TIMES AN ATTENTION
; SUMMARY REGISTER BIT COULDN'T BE
; CLEARED BY WRITING IT TO A 1. USED
; TO TELL WHEN TO DO A MASSBUS INIT.
;LH=TOTAL NUMBER OF MASSBUS INITS DONE
RNXEC1:!BLOCK 1 ;LH=NUMBER OF TIMES LOGUPE WAS CALLED TO
; LOG AN ERROR THAT FILIO WOULDN'T HAVE
;RH=NUMBER OF TIMES WGOCLR DIDN'T TIME
; OUT THE GO BIT
RNXEC2:!BLOCK 1 ;LH=NUMBER OF TIMES CMDWAT TOSSED A SEEK
; BECAUSE AN XFER WAS IN PROGRESS
;RH=NUMBER OF TIMES CMDWAT WAS CALLED
RNXEC3:!BLOCK 1 ;LH=NUMBER OF TRANSFERS WHICH RESULTED IN
; MISSED REVOLUTIONS DURING LAST INTERVAL
;RH=NUMBER OF TRANSFERS ATTEMPTED DURING LAST
; INTERVAL
RNXRSC:!BLOCK 1 ;NUMBER OF TIMES THIS DX20 WAS RESTARTED.
RNXFLG:!BLOCK 1 ;FLAGS (SEE RNXKON FOR DEFINITIONS)
RNXCMD:!BLOCK 1 ;LAST COMMAND+FUNCTION FLAGS ISSUED TO
; KONTROLLER
RNXLAS:!BLOCK 1 ;VALUE OF RNXCMD AT LAST INTERRUPT
; (FOR DEBUGGING)
RNXATN:!BLOCK 1 ;LH=ATTENTION BITS FOR DRIVES PRESENTING
; ASYNCHRONOUS STATUS
;RH=UNUSED
RNXITB:!BLOCK 2 ;VALUE OF THE KL TIME BASE AT THE TIME
; THE LAST TRANSFER WAS STARTED. USED
; TO CALCULATE MISSED REVOLUTIONS.
RNXIUM:! BLOCK RNXDMW ;IGNORE DRIVE MASK
RNXNUM:! BLOCK RNXDMW ;NEW DRIVE MASK
RNXKLN:! ;LENGTH OF KDB
.ORG
;PROTOTYPE KDB
RNXKDB: XXKON (RN)
SETWRD (RNXCO2,<CONO 000,(T2)>)
SETWRD (RNXCO4,<CONO 000,(T4)>)
SETWRD (RNXCI2,<CONI 000,T2>)
SETWRD (RNXDO2,<DATAO 000,T2>)
SETWRD (RNXDO1,<DATAO 000,T1>)
SETWRD (RNXDI2,<DATAI 000,T2>)
SETWRD (RNXRAE,<CONSZ 000,CI.RAE>)
KDBEND
EQUATE (LOCAL,0,<RNXUDB>)
EQUATE (LOCAL,CPOPJ##,<RNXHWP,RNXINI>)
RNXICD==DSKICD## ;PROTOTYPE INTERRUPT CODE
RNXICL==DSKICL##
RNXUDB==0 ;NO PROTOTYPE UDB
RNXULN==UNIEBK+RNERNO ;LENGTH OF UDB
RNXDSP: DRVDSP (RNX,DSKCHN##,DSKDDB##,DDBLEN##,DSKDIA##)
RNXCKT: EXP TYPRN, 0 ;COMPATIBLE KONTROLLER TABLE
;PROTOTYPE MICROCODE LOADER BLOCK
RNXULP: EXP .BTRP2## ;MICROCODE INDEX
XWD 000,0 ;DEVICE CODE,,MASSBUS UNIT NUMBER
SIXBIT /RP20/ ;INTERFACE NAME
SIXBIT /DX20/ ;CHANNEL NAME
EXP RNXMVR ;MINIMUM MICROCODE VERSION
EXP 0 ;DATE/TIME OF LOAD SUCCESS OR FAILURE
EXP 0 ;MICROCODE VERSION
EXP 0 ;POINTER TO MAGIC TABLE
EXP 0 ;MICROCODE LENGTH
EXP 0 ;MICROCODE ADDRESS
SUBTTL START DRIVE POSITIONING
;ROUTINE TO CAUSE THE DRIVE TO DO A RECALIBRATE OPERATION.
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,RNXRCL
;RETURN CPOPJ IF ERROR
; CPOPJ1 WITH RECAL STARTED
RNXRCL: MOVEI T1,.DXCTR!.CRRCL ;GET RECAL FUNCTION CODE
PUSHJ P,CONECT ;CONNECT TO THE DRIVE
JRST RNXDWN ;DRIVE IS DOWN
MOVSI T2,(.DXDCR) ;SET CYLINDER AND
MOVSI T3,(.DXDAR) ; TRACK/SECTOR TO ZERO
PJRST RNXGO ;JOIN COMMON CODE
;ROUTINE TO START A POSITION OPERATION GOING. FOR RP20'S, FILIO ALWAYS
;DOES A SEEK BEFORE EVERY TRANSFER REGARDLESS OF WHETHER THE DRIVE IS
;ALREADY ON CYLINDER. WE TURN THAT INTO A SEARCH COMMAND SO THAT WE
;GET AN INTERRUPT WHEN THE DRIVE IS BOTH ON CYLINDER AND ON SECTOR.
;CALL WITH UNIBLK(U) CONTAINING THE DESIRED BLOCK NUMBER.
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,RNXPOS
;RETURN CPOPJ IF ERRORS
; CPOPJ1 WITH POSITION STARTED
RNXPOS: MOVEI T1,.DXCTR!.CRSRC ;GET SEARCH COMMAND
PUSHJ P,CONECT ;CONNECT TO DRIVE
JRST RNXDWN ;DRIVE IS DOWN
PJRST RNXGO ;JOIN COMMON CODE
SUBTTL START DATA TRANSFERS
;ROUTINES TO START A DATA TRANSFER GOING ON A DRIVE. ENTRY POINTS
;ARE:
; RNXRED - READ DATA, DON'T STOP ON ERROR
; RNXRDS - READ DATA, STOP ON ERROR
; RNXRDF - READ FORMAT
; RNXWRT - WRITE DATA, DON'T STOP ON ERROR
; RNXWTS - WRITE DATA, STOP ON ERROR
; RNXWTF - WRITE FORMAT
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; P1/CHANNEL DATA BLOCK ADDRESS
; PUSHJ P,ROUTINE
;RETURN CPOPJ IF ERRORS WITH:
; T1/ERROR BITS
; CPOPJ1 IF TRANSFER STARTED SUCCESSFULLY
;HERE TO START TRANSFER TO READ/WRITE FORMATS.
RNXRDF: SKIPA T1,[.CRRDF] ;GET FUNCTION CODE FOR READ FORMAT
RNXWTF: MOVEI T1,.CRWTF ;DITTO FOR WRITE FORMAT
MOVE T2,KONCNT(J) ;WHEN READING OR WRITING FORMATS,
IDIVI T2,202 ; SECTORS ARE 202 WORDS LONG BUT FILIO
SKIPE T3 ; COMPUTED THE BLOCK COUNT BASED ON 200
ADDI T2,1 ; WORD SECTORS. RECOMPUTE THE BLOCK
HRRM T2,CHNNUM(P1) ; COUNT TO KEEP THE RH20 HAPPY.
JRST RNXDGO ;JOIN COMMON TRANSFER CODE
;HERE TO START TRANSFER TO READ/WRITE DATA, NOT STOPPING ON ERRORS.
RNXRED: SKIPA T1,[DO.DTE!.CRRED] ;GET FUNCTION FOR READ DATA+DXES
RNXWRT: MOVEI T1,DO.DTE!.CRWRT ;DITTO FOR WRITE DATA+DXES
JRST RNXDGO ;JOIN COMMON CODE
;HERE TO START TRANSFER TO READ/WRITE DATA, STOPPING ON ERRORS.
RNXRDS: SKIPA T1,[.CRRED] ;GET FUNCTION CODE FOR READ DATA
RNXWTS: MOVEI T1,.CRWRT ;DITTO FOR WRITE DATA
;HERE FROM ALL TRANSFER OPERATIONS TO ACTUALLY DO THE WORK WITH
;T1 CONTAINING THE FUNCTION.
RNXDGO: PUSHJ P,CONECT ;CONNECT TO DRIVE
JRST RNXDWN ;DRIVE IS DOWN
PUSH P,T4 ;SAVE IGNORE COMMAND FLAG
MOVN T4,CHNNUM(P1) ;GET NEGATIVE BLOCK COUNT FOR TRANSFER
STORE T4,T1,DO.CNT ;STORE IN APPRPRIATE PLACE IN STCR
TLO T1,(.DOSTC!DO.RCP!DO.SCS) ;SETUP TO TALK TO STCR
POP P,T4 ;RESTORE T4
;HERE TO START ALL OPERATIONS GOING THROUGH EITHER THE STCR OR THE
;DX20 CONTROL REGISTER WITH:
; T1/STCR OR CONTROL REGISTER DATAO
; T2/DATAO TO SETUP DESIRED CYLINDER REGISTER
; T3/DATAO TO SETUP DESIRED ADDRESS REGISTER
; T4/NON-ZERO TO TOSS THIS COMMAND
RNXGO: JUMPN T4,RNXGO1 ;DON'T DO DATAO'S IF TOSSING COMMAND
PUSH P,T3 ;SAVE DESIRED ADDRESS REGISTER
PUSHJ P,DODTO ;WRITE DESIRED CYLINDER REGISTER
POP P,T2 ;RESTORE DESIRED ADDRESS REGISTER
PUSHJ P,DODTO ;WRITE THAT ALSO
RNXGO1: HLRZ T3,KDBUNI(J) ;GET DX20 NUMBER
TLO T1,<(DO.LDR!DO.DRE)>(T3) ;SET LDR, DRE, AND DS
SKIPE T4 ;TOSSING THIS COMMAND?
TLO T1,(CR.IGN) ;YES, SET FLAG SO WE CAN TELL
MOVEM T1,UNILAS(U) ;STORE AS LAST COMMAND FOR THIS UNIT
JUMPN T4,RNXGO2 ;EXIT NOW IF TOSSING COMMAND
STORE T1,RNXCMD(J),CM.FNC ;STORE FUNCTION IN KDB
TRNE T1,CR.IOP ;THIS AN I/O FUNCTION?
RDTIME RNXITB(J) ;YES, READ THE STARTING TIME BASE
RNXBP1: XCT RNXDO1(J) ;START THE OPERATION
RNXGO2: PUSHJ P,REASPI ;REASSIGN PIA
JRST CPOPJ1## ;GIVE SKIP RETURN
;HERE IF THE DRIVE OR KONTROLLER WAS DECLARED DOWN BY CONECT TO RETURN
;AN ERROR INDICATION TO FILIO.
RNXDWN: PUSHJ P,SETCO ;SET CONO MASK
TRO T4,CO.RAE ;MAKE SURE RAE IS CLEAR
XCT RNXCO4(J) ;GIVE IT A PIA
XCT RNXCI2(J) ;GET CONI INTO T2
MOVE T3,RNXEBK+.EBERR(J) ;GET ERROR REGISTER
HRL T3,RNXEBK+.EBSTR(J) ;MAKE IT STATUS,,ERROR REGISTER
RNXBP5: POPJ P, ;RETURN
SUBTTL STOP TRANSFER FOR HUNG RECOVERY
;ROUTINE TO STOP THE CURRENT TRANSFER WHEN THE HUNG TIMER TIMES
;OUT. NOTE THAT THE SETTING OF STOP TRANSFER CAUSES AN IMMEDIATE
;INTERRUPT SO RNXINT HAS TO KNOW ABOUT THESE KINDS OF INTERRUPTS.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXSTP
;RETURN CPOPJ IF COULDN'T GET BUSY TO CLEAR
; CPOPJ1 IF SUCCESSFUL
RNXSTP: XCT RNXCI2(J) ;GET CONI BEFORE STOPPING TRANSFER
PUSH P,T2 ;SAVE IT
PUSHJ P,RNXIVI ;ASSIGN AN IVI SINCE WE MIGHT BE HERE
; AS THE RESULT OF POWER FAIL RESTART
MOVSI T2,(CM.HNG) ;SET BIT TELLING RNXINT THAT THIS
IORM T2,RNXCMD(J) ; INTERRUPT WAS THE RESULT OF A HUNG
MOVEI T2,CO.STP ;GET THE STOP TRANSFER BIT
XCT RNXCO2(J) ;STOP THE RH20
XCT RNXCI2(J) ;GET THE CONI BACK
RNXBP6: TRNN T2,CI.BSY ;DID BUSY CLEAR?
AOS -1(P) ;YES, GIVE SKIP RETURN
POP P,T2 ;RESTORE CONI
MOVEI T3,0 ;DATAI WILL BE SAVED BY RNXINT
PJRST REASPI ;REASSIGN PIA AND RETURN
SUBTTL INTERRUPT HANDLER
;ROUTINE TO PROCESS RP20 INTERRUPTS.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXINT
;EXITS CPOPJ ALWAYS THROUGH FILINT WITH:
; T1/COMMUNICATIONS WORD (ATN BITS+DRIVE,,ERROR+FUNCTION)
; T2/CONI
; T3/ENDING STATUS,,ERROR REGISTER
RNXINT: PUSHJ P,SAVE3## ;SAVE P1-P3
MOVE W,J ;SET UP KDB ADDRESS
PUSHJ P,SVMBR## ;SAVE CURRENT MBR FOR UUO LEVEL
MOVEI T2,^D2000 ;JUST IN CASE SOMETHING IS HAPPENING,
PUSHJ P,WGOCLR ; WAIT FOR THE GO BIT TO CLEAR
PUSHJ P,RNXINR ;PROCESS ANY OPERATION IN PROGRESS
; PLUS ANY ERRORS THAT OCCURRED WHILE
; THERE WAS NO OPERATION IN PROGRESS
; (MICRODIAGNOSTIC FAILURE, UCODE RELOAD)
PUSHJ P,CHKATN ;CHECK ON ASYNCHRONOUS EVENTS AND CALL FILIO
POPJ P, ;RETURN
;ROUTINE TO PROCESS ANY OPERATION CURRENTLY IN PROGRESS OR ERRORS
;THAT OCCURRED WHILE THERE WAS NO OPERATION IN PROGRESS SUCH
;AS MICRODIAGNOSTIC FAILURES OR INTERRUPTS FOR MICROCODE RELOADS.
;CALLED FROM INTERRUPT SERVICE AND CONECT.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXINR
;RETURN CPOPJ ALWAYS WITH:
; J/KDB ADDRESS
; T1/FILIO COMMUNICATION WORD
; P1/FLAGS FROM RNXCMD OR 0 IF NO OPERATION IN PROGRESS
; P2/ERROR REGISTER,,ENDING STATUS REGISTER
; P3/CHANNEL STATUS,,CONI
RNXINR: SETZB T1,P2 ;CLEAR COMMUNICATION AND DATAI WORDS
XCT RNXCI2(J) ;GET CONI IN T2
MOVEI P3,(T2) ;MOVE TO P3
MOVEI P1,0 ;START WITH ZERO FLAGS
EXCH P1,RNXCMD(J) ;ZERO FLAG WORD, PUT FLAGS IN P1
MOVEM P1,RNXLAS(J) ;SAVE VALUE FOR DEBUGGING
MOVSI T2,(.DXESR) ;POINT AT ENDING STATUS REGISTER
PUSHJ P,DODTI ;READ IT
MOVEI P2,(T2) ;MOVE TO P2
JUMPGE P1,RNXIN2 ;GO IF NOT A DATA TRANSFER OPERATION
MOVE T2,KDBICP(J) ;GET ADDRESS OF RH20 LOGOUT AREA
HLL P3,.CSCLP(T2) ;COPY CHANNEL STATUS TO LH(P3)
RNXIN2: MOVE U,KONCUA(J) ;SETUP POSSIBLE UDB ADDRESS
PUSHJ P,CHKERR ;CHECK ON DX20 DETECTED ERRORS
JUMPL P1,DATINT ;DISPATCH TO DATA XFER DONE HANDLER
JUMPE P1,NOPINT ;DISPATCH IF NO OPERATION IN PROGRESS
MOVE T2,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
MOVE T2,BITTBL##(T2) ;AND CORRESPONDING BIT
TLNE P1,(CM.HNG) ;COME THROUGH RNXSTP?
IORM T2,RNXATN(J) ;YES, MUST BE A HUNG RECAL
;; PJRST POSINT ;FALL INTO POSITION DONE HANDLER
;HERE ON A POSITION INTERRUPT AT POSINT OR AN INTERRUPT WITH NO
;OPERATION IN PROGRESS AT NOPINT WITH THE FOLLOWING AC'S SETUP:
; T1/ERROR BITS
; P1/FLAGS FROM RNXCMD OR 0 IF NO OPERATION IN PROGRESS
; P2/ERROR REGISTER,,ENDING STATUS REGISTER
; P3/CONI
POSINT: LOAD T2,P1,CM.UNF ;GET UNIT NUMBER OF DRIVE
TRNN T1,ALLERR ;NO 2ND INTERRUPT IF WE GOT AN ERROR
TRNE P2,ES.DVE ;DEVICE END UP IN ENDING STATUS REGISTER?
PUSHJ P,POSDON ;YES, SET CORRESPONDING BIT IN RNXATN
NOPINT: TRO T1,OPPOS ;FLAG THIS AS A POSITION OPERATION
TRZE T1,ALLERR ;ANY ERRORS DETECTED?
PUSHJ P,LOGUPE ;YES, LOG THEM
POPJ P, ;RETURN
;HERE ON A DATA TRANSFER INTERRUPT WITH THE FOLLOWING AC'S SETUP:
; T1/ERROR BITS
; P1/FLAGS FROM RNXCMD
; P2/ERROR REGISTER,,ENDING STATUS REGISTER
; P3/CHANNEL STATUS,,CONI
DATINT: TLNE P1,(CM.HNG) ;HERE FROM RNXSTP?
TRO T1,IODERR ;YES, SET DEVICE ERROR
TLNE P1,(CM.IO) ;DOING A READ?
TROA T1,OPRED ;YES, FLAG IT AS SUCH
TRO T1,OPWRT ;NO, FLAG IT AS A WRITE
TLC P3,(CS.NAE) ;COMPLEMENT ADDRESS PARITY BIT
TDNN P3,[CS.ERR!CI.ERR] ;ANY CHANNEL OR RH20 ERRORS DETECTED?
JRST DATIN1 ;NO
TLNE P3,(CS.MPE) ;MEMORY PARITY ERROR?
TRO T1,IOCHMP ;YES
TLNE P3,(CS.NXM) ;NXM?
TRO T1,IOCHNX ;YES
TLNE P3,(CS.OVR) ;OVERRUN?
TRO T1,IOVRUN ;YES
TRNN T1,ALLERR ;ANY ERRORS FLAGGED (BETTER BE)
TRO T1,IODERR ;NO??? FLAG A DEVICE ERROR
DATIN1: TLC P3,(CS.NAE) ;RECOMPLEMENT ADDRESS PARITY BIT
TRNN T1,ALLERR ;ANY ERRORS DETECTED?
SKIPLE UNIECT(U) ;NO, READ SUCCEED ON RETRY?
PUSHJ P,RDREG ;YES, READ THE REGISTERS
MOVE T2,UDBKDB(U) ;UPDATE THE LAST KNOWN POSITION
MOVE T2,KDBCHN(T2)
MOVE T2,CHNNUM(T2) ; OF THE DISK
ADD T2,UNIBLK(U)
ADDI T2,^D14 ;PLUS A FUDGE FACTOR
LDB T3,UNYBPT##
IDIV T2,T3
DPB T3,UNYLKP##
POPJ P, ;RETURN
;ROUTINE TO CHECK FOR ASYNCHRONOUS EVENTS AND DO THE FINAL INTERRUPT
;PROCESSING BEFORE CALLING FILINT.
;CALL:
; J/KDB ADDRESS
; T1/ERROR BITS
; P1/FLAGS FROM RNXCMD OR 0
; P2/ERROR REGISTER,,ENDING STATUS REGISTER
; P3/CHANNEL STATUS,,CONI
; PUSHJ P,CHKATN
;RETURN CPOPJ ALWAYS
CHKATN: PUSHJ P,CLRATN ;CLEAR ATTENTION BITS
PUSHJ P,CLRERG ;CLEAR THE ERROR REGISTER
MOVSI T2,(.DXASY) ;POINT AT THE ASYNCHRONOUS STATUS REGISTER
PUSHJ P,DODTI ;READ IT
JUMPE T2,INTDON ;GO IF NONE THERE
TRNE T2,AS.DVS ;ANY STATUS BITS SET?
JRST RNXBP2 ;YES, CONTINUE
MOVSI T2,(.DXASY) ;THERE'S A UCODE RACE WHICH CAUSES IT TO GIVE
PUSHJ P,DODTI ;US A DRIVE WITH NO STATUS, SO READ IT AGAIN
RNXBP2: PUSH P,T2 ;SAVE IT
MOVSI T2,(.DXASY) ;POINT AT REGISTER AGAIN
PUSHJ P,DODTO ;CLEAR IT SO WE CAN GET MORE
POP P,T2 ;RESTORE VALUE TO PROCESS
SKIPN P1 ;IF NO OPERATION IN PROGRESS,
MOVEI P2,(T2) ;MOVE ASYNCHRONOUS STATUS TO P2 FOR .SYS P
LOAD T2,T2,AS.UNF ;GET UNIT NUMBER PRESENTING STATUS
PUSHJ P,POSDON ;SET THE CORRESPONDING BIT IN RNXATN
;; PJRST INTDON ;FALL INTO INTDON
;HERE TO DO THE FINAL EXIT PROCESSING BEFORE CALLING FILINT WITH:
; J/KDB ADDRESS
; T1/ERROR BITS
; P1/FLAGS FROM RNXCMD OR 0
; P2/ERROR REGISTER,,ENDING STATUS REGISTER
; P3/CHANNEL STATUS,,CONI
; LH(RNXATN(J))/ATTENTION BITS OF DRIVES IN POSITION
INTDON: MOVEI T4,CO.CLR ;GET BITS TO CLEAR RH20
XCT RNXCO4(J) ;DO SO
PUSHJ P,REASPI ;REASSIGN PIA
HLLZ T4,RNXATN(J) ;GET ATTENTION BITS
LOAD T2,P1,CM.UNF ;GET UNIT NUMBER LAST CONNECTED TO
TLO T1,(T2) ;SET IN LH OF T1
TRNN T1,OPPOS ;THIS A POSITION OPERATION?
TDZ T4,BITTBL##(T2) ;NO, MAKE SURE WE DON'T CALL FILIO WITH
; A POSITION DONE INTERRUPT ON A TRANSFERRING
; DRIVE. IT HAPPENS AND IT CONFUSES FILIO
;PJRST CALFIO ;CALL FILIO TO PROCESS THIS EVENT
;ROUTINE TO ACTUALLY CALL FILIO TO PROCESS AND INTERRUPT.
;CALL:
; J/KDB ADDRESS
; T1/COMMUNICATION WORD
; T4/ATTENTION BITS
; P2/ERROR REGISTER,,ENDING STATUS REGISTER
; P3/CHANNEL STATUS,,CONI
; PUSHJ P,CALFIO
;RETURN CPOPJ ALWAYS
CALFIO: PUSH P,J ;SAVE KONTROLLER ADDRESS; FILINT MAY SMASH IT
HRRZS RNXATN(J) ;CLEAR ATTENTION BITS IN KDB
MOVE T2,P3 ;GET CONI IN T2
MOVS T3,P2 ; AND DATAI'S IN T3
MOVEM T1,RNXEC3(J) ;****; TEMPORARY FOR DEBUGGING
TLZ T1,777700 ;CLEAR UNUSED BITS
TRNE T1,OPPOS ;POSITION INTERRUPT?
TLNE T4,777774 ; WITH NO ATTENTION BITS UP?
SKIPA ;NO
JRST JPOPJ## ;AVOID A LONG NO-OP IN FILIO
PUSH P,T2 ;SAVE T2
PUSHJ P,RNXCSB ;CLEAR MICROPROCESSOR STOPPED BIT
POP P,T2 ;RESTORE T2
PUSHJ P,FLHTID## ;CALL FILIO
PJRST JPOPJ## ;RESTORE J AND RETURN
SUBTTL DETERMINE CAPACITY AND STATUS
;ROUTINE TO RETURN CAPACITY AND STATUS OF AN RP20 DRIVE TO FILSER.
;CALL: J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,RNXCPY
;RETURN CPOPJ IF ERROR
; CPOPJ1 IF DRIVE EXISTS AND IS OK TO USE WITH:
; T1/BLOCKS PER UNIT
; T2/BLOCKS PER UNIT INCLUDING MAINTENANCE CYLINDERS
; T3/BLOCKS PER UNIT IN 10/11 COMPATABILITY MODE
; T4/STATUS BITS (KOPUHE,KOPNSU),,UNIT TYPE
; LH(J)/DRIVE SERIAL NUMBER
; W/BLOCKS PER TRACK,,BLOCKS PER CYLINDER
RNXCPY: PUSHJ P,SAVE2## ;SAVE P1-P2
MOVEI T2,CO.MBE ;MAKE SURE MASSBUS
XCT RNXCO2(J) ; ENABLE IS ON AND DEASSIGN PI
PUSHJ P,RNXIVI ;SET INTERRUPT VECTOR ADDRESS
MOVEI T4,0 ;UNIT TYPE IS 0
SKIPE RNXCMD(J) ;ARE WE DOING SOMETHING NOW?
JRST RNXCP4 ;YES, CAN'T TOUCH THE DRIVE
RNXCP1: PUSHJ P,MPRUN ;DX20 STILL RUNNING?
JRST RNXCP4 ;NO, CALL UNIT OFF-LINE
PUSHJ P,DO2TIO ;DO TWO TEST I/O'S
JRST RNXCP4 ;GO IF THE DX20 DIDN'T RESPOND
PUSHJ P,INIERR ;CHECK FOR ERRORS
JRST RNXCP5 ;DRIVE IS ON-LINE
JRST RNXCP4 ;DRIVE EXISTS BUT IS OFF-LINE
;HERE IF NO SUCH UNIT EXISTS OR THE DRIVE TYPE REGISTER IS NOT
;FOR A DX20.
RNXCP3: TLOA T4,KOPUHE!KOPNSU ;INDICATE NO SUCH UNIT
;HERE IF THE UNIT EXITS BUT IS OFF-LINE OR IF WE'RE NOT REALLY SURE
;AND DON'T WANT TO TELL FILSER THAT NO SUCH UNIT EXISTS.
RNXCP4: TLO T4,KOPUHE ;INDICATE OFF-LINE
JRST RNXCP6 ;JOIN COMMON EXIT CODE
;HERE IF THE DRIVE IS ON-LINE AND NO ERRORS WERE DETECTED.
RNXCP5: AOS 0(P) ;GIVE SKIP RETURN
RNXCP6: LDB T1,RNYDCA ;GET DCU
;THERE'S NO WAY TO READ THE SERIAL NUMBER OF AN RP20 SO WE BUILD A FAKE
;SERIAL NUMBER BASED ON THE UNIT NUMBER. THE QUESTION IS: IF YOU'VE GOT
;SEVERAL RH20'S WORTH OF RP20'S, HOW DO YOU TELL WHICH RH20 IS DUAL PORTED
;WITH WHICH? THE ANSWER IS: YOU CUT THE TWO DCU'S TO BE THE SAME ADDRESS.
;IF THE DCU'S MATCH THE DRIVES WILL BE CONSIDERED DUAL PORTED. THERE'S A
;SPECIAL CASE, HOWEVER, IN THAT A DCU OF ZERO DOESN'T MATCH ANYTHING. NOTE
;THAT THE FACTORY SETS ALL THE DCU ADDRESSES TO ZERO. YOU CAN INSTALL ANY
;NUMBER OF THESE WITH NO MODIFICATION AND THEY WILL ALL BE SINGLE PORTED. IF
;YOU WANT THEM TO BE DUAL PORTED THEN YOU HAVE TO ASSIGN A UNIQUE DCU ADDRESS.
JUMPE T1,RNXCP7 ;GO IF FACTORY JUMPERS
LSH T1,4 ;MAKE ROOM FOR UNIT NUMBER
IOR T1,UDBPDN(U) ;DUMMY UP A DRIVE SERIAL NUMBER
MOVEI T2,.DTCOD ;GET DT VALUE, VERIFIED BY CHKDTR
RNXCP7: SETZM UDBDSN(U) ;NO HIGH WORDER S/N WORD
HRRZM T1,UDBDSN+1(U) ;RETURN SERIAL NUMBER IN UNISER
PUSHJ P,CLRERG ;CLEAR ERROR REGISTER
PUSHJ P,CLRATN ;CLEAR ATTENTIONS
PUSHJ P,REASPI ;RESTORE PI ASSIGNMENT
DMOVE T1,[EXP ^D839250,^D840000] ;BLOCKS/UNIT WITH/WITHOUT MAINT CYL
TLNE T4,KOPNSU ;NO SUCH UNIT?
SETZB T1,T2 ;YES, RETURN 0'S
MOVEI T3,0 ;NO BLOCKS IN 10/11 COMPATABILITY MODE
MOVE W,[^D25,,^D750] ;BLOCKS/TRACK,,BLOCKS/CYLINDER
POPJ P, ;RETURN
$INIT
;CHECK FOR KONTROLLER UP
RNXUPA: PUSHJ P,RNXIVI ;ASSIGN INTERRUPT VECTOR ADDRESS
MOVSI T1,(RN.UPA) ;ALREADY BEEN THROUGH HERE FOR
TDNE T1,RNXFLG(J) ; THIS CONTROLLER?
SJSP T1,CPOPJ1## ;YES, IT'S UP
SETZM RNXCMD(J) ;CLEAR COMMAND/FLAGS
MOVEI T2,CO.RAE!CO.MBE!CO.AIE!CO.CCD+DSKCHN## ;GET BITS TO CLEAR
; ERROR IN RH20
XCT RNXCO2(J) ;DO SO
XCT RNXCI2(J) ;GET CONI
TRNN T2,CI.DBP!CI.LWC!CI.DRE!CI.RAE!CI.OVR!CI.BSY ;ANY ERRORS?
TRNN T2,CI.PIA ; OR NO PIA?
POPJ P, ;DRIVE IS DOWN
MOVSI T1,(RN.UPA) ;SET FLAG THAT WE HAVE
IORM T1,RNXFLG(J) ; BEEN HERE BEFORE
SJSP T1,CPOPJ1## ;AND GIVE SKIP RETURN WITH T1 NON-ZERO
$HIGH
SUBTTL RETURN ECC MASK AND POSITION
;ROUTINE TO RETURN THE ECC POSITION AND MASK TO FILIO FOR AN ECC
;CORRECTABLE ERROR IN A BLOCK. THE RP20 RETURNS THE ECC POSITION
;AND MASK IN THE SENSE BYTES WHICH ARE NOW IN RNXEBK AS FOLLOWS:
; 18-19 FIRST BYTE IN ERROR COUNTED FROM THE LAST BYTE IN THE
; BLOCK. A COUNT OF ZERO MEANS THAT THE ECC ERROR OCCURRED
; IN THE ECC BYTE ITSELF AND MAY BE IGNORED.
; 20-21 MASK WHICH WHEN XORED WITH THE DATA ACTUALLY READ WILL
; CORRECT THE ERROR.
;NOTE THAT THE BOTH MASK WORDS ARE SWAPPED SINCE THAT'S THE WAY AN
;RP06 WOULD RETURN THEM AND THE WAY FILIO EXPECTS THEM.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXECC
;RETURN CPOPJ IF NO ECC INFORMATION AVAILABLE
; CPOPJ1 WITH CORRECTION DATA AS FOLLOWS:
; T1/WORD POSITION OF START OF ERROR RELATIVE TO START OF BLOCK
; T2-T3/MASK
RNXECC: HLRZ T2,RNXEBK+.EBDVL(J) ;GET NUMBER OF DEVICE REGS STORED
JUMPE T2,CPOPJ## ;GIVE UP IF NONE
LOAD T3,RNXEBK+.EBS07(J),EB.S07 ;GET FORMAT TYPE AND CODE
CAIN T3,.S7ECC ;ECC ERROR?
CAIGE T2,.EBS07-.EBSDR+1 ;OR IF WE DIDN'T GET AT LEAST 0-7
POPJ P, ;NO ECC INFORMATION AVAILABLE
SETZB T2,T3 ;ZERO MASKS FOR EARLY EXIT
LOAD T1,RNXEBK+.EBS18(J),EB.S18 ;GET BYTES 18-19
JUMPE T1,CPOPJ1## ;NO CORRECTION IF IN ECC BYTE
CAILE T1,^D576 ;OR IF OUT
POPJ P, ; OF RANGE
MOVNI T1,-^D576(T1) ;COMPUTE NUMBER OF BYTES FROM START OF BLOCK
LSH T1,3 ;CONVERT TO COUNT OF BITS
TLZ T1,-1 ;CLEAR JUNK
IDIVI T1,^D36 ;COMPUTE WORD COUNT, OFFSET IN WORD
MOVNI T4,-<^D36-^D16>(T2) ;COMPUTE SHIFT COUNT IN THIS WORD
LOAD T2,RNXEBK+.EBS20(J),EB.S20 ;GET CORRECTION MASK
LSHC T2,(T4) ;SHIFT TO PROPER POSITION FOR MASK
MOVSS T2 ;SWAP THE MASK SO THAT IT
MOVSS T3 ; LOOKS LIKE THAT RETURNED BY AN RP06
JRST CPOPJ1## ;GIVE SKIP RETURN
SUBTTL DIRECT FILIO IN ERROR RECOVERY
;ROUTINE TO DIRECT FILIO IN ERROR RECOVERY. SINCE THE DCU DOES ITS OWN
;SEEK ERROR RECOVERY AND SINCE WE DON'T HAVE ANY OFFSET CAPABILITY,
;THE BASIC ERROR RECOVERY ALGORITHM IS TO SIMPLY DO 24 STRAIGHT RETRIES.
;IF RN.FTL IS SET IN RNXFLG, HOWEVER, WE GIVE UP IMMEDIATELY.
;CALL:
; J/KDB ADDRESS
; T1/RETRY NUMBER
; P1/CHANNEL DATA BLOCK ADDRESS
; PUSHJ P,RNXERR
;RETURN CPOPJ ALWAYS WITH:
; T1/0 IF STRAIGHT RETRY
; 2 IF LAST TIME
; 3 IF GIVE UP
RNXERR: MOVE T2,RNXFLG(J) ;GET ERROR FLAGS SET BY CHKERR
TLNE T2,(RN.FTL) ;FATAL ERROR?
MOVEI T1,RTYNUM ;YES, FORCE IT TO BE FATAL
CAIGE T1,RTYNUM-1 ;STILL DOING STRAIGHT RETRIES?
MOVEI T2,0 ;YES
CAIN T1,RTYNUM-1 ;LAST TIME?
MOVEI T2,2 ;YES
CAIL T1,RTYNUM ;TIME TO GIVE UP?
MOVEI T2,3 ;YES
MOVEI T1,(T2) ;MOVE TO WHERE FILIO WANTS IT
POPJ P, ;RETURN
SUBTTL MISCELANEOUS GLOBAL FUNCTIONS
;ROUTINE TO RETURN THE LATENCY TIME FOR AN RP20 DRIVE. SINCE THE
;RP20 CAN'T TELL US WHERE IT REALLY IS (THAT'S RIGHT, NO LOOK AHEAD
;REGISTER RP06 FANS), AND SINCE WE ALWAYS DO SEARCHES BEFORE EACH
;DATA TRANSFER SO THAT WE GET AN INTERRUPT WHEN THE DRIVE IS ON
;BOTH CYLINDER AND SECTOR, WE ALWAYS RETURN A LATENCY TIME OF
;ZERO IN THE HOPE THAT FILIO WILL GET BACK TO START THE TRANSFER
;BEFORE THE DISK REVOLVES PAST THE BLOCK.
;CALL:
; PUSHJ P,RNXLTM
;RETURN CPOPJ1 ALWAYS WITH:
; T1/LATENCY TIME (ZERO)
RNXLTM: MOVEI T1,0 ;RETURN A ZERO
JRST CPOPJ1## ;GIVE SKIP RETURN
;ROUTINE TO RETURN THE DISTANCE TO THE TARGET CYLINDER. SINCE WE WANT
;TO DO SEEKS (REALLY SEARCHES), WE ALWAYS TELL FILIO THAT WE ARE OFF
;CYLINDER EVEN IF WE ARE ON CYLINDER.
;BE AWARE THAT WHEN CHOOSING SOMEBODY FROM THE POSITION WAIT QUEUE,
;IF THERE ARE SEVERAL PEOPLE ALREADY ON CYLINDER, FILIO
;WILL TRY TO CHOOSE THE ONE WHOSE ROTATIONAL LATENCY IS THE
;SMALLEST. IN THE CASE OF AN RP20, WE MUST LIE TO FILIO.
;IF WE'RE ON CYLINDER, LIE TO FILIO AND TELL HIM THAT WE'RE OFF
;CYLINDER. BUT LIE BY AN AMOUNT LINEARLY PROPORTIONATE TO THE
;EXPECTED ROTATIONAL LATENCY OF THE DISK. THE EXPECTED LATENCY
;IS CALCULATED FROM THE LAST KNOWN POSITION OF THE DISK.
;THE ONLY TIME WE CAN ACCURATELY KNOW THE POSITION OF THE DISK
;IS AT THE CONCLUSION OF A TRANSFER. IT HAPPEN'S THAT'S
;THE ONLY TIME WE PICK SOMEBODY FROM THE POSITION WAIT QUEUE
;ANYWAY.
;CALL:
; PUSHJ P,RNXCCM
;RETURN CPOPJ ALWAYS WITH:
; T1/DISTANCE FROM CURRENT CYLINDER TO TARGET CYLINDER
RNXCCM: PUSHJ P,CYLCM## ;LET FILIO COMPUTE THE REAL DISTANCE
MOVMS T1
ADDI T1,100 ;EXCESS 100
CAIE T1,100 ;ON CYL?
POPJ P, ;NO
MOVE T1,DEVBLK##(F) ;YES, COMPUTE TARGET SECTOR
LDB T3,UNYBPT##
IDIV T1,T3
LDB T1,UNYLKP## ;LAST KNOWN POSITION OF DISK
CAMLE T1,T2 ;TOO LATE?
ADD T2,T3 ;YES, WAIT ANOTHER REVOLUTION
SUBM T2,T1 ;DISTANCE TO TARGET
ADDI T1,1 ;ASSURE NON-ZERO
SKIPL UNIECT(U) ;IN ERROR RECOVERY?
SETZ T1, ;YES, TELL THE TRUTH (ON CYL)
POPJ P, ;RETURN
;ROUTINES WHICH SHOULD NEVER BE CALLED SINCE THE DISPATCH BITS
;IN COMMOD PROHIBIT THIS. IF WE DO GET HERE HOWEVER...
RNXRDC: ;READ 10/11 COMPATABILITY MODE
RNXWTC: ;WRITE 10/11 COMPATABILITY MODE
RNXUNL: ;UNLOAD DRIVE
STOPCD CPOPJ1##,DEBUG,NIF, ;++RNXKON ISN'T FANCY
SUBTTL CHECK DRIVE/CONTROLLER STATUS
;ROUTINE TO INSURE THAT THE RH20 AND DX20 ARE OK FOR THE OPERATION
;ABOUT TO BE DONE AND SETUP FOR THAT OPERATION.
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; T1/FUNCTION
; PUSHJ P,CONECT
;RETURN CPOPJ IF ERROR WITH:
; T1/ERROR BITS
; CPOPJ1 IF OK WITH:
; T1/FUNCTION
; T2/CYLINDER
; T3/TRACK/SECTOR IN .DXDAR FORMAT
; T4/NON-ZERO TO TOSS THIS COMMAND
CONECT: MOVEI T4,CO.MBE ;MAKE SURE PIA IS OFF AND MBE
XCT RNXCO4(J) ; IS ON
SKIPE T4,RNXCMD(J) ;COMMAND IN PROGRESS ALREADY?
RNXBP4: PUSHJ P,CMDWAT ;YES, WAIT FOR IT TO FINISH
JUMPN T4,CONEC2 ;GO IF TOSSING COMMAND
MOVSI T2,(RN.CLR) ;CLEAR TEMPORARY BITS
ANDCAM T2,RNXFLG(J) ; IN KDB
PUSHJ P,RNXIVI ;MAKE SURE RH20 HAS AN IVI
XCT RNXCI2(J) ;GET CONI IN T2
TRNE T1,CR.IOP ;TRYING TO DO I/O?
TRNN T2,CI.BSY!CI.DON ;YES, IS BUSY OR DONE UP?
JRST CONEC1 ;NO
;HERE WHEN WE ARE TRYING TO DO AN I/O OPERATION AND BUSY OR DONE
;IS STILL UP IN THE RH20 CONI. TRY TO FORCE THE RH20 INTO A
;REASONABLE STATE, FIRST GENTLY AND, IF THAT FAILS, BY BLASTING IT.
PUSH P,T1 ;SAVE FUNCTION
PUSHJ P,RDREG ;READ THE REGISTERS
POP P,T1 ;RESTORE FUNCTION
MOVSI T2,UNPHNG+UNPFIR ;IF NOT IN ERROR RECOVERY,
SKIPGE UNIECT(U) ; SET A FLAG
MOVEM T2,UNIECT(U) ; FOR FILIO
XCT RNXCI2(J) ;GET THE CONI BACK
MOVEI T4,CO.MBE!CO.STP ;GET BITS TO CLEAR BUSY, SET DONE
TRNE T2,CI.BSY ;IS BUSY STILL UP?
XCT RNXCO4(J) ;YES, ATTEMPT TO CLEAR IT
AOS UNIHNG(U) ;COUNT THE OCCURRANCE
MOVEI T2,CO.MBE!CO.CLR ;GET BITS TO CLEAR DONE
XCT RNXCO2(J) ;DO SO
XCT RNXCI2(J) ;GET THE CONI BACK
TRNE T2,CI.BSY ;IS BUSY STILL SET?
JRST CONERR ;YES, CALL THE DRIVE DOWN
TRNN T2,CI.DON ;HOW ABOUT DONE?
JRST CONEC1 ;CLEAR, CONTINUE WITH SETUP
PUSHJ P,CLRRH2 ;BLAST THE RH20
XCT RNXCI2(J) ;GET THE CONI BACK
TRNE T2,CI.BSY!CI.DON ;DID WE MANAGE TO CLEAR IT UP?
JRST CONERR ;NO, GIVE UP AND CALL IT OFFLINE
;HERE WHEN THE RH20 IS IN SOME KIND OF REASONABLE STATE TO START THE
;OPERATION. MAKE SURE THAT THE DX20 IS ALSO IN SOME REASONABLE STATE
;AND CONTINUE THE FINAL SETUP.
CONEC1: SETZ T4, ;LET THIS COMMAND GO THROUGH
CONEC2: PUSHJ P,MPRUN ;IS THE DX20 STILL RUNNING?
AOSA T2,RNXRSC(J) ;NO, COUNT THIS
JRST CONEC3 ;YES, CONTINUE
CAIG T2,MAXRSC ;ALREADY RESTARTED IT TOO MANY TIMES?
PUSHJ P,MPCHKS ;NO, TRY TO RESTART IT AGAIN
JRST CONMPS ;FAILED, CALL THE DRIVE OFF-LINE
CONEC3: JUMPN T4,CONEC5 ;DON'T TOUCH HARDWARE IF TOSSING COMMAND
TRNE T1,CR.IOP ;THIS AN I/O FUNCTION?
TRNE T1,CR.RED ;YES, A WRITE?
JRST CONEC4 ;NO, DON'T CARE ABOUT WRITE PROTECT
MOVSI T2,UNPHWP ;GET HARDWARE WRITE PROTECT BIT
TDNE T2,UNIDES(U) ;IS THE UNIT WRITE PROTECTED?
JRST CONHWP ;YES
CONEC4: MOVSI T2,UNPOFL ;GET OFF-LINE BIT (SET BY CHKERR)
TDNE T2,UNIDES(U) ;DRIVE OFF-LINE?
JRST CONOFL ;YES
PUSHJ P,SETDRV ;SETUP TO TALK TO THAT DRIVE
STORE T2,RNXCMD(J),CM.DVA ;STORE DRIVE ADDRESS
CONEC5: MOVE T2,UNIBLK(U) ;GET THE BLOCK WE WANT TO ACCESS
LDB T3,UNYBPY## ; AND THE NUMBER OF BLOCKS/CYLINDER
IDIVI T2,(T3) ;T2=CYLINDER, T3=REMAINDER
MOVEM T2,UNICYL(U) ;STORE IN UDB
HRLI T2,(.DXDCR) ;SETUP REGISTER SELECT FOR DCR
PUSH P,T2 ;SAVE CYLINDER
MOVE T2,T3 ;MOVE REMAINDER TO T2
LDB T3,UNYBPT## ;GET NUMBER OF BLOCKS PER TRACK
IDIVI T2,(T3) ;T2=TRACK, T3=BLOCK
STORE T2,T3,DA.TRK ;STORE IN CORRECT PLACE IN T3
HRLI T3,(.DXDAR) ;SETUP REGISTER SELECT FOR DAR
JRST T2POJ1## ;RESTORE T2 AND GIVE SKIP RETURN
;HERE WHEN AN ERROR WAS DETECTED IN EITHER THE RH20 OR DX20 DURING
;THE SETUP. READ THE REGISTERS AND RETURN AN ERROR INDICATION TO FILIO.
CONHWP: TDZA T1,T1 ;SET NO FLAGS IF WRITE PROTECTED
CONMPS: PUSHJ P,RNXSSB ;SET KOPMPS FOR KONTROLLER
CONOFL: PUSHJ P,RDREG ;READ THE REGISTERS
JUMPE T1,CPOPJ## ;GO IF HARDWARE WRITE PROTECTED
CONERR: MOVEI T1,KOPOFL ;SET BIT FOR OFF-LINE
POPJ P, ; AND RETURN
;ROUTINE TO CHECK IF THE RH20 HAS A PI
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXALV
;RETURN CPOPJ ALWAYS
RNXALV: XCT RNXCI2(J) ;CONI
TRNE T2,7 ;IS IT ALIVE?
POPJ P, ;YES
PUSHJ P,CLRRH2 ;NO, CLEAR THE RH
PJRST REASPI ;GIVE IT A PI AND RETURN
SUBTTL ERROR ANALYSIS ROUTINES
;ROUTINE TO CHECK TO SEE IF THE DX20 MICROCODE DETECTED AN ERROR
;IN THE LAST OPERATION.
;CALL:
; J/KDB ADDRESS
; T1/ERROR BITS
; P1/FLAGS FROM RNXCMD OR 0 IF NO OPERATION IN PROGRESS
; P2/ENDING STATUS REGISTER
; P3/CHANNEL STATUS OR 0,,CONI
; PUSHJ P,CHKERR
;RETURN CPOPJ ALWAYS WITH AC'S AS ABOVE AND:
; LH(P2)/ERROR REGISTER IF ERRORS
CHKERR: MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
PUSHJ P,DODTI ;READ IT
TRNN T2,ST.RUN ;IS MICROPROCESSOR STILL RUNNING?
JRST FTLERR ;NO
TRNN T2,ST.CER ;COMPOSITE ERROR UP?
POPJ P, ;NO, NO ERRORS
MOVSI T2,(.DXERR) ;POINT AT ERROR REGISTER
PUSHJ P,DODTI ;READ IT
HRLI P2,(T2) ;MOVE TO P2
TLNE P2,ER.ERR ;ANY GENERIC HARDWARE FAILURES?
TRO T1,IODERR ;YES, FLAG A DEVICE ERROR
TLNN P2,ER.UPE ;MICROPROCESSOR ERROR?
POPJ P, ;NO, CODE IS MEANINGLESS
LOAD T2,P2,<ER.ECC_^D18> ;GET ERROR CODE IN T2
CAIL T2,ERRTBL ;IN THE RANGE WE KNOW ABOUT?
JRST FTLERR ;NO, THAT'S FATAL
JRST @ERRTAB(T2) ;DISPATCH TO PROCESSING ROUTINE
;THE FOLLOWING TABLE GIVES THE DISPATCH ADDRESS FOR EACH CLASS OF ERROR.
ERRTAB: EXP FTLERR ;0 - UNKNOWN
EXP UDSERR ;1 - UNUSUAL DEVICE STATUS
EXP RLNERR ;2 - RECORD LENGTH ERROR
EXP SELERR ;3 - DEVICE SELECTION ERROR
EXP RCVERR ;4 - RECOVERABLE ERROR
EXP RTYERR ;5 - COMMAND RETRY REQUEST
EXP NRCERR ;6 - NON-RECOVERABLE ERROR
EXP LOGUPE ;7 - RETRY LOG INFORMATION, LOG IT
EXP FTLERR ;10 - FATAL ERROR
EXP FTLERR ;11 - MICRODIAGNOSTIC FAILURE
EXP RLDERR ;12 - MICROCODE RELOAD FOR INFORMATION
ERRTBL==.-ERRTAB
;HERE ON UNUSUAL DEVICE STATUS
UDSERR: TRNN P2,ES.UCK ;UNIT CHECK UP IN ENDING STATUS BYTE?
JRST RCVERR ;NO, JUST CALL IT RECOVERABLE
MOVEI T2,.ESSB0 ;INDEX INTO EST TO GET SENSE BYTES
PUSHJ P,RDEST ;READ SENSE BYTES 0-3
MOVEI T2,0 ;SHOULDN'T HAPPEN, DEFAULT TO ZERO BYTES
JUMPE P1,UDSER1 ;DON'T KNOW DRIVE IF NO OPERATION
MOVSI T3,UNPHWP ;GET WRITE PROTECT BIT
TLNE T2,(S1.WRI) ;WRITE INHIBITED?
IORM T3,UNIDES(U) ;YES, SET THE BIT IN THE UDB
TLNE T2,(S0.IRQ) ;INTERVENTION REQUIRED?
JRST SELERR ;YES, CALL THE DRIVE OFF-LINE
UDSER1: TLNE T2,(S0.DTC) ;DATA CHECK?
TROA T1,IODTER ;YES, CALL IT A DATA ERROR
TRO T1,IODERR ;NO, FLAG A DEVICE ERROR
MOVEI T2,.ESSB7 ;EST INDEX TO GET SENSE BYTE 7
PUSHJ P,RDEST ;READ IT (ACTUALLY 4-7)
MOVEI T2,0 ;SHOULDN'T HAPPEN, DEFAULT TO 0
ANDI T2,EB.S07 ;KEEP JUST THE ONE BYTE
CAIN T2,.S7ECC ;ECC ERROR?
TRO T1,IOECCX ;YES, SET BIT FOR FILIO
POPJ P, ;RETURN
;HERE ON A RECORD LENGTH ERROR
RLNERR: SKIPE DINITF## ;IN ONCE-ONLY?
TLNN P1,(CM.IO) ; AND DOING A READ?
JRST RLNER1 ;NO
TRNE T1,ALLERR ;ANY OTHER ERRORS DETECTED SO FAR?
POPJ P, ;YES, THEY TAKE PRECEDENCE
TDZ P3,[CS.SWC!CS.OVR!CI.OVR] ;NO, MUST BE ONCE READING THE
TLZA P2,-1 ; HOME BLOCKS OF A TOPS20 FORMATTED PACK
RLNER1: TRO T1,IODERR ;ELSE FLAG A DEVICE ERROR
POPJ P, ;RETURN
;HERE ON A DEVICE SELECTION ERROR
SELERR: MOVSI T3,UNPOFL ;GET OFF-LINE BIT
SKIPE P1 ;DON'T NO WHAT DRIVE IF NO OPERATION
IORM T3,UNIDES(U) ;MARK THE DRIVE OFF-LINE
;; PJRST RCVERR ;FALL INTO RCVERR
;HERE ON RECOVERABLE ERROR
RCVERR: TRO T1,IODERR ;FLAG DEVICE ERROR
POPJ P, ;RETURN
;HERE ON COMMAND RETRY REQUEST
RTYERR: TRO T1,IODERR ;FLAG DEVICE ERROR
MOVSI T2,(.DXFLG) ;POINT AT FLAG REGISTER
PUSHJ P,DODTI ;READ IT
TRZ T2,FA.RTY ;CLEAR RETRY REQUEST BIT
HRLI T2,(.DXFLG) ;SET TO CLEAR IT
PJRST DODTO ;CLEAR BIT AND RETURN
;HERE ON NON-RECOVERABLE ERROR
NRCERR:
;HERE ON FATAL ERROR OR UNKNOWN CODE
FTLERR: TRO T1,IODERR ;FLAG DEVICE ERROR
MOVSI T2,(RN.FTL) ;FLAG THIS FOR CALL TO RNXERR
IORM T2,RNXFLG(J) ; AS UNRECOVERABLE
POPJ P, ;RETURN
;HERE ON MICROCODE RELOAD. DETERMINE WHICH UNITS ON THIS DX20
;ARE OFFLINE WAITING FOR OPERATOR INTERVENTION AND GIVE A FREE
;ATTENTION INTERRUPT TO FILIO FOR THOSE DRIVES. THIS MEANS THAT
;RELOADING THE MICROCODE SHOULD BE SUFFICIENT TO RESTART ANY JOBS THAT
;ARE STOPPED WITH OFFLINE MESSAGES BECAUSE THE DX20 STOPPED.
RLDERR: PUSHJ P,LOGUPE ;LOG IT SINCE MPCHK WILL BLAST THE REGISTERS
PUSHJ P,MPCHKS ;MAKE SURE IT'S VALID MICROCODE
JRST FTLERR ;IT'S NOT, CALL IT FATAL
SETZM RNXRSC(J) ;CLEAR RESTART COUNTER
PUSHJ P,RNXCSB ;CLEAR THE BIT IN THE KDB
PUSHJ P,SAVE2## ;SAVE P1-P2
;HERE FOR EACH KDB ASSOCIATED WITH THIS DX20 WITH THE KDB ADDRESS IN
;J TO LOOK AT ALL UDB'S TO SEE IF WE SHOULD GIVE FILIO AN ATTENTION
;INTERRUPT FOR THE UNIT.
RLDER1: PUSH P,U ;SAVE U
MOVE P1,KDBIUN(J) ;GET AOBJN POINTER TO UDB TABLE
MOVEI P2,0 ;START WITH NO BITS TO SET
RLDER2: HRRZ U,(P1) ;GET THE NEXT KDB ADDRESS
JUMPE U,RLDER3 ;GO IF NO UDB
MOVE T2,UNISTS(U) ;GET THE UNIT STATUS FOR THIS UDB
MOVE T3,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
CAIE T2,OWCOD ;IS IT IN ONE OF THE STATES WAITING FOR
CAIN T2,OCOD ; OPERATOR INTERVENTION?
IOR P2,BITTBL##(T3) ;YES, SET THE CORRESPONDING BIT IN P2
RLDER3: AOBJN P1,RLDER2 ;LOOP FOR ALL UDB'S ON THIS KDB
IORM P2,RNXATN(J) ;SET THE APPROPRIATE ATTENTION BITS
JRST UPOPJ## ;RESTORE U AND RETURN
SUBTTL ERROR LOGGING ROUTINES
;ROUTINE TO READ THE "REGISTERS" INTO RNXEBK FOR THE RP20.
;ENTER AT RDREG FOR INTERNAL CALL.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXREG
;RETURN CPOPJ ALWAYS
;DESTROYS T2-T3
RNXREG: PUSHJ P,SETRH2 ;SET IVI, MBE, PIA
RDREG: PUSHJ P,SAVE2## ;SAVE P1-P2
MOVSI T2,(.DIPBA) ;POINT AT RH20 PBAR
PUSHJ P,DODTIC ;READ IT
MOVEM T2,KONEDB(J) ;STORE IN KDB
MOVSI T2,(.DIPTC) ;POINT AT RH20 PTCR
PUSHJ P,DODTIC ;READ IT
MOVEM T2,KONECR(J) ;STORE IN KDB
MOVE T2,KDBICP(J) ;GET ADDRESS OF LOGOUT AREA
MOVE T2,.CSICW(T2) ;GET INITIAL CHANNEL JUMP WORD
MOVEI T3,0 ;ASSUME NO IOWDS
TRNE T2,-1 ;ANY ADDRESS?
MOVE T3,0(T2) ;YES, GET FIRST CCW
MOVEM T3,RNXEBK+.EBCC1(J) ;STORE IT
TRNE T2,-1 ;ANY ADDRESS?
MOVE T3,1(T2) ;YES, GET SECOND CCW
MOVEM T3,RNXEBK+.EBCC2(J) ;STORE IT
HRLZ T2,KDBICP(J) ;GET LOGOUT AREA ADDRESS BACK
HRRI T2,RNXEBK+.EBCS0(J) ;MAKE IT A BLT POINTER
BLT T2,RNXEBK+.EBCS2(J) ;STORE LOGOUT AREA WORDS 0-2
MOVE T2,KDBCHN(J) ;GET ADDRESS OF CHANNEL DATA BLOCK
MOVE T3,CHNMPE(T2) ;GET COUNT OF MEMORY PARITY ERRORS
MOVEM T3,RNXEBK+.EBMPE(J) ;STORE IT
MOVE T3,CHNNXM(T2) ;GET COUNT OF NXM'S
MOVEM T3,RNXEBK+.EBNXM(J) ;STORE IT
HLRZ T2,KDBUNI(J) ;GET DX20 NUMBER
LSH T2,^D9 ;SHIFT BY 9 BITS
HRLM T2,RNXEBK+.EBTYP(J) ;STORE IN KDB
;CONTINUED ON THE NEXT PAGE
;CONTINUED FROM THE PREVIOUS PAGE
;HERE TO STORE THE MASSBUS REGISTERS IN THE KDB. WE ONLY SAVE THOSE
;REGISTERS SPECIFIED BY THE BIT TABLE MBRTBL.
MOVE T2,[.EBNMR,,.EBSMR-.EBMBR] ;GET POINTER TO MASSBUS REGS
MOVEM T2,RNXEBK+.EBMBR(J) ;STORE IN KDB
MOVEI P1,RNXEBK+.EBSMR(J) ;POINT TO START OF BLOCK
MOVE P2,[MBRTBL] ;GET BIT TABLE OF REGISTERS TO SAVE
RDREG1: JUMPGE P2,RDREG2 ;IF BIT NOT SET, DON'T SAVE THIS ONE
HLLZ T2,P1 ;GET REGISTER ADDRESS
CAMN T2,[.DXMIR] ;TRYING TO READ THE IR?
TDZA T2,T2 ;YES, DO IT LATER
PUSHJ P,DODTI ;READ IT
MOVEM T2,(P1) ;STORE IN BLOCK
HRRI P1,1(P1) ;BUMP BLOCK POINTER BY 1
RDREG2: ADD P1,[1B5] ;PLUS REGISTER ADDRESS BY 1
LSH P2,1 ;SHIFT BIT TABLE BY 1
JUMPN P2,RDREG1 ;LOOP IF MORE TO READ
PUSHJ P,REDMIR ;CONDITIONALLY READ THE IR REGISTER
;HERE TO STORE THE DX20 REGISTERS IN THE KDB. THE DX20 MUST BE RUNNING
;IN ORDER TO DO THIS SINCE WE REQUEST EACH REGISTER THROUGH THE
;EXTENDED STATUS TABLE.
PUSHJ P,MPRUN ;MICROPROCESSOR STILL RUNNING?
JRST RDREG5 ;NO, ZERO COUNT AND RETURN
MOVSI P1,-.EBNDR ;BUILD AOBJN POINTER TO REGISTERS
RDREG3: MOVEI T2,(P1) ;MOVE INDEX INTO EST TO T2 FOR RDEST
PUSHJ P,RDEST ;READ APPROPRIATE SENSE BYTES
JRST RDREG4 ;QUIT IF DX20 DIDN'T RESPOND
MOVEI T3,RNXEBK+.EBSDR(J) ;GET ADDRESS OF START OF BLOCK
ADDI T3,(P1) ;OFFSET INTO IT FOR THIS REGISTER
MOVEM T2,(T3) ;STORE REGISTER IN BLOCK
AOBJN P1,RDREG3 ;LOOP FOR ALL REGISTERS
RDREG4: MOVSS P1 ;PUT NUMBER OF REGISTERS IN LH
HRRI P1,.EBSDR-.EBDVL ;PUT OFFSET IN RH
TLNN P1,-1 ;IF COUNT IS ZERO,
RDREG5: MOVEI P1,0 ;ZERO THE WHOLE WORD
MOVEM P1,RNXEBK+.EBDVL(J) ;STORE IN KDB
POPJ P, ;RETURN
;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:
; J/KDB ADDRESS
; PUSHJ P,REDMIR
;RETURN CPOPJ ALWAYS
REDMIR: DMOVE T2,RNXEBK+.EBSMR+.EBM00(J) ;GET CONTROL AND STATUS REGS
TRNN T2,CR.GO ;IS GO STILL UP?
TRNE T3,ST.RUN ;NO, IS THE UCODE STILL RUNNING?
POPJ P, ;YES, DON'T READ THE REGISTER
MOVSI T2,(.DXPCR) ;SETUP TO READ THE PC REGISTER
PUSHJ P,DODTI ;DO SO
TRZ T2,PC.IRE ;TURN OFF IR ENABLE
HRLI T2,(.DXPCR) ;PUT THE REGISTER NUMBER BACK
PUSHJ P,DODTO ;WRITE OFF IR ENABLE
MOVSI T2,(.DXMIR) ;POINT TO IR REGISTER
PUSHJ P,DODTI ;READ IT
MOVEM T2,RNXEBK+.EBSMR+.EBM30(J) ;STORE WHERE IT BELONGS
POPJ P, ;RETURN
;ROUTINE TO CALL DAEMON TO LOG AN ERROR THAT FILIO WILL NOT, E.G.,
;POSITIONING ERRORS, MICRODIAGNOSTICS FAILURES WHILE NO OPERATION
;IS IN PROGRESS, ETC.
;CALL:
; J/KDB ADDRESS
; P1/FLAGS FROM RNXCMD
; P3/CHANNEL STATUS OR 0,,CONI
; PUSHJ P,LOGUPE
;RETURN CPOPJ ALWAYS
LOGUPE: SKIPE DINITF## ;IN ONCE-ONLY?
POPJ P, ;YES, CAN'T LOG THEM THIS EARLY
PUSHJ P,SAVT## ;SAVE T1-T4
PUSH P,U ; AND U
PUSH P,F ; AND F
MOVSI T2,1 ;COUNT THE NUMBER OF TIMES WE
ADDM T2,RNXEC1(J) ; WERE CALLED TO LOG AN ERROR
PUSHJ P,RDREG ;READ THE REGISTERS
HRRZ U,KDBIUN(J) ;GET BASE ADDRESS OF UDB TABLE
LOAD T2,P1,CM.UNF ;GET UNIT NUMBER FOR OPERATION
ADDI U,(T2) ;OFFSET TO CORRECT WORD IN TABLE
HRRZ U,(U) ;GET UDB ADDRESS
JUMPE U,FUPOPJ## ;QUIT IF NO UDB
SKIPL UNIECT(U) ;IF THIS UDB IS IN ERROR RECOVERY, DON'T
JRST FUPOPJ## ;OVERWRITE THE (MORE IMPORTANT) DATA
MOVEI F,DSKDDB## ;GET THE GENERIC DDB
PUSHJ P,FSTREG## ;COPY INITIAL REGISTERS TO UDB
PUSHJ P,LSTER## ; PLUS FINAL REGISTERS
MOVEM P3,UNISOF(U) ;STORE INITIAL CONI
MOVEM P3,UNIERR(U) ; AND FINAL CONI
MOVEI T1,.ERDPE ;GET CODE FOR DISK ERROR
HRL T1,F ;PUT DDB ADDRESS IN LH(T1)
PUSH P,J ;DAEEIM SMASHES J
PUSHJ P,DAEEIM## ;TELL DAEMON
POP P,J ;RESTORE J
JRST FUPOPJ## ;RESTORE F, U AND RETURN
;ROUTINE TO REQUEST AND THEN READ INFORMATION FROM THE TWO EXTENDED
;STATUS REGISTERS IN THE DX20. THE INFORMATION THAT IS RETURNED IS
;A FUNCTION OF THE VALUE OF THE STATUS INDEX WHICH IS AN INPUT ARGUMENT
;TO THIS ROUTINE.
;CALL:
; T2/STATUS INDEX
; J/KDB ADDRESS
; PUSHJ P,RDEST
;RETURN CPOPJ IF THE DX20 DIDN'T RESPOND TO THE HANDSHAKE
; CPOPJ1 IF WE GOT THE DATA WITH:
; T2/.DXES1,,.DXES2
RDEST: PUSHJ P,SAVE1## ;GET A REGISTER TO USE
IOR T2,[.DXESR!ES.SUI] ;SET REGISTER AND REQUEST UPDATE
PUSHJ P,DODTO ;ASK THE DX20 FOR THE REGISTERS
MOVEI P1,^D1000 ;TIME TO WAIT FOR THE BIT TO CLEAR
RDEST1: MOVSI T2,(.DXESR) ;POINT TO STATUS INDEX REGISTER
PUSHJ P,DODTI ;READ IT
TRNE T2,ES.SUI ;DID THE DX20 CLEAR THE BIT YET?
SOJG P1,RDEST1 ;NO, LOOP
JUMPLE P1,CPOPJ## ;RETURN NON-SKIP IF THE DX20 DIDN'T RESPOND
MOVSI T2,(.DXES2) ;POINT AT SECOND EXTENDED STATUS REGISTER
PUSHJ P,DODTI ;READ IT
PUSH P,T2 ;SAVE FOR LATER
MOVSI T2,(.DXES1) ;POINT AT FIRST REGISTER
PUSHJ P,DODTI ;READ IT
HRLM T2,0(P) ;STORE IN LH OF STACK LOCATION
JRST T2POJ1## ;GIVE SKIP RETURN WITH VALUE IN T2
SUBTTL MISCELLANEOUS SUPPORT SUBROUTINES
;ROUTINE TO SET .DXDNM TO THE DRIVE NUMBER OF THE DRIVE FOR WHICH
;WE ARE ABOUT TO PERFORM AN OPERATION.
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,SETDRV
;RETURN CPOPJ ALWAYS WITH:
; RH(T2)/DRIVE ADDRESS
;DESTROYS T3
SETDRV: MOVE T2,UDBPDN(U) ;PHYSICAL DRIVE NUMBER FROM UDB
LDB T3,RNYDCA ;GET CONTROL UNIT ADDRESS FROM KDB
LSH T3,4 ;POSITION IT
IOR T2,T3 ;BUILD FULL DRIVE ADDRESS
;; PJRST WDVNUM ;FALL INTO WDVNUM
;ROUTINE TO SET .DXDNM TO THE DRIVE NUMBER OF THE DRIVE FOR WHICH
;WE ARE ABOUT TO PERFORM AN OPERATION
;CALL:
; T2/DRIVE ADDRESS
; J/KDB ADDRESS
; PUSHJ P,WDVNUM
;RETURN CPOPJ ALWAYS WITH:
; RH(T2)/DRIVE ADDRESS
WDVNUM: HRLI T2,(.DXDNM) ;GET REGISTER TO WRITE
PJRST DODTO ;WRITE REGISTER AND RETURN
;ROUTINE TO WAIT FOR A COMMAND TO COMPLETE AND CALL RNXINR TO PROCESS
;IT BEFORE STARTING A NEW COMMAND.
;CALL:
; T1/CURRENT COMMAND
; T4/FLAGS FROM RNXCMD FOR OLD COMMAND
; U/UDB ADDRESS
; J/KDB ADDRESS
; PUSHJ P,CMDWAT
;RETURN CPOPJ ALWAYS WITH:
; T4/NON-ZERO TO TOSS THIS COMMAND
;PRESERVES T1, U
CMDWAT: AOS RNXEC2(J) ;COUNT NUMBER OF TIMES WE GOT HERE
JUMPGE T4,CMDWA2 ;GO IF PREVIOUS COMMAND NOT AN XFER
PUSHJ P,RDREG ;READ THE REGISTERS FOR THE DUMP
STOPCD CPOPJ##,DEBUG,KCP, ;++KDB COMMAND IN PROGRESS
CMDWA2: MOVEI T2,^D2000 ;WAIT FOR THE COMMAND
PUSHJ P,WGOCLR ; TO FINISH
JUMPLE T2,CMDWA3 ;JUMP IF GO STILL UP
PUSHJ P,SAVE3## ;RNXINR DESTROYS P1-P2
PUSH P,T1 ; AND T1
PUSH P,U ; AND U
PUSHJ P,RNXINR ;DO SUBSET OF INTERRUPT PROCESSING
POP P,U ;RESTORE U
SETZ T4, ;LET THIS COMMAND THROUGH
JRST TPOPJ## ;RESTORE T1 AND RETURN
;HERE IF THE GO BIT DIDN'T COME DOWN IN TIME.
;EXIT FROM THE NEW COMMAND WITHOUT DOING ANYTHING.
;WAIT FOR THE PREVIOUS COMMAND TO FINISH, THEN TELL
;FILIO THAT THE NEW COMMAND IS FINISHED (THIS IS A LIE).
;IF THE NEW COMMAND IS A TRANSFER, THEN TELL FILIO "POSITION DONE".
;FILIO WILL THINK HE'S IN THUNG RECOVERY AND WILL RE-ISSUE THE
;TRANSFER COMMAND.
;IF THE NEW COMMAND IS A POSITION, THEN TELL FILIO "RECAL DONE".
;FILIO WILL THINK HE'S IN PHUNG RECOVERY AND WILL RE-ISSUE THE
;POSITION COMMAND.
CMDWA3: MOVSI T4,(1B0) ;RECAL BIT (PHUNG RECOVERY)
CAIN T1,.DXCTR!.CRSRC;POSITION COMMAND?
IORM T4,UNISTS(U) ;YES, TELL FILIO "RECAL DONE"
MOVE T4,UDBPDN(U) ;PHYSICAL DRIVE NUMBER
MOVE T4,BITTBL##(T4) ;GET CORRESPONDING BIT
IORM T4,RNXATN(J) ;SET IN KDB FOR INTERRUPT
MOVSI T4,1 ;COUNT THIS EVENT
ADDM T4,RNXEC2(J) ; IN THE KDB
POPJ P, ;RETURN WITH T4 NON-ZERO
;ROUTINE TO WAIT FOR THE GO BIT TO CLEAR IN THE CONTROL REGISTER.
;CALL:
; J/KDB ADDRESS
; T2/LOOP COUNT TO WAIT BEFORE TIMING OUT
; PUSHJ P,WGOCLR
;RETURN CPOPJ ALWAYS WITH:
; T2/LOOP COUNT AT WHICH GO BIT CLEARED
;DESTROYS T2,T3
WGOCLR: PUSH P,T2 ;SAVE LOOP COUNT
WGOCL1: MOVSI T2,(.DXCTR) ;POINT AT CONTROL REGISTER
PUSHJ P,DODTI ;READ IT
TRNN T2,CR.GO ;GO BIT STILL UP?
JRST T2POPJ## ;NO, RETURN
SOSLE 0(P) ;DECREMENT LOOP COUNT
JRST WGOCL1 ;AND LOOP
AOS RNXEC1(J) ;COUNT NUMBER OF TIMES GO BIT DIDN'T CLEAR
JRST T2POPJ## ;TIMED OUT, RETURN ANYWAY
;ROUTINE TO CLEAR THE ATTENTION SUMMARY REGISTER FOR THIS DX20. WE
;ALSO CHECK TO MAKE SURE THAT NO SPURIOUS ATTENTION BITS HAVE COME UP
;FOR SOME OTHER DEVICE ON THIS RH20 AND MAKE SURE THAT THEY ARE
;CLEARED.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,CLRATN
;RETURN CPOPJ ALWAYS
;DESTROYS T2,T3
CLRATN: PUSH P,T4 ;SAVE T4 (SEE RNXCPY)
MOVEI T4,1 ;GET A BIT TO SHIFT
HLRZ T2,KDBUNI(J) ;GET DX20 MASSBUS UNIT NUMBER
LSH T4,(T2) ;SHIFT TO CORRECT POSITION
HRLS T4 ;COPY TO LH
TLC T4,AT.ATN ;MAKE IT ALL BUT THAT BIT IN LH
MOVSI T2,(.DXASR) ;SET TO READ ATTENTION SUMMARY REGISTER
PUSHJ P,DODTI ;READ IT
; TSNE T2,T4 ;ANY UNEXPECTED ATTENTION BITS SET?
; PUSHJ P,LOGUPE ;YES, LOG THIS AS AN ERROR
TRNN T2,AT.ATN ;ANY ATTENTION BITS TO CLEAR?
JRST CLRAT2 ;NO, EXIT
HRLI T2,(.DXASR) ;SET TO CLEAR THE BITS WE READ
PUSHJ P,DODTO ;CLEAR THE ATTENTION BITS
MOVSI T2,(.DXASR) ;SET TO READ THE REGISTER AGAIN
PUSHJ P,DODTI ;READ IT
TSNE T2,T4 ;STILL HAVE UNEXPECTED BITS SET?
JRST CLRAT1 ;YES, HAVE TO BLAST THE RH20 THEN
TDNN T2,T4 ;STILL HAVE THE DX20 BIT UP?
JRST CLRAT2 ;NO, EXIT
AOS T2,RNXAEC(J) ;INCREMENT RETRY COUNT OF TIMES TO CLEAR IT
TLZ T2,-1 ;CLEAR LEFT HALF
CAIG T2,ATNRTY ;FAIL TO CLEAR IT TOO MANY TIMES?
JRST T4POPJ## ;BELOW THE THRESHOLD, JUST EXIT
; PUSHJ P,LOGUPE ;LOG THIS AS AN ERROR
CLRAT1: MOVSI T2,1 ;INCREMENT THE LEFT HALF TO
ADDM T2,RNXAEC(J) ; INDICATE THAT WE DID SOMETHING
PUSHJ P,CLRRH2 ;BLAST THE RH20 TO CLEAR THE BITS
CLRAT2: HLLZS RNXAEC(J) ;CLEAR RH OF RETRY COUNT WORD
JRST T4POPJ## ;RESTORE T4 AND EXIT
;The calls to LOGUPE are not assembled because CLRATN is called from
;RNXCPY without P1 and P3 containing the data that LOGUPE wants in
;those ACs. We really need a BUGCHK mechanism for this kind of
;thing.
;ROUTINE TO CLEAR THE ERROR REGISTER IN THE DX20.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,CLRERG
;RETURN CPOPJ ALWAYS
;DESTROYS T2,T3
CLRERG: MOVSI T2,(.DXERR) ;POINT AT ERROR REGISTER
PJRST DODTO ;CLEAR IT AND RETURN
;ROUTINES TO SET/CLEAR KOPMPS IN THE KDB WHEN THE MICROPROCESSOR
;STOPS/RESTARTS.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNX?SB
;RETURN CPOPJ ALWAYS
;DESTROYS T2
RNXCSB::SKIPA T2,[ANDCAM T2,KONMPS(J)] ;GET INSTR TO CLEAR BIT
RNXSSB: MOVE T2,[IORM T2,KONMPS(J)] ;OR INSTR TO SET BIT
PUSH P,T2 ;SAVE INSTRUCTION
MOVSI T2,KOPMPS ;GET THE BIT
XCT 0(P) ;SET/CLEAR IT
JRST T2POPJ## ;BRING STACK INTO PHASE AND RETURN
;ROUTINE TO READ THE DRIVE TYPE REGISTER FOR THE DX20 AND CHECK
;TO MAKE SURE THAT IT IS CORRECT FOR THE RP20.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,CHKDTR
;RETURN CPOPJ IF NOT A DX20 FOR AN RP20
; CPOPJ1 IF MATCH WITH:
; T2/CONTENTS OF REGISTER
CHKDTR: MOVSI T2,(.DXDTR) ;POINT AT DRIVE TYPE REGISTER
PUSHJ P,DODTI ;READ IT
PUSH P,T2 ;SAVE FOR RETURN
ANDI T2,DT.COD ;MASK OFF JUST THE DRIVE TYPE
CAIN T2,.DTCOD ;DOES IT MATCH?
AOS -1(P) ;YES, GIVE SKIP RETURN
PJRST T2POPJ ;RETURN VALUE IN T2
;ROUTINE TO ASSIGN AN INTERRUPT VECTOR ADDRESS TO THE RH20 AND
;GIVE IT A PIA WITH OR WITHOUT ATTENTION INTERRUPT ENABLE DEPENDING
;ON WHAT'S HAPPENING.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,SETRH2
;RETURN CPOPJ ALWAYS
;PRESERVES ALL AC'S
SETRH2: PUSHJ P,RNXIVI ;ASSIGN IVI, ENABLE MASSBUS
; PJRST REASPI ;FALL INTO REASPI
;ROUTINE TO REASSIGN THE PIA FOR THE RH20 WITH OR WITHOUT ATTENTION
;INTERRUPT ENABLE DEPENDING ON WHAT'S HAPPENING.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,REASPI
;RETURN CPOPJ ALWAYS
;PRESERVES ALL AC'S
REASPI: PUSH P,T4 ;SAVE T4
PUSHJ P,SETCO ;SETUP CONO MASK
XCT RNXCO4(J) ;LIGHT PIA, POSSIBLY AIE
JRST T4POPJ## ;RESTORE T4 AND RETURN
;ROUTINE TO FORCE THE RH20 AND CONNECTED DEVICES INTO A KNOWN STATE.
;THIS INVOLVES DOING A MASSBUS INIT, A STOP TRANSFER, AND A CLEAR
;DONE. WE THEN HAVE TO REASSIGN THE RH20 IVI AND RESTART THE MICRO-
;PROCESSOR.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,CLRRH2
;RETURN CPOPJ ALWAYS
CLRRH2: MOVEI T2,CO.MBI ;THE ONLY THING LEFT TO DO IS TO
XCT RNXCO2(J) ; BLAST THE RH20. DO A MASSBUS INIT FIRST
MOVEI T2,CO.MBE!CO.STP ;THEN A
XCT RNXCO2(J) ; STOP TRANSFER
MOVEI T2,CO.MBE!CO.CLR ;AND FINALLY A
XCT RNXCO2(J) ; CLEAR DONE
PUSHJ P,RNXIVI ;GIVE IT AN IVI AGAIN SINCE MBI BLASTS IT
PJRST RNXMPS ;START THE MICROPROCESSOR GOING AGAIN
;ROUTINE TO ASSIGN AN INTERRUPT VECTOR ADDRESS TO THE RH20.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXIVI
;RETURN CPOPJ ALWAYS
;PRESERVES ALL AC'S
RNXIVI: PUSHJ P,SAVT## ;SAVE T1-T4
MOVEI T2,CO.MBE ;ENABLE MASSBUS TRANSCEIVERS
XCT RNXCO2(J) ; FIRST
MOVEI T2,40+DSKCHN##_1 ;COMPUTE INTERRUPT ADDRESS
HRLI T2,(.DOIVI) ;POINT TO PROPER REGISTER
PJRST DODTO ;WRITE REGISTER AND RETURN
;ROUTINE TO SETUP A CONO MASK WITH THE PIA AND POSSIBLY ATTENTION
;INTERRUPT ENABLE IF NO TRANSFER IS TAKING PLACE.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,SETCO
;RETURN CPOPJ ALWAYS WITH:
; T4/CONO MASK
SETCO: MOVEI T4,CO.MBE+DSKCHN## ;SET TO ENABLE MASSBUS TRANSCEIVERS
SKIPL RNXCMD(J) ;TRANSFER IN PROGRESS?
TRO T4,CO.AIE ;NO, ALLOW INTERRUPTS ON ATTENTIONS
POPJ P, ;RETURN
;ROUTINE TO SET A BIT IN RNXATN CORRESPONDING TO A DRIVE NUMBER
;WHICH JUST COMPLETED A POSITION OPERATION.
;CALL:
; T2/DRIVE NUMBER (ALL 4 BITS)
; PUSHJ P,POSDON
;RETURN CPOPJ ALWAYS
POSDON: MOVE T3,BITTBL##(T2) ;GET THE APPROPRIATE BIT
IORM T3,RNXATN(J) ;SET BIT IN KDB
HRRZ T3,T2 ;COPY 4 BIT DRIVE ADDRESS
ADD T3,KDBIUN(J) ;POINT AT UDB ADDRESS SLOT IN KDB
SKIPN T3,(T3) ;GET UDB ADDRESS
JRST POSDO3 ;NO UDB, CALL NEWDSK
MOVSI T2,UNPHWP ;GET HARDWARE WRITE PROTECT BIT
SKIPE T4,UNISTS(T3) ;UNIT IDLE?
CAIL T4,OWCOD ; OR SOME FORM OF OPERATOR WAIT?
ANDCAM T2,UNIDES(T3) ;CLEAR HARDWARE WRITE PROTECT BIT
POPJ P, ;RETURN
;HERE IF THERE WAS NO UDB FOR THE DRIVE. CALL NEWDSK TO TELL THE
;MONITOR THAT A NEW DRIVE JUST CAME ON-LINE. T2 CONTAINS THE 4 BIT
;DRIVE ADDRESS OF THE UNIT THAT CAME ON-LINE.
POSDO3: PUSH P,T2 ;SAVE DRIVE NUMBER
MOVE T2,BITTBL##(T2) ;GET ASSOCIATED BIT
IORM T2,RNXNUM(J) ;TELL ONCE A SECOND CODE WHAT TO DO
HRROS KDBNUM(J) ;FLAG IT FOR OUTSIDE WORLD TOO
POP P,T2 ;RESTORE T2
POPJ P, ;AND RETURN
SUBTTL INITIALIZATION SUPPORT SUBROUTINES
;ROUTINE TO DO TWO TEST I/O COMMANDS TO A PARTICULAR DRIVE TO SEE
;IF IT IS ON-LINE. TWO COMMANDS ARE REQUIRED BECUASE SOMETIMES THE
;8000 LIES AND SAYS THE DRIVE IS ON-LINE WHEN IT ISN'T AND THE FIRST
;ATTEMPT TO ACCESS THE DRIVE CAUSES OFF-LINE MESSAGES. TWO TEST I/O'S
;ALWAYS SEEM TO WORK (IF YOU BELIEVE...)
;CALL DOTIOC IF THE CONTROLLER AND DRIVE NUMBERS HAVE ALREADY BEEN
;WRITTEN INTO MASSBUS REGISTER .DXDNM. THIS ENTRY POINT DOES NOT
;REQUIRE THAT U BE SETUP TO THE UDB ADDRESS.
;CALL:
; U/UDB ADDRESS
; J/KDB ADDRESS
; PUSHJ P,DO2TIO
;RETURN CPOPJ IF THE DX20 DIDN'T RESPOND
; CPOPJ1 IF IT PROCESSED BOTH COMMANDS
DO2TIO: PUSHJ P,SETDRV ;SETUP TO TALK TO THE DRIVE
DOTIOC: MOVSI T2,<(.DXFLG)>+INSVL.(.FATIO,FA.FNC) ;TELL THE DX20
PUSHJ P,DODTO ; THAT IT'S A TEST I/O
PUSHJ P,DO2TI1 ;DO THE FIRST TEST I/O
POPJ P, ;RETURN IF THE DX20 DIDN'T RESPOND
DO2TI1: PUSHJ P,CLRERG ;CLEAR THE ERROR REGISTER
MOVEI T2,.DXCTR!.CRNOP ;NO-OP IS THE GENERIC COMMAND
PUSHJ P,DODTO ;START IT GOING
MOVEI T2,^D5000 ;MAX TIME TO WAIT FOR IT TO FINISH
PUSHJ P,WGOCLR ;WAIT FOR THE GO BIT TO CLEAR
JUMPG T2,CPOPJ1## ;GIVE SKIP RETURN IF THE BIT CLEARED
POPJ P, ;NON-SKIP IF IT DIDN'T
;ROUTINE TO CHECK FOR ERRORS IN THE TEST I/O SEQUENCE DONE TO
;SEE IF A UNIT IS ON-LINE.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,INIERR
;RETURN CPOPJ IF DRIVE IS ON-LINE
; CPOPJ1 IF DRIVE EXISTS BUT IS OFF-LINE
; CPOPJ2 IF DRIVE DOESN'T EXIST
INIERR: MOVSI T2,(.DXERR) ;POINT TO THE ERROR REGISTER
PUSHJ P,DODTI ;READ IT
TRNN T2,ER.UPE!ER.STP!ER.ERR ;ANY ERRORS SEEN?
POPJ P, ;NO, DRIVE IS ON-LINE
LOAD T2,T2,ER.ECC ;GET ERROR CLASS CODE
CAIE T2,.ERSEL ;WAS IT SELECT ERROR?
JRST CPOPJ1## ;NO, IT EXISTS BUT IT'S OFF-LINE
JRST CPOPJ2## ;ELSE IT DOESN'T EXIST
;AUTOCONFIGURE
;ENTERED WITH DEVICE CODE/4 IN T1, AND CONI DEV, IN T2
RNXCFG: 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,SAVE3## ;SAVE SOME ACS
SETZB P1,P2 ;MASSBUS UNIT NUMBER 0, DRIVE 0 & COUNT
RNXCF1: PUSHJ P,RNXUNI ;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 RNXCF1 ;LOOP BACK FOR ANOTHER
SKIPN P2 ;FOUND AT LEAST A KDB?
AOS (P) ;NO--MUST TRY ANOTHER DRIVER
POPJ P, ;RETURN
;AUTOCONFIGURE A SINGLE MASSBUS UNIT
RNXUNI: PUSHJ P,RDDTR## ;READ DRIVE TYPE REGISTER
CAIE T2,TY.DXB ;IS IT A DX20/DISK?
POPJ P, ;NO--GIVE UP
MOVSI T1,CP.RH2 ;RH20 CHANNEL
PUSHJ P,AUTCHN## ;BUILD A CHANNEL DATA BLOCK
POPJ P, ;NO CORE
HLRZ T1,P1 ;GET MASSBUS UNIT NUMBER
MOVEI T2,TYPRN ;UNIT TYPE CODE
PUSHJ P,DSKKON## ;BUILD A DISK KDB
POPJ P, ;GIVE UP IF NO CORE
AOS P2 ;REMEMBER WE FOUND AT LEAST A KDB
MOVSI T1,-<RNXIOE-RNXIOB> ;NUMBER OF WORDS TO CHECK
XMOVEI T2,RNXIOB(J) ;STARTING WORD
HRRZ T3,.CPDVC## ;<DEVICE CODE>/4
PUSHJ P,AUTDVC## ;SET DEVICE CODES
MOVE T1,KDBCSO(J) ;GET CONSO SKIP CHAIN ADDRESS
MOVEI T2,CI.RAE!CI.ATN!CI.DON ;AND INTERRUPT FLAGS
HRRM T2,DICDIF##(T1) ;SET THEM
RNXUN1: PUSHJ P,MPRES ;RESET THE MICROPROCESSOR
PUSHJ P,RNXRLD ;LOAD THE MICROCODE
POPJ P, ;GIVE UP
HRRZS P2 ;CLEAR VALID DCU FLAG (SIGN BIT)
MOVSI P3,-MAXDCU ;INIT DCU NUMBER
RNXUN2: PUSHJ P,RNXDRV ;AUTOCONFIGURE A SINGLE DRIVE
JFCL ;IGNORE ERRORS
HRRZ T1,P1 ;GET DRIVE NUMBER
CAIGE T1,RNXDMX-1 ;DONE ALL DRIVES?
AOJA P1,RNXUN2 ;LOOP BACK FOR MORE
POPJ P, ;ALL DONE
;AUTOCONFIGURE A SINGLE DRIVE
RNXDRV: HRRZ T1,P1 ;GET UNIT
MOVE T1,BITTBL##(T1) ;AND IT'S BIT
TDNE T1,RNXIUM(J) ;WANT TO IGNORE THIS DRIVE?
POPJ P, ;SAY IT DOESN'T EXIST
HRRZ T1,P3 ;GET DCU NUMBER
LSH T1,4 ;POSITION
HRRZ T2,P1 ;GET PHYSICAL DRIVE NUMBER
IOR T2,T1 ;MERGE WITH MASSBUS UNIT
HRLI T2,(.DXDNM) ;DRIVE NUMBER REGISTER
PUSHJ P,DODTO ;WRITE IT
PUSHJ P,DOTIOC ;DO TWO TEST I/O'S ON THE DRIVE
POPJ P, ;DX20 DIDN'T RESPOND, GIVE UP
PUSHJ P,INIERR ;CHECK FOR ERRORS
JRST RNXDR1 ;DRIVE ONLINE
JRST RNXDR1 ;DRIVE OFFLINE
JUMPL P2,CPOPJ## ;JUST GIVE UP IF DCU IS VALID
AOBJN P3,RNXDRV ;TRY ANOTHER DCU
POPJ P, ;NON-EXISTANT DRIVE
RNXDR1: TLO P2,400000 ;REMEMBER DCU IN RH OF P3 IS VALID
DPB P3,RNYDCA ;STORE DCU ADDRESS
HRLZ T1,P1 ;PHYSICAL DRIVE NUMBER
HRR T1,P1 ;UDB TABLE INDEX
MOVSI T2,(1B0) ;NON-REMOVABLE MEDIA, UNIT TYPE = RP20
PUSHJ P,DSKDRV## ;BUILD AND LINK THE UDB
POPJ P, ;NO CORE
LDB T1,RNYDCA ;GET DCU NUMBER
LSH T1,4 ;POSITION
HRRZ T2,P1 ;GET PHYSICAL DRIVE NUMBER
IOR T2,T1 ;BUILD FAKE DRIVE S/N SINCE IT CAN'T BE READ
SETZ T1, ;REALLY A ONE-WORD QUANTITY
DMOVEM T1,UDBDSN(U) ;SET SERIAL NUNBER IN UDB
JRST CPOPJ1## ;RETURN
SUBTTL KONTROLLER ONCE-A-SECOND CODE
;ROUTINE TO CHECK THE MICROPROCESSOR
;CALL: PUSHJ P,RNXSEC
;RETURN CPOPJ ALWAYS
RNXSEC: MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
PUSHJ P,DODTI ;READ IT
TRNE T2,ST.RUN ;IS MICROPROCESSOR STILL RUNNING?
JRST RNXSE1 ;SEE IF DRIVES TO CONFIGURE
SKIPG KONRLD(J) ;NOT RUNNING--OK TO ATTEMPT RELOAD?
POPJ P, ;RETURN
PJRST RNXRLD ;GO RELOAD MICROPROCESSOR
RNXSE1: SKIPL @KDBCHN(J) ;CHANNEL BUSY?
POPJ P, ;LEAVE IT ALONE
SKIPE T1,RNXNUM(J) ;GET BIT MASK
JFFO T1,RNXSE2 ;FIND FIRST UNIT NUMBER
HRRZS KDBNUM(J) ;INDICATE NO DRIVES TO CONFIGURE
POPJ P, ;DONE
RNXSE2: PUSHJ P,AUTLOK## ;GET AUTCON INTERLOCK
POPJ P, ;TRY AGAIN NEXT TIME
PUSHJ P,SAVW## ;PRESERVE W
MOVE W,J ;COPY KDB ADDRESS TO W FOR AUTCON
PUSH P,T2 ;SAVE PHYSICAL DRIVE NUMBER
MOVE T1,KDBDVC(J) ;DEVICE CODE
XMOVEI T2,RNXDSP ;DISPATCH
MOVE T3,KDBCHN(J) ;CHANNEL DATA BLOCK
PUSHJ P,AUTSET## ;SET UP CPU VARIABLES
HLLZ P1,KDBUNI(J) ;GET MASSBUS UNIT NUMBER FOR DX20
MOVSI P2,(1B0) ;INDICATE DCU IS VALID
LDB P3,RNYDCA ;GET DCU NUMBER
PUSHJ P,RNXDRV ;CONFIGURE A NEW UNIT
JFCL ;IGNORE ERRORS
PJRST AUTULK## ;RELEASE AUTCON INTERLOCK AND RETURN
SUBTTL MICROPROCESSOR HANDLING ROUTINES
;ROUTINE TO CHECK THE VALIDITY OF THE MICROPROCESSOR CONTROL STORE.
;THIS INVOLVES CHECKING THREE THINGS AS FOLLOWS:
; 1. CRAM LOCATION 7 MUST CONTAIN A COPY OF THE DRIVE TYPE REGISTER
; 2. CRAM LOCATION 10 MUST CONTAIN AN OCTAL 210 (.CRM10)
; 3. DX.IPE MUST NOT COME UP WHILE READING ANY OF THE ABOVE
;STORES THE MICROCODE VERSION NUMBER IN THE KDB(S) FOR THE DX20.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,MPCHK
;RETURN CPOPJ IF AN ERROR IS DETECTED
; CPOPJ1 IF ALL OK
;PRESERVES T1
MPCHK: PUSHJ P,MPRES ;RESET THE MICROPROCESSOR
MOVE T2,[.DXPCR!PC.IRE!PC.PCE!PC.PCI!INSVL.(7,PC.MPC)] ;REGISTER TO WRITE+
; IR ENABLE+PC ENABLE+PC AUTO INCR+PC TO READ
PUSHJ P,DODTO ;WRITE THE REGISTER
MOVSI T2,(.DXMIR) ;POINT AT IR REGISTER
PUSHJ P,DODTI ;READ THE CONTENTS
PUSH P,T2 ;SAVE FOR COMPARE
MOVSI T2,(.DXDTR) ;POINT AT DRIVE TYPE REGISTER
PUSHJ P,DODTI ;READ THAT
POP P,T3 ;RESTORE CRAM LOCATION 7
CAME T2,T3 ;HAVE TO BE THE SAME
POPJ P, ;ERROR IF NOT
MOVSI T2,(.DXIPE) ;POINT AT DIAGNOSTIC REGISTER 7
PUSHJ P,DODTI ;READ IT
TRNE T2,DX.IPE ;IR PARITY ERROR ON LAST READ?
POPJ P, ;YES, THAT'S AN ERROR
MOVSI T2,(.DXMIR) ;POINT AT DIAGNOSTIC REGISTER 0 AGAIN
PUSHJ P,DODTI ;READ CRAM LOC 10 (PC AUTO INCR SET)
CAIE T2,.CRM10 ;MUST BE THIS VALUE
POPJ P, ;NOT, ERROR
MOVSI T2,(.DXIPE) ;POINT AT DIAGNOSTIC REGISTER 7
PUSHJ P,DODTI ;READ IT
TRNE T2,DX.IPE ;IR PARITY ERROR ON LAST READ?
POPJ P, ;YES, THAT'S AN ERROR
MOVE T2,[.DXPCR!PC.IRE!PC.PCE!INSVL.(0,PC.MPC)] ;SET TO READ CRAM LOC 0
PUSHJ P,DODTO ;TELL THE DX20
MOVSI T2,(.DXMIR) ;ANSWER APPEARS HERE
PUSHJ P,DODTI ;READ VERSION NUMBER
MOVEM T2,RNXEBK+.EBTYP(J) ;STORE MP VERSION IN KDB
JRST CPOPJ1## ;GIVE SKIP RETURN
;ROUTINE TO CHECK THE VALIDITY OF THE MICROPROCESSOR CONTROL STORE AND
;START IT IF NO ERRORS ARE DETECTED.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,MPCHKS
;RETURN CPOPJ IF AN ERROR IS DETECTED
; CPOPJ1 WITH MICROPROCESSOR RESTARTED
;PRESERVES T1
MPCHKS: PUSHJ P,MPCHK ;CHECK THE CONTROL STORE
POPJ P, ;ERROR DETECTED
AOS 0(P) ;GIVE SKIP RETURN
;; PJRST RNXMPS ;FALL INTO RNXMPS
;ROUTINE TO START THE MICROPROCESSOR AT .DXSAD.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXMPS
;RETURN CPOPJ ALWAYS
RNXMPS: PUSHJ P,MPRES ;RESET THE MICROPROCESSOR
MOVE T2,[.DXPCR!PC.IRE!PC.PCE!PC.PCI!INSVL.(.DXSAD,PC.MPC)]
;POINT TO REGISTER AND SET BITS
PUSHJ P,DODTO ;TELL MP ITS START ADDRESS
MOVE T2,[.DXMTR!MR.STR] ;SET START BIT IN MAINTENANCE REG
PJRST DODTO ;START IT AND RETURN
;ROUTINE TO RESET THE MICROPROCESSOR
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,MPRES
;RETURN CPOPJ ALWAYS
MPRES: MOVE T2,[.DXMTR!MR.RES] ;SET RESET BIT IN MAINT REG
PJRST DODTO ;WRITE REGISTER AND RETURN
;ROUTINE TO SEE IF THE DX20 MICROCODE IS STILL RUNNING.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,MPRUN
;RETURN CPOPJ IF NOT RUNNING
; CPOPJ1 IF RUNNING
;DESTROYS T2,T3
MPRUN: MOVSI T2,(.DXSTR) ;POINT AT STATUS REGISTER
PUSHJ P,DODTI ;READ IT
TRNE T2,ST.RUN ;IS IT RUNNING?
AOS 0(P) ;YES
POPJ P, ;RETURN
;ROUTINE TO CHECK THE VALIDITY OF THE MICROPROCESSOR CONTROL STORE
;AND ATTEMPT TO RELOAD IT IF IT IS BAD. RETURNS WITH THE
;MICROPROCESSOR STARTED.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,MPINI
;RETURN CPOPJ IF COULDN'T VERYIFY, RELOAD, OR START IT
; CPOPJ1 WITH THE PROCESSOR RUNNING
MPINI: PUSHJ P,MPCHKS ;CHECK INTEGRETY OF MP CONTROL STORE
JRST RNXRLD ;BAD, TRY TO RELOAD IT
JRST CPOPJ1## ;GIVE SKIP RETURN
; ENABLE/DISABLE MICROCODE LOADING
RNXEDL: SE1ENT ;ENTER SECTION ONE
HRRZS J ;REMOVE JUNK IN LH
MOVE T2,T1 ;COPY BIT
XMOVEI T1,RNXULB(W) ;POINT TO UCODE LOADER BLOCK IN KDB
PJRST BTUEDL## ;ENABLE OR DISABLE
;ROUTINE TO RELOAD THE DX20 MICROCODE IF IT IS FOUND BAD. CALLED
;VIA THE KONRLD KDB DISPATCH AND FROM MPINI INTERNALLY. RETURNS
;WITH THE MICROPROCESSOR STARTED.
;CALL:
; J/KDB ADDRESS
; PUSHJ P,RNXRLD
;RETURN CPOPJ IF COULDN'T VERIFY, RELOAD OR START MICROPROCESSOR
; CPOPJ1 WITH THE PROCESSOR RUNNING
RNXRLD: SE1ENT ;ENTER SECTION ONE
PUSHJ P,SAVW## ;SAVE W
MOVE W,J ;LOAD UP KDB ADDRESS
HRRZS KONRLD(J) ;ASSUME RELOAD WILL SUCCEED
XMOVEI T1,RNXULB(J) ;POINT TO MICROCODE LOADER BLOCK
PUSHJ P,DXLOAD## ;TRY TO RELOAD AND VERIFY THE DX20
SKIPA ;FAILED
JRST CPOPJ1## ;GIVE SKIP RETURN
HRROS KONRLD(J) ;INDICATE RELOAD FAILED
POPJ P, ;AND RETURN
SUBTTL ROUTINES TO ACCESS MASSBUS REGISTERS
;ROUTINE TO WRITE ONE MASSBUS REGISTER.
;CALL:
; T2/DATAO ARGUMENT
; J/KDB ADDRESS
; PUSHJ P,DODTO
;RETURN CPOPJ ALWAYS
;DESTROYS T3
DODTO: HLRZ T3,KDBUNI(J) ;GET THE MASSBUS UNIT NUMBER OF THE DX20
TLO T2,<(DO.LDR!DO.DRE)>(T3) ;DRIVE NUMBER, LOAD REG, DISABLE RAE
XCT RNXDO2(J) ;DO THE DATAO
XCT RNXRAE(J) ;DID IT RESULT IN AN RAE?
AOSA RNXRAC(J) ;YES, INCREMENT COUNT AND RETRY
POPJ P, ;NO, RETURN
PUSH P,T4 ;SAVE T4
MOVEI T3,^D10 ;RETRY OPERATION 10 TIMES
MOVEI T4,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
DODTO1: XCT RNXCO4(J) ;CLEAR THE ERROR
XCT RNXDO2(J) ;RETRY THE OPERATION
XCT RNXRAE(J) ;STILL HAVE AN ERROR?
SOJG T3,DODTO1 ;YES, LOOP BUT NOT TOO MANY TIMES
XCT RNXCO4(J) ;INSURE THAT RAE IS CLEARED
JRST T4POPJ## ;RESTORE T4 AND RETURN
;ROUTINE TO READ A DRIVE OR CONTROLLER REGISTER.
;CALL:
; T2/DATAO ARGUMENT TO LOAD PREPARATION REGISTER
; J/KDB ADDRESS
; PUSHJ P,DODTI
;RETURN CPOPJ ALWAYS WITH:
; T2/16 BITS OF RETURNED DATAI
;DESTROYS T3
DODTI: HLRZ T3,KDBUNI(J) ;GET MASSBUS UNIT NUMBER OF DX20
TLO T2,<(DO.DRE)>(T3) ;INSERT NUMBER AND DISABLE RAE
XCT RNXDO2(J) ;SETUP THE PREPARATION REGISTER
PUSH P,T2 ;SAVE THE ARGUMENT
STALL ;WAIT FOR THINGS TO SETTLE
XCT RNXDI2(J) ;READ THE VALUE
XCT RNXRAE(J) ;DID WE GET AN RAE?
JRST DODTI2 ;YES, TRY TO RECOVER
DODTI1: POP P,(P) ;BRING STACK INTO PHASE
ANDI T2,177777 ;RETURN ONLY DATA BITS
POPJ P, ;RETURN
DODTI2: MOVSI T3,1 ;ASSUME CONTROL BUS PARITY ERROR
TLNN T2,(DI.TRA) ;DID TRA COME UP?
MOVEI T3,1 ;NO, MUST BE NON-EXISTENT DRIVE
ADDM T3,RNXRAC(J) ;INCREMENT CORRECT COUNT
PUSH P,T4 ;SAVE T4
MOVEI T3,^D10 ;RETRY OPERATION 10 TIMES
MOVEI T4,CO.MBE!CO.RAE ;MASSBUS ENABLE PLUS CLEAR RAE
DODTI3: XCT RNXCO4(J) ;CLEAR THE ERROR
MOVE T2,-1(P) ;GET DATAO ARGUMENT BACK
XCT RNXDO2(J) ;SETUP THE PREPARATION REGISTER AGAIN
STALL ;WAIT FOR THINGS TO SETTLE
XCT RNXDI2(J) ;READ THE VALUE
XCT RNXRAE(J) ;STILL HAVE THE ERROR?
SOJG T3,DODTI3 ;YES, LOOP
XCT RNXCO4(J) ;MAKE SURE THE RAE IS CLEARED
POP P,T4 ;RESTORE T4
JRST DODTI1 ;RETURN TO THE USER
;ROUTINE TO READ A CONTROLLER REGISTER
;CALL:
; T2/DATAO ARGUMENT TO LOAD PREPARATION REGISTER
; J/KDB ADDRESS
; PUSHJ P,DODTIC
;RETURN CPOPJ ALWAYS WITH:
; T2/36 BITS OF RETURNED DATAI
DODTIC: XCT RNXDO2(J) ;SETUP THE PREPARATION REGISTER
XCT RNXDI2(J) ;READ THE DATA
POPJ P, ;RETURN
END