ER[DSKD]; % A DISK DIAGNOSTIC ROUTINE last modified January 10, 1977 1:39 PM TO ASSEMBLE: @MI@ DSKD LOAD: DSKD % INSERT[DBEG]; * * * OUTGOING COMMAND BITS FROM MAXC TO DISK AND CONTROLLER * TARGET[ILC]; MP[UDSEL,13]; * DESELECT THE UNIT MP[RSC,7]; * RESET SECTOR CONDITION MP[RPDL,10]; * RESET PROCESSOR DATA LATE MP[RCDL,11]; * RESET CONTROLLER DATA LATE MP[RSO,12]; * RESET SECTOR OVERFLOW MP[I1EN,0]; * ENABLE SECTOR INTERRUPTS MP[I2EN,4]; * ENABLE TYPE 1 WORD INTERRUPTS MP[I3EN,5]; * ENABLE TYPE 2 WORD INTERRUPTS MP[I4EN,6]; * ENABLE TYPE 3 WORD INTERRUPTS MP[LCR,1]; * LOAD CYLINDER ADDRESS REGISTER MP[LHR,2]; * LOAD HEAD ADDRESS REGISTER MP[COM,3]; * INTERPRET THIS AS A COMMAND MP[WRGAT,20]; * TURN ON WRITING MP[RDGAT,21]; * TURN ON READING MP[ERGAT,24]; * TURN ON ERASING MP[SEEK,22]; * INITIATE SEEK TO C.A.R. MP[RHR,23]; * RESET HEAD ADDRESS REGISTER TO 0 MP[HDS,25]; * ACTIVATE R/W HEAD IN H.A.R. MP[RESTOR,26]; * SEEK TO CYLINDER 0 SP[RESET,RSC,RPDL,RCDL,RSO]; * RESETS CONTROLLER ERRORS PM[ALL1CYL,777 0000]; F[HDADR,23,27]; * HEAD ADDRESS FIELD F[CYLADR,17,27];* CYLINDER ADDRESS FIELD * * INCOMING STATUS FROM DISK AND CONTROLLER * MP[IC,0]; * INDEX CONDITION MP[UUNS,1]; * UNIT UNSAFE MP[UOFF,2]; * UNIT OFF LINE MP[UNR,3]; * UNIT NOT READY (NORMALLY = SEEKING) MP[SKFAIL,4]; * SEEK HAS FAILED MP[URDONLY,5]; * UNIT CANNOT BE WRITTEN ON MP[CNR,6]; * CONTROLLER IS NOT READY MP[SC,7]; * SECTOR CONDITION MP[PDL,10]; * PROCESSOR DATA LATE CONDITION MP[CDL,11]; * CONTROLLER DATA LATE CONDITION MP[SO,12]; * SECTOR OVERFLOW CONDITION * REPEATEDLY SELECT A NON-EXISTENT DISK UNIT AND CONTROLLER * PM[UFOUR,4]; MC[UNIT4,UFOUR]; * MAKE A CONSTANT FOR UNIT 4 RSELU4: KUNIT_UNIT4, GOTO[.]; * REPEATEDLY READ OUT THE KUNIT REGISTER * RKUNIT: P_KUNIT, GOTO[.]; * REPEATEDLY SELECT A NON-EXISTENT DISK UNIT AND CONTROLLER AND * THEN READ THE KUNIT REGISTER SELLOOP: KUNIT_UNIT4; P_NULL; P_KUNIT, GOTO[SELLOOP]; * REPEATEDLY READ OUT THE KSTAT REGISTER * RKSTAT: P_KSTAT, GOTO[.]; * * SELECT A NON-EXISTENT DISK UNIT AND CONTROLLER * SELU4: KUNIT_UNIT4; P_NULL; P_KUNIT; P_KSTAT; * * SELECT A REAL DISK UNIT AND CONTROLLER * PM[UZERO,0]; MC[UNIT,UZERO]; * MAKE A CONSTANT FOR UNIT 0 PM[IDLP,0]; MC[IDLE,IDLP]; MC[DISCONN,UDSEL,RESET]; MC[TIMES]; SV[RANGEN,0]; SELUNIT: Q_7S; * Reset and turn off interrupts on all controllers SU1: KUNIT_Q; P_AQ; KSET_DISCONN,KNEWCOMM; P_P-1; Q_P,GOTO[SU1,ALU>=0]; KUNIT_UNIT; P_TIMES; Q_P+1; TIMES_Q; KSET_IDLE,KNEWCOMM; P_KUNIT; P_KSTAT; P_RANGEN; 2P; CALL[STORLM,ALU=0]; RETURN; * * ROUTINE TO SEND A SET CYLINDER REGISTER COMMAND FOLLOWED BY * A SEEK COMMAND REPEATEDLY TO A TURNED-OFF DISK UNIT. * MC[CYLVAL,LCR,RESET,ALL1CYL]; MC[PAUSMSK,CNR]; MC[SKVAL,COM,RESET,SEEK]; CRLP: KUNIT_UNIT; P_NULL; KSET_CYLVAL,KNEWCOMM; Q_PAUSMSK; P_KSTAT; P AND Q; GOTO[.-2,ALU#0]; KSET_SKVAL,KNEWCOMM; Q_PAUSMSK; P_KSTAT; P AND Q; GOTO[.-2,ALU#0]; GOTO[CRLP]; * * ROUTINES TO REPEATEDLY STORE AND READ THE KATA REGISTERS * PM[TDP,0]; MC[DATWD,TDP]; MC[DATEXT,TDP]; KWDATL: CALL[SELUNIT]; KMDR_DATWD; KMDRL_DATEXT; P_KMDR; Q_KMDRL; KWDATA,GOTO[.]; KRDATL: CALL[SELUNIT]; P_KRDATA; Q_KMDRL,GOTO[.-1]; * * WAIT UNTIL DISK UNIT AND CONTROLLER BOTH READY * MC[ALLRDY,UOFF,SKFAIL,UNR,CNR]; WAITRDY:Q_ALLRDY; P_KSTAT; P_P AND Q; *LOOP UNTIL READY GOTO[.-2, ALU#0]; RETURN; * * INTERRUPT HANDLERS FOR SECTOR AND WORD INTERRUPTS * IM[SILOC,5]; SILOC[(CALL[SIHAND])]; IM[WILOC,11]; WILOC[(CALL[WIHAND])]; MC[SECRDY]; MC[WDRDY]; MC[RSCC,RSC,I1EN]; MC[KDO]; MC[KDOL]; MC[KDI]; MC[KDIL]; MC[IUNIT]; MC[STAAFT]; SIHAND: P_AQ, Q_1S; SECRDY_Q, P_P; KCSET_RSCC, P_P; P_P; P_P; Q_KUNIT, P_P; IUNIT_Q, P_P; Q_KSTAT, P_P; STAAFT_Q, P_P; Q_P, P_P; RETURN,P_P1,IRET; WIHAND: P_AQ, Q_1S; WDRDY_Q, P_P; KMDR_KDO, P_P; KMDRL_KDOL, P_P; KWDATA, P_P; Q_KRDATA, P_P; KDI_Q, P_P; KDIL_KMDRL, Q_P, P_P; RETURN,P_P1,IRET; * * WAIT UNTIL THE BEGINNING OF NEXT INDEX SECTOR * NMC[NISC,IC,SC]; WAITIDX:SECRDY_NULL; WIX1: P_SECRDY; P; GOTO[WIX1,ALU=0]; P_KSTAT; P_(P) U (NISC); P_P+1; GOTO[WAITIDX,ALU#0]; RETURN; * * WAIT UNTIL READY FOR NEXT WORD. INTERRUPT 4 REQUEST MUST NOT * BE BACK-PANEL JUMPERED. * SP[BADUNIT,UUNS,UOFF,UNR,SKFAIL,URDONLY]; MC[OOPSMSK,BADUNIT,PDL,CDL,SO]; WAITWD: Q_OOPSMSK; P_NULL; P_KSTAT; P AND Q; GOTO[ANALYZE,ALU#0]; P_WDRDY; P; P_NULL, GOTO[WAITWD,ALU=0]; WDRDY_NULL,P, RETURN; * RETURN WITH ALU=0 MEANS ALL WENT OK * * ANALYZE WHY WAITWD FAILED * SV[CONDMSK,7777 7777 7777]; ANALYZE:Q_P AND Q, P_CONDMSK; P AND Q; GOTO[.+2,ALU=0]; STOP1: BRKP[1], GOTO[.]; AQ, RETURN; * SET THE ALU OUTPUT NONZERO, REQUESTING RECOVERY * * SEEK TO CYLINDER SPECIFIED IN CURCYL[17-27]. * MC[CURCYL,UZERO]; MC[CYLCOM,UZERO]; MC[SCRCOM,LCR,RESET]; MC[SEECOM,COM,RESET,SEEK]; SEEKSUB:CALL[WAITRDY]; Q_CURCYL; P_SCRCOM; Q_ P OR Q; CYLCOM_Q; KSET_CYLCOM,KNEWCOMM; CALL[WAITRDY]; KSET_SEECOM,KNEWCOMM; CALL[WAITRDY]; RETURN; * * GET A DATA WORD AND PUT IT IN DWD. IF SWITCH=0, GENERATE A RANDOM * DATA WORD. IF SWITCH#0, USE PWORD AS THE DATA WORD. THE ROUTINE * ASSUMES THAT X, L0-L7, AND DWD HAVE BEEN PRESERVED FROM THE * LAST CALL. * MC[SWITCH,UZERO]; MC[PWORD,UZERO]; MC[WDSLFT]; MC[DWD]; LV[LDWDL]; SV[X0,7654321]; SV[X1,76543210]; SV[X2,765432100]; SV[X3,7654321000]; SV[X4,76543210000]; SV[X5,765432100000]; SV[X6,654321000007]; SV[X7,543210000076]; SV[ZAP,0]; SV[@X7,IP[X7]]; SV[NXTIX,0]; GETDWD: P_SWITCH; 2P; Q_PWORD,GOTO[STDWD,ALU#0]; Q_DWD,GOTO[.+2,X>=0]; X_7S; P_LX; LX_Q_P+Q,DECX; STDWD: DWD_Q,RETURN; * * PICK UP RANDOM NUMBER PARAMETERS FROM SCRATCHPAD. * LOADLM: X_7S; Y_@X7; Q_ZAP; DWD_Q; LOADLMP:P_SY,DECY,GOTO[GETX,X<0]; LX_P,DECX,GOTO[LOADLMP]; GETX: X_NXTIX,RETURN; * * STORE UPDATED RANDOM NUMBER PARAMETERS IN SCRATCHPAD. * STORLM: NXTIX_X; X_7S; Y_@X7; Q_DWD; ZAP_Q; STORLMP:Q_LX,DECX,RETURN[X<0]; SY_Q,DECY,GOTO[STORLMP]; * * SEEK FORWARD ONE CYLINDER * SLC[LOCYL: CYLADR[0]]; SLC[HICYL: CYLADR[626]]; SLC[ONECYL: CYLADR[1]]; SEEKFWD:P_CURCYL; Q_ONECYL; P_P+Q; Q_LOCYL; P-Q; GOTO[.+2,ALU>0]; P_Q; Q_HICYL; P-Q; GOTO[.+2,ALU<0]; P_LOCYL; Q_P; CURCYL_Q; CALL[SEEKSUB]; RETURN; * * WRITE A MULTIPLE WORD RECORD ON THE INDEX SECTOR OF HEAD 0 * OF CYLINDER CURCYL. * PM[DZEROP,0]; MC[DZERO,DZEROP]; PM[DSYNCP,17]; MC[DSYNC,DSYNCP]; PM[WDMAXP,1100]; MC[WDMAXW,WDMAXP]; MC[RESETHD,RESET,COM,RHR,I1EN]; MC[SETHD,LHR,I1EN]; MC[SHCOM]; MC[HDSEL,RESET,COM,HDS,I4EN,I1EN]; MC[WRITEC,COM,WRGAT,ERGAT,HDS,I4EN,I1EN]; MC[ERASE,COM,ERGAT,HDS,I4EN,I1EN]; MC[STATUSW]; SETCHD: CALL[SEEKSUB]; KSET_RESETHD,KNEWCOMM,CALL[WAITRDY]; P_CURCYL; Q_37 0000S; * MASK CYLINDER TO GET HEAD NUMBER P_P AND Q; Q_23 0000S; * MAKE SURE HEAD IS IN [0-23] Q_P-Q; GOTO[.+2,ALU<0]; P_AQ; Q_SETHD; Q_P OR Q; SHCOM_Q; KSET_SHCOM,KNEWCOMM,CALL[WAITRDY]; KMDR_DZERO; KMDRL_DZERO; KWDATA; Q_DZERO; KDO_Q; KDOL_Q; WDRDY_NULL; RETURN; WRITE: CALL[SETCHD]; WRITER: CALL[WAITIDX]; CALL[LOADLM]; Q_0S; WDSLFT_Q; Q_KSTAT; STATUSW_Q; KSET_HDSEL,KNEWCOMM,CALL[WAITWD]; KSET_WRITEC,CALL[WAITWD]; CALL[WAITWD]; CALL[WAITWD]; CALL[WAITWD]; CALL[WAITWD]; CALL[WAITWD]; Q_DSYNC; KDO_Q; KDOL_Q; CALL[WAITWD]; WDLP: P_WDSLFT; Q_P+1; WDSLFT_Q; P_WDMAXW; P-Q; GOTO[WEXIT,ALU<0]; CALL[GETDWD]; Q_DWD; KDO_Q, Q_LDWDL; KDOL_Q; CALL[WAITWD]; GOTO[WDLP]; WEXIT: Q_DZERO; KDO_Q; KDOL_Q; CALL[WAITWD]; CALL[WAITWD]; KSET_ERASE; CALL[WAITWD]; KSET_IDLE; KMDR_DZERO; KMDRL_DZERO; KWDATA; RETURN; * * READ A MULTIPLE WORD RECORD FROM THE INDEX SECTOR OF HEAD 0 * ON CYLINDER CURCYL AND CHECK IT WORD FOR WORD. IF LOOKAT>0, DISPLAY * WORD[LOOKAT] IN P AND Q REGISTERS. * MC[WDMAXR,WDMAXP]; MC[READC,COM,RDGAT,HDS,I4EN,I1EN]; MC[STATUSR]; MC[LOOKAT,DZEROP]; PM[IERMSK,777777777777]; MC[ERRMSK,IERMSK]; PM[IERMSKL,17]; MC[ERRMSKL,IERMSKL]; READ: CALL[SETCHD]; READR: CALL[WAITIDX]; CALL[LOADLM]; Q_0S; WDSLFT_Q; Q_KSTAT; STATUSR_Q; KSET_HDSEL,KNEWCOMM,CALL[WAITWD]; CALL[WAITWD]; CALL[WAITWD]; KSET_READC,CALL[WAITWD]; CALL[WAITWD]; * SKIP FIRST GARBAGE WORD RDLP: P_WDSLFT; Q_P+1; WDSLFT_Q; P_WDMAXR; P-Q; GOTO[REXIT,ALU<0]; CALL[GETDWD]; P_LOOKAT; 2P; GOTO[CHECK,ALU<=0]; Q_WDSLFT; P-Q,P_KDI; GOTO[OKAY,ALU#0]; Q_KDIL; GOTO[OKAY]; CHECK: Q_DWD; P_KRDATA; Q_P#Q, P_ERRMSK; P AND Q; GOTO[HANG,ALU#0]; Q_DWD; P_KMDRL; Q_P#Q, P_ERRMSKL; P AND Q; GOTO[OKAY,ALU=0]; HANG: P_KMDRL;BRKP[1]; OKAY: CALL[WAITWD]; GOTO[RDLP,ALU=0]; * CHECK THAT WAITWD WENT OK REXIT: KSET_IDLE,KNEWCOMM; P_KRDATA; RETURN; * * CALLS ON THE VARIOUS ROUTINES * MC[IENABLE,IENABLE]; CLRTIMES:ARM_2100S,INHINT, Q_A0; SETF[IENABLE],INHINT; IRET, INHINT, TIMES_Q, GOTO[LOADLM]; * ST: CALL[CLRTIMES],INHINT; SEEKTST:CALL[SELUNIT]; CALL[SEEKFWD]; GOTO[SEEKTST]; * WT: CALL[CLRTIMES],INHINT; WCONT: CALL[SELUNIT]; CALL[WRITE]; GOTO[WCONT]; * RT: CALL[CLRTIMES],INHINT; RCONT: CALL[SELUNIT]; CALL[READ]; GOTO[RCONT]; * WRT: CALL[CLRTIMES],INHINT; WRCONT: CALL[SELUNIT]; CALL[WRITE]; CALL[READ]; GOTO[WRCONT]; * SWRT: CALL[CLRTIMES],INHINT; SWRCONT:CALL[SELUNIT]; CALL[SEEKFWD]; CALL[WRITE]; CALL[READ]; GOTO[SWRCONT];