Trailing-Edge
-
PDP-10 Archives
-
bb-bt99q-bb
-
rnxkon.x23
There is 1 other file named rnxkon.x23 in the archive. Click here to see a list.
TITLE RNXKON -- DRIVER FOR RP20'S V074
SUBTTL G.M. UHLER/GMU 25-APRIL-89
SEARCH F,S,DEVPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY BE USED
; OR COPIED ONLY IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
;COPYRIGHT (c) DIGITAL EQUIPMENT CORPORATION 1980,1982,1984,1986,1988.
;ALL RIGHTS RESERVED.
.CPYRT<1980,1988>
XP VRNKON,074
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.
;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>
.EBNMR==RNVNMR ;NUMBER OF MASSBUS REGISTERS
.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
>
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==RNVEBK ;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
PUSHJ P,SAVJW## ;AND KONTROLLER POINTERS
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
MOVE W,J ;MOVE KDB POINTER FOR ERROR ROUTINE
SETZ J, ;BLAME JOB 0
MOVEI T4,(F) ;'SOFT CODE' FOR THIS CASE
AOS SYSERR## ;IT'S A SYSTEM ERROR
PUSHJ P,RNXELG ;TELL DAEMON
JRST FUPOPJ## ;RESTORE F, U AND RETURN
;ROUTINE CALLED FROM FILIO TO NOTIFY OF DAEMON OF AN ERROR WITH A
;SYSTEM ERROR BLOCK. SEE MDEERR IN FILIO FOR CALLING SEQUENCE DETAILS.
RNXELG: MOVEI T1,45+1 ;TABLE ENTRIES PLUS FILSER CODE
HLRZ T2,UNIEBK+.EBMBR(U) ;GET NUMBER OF MASSBUS REGS SAVED
ADDI T1,(T2) ;INCLUDE IN DESIRED LENGTH
HLRZ T2,UNIEBK+.EBDVL(U) ;GET NUMBER OF DEVICE REGS SAVED
ADDI T1,(T2) ;INCLUDE THAT, TOO
PUSH P,T4 ;SAVE FILIO'S CODE
PUSH P,T1 ;AND THE TOTAL LENGTH WE REQUESTED
PUSHJ P,ALCSEB## ;GET A BLOCK OF THE DESIRED SIZE
JRST TTPOPJ## ;PUNT IF NO CORE
POP P,T4 ;RESTORE THE LENGTH
ADD T4,T1 ;OFFSET FOR END+1
POP P,.EBHDR-1(T4) ;STORE LAST ENTRY FIRST
XMOVEI T2,ELGBEG ;POINT TO XFER TABLE
PUSHJ P,XFRSEB## ;MOVE SOME DATA
JFCL ;CAN'T FAIL HERE
MOVE T3,UNIUSC(U) ;GET USER SEEKS
ADDM T3,.EBHDR+07(T1) ;UPDATE MONITOR SEEKS TO TOTAL UNIT SEEKS
MOVE T3,UNIDRC(U) ;GET DUMP READ COUNT
ADD T3,UNIMRC(U) ;ADD IN MONITOR READ COUNT
ADDM T3,.EBHDR+10(T1) ;UPDATE BUFFERED READS TO TOTAL UNIT READS
MOVE T3,UNIDWC(U) ;GET DUMP WRITES
ADD T3,UNIMWC(U) ;ADD IN MONITOR WRITES
ADDM T3,.EBHDR+11(T1) ;UPDATE BUFFERED WRITES TO TOTAL UNIT WRITES
HRLZ T3,KDBDVC(W) ;GET DEVICE CODE/4
LSH T3,2 ;MAKE REAL DEVICE CODE
IOR T3,UNIEBK+.EBTYP(U) ;INCLUDE DX20 ADDRESS
HLLM T3,.EBHDR+02(T1) ;UPDATE SPEAR DEVICE INFO
XMOVEI T4,.EBHDR+45(T1) ;POINT TO START OF DYNAMIC SPACE
XMOVEI T3,UNIEBK+.EBSMR(U) ;POINT TO START OF SAVED MASSBUS REGS
HLRZ T2,UNIEBK+.EBMBR(U) ;GET COUNT OF SAVED MASSBUS REGS
JUMPE T2,RNXEL1 ;SKIP THIS IF NONE TO SAVE
EXTEND T2,[XBLT] ;COPY THE DATA, UPDATING POINTER IN T4
MOVEI T2,43 ;RELATIVE POINTER
ADDM T2,.EBHDR+43(T1) ;UPDATE THE WAY DAEMON USED TO
RNXEL1: XMOVEI T3,UNIEBK+.EBSDR(U) ;POINT TO START OF SAVED DEVICE REGS
HLRZ T2,UNIEBK+.EBDVL(U) ;GET COUNT OF SAVED DEVICE REGS
JUMPE T2,RNXEL2 ;SKIP THIS IF NONE
EXTEND T2,[XBLT] ;MOVE THE DATA
MOVEI T2,44 ;RELATIVE POINTER
ADDM T2,.EBHDR+44(T1) ;UPDATE FOR SPEAR
RNXEL2: PJRST QUESEB## ;GIVE IT TO DAEMON AND RETURN
ELGBEG: SEBTBL(.ERDXE,ELGEND,) ;START OUR XFER TABLE
MOVE UDBNAM(U) ;(R00) UNIT PHYSICAL NAME
MOVE UNILOG(U) ;(R01) LOGICAL UNIT NAME
MOVEI 2 ;(R02) RH20/DISK CODE
MOVE UNIHBN(U) ;(R03) BLOCK IN ERROR
MOVE UNIECT(U) ;(R04) FINAL ERROR STATE
MOVE UNISOF(U) ;(R05) 1CONI
MOVE UNIERR(U) ;(R06) 2CONI
MOVE UNIMSC(U) ;(R07) TOTAL UNIT SEEKS
MOVE UNIBRC(U) ;(R10) TOTAL UNIT READS
MOVE UNIBWC(U) ;(R11) TOTAL UNIT WRITES
MOVE DEVFIL(F) ;(R12) FILENAME
MOVE JBTPPN##(J) ;(R13) USER'S PPN
MOVE JBTNAM##(J) ;(R14) USER'S PROGRAM NAME
MOVE UNISCR(U) ;(R15) DATAI PTCR INITIAL
MOVE UNIHCR(U) ;(R16) DATAI PTCR FINAL
MOVE UNISDR(U) ;(R17) DATAI PBAR INITIAL
MOVE UNIHDR(U) ;(R20) DATAI PBAR FINAL
MOVE UNIHCT(U) ;(R21) HARD ERROR COUNTS
MOVE UNISCT(U) ;(R22) SOFT ERROR COUNTS
MOVE UNIMCT(U) ;(R23) SOFTWARE DETECTED ERRORS
MOVE UNIHNG(U) ;(R24) HUNG COUNTS
SETZ ;(R25) UNUSED
SETZ ;(R26) UNUSED
MOVE UNIEBK+.EBCS0(U) ;(R27) CHANNEL LOGOUT 0
MOVE UNIEBK+.EBCS1(U) ;(R30) CHANNEL LOGOUT 1
MOVE UNIEBK+.EBCS2(U) ;(R31) CHANNEL LOGOUT 2
MOVE UNIEBK+.EBCC1(U) ;(R32) FIRST CCW
MOVE UNIEBK+.EBCC2(U) ;(R33) SECOND CCW
MOVE UNIEBK+.EBMPE(U) ;(R34) COUNT OF MP ERRORS
MOVE UNIEBK+.EBNXM(U) ;(R35) COUNT OF CHANNEL NXM
SETZ ;(R36) UNUSED
SETZ ;(R37) UNUSED
SETZ ;(R40) UNUSED
MOVE UNIEBK+.EBICR(U) ;(R41) INITIAL CONTROL REGISTER
HRRZ UNIEBK(U) ;(R42) MICROCODE VERSION NUMBER
MOVE UNIEBK+.EBMBR(U) ;(R43) POINTER TO MASSBUS REGS
MOVE UNIEBK+.EBDVL(U) ;(R44) POINTER TO DX20 REGS
ELGEND:! ;END OF TRANSFER DATA
;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