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];