Trailing-Edge
-
PDP-10 Archives
-
BB-X140B-BB_1986
-
10,7/703mon/rnxkon.mac
There are 8 other files named rnxkon.mac in the archive. Click here to see a list.
TITLE RNXKON -- DRIVER FOR RP20'S V050
SUBTTL G.M. UHLER/GMU 10 SEP 85
SEARCH F,S,ICHPRM
$RELOC
$HIGH
;THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
; OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.
;
.CPYRT<1980,1986>
;COPYRIGHT (C) 1980,1982,1984,1986
;BY DIGITAL EQUIPMENT CORP., MAYNARD, MASS.
;ALL RIGHTS RESERVED.
;
XP VRNKON,050
SALL
;ASSEMBLY INSTRUCTIONS:
; .R MACRO
; *RNXKON,RNXKON/C=KONPAR,RNXKON
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 KONEBK/UNIEBK BLOCK OFFSETS
;OFFSETS IN THE KONEBK 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 KONEBK/UNIEBK
SUBTTL DATA STRUCTURE FIELD AND BYTE POINTER DEFINITIONS
RNXMVR==:300,,1 ;MINIMUM MICROCODE VERSION ALLOWED
;FIELDS IN RNXFLG(J)
RN.DCU==1B0 ;KNOW THE DCU CONTROLLER ADDRESS
;MUST BE SIGN BIT FOR SKIPL
RN.UPA==:1B1 ;BEEN THROUGH RNXUPA ONCE FOR THIS CONTROLLER
RNPUPA==:(RN.UPA) ;PUBLISH THIS SYMBOL FOR THE REST OF THE MONITOR
RN.FKA==1B2 ;FOUND THE DX20 MASSBUS ADDRESS 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)
RN.DXN==7B35 ;DX20 ADDRESS (MASSBUS SLOT)
;BYTE POINTERS TO ABOVE FIELDS
RNYDCA::POINTR RNXFLG##(J),RN.DCA ;DCU ADDRESS
RNYDXN::POINTR RNXFLG##(J),RN.DXN ;DX20 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 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: LDB T3,RNYDXN ;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,KONEBK##+.EBERR(J) ;GET ERROR REGISTER
HRL T3,KONEBK##+.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
XCT RNXDI2##(J) ;GET REGISTER RH20 IS CONNECTED TO
PUSH P,T2 ;SAVE IT
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
HLLZ T2,0(P) ;GET BACK REGISTER (WE MAY HAVE INTERRUPTED
TLZ T2,^-<(DO.REG!DO.DRV)> ; BETWEEN THE DATAO AND DATAI
XCT RNXDO2##(J) ; IN DODTI AT UUO LEVEL SO RESTORE IT
JRST T2POPJ## ;RESTORE T2 AND 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,KONIOC##(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
LDB T2,UNYPUN## ;GET PHYSICAL UNIT 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
HRRZ T2,UNICHN##(U) ;UPDATE THE LAST KNOWN POSITION
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?
RNXBP3: PUSHJ P,FLHTID## ;NO, CALL FILIO AND RETURN
PJRST JPOPJ## ;YES, AVOID A LONG NO-OP IN FILIO
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,KOP22B),,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
MOVSI T2,U2PNRM## ;SET NON-REMOVABLE MEDIUM
IORM T2,UNIDS2##(U) ; IN UDB
MOVSI T4,KOP22B## ;RP20 IS ALWAYS 22 BIT, UNIT TYPE IS 0
SKIPE RNXCMD##(J) ;ARE WE DOING SOMETHING NOW?
JRST RNXCP4 ;YES, CAN'T TOUCH THE DRIVE
PUSHJ P,RNXFKA ;FIND DX20 ADDRESS, CHECK MICROPROCESSOR
JRST RNXCP6 ;SOMETHING FAILED, BITS SET IN T4
MOVSI P1,-MAXDCU ;LOOP INDEX FOR ALL POSSIBLE DCU'S
RNXCP1: PUSHJ P,MPRUN ;DX20 STILL RUNNING?
JRST RNXCP4 ;NO, CALL UNIT OFF-LINE
SKIPL RNXFLG##(J) ;DO WE KNOW THE DCU CONTROLLER ADDRESS?
DPB P1,RNYDCA ;NO, TRY THE NEXT
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
SKIPL RNXFLG##(J) ;ALREADY KNOW THE DCU CONTROLLER ADDRESS?
AOBJN P1,RNXCP1 ;NO, TRY NEXT CONTROLLER FOR THIS UNIT
;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
MOVSI T2,(RN.DCU) ;INDICATE THAT WE NOW KNOW THE
IORM T2,RNXFLG##(J) ; DCU CONTROLLER ADDRESS
RNXCP6: LDB T1,RNYDCA ;GET DCU
IFN FTDUAL,<
;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
LDB T2,UNYPUN## ;GET UNIT NUMBER
IOR T1,T2 ;DUMMY UP A DRIVE SERIAL NUMBER
MOVEI T2,.DTCOD ;GET DT VALUE, VERIFIED BY CHKDTR
RNXCP7: HRRZM T1,UNISER##(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
TRNE 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
;ROUTINE TO FIND THE DX20 CONTROLLER MASSBUS ADDRESS AND CHECK
;THE INTEGRETY OF THE MICROPROCESSOR CONTROL STORE.
;CALL:
; J/KDB ADDRESS
; U/UDB ADDRESS
; PUSHJ P,RNXFKA
;RETURN CPOPJ IF ERROR WITH:
; T4/ERROR BITS INDICATING TYPE OF FAILURE
; CPOPJ1 IF NO ERROR WITH MICROPROCESSOR RUNNING
RNXFKA::MOVSI T2,(RN.FKA) ;DO WE ALREADY KNOW
TDNE T2,RNXFLG##(J) ; THE DX20 CONTROLLER ADDRESS?
JRST RNXFK2 ;YES, JUST CHECK THE MICROPROCESSOR
PUSHJ P,SAVE1## ;SAVE P1
HLLZ P1,KONTBP##(J) ;MAKE AOBJN POINTER TO MAX CONTROLLER ADDR
RNXFK1: DPB P1,RNYDXN ;STORE CONTROLLER ADDRESS
PUSHJ P,CHKDTR ;CHECK DRIVE TYPE REGISTER
JRST RNXFK4 ;NO MATCH, TRY NEXT
RNXFK2: PUSHJ P,MPINI ;CHECK AND RELOAD MICRO IF NECESSARY
JRST RNXFK5 ;FAILED, CALL THE DRIVE OFF-LINE
MOVSI T2,(RN.FKA) ;SET FLAG INDICATING THAT WE
IORM T2,RNXFLG##(J) ; KNOW THE DX20 ADDRESS
AOS 0(P) ;GIVE SKIP RETURN
JRST RNXFK6 ;AND EXIT
RNXFK4: MOVEI T2,CO.RAE!CO.MBE ;GET BIT TO CLEAR RAE
XCT RNXCO2##(J) ;CLEAR ANY POSSIBLE RAE
AOBJN P1,RNXFK1 ;AND TRY NEXT DX20 ADDRESS
TLOA T4,KOPUHE##!KOPNSU## ;IF NO DX20, MARK THIS UNIT NONEXISTANT
RNXFK5: TLO T4,KOPUHE## ;ELSE JUST CALL IT OFF-LINE
RNXFK6: MOVEI T2,CO.CLR!CO.MBE ;GET BITS TO CLEAR THE RH20
XCT RNXCO2##(J) ;DO SO
POPJ P, ;RETURN SKIP/NONSKIP
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 KONEBK 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,KONEBK##+.EBDVL(J) ;GET NUMBER OF DEVICE REGS STORED
JUMPE T2,CPOPJ## ;GIVE UP IF NONE
LOAD T3,KONEBK##+.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,KONEBK##+.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,KONEBK##+.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: SKIPL RNXFLG##(J) ;MUST KNOW THE CONTROLLER ADDRESS
JRST CONOFL ;CALL THE DRIVE OFF-LINE
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,KONTBP##(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
LDB T3,UNYPUN## ;PLUS THE PHYSICAL UNIT NUMBER ON THE KDB
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 KONEBK 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,KONIOC##(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,KONEBK##+.EBCC1(J) ;STORE IT
TRNE T2,-1 ;ANY ADDRESS?
MOVE T3,1(T2) ;YES, GET SECOND CCW
MOVEM T3,KONEBK##+.EBCC2(J) ;STORE IT
HRLZ T2,KONIOC##(J) ;GET LOGOUT AREA ADDRESS BACK
HRRI T2,KONEBK##+.EBCS0(J) ;MAKE IT A BLT POINTER
BLT T2,KONEBK##+.EBCS2(J) ;STORE LOGOUT AREA WORDS 0-2
MOVE T2,KONCHN##(J) ;GET ADDRESS OF CHANNEL DATA BLOCK
MOVE T3,.CHMPE(T2) ;GET COUNT OF MEMORY PARITY ERRORS
MOVEM T3,KONEBK##+.EBMPE(J) ;STORE IT
MOVE T3,.CHNXM(T2) ;GET COUNT OF NXM'S
MOVEM T3,KONEBK##+.EBNXM(J) ;STORE IT
LDB T2,RNYDXN ;GET DX20 ADDRESS
LSH T2,^D9 ;SHIFT BY 9 BITS
HRLM T2,KONEBK##+.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,KONEBK##+.EBMBR(J) ;STORE IN KDB
MOVEI P1,KONEBK##+.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,KONEBK##+.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,KONEBK##+.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,KONEBK##+.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,KONEBK##+.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,KONTBP##(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: LDB T2,UNYPUN## ;GET PHYSICAL UNIT 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"
LDB T4,UNYPUN## ;GET PHYSICAL UNIT NUMBER OF UNIT
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
LDB T2,RNYDXN ;GET DX20 MASSBUS SLOT
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
LDB T2,KOYPI## ;GET PI ASSIGNMENT
LSH T2,1 ;COMPUTE AN INTERRUPT
ADDI T2,40 ; ADDRESS OF 40+2N
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: LDB T4,KOYPI## ;GET PIA FOR THE RH20
TRO T4,CO.MBE ;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,KONTBP##(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:
IFE FTAUTC,<
POPJ P, ;CHUCK IT IF NO AUTCON
>
IFN FTAUTC,<
PUSHJ P,SAVT## ;SAVE THE T AC'S
MOVEI T1,.DTCOD ;SETUP DRIVE TYPE FOR NEWDSK
HRLZS T2 ;PUT THE DRIVE NUMBER IN THE LEFT HALF
PJRST NEWDSK## ;CALL NEWDSK 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
;ROUTINE TO FIND THE NEXT RP20 UNIT THAT EXISTS AND RETURN THE
;CONTROLLER AND UNITS NUMBERS TO AUTCON.
;CALL:
; T1/CONTROLLER ADDRESS,,UNIT ADDRESS (-1 FOR FIRST TIME)
; T2/DRIVE SELECT CODE FOR DATAO (RNYDXN)
; J/KDB ADDRESS
; PUSHJ P,RNXCFG
;RETURN CPOPJ IF NO MORE UNITS ON THIS DX20
; CPOPJ1 IF ANOTHER UNIT FOUND WITH:
; T1/CONTROLLER ADDRESS,,UNIT ADDRESS OF NEXT UNIT
RNXCFG::PUSHJ P,SAVE3## ;SAVE P1-P3
MOVE P1,T1 ;SAVE INITIAL VALUE OF T1 FOR FLAG
HLRE P2,T1 ;GET THE INITIAL CONTROLLER NUMBER
HRRE P3,T1 ; AND THE INITIAL UNIT NUMBER
DPB T2,RNYDXN ;STORE THE DRIVE SELECT CODE IN THE KDB
AOJN P3,RNXCF1 ;GO IF NOT THE FIRST TIME FOR THIS DX20
PUSHJ P,MPINI ;MAKE SURE THE MICROCODE IS VALID
POPJ P, ;IT'S NOT, GIVE UP
RNXCF1: PUSHJ P,MPRUN ;CHECK TO MAKE SURE IT'S STILL RUNNING
POPJ P, ;IT'S NOT, GIVE UP ON THAT ALSO
RNXCF2: CAIL P3,MAXSPD ;DONE ALL THE POSSIBLE UNITS YET?
POPJ P, ;YES, NO MORE UNITS FOUND
JUMPGE P1,RNXCF4 ;GO IF ALREADY HAD THE CONTROLLER ADDR
SETOM P2 ;INITIALIZE IT TO ZERO
RNXCF3: AOS P2 ;INCREMENT THE CONTROLLER ADDRESS
CAIL P2,MAXDCU ;CHECKED ALL THE ONES FOR THIS UNIT?
AOJA P3,RNXCF2 ;YES, INCREMENT THE UNIT AND CONTINUE
RNXCF4: HRRZ T2,P2 ;GET THE CONTROLLER ADDRESS
LSH T2,4 ;MAKE ROOM FOR THE UNIT NUMBER
IOR T2,P3 ;OR IN THE UNIT NUMBER
PUSHJ P,WDVNUM ;TELL THE DX20 WHICH UNIT
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 RNXCF5 ;ON-LINE DRIVE, RETURN IT
JRST RNXCF5 ;OFF-LINE DRIVE, RETURN IT
JUMPL P1,RNXCF3 ;TRY NEXT DCU ADDR IF NOT FOUND YET
AOJA P3,RNXCF2 ;ELSE INCREMENT UNIT ADDRESS AND CONTINUE
RNXCF5: MOVSI T1,(RN.FKA) ;SET FLAG TO AVOID THE DRIVE
IORM T1,RNXFLG##(J) ; SELECT LOOP IN RNXFKA
; DPB P2,RNYDCA ;STORE DCU
; MOVSI T1,(RN.DCA)
; IORM T1,RNXFLG##(J)
HRLZ T1,P2 ;CONTROLLER ADDRESS TO LH
HRR T1,P3 ;UNIT ADDRESS TO RH
JRST CPOPJ1## ;GIVE SKIP 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
TRNN T2,ST.RUN ;IS MICROPROCESSOR STILL RUNNING?
SKIPG KONRLD##(J) ;NOT RUNNING--OK TO ATTEMPT RELOAD?
POPJ P, ;RETURN
PJRST RNXRLD ;GO RELOAD MICROPROCESSOR
SUBTTL MICROPROCESSOR HANDLING ROUTINES
;ROUTINE TO START ALL DX20'S FOR RP20'S ON THIS CPU IF THEY ARE NOT
;ALREADY RUNNING.
;CALL: PUSHJ P,RNXSAK
;RETURN CPOPJ ALWAYS
RNXSAK::PJSP T1,RNXAPP ;RETURN AT .+1 FOR EACH DX20
PUSHJ P,MPRUN ;THIS DX20 RUNNING?
PUSHJ P,MPCHKS ;NO, CHECK THE CRAM AND RESTART IT
POPJ P, ;ALWAYS GIVE CPOPJ RETURN
POPJ P, ;DITTO
;ROUTINE TO CALL A SUBROUTINE FOR EACH RP20 DX20 ON THIS CPU.
;CALL:
; T1/ADDRESS OF ROUTINE TO CALL
; PUSHJ P,RNXAPP
;RETURN CPOPJ ALWAYS
;THE ROUTINE BEING CALLED MUST RETURN CPOPJ ONLY.
RNXAPP: PUSHJ P,SAVT## ;SAVE THE T REGS
PUSH P,J ;DON'T SMASH J
PUSH P,T1 ;SAVE THE ROUTINE ADDRESS
MOVEI J,SYSKON##-KONNXT## ;POINT TO START OF KDB CHAIN
RNXAP1: HLRZ J,KONNXT##(J) ;STEP TO NEXT DISK KDB
JUMPE J,RNXAP2 ;GO IF END OF CHAIN
LDB T1,KOYKTP## ;GET KONTROLLER TYPE
MOVE T2,KONCAM##(J) ; AND OWNING CPU MASK
CAIN T1,TYPRN## ;THIS AN RP20?
TDNN T2,.CPBIT## ;YES, IS IT ON THIS CPU?
JRST RNXAP1 ;NO, CONTINUE
PUSHJ P,CHKDTR ;MAKE SURE IT'S REALLY AN RP20
JRST RNXAP1 ;NOT, CONTINUE
PUSHJ P,@0(P) ;CALL ROUTINE FOR THIS ONE
JRST RNXAP1 ;TRY NEXT
RNXAP2: POP P,0(P) ;BRING STACK INTO PHASE
JRST JPOPJ## ;RESTORE J AND RETURN
;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,KONEBK##+.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
HRRZS KONRLD##(J) ;ASSUME RELOAD WILL SUCCEED
LDB T1,[POINT 7,RNXDO2##(J),9] ;GET RH20 DEVICE CODE
LSH T1,2 ;MAKE IT FULL 9 BIT DEVICE CODE
LDB T2,RNYDXN ;GET THE DX20 NUMBER
HRL T2,T1 ;MAKE IT DEVICE CODE,,DX20 NUMBER
MOVEM T2,RNXULB##+.ULDEV(J) ;SAVE
MOVEI 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: LDB T3,RNYDXN ;GET "DRIVE NUMBER" OF DX20 ON MASSBUS
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: LDB T3,RNYDXN ;GET "DRIVE NUMBER" OF DX20 MASSBUS SLOT
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