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">, IFG <"VAL"-"9">, > > 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<-<_<^L>>-1>>> ;MACRO TO COMPUTE THE POSITION OF A MASK DEFINE POS(MASK),<<^L+^L<-<_<^L>>-1>-1>> ;MACRO TO BUILD A POINTER TO A MASKED QUANTITY ; POINTR LOCATION,MASK DEFINE POINTR(LOC,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 ,<..T==0 IFE C-777777,<..T==1 D A,B> IFE C-777777000000,<..T==1 E A,B> IFE ..T,> IFB , > ;END OF DEFINE .LDST. ;MACRO TO INSERT A VALUE IN A MASKED FIELD ; INSVL.(VALUE,MASK) DEFINE INSVL.(VALUE,MASK),<<<B)>>&>> ;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 ,<.EBM00==..CNT> IFE ,<.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, ;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