;+++++++++++++++++++++++++++++++++++++++++++++++++ ;+++++++++++++++++++++++++++++++++++++++++++++++++ ;++ D I S K T E S T ++ ;++ FLOPPY DISK DIAGNOSTIC - 11/15/78 ++ ;++ TARBELL ELECTRONICS - VERSION 1.3 ++ ;+++++++++++++++++++++++++++++++++++++++++++++++++ ;+++++++++++++++++++++++++++++++++++++++++++++++++ ;THIS PROGRAM READS ALL DISK SECTORS ;AND PRINTS THE TRACK AND SECTOR NUMBER ;WHERE AN ERROR IS FOUND. ;RETRY COUNT CAN BE SET AT 0 - 9. ;NORMALLY SET RETRY COUNT AT 0. ;SETTING RETRY COUNT TO GREATER THAN ZERO WILL CAUSE THE ;PROGRAM TO TRY TO READ A SECTOR WHERE AN ERROR IS FOUND ;THAT MANY TIMES OVER BEFORE IT WILL PRINT AN ERROR MESSAGE. ;THE TOTAL ERROR COUNT AT THE END OF THE TEST WILL REFLECT ;ALL ERRORS INCLUDING RETRYS. THEREFORE, IF THERE IS ONLY ;ONE ERROR ON A DISK, AND THE RETRY COUNT IS SET TO NINE, ;THE TOTAL READ ERROR COUNT DISPLAYED AT THE END OF THE ;TEST WILL SHOW NINE READ ERRORS. ;STEP RATE CAN BE SET TO SLOW (20MS.), MEDIUM (10MS.), ;OR FAST (6MS.). ;FULL TRACK SEEK SEEKS TRACK 76 BEFORE READING EACH TRACK ;UP TO TRACK 40, AND SEEKS TRACK ZERO BEFORE READING ;EACH TRACK AFTER TRACK 40. ;CONTROL C TERMINATES TEST AND DOES A WARM BOOT. ;CONTROL D TERMINATES TEST AND STARTS OVER. ;THIS PROGRAM INCLUDES DISK I/O ROUTINES AND CALLS CP/M ;ONLY FOR CONSOLE I/O. ;DISK WRITE ROUTINES HAVE BEEN INCLUDED IN THE SOURCE ;ALTHOUGH THEY ARE NOT USED BY THIS VERSION OF THE PROGRAM. ;WRITTEN BY MARC D. FARJEON USING DISK I/O ROUTINES ;FROM THE TARBELL CBIOS. ;<<<<<32>>>>>. FALSE EQU 0 ;DEFINE VALUE OF FALSE. TRUE EQU NOT FALSE ;DEFINE VALUE OF TRUE. STD EQU TRUE ;TRUE IF STANDARD DRIVE. FAST EQU NOT STD ;TRUE IF FAST SEEK. DISK EQU 0F8H ;DISK BASE ADDRESS. DCOM EQU DISK ;DISK COMMAND PORT. DSTAT EQU DISK ;DISK STATUS PORT. TRACK EQU DISK+1 ;DISK TRACK PORT. SECTP EQU DISK+2 ;DISK SECTOR PORT. DDATA EQU DISK+3 ;DISK DATA PORT. WAIT EQU DISK+4 ;DISK WAIT PORT. DCONT EQU DISK+4 ;DISK CONTROL PORT. DOS EQU 5 ;BDOS ENTRY POINT. CREAD EQU 1 ;CODE FOR CONSOLE READ. CWRITE EQU 2 ;CODE FOR CONSOLE WRITE. CPB EQU 9 ;CODE FOR PRINT BUFFER. CSTAT EQU 11 ;CODE FOR STATUS CHECK. DRINT EQU 25 ;CODE FOR DRIVE INTERROGATE. ORG 100H START: LXI H,OMSG ;GET MESSAGE ADDRESS. CALL CPRINT ;PRINT MESSAGE. RSTART: LXI H,SELMSG ;DRIVE SELECT MESSAGE. CALL CPRINT ;PRINT MESSAGE. CALL CONIN ;READ DRIVE. ANI 0DFH ;CONVERT TO UPPER CASE. CPI 'A' ;COMPARE JC RSTART ;FOR CPI 'E' ;CORRECT JNC RSTART ;DRIVE. STA DRIVE ;SAVE IT. LXI H,REMSG ;RETRY QUESTION. CALL CPRINT ;PRINT QUESTION. CALL CONIN ;READ RETRY COUNT. ANI 0FH ;MASK OUT UPPER NYBBLE. ADI 1 ;ADD ONE. STA RTCNT ;STASH IT. IF STD ;IF STANDARD DRIVE. STPSET: LXI H,STPMSG ;STEP RATE MESSAGE. CALL CPRINT ;PRINT IT. CALL CONIN ;GET CHARACTER. ANI 0DFH ;MAKE UPPER CASE. CALL SETSTP ;SET STEP RATE. JNZ STPSET ;WRONG CODE IF NOT ZERO. ENDIF LXI H,LSMSG ;LONG SEEK QUESTION. CALL CPRINT ;PRINT IT. CALL CONIN ;READ RESPONSE. ANI 0DFH ;MAKE UPPER CASE. CPI 'Y' ;IS IT Y? IF SO, LXI H,LST ;SET LOCATION LST TO MVI M,55 ;00110111 FOR LONG SEEK. JZ READY ;JUMP. MVI M,0 ;ZERO FOR SEQUENTIAL SEEK. READY: LXI H,RMSG ;GET MESSAGE ADDRESS. CALL CPRINT ;PRINT MESSAGE. CALL CONIN ;READ RETURN. LXI H,CRLF ;OUTPUT A RETURN AND CALL CPRINT ;LINEFEED TO CRT. XRA A ;SET A = 0. STA TRK ;TRACK COUNTER = 0. STA BCDTRK ;BCD TRACK COUNTER = 0. STA BCDREC ;BCD READ ERRORS = 0. STA BREHUN ;BREHUN = 0. STA RECH ;RECH = 0. STA RECM ;RECM = 0. STA RECL ;RECL = 0. STA HLNHL ;READ ERROR FLAG = 0. STA OTIT ;OTIT = 0. STA OT ;OT = 0. MVI A,1 ;SET A = 1. STA SECT ;SECTOR COUNTER = 1. STA BCDSEC ;BCD SECTOR COUNTER = 1. MVI A,77 ;SET A = 77. STA IT ;IT = 77. CALL SELECT ;SELECT DRIVE. XRA A ;SET A = 0 FOR A CALL SEEK ;SEEK TO TRACK ZERO. JMP READFS ;START READING. INRTRK: CALL CONST ;CHECK CONSOLE INPUT STATUS. LDA LST ;CHECK LOCATION LST CPI 55 ;FOR LONG SEEK. IF 55, JZ LSTRK ;DO IT. IF NOT, LDA TRK ;GET PRESENT TRACK NUMBER. INR A ;INCREMENT TRACK NUMBER. CPI 77 ;IF LAST TRACK WAS 76, JZ FINIS ;JUMP TO END ROUTINE. STA TRK ;SAVE NEW TRACK NUMBER. CALL SEEK ;MOVE HEAD TO NEW TRACK. JC FINIS1 ;QUIT IF SEEK ERROR. LDA BCDTRK ;GET BCD TRACK NUMBER. ADI 1 ;ADD ONE TO TRACK COUNT. DAA ;DECIMAL ADJUST. STA BCDTRK ;STASH IT. MVI A,1 ;SET A = 1. STA SECT ;SECTOR = 1 FOR NEW TRACK. STA BCDSEC ;BCD SECTOR NUMBER = 1. READFS: CALL READ ;READ FIRST SECTOR. INRSEC: LDA SECT ;GET PRESENT SECTOR NUMBER. INR A ;INCREMENT SECTOR NUMBER. CPI 27 ;IF LAST SECTOR WAS 26, JZ INRTRK ;START NEW TRACK. IF NOT, STA SECT ;SAVE NEW SECTOR NUMBER. ORA A ;CLEAR FLAGS. LDA BCDSEC ;GET BCD SECTOR NUMBER. ADI 1 ;ADD ONE TO SECTOR COUNT. DAA ;DECIMAL ADJUST. STA BCDSEC ;STASH IT. LDA HLNHL ;CHECK FOR ERROR IN LAST ORA A ;SECTOR READ. IF ERROR JNZ READL ;READ WITH HEAD LOAD. CALL READN ;READ NEW SECTOR. JMP INRSEC ;READ NEXT SECTOR. READL: CALL READ ;READ SECTOR. JMP INRSEC ;READ NEXT SECTOR. LSTRK: LDA OTIT ;CHECK TO READ OUTER OR INR A ;INNER TRACK. INCREMENT STA OTIT ;OTIT. SAVE IT. ANI 1 ;IF LSB IS HIGH, JNZ ITRK ;READ INNER TRACK. LDA OT ;GET OUTER TRACK NUMBER. INR A ;INCREMENT TRACK. CPI 77 ;IF LAST TRACK WAS 76, JZ FINIS ;DO QUIT ROUTINE. STA OT ;SAVE IT. STA TRK ;PUT IN TRACK COUNTER. CALL SEEK ;MOVE HEAD TO TRACK. JC FINIS1 ;QUIT IF SEEK ERROR. LDA BCDTRK ;GET BCD TRACK NUMBER. ADI 1 ;ADD ONE TO TRACK COUNT. DAA ;DECIMAL ADJUST. STA BCDTRK ;SAVE IT. MVI A,1 ;SET A = 1. STA SECT ;SECTOR = 1 FOR NEW TRACK. STA BCDSEC ;BCD SECTOR = 1 FOR NEW TRACK. JMP READFS ;READ NEW TRACK. ITRK: LDA TRK ;GET TRACK NUMBER. CPI 40 ;IF TRACK < 40, JC INMOST ;SEEK TRACK 76. XRA A ;SET A = 0. STA TRK ;PUT IN TRACK COUNTER. CALL SEEK ;MOVE HEAD TO TRACK 0. JMP LSTRK ;READ NEXT TRACK. INMOST: MVI A,76 ;SET A = 76. STA TRK ;PUT IN TRACK COUNTER. CALL SEEK ;MOVE HEAD TO TRACK 76. JMP LSTRK ;READ NEXT TRACK. ETS: LDA BCDTRK ;GET BCD TRACK NUMBER. RRC ;SHIFT RRC ;RIGHT RRC ;FOUR RRC ;BITS. ANI 0FH ;MASK OFF UPPER NYBBLE. ADI '0' ;ADD ASCII FOR ZERO. CPI '0' ;SEE IF MSD IS ZERO. JNZ TLSD ;PRINT IT IF NOT ZERO. MVI A,20H ;DO NOT PRINT IF ZERO. TLSD: STA TRKM ;INSERT IN BUFFER. LDA BCDTRK ;GET BCD TRACK AGAIN. ANI 0FH ;MASK OFF UPPER NYBBLE. ADI '0' ;ADD ASCII FOR ZERO. STA TRKL ;INSERT IN BUFFER. LDA BCDSEC ;GET BCD SECTOR NUMBER. RRC ;SHIFT RRC ;RIGHT RRC ;FOUR RRC ;BITS. ANI 0FH ;MASK OFF UPPER NYBBLE. ADI '0' ;ADD ASCII FOR ZERO. CPI '0' ;CHECK FOR MSD OF ZERO. JNZ SLSD ;PRINT IT IF NOT ZERO. MVI A,20H ;DO NOT PRINT IF ZERO. SLSD: STA SECM ;INSERT IN BUFFER. LDA BCDSEC ;GET BCD SECTOR AGAIN. ANI 0FH ;LOOK AT LOWER NYBBLE. ADI '0' ;ADD 30 HEX. STA SECL ;INSERT IN BUFFER. LXI H,TSMSG ;GET MESSAGE ADDRESS. CALL CPRINT ;PRINT IT. LXI H,HLNHL ;GET HLNHL ADDRESS. MVI M,55H ;SET TO 01010101. RET ;RETURN. FINIS: LDA BCDREC ;GET BCD READ ERROR COUNT. RRC ;SHIFT RRC ;RIGHT RRC ;FOUR RRC ;BITS. ANI 0FH ;MASK OUT UPPER NYBBLE. ADI '0' ;ADD ASCII FOR ZERO. CPI '0' ;CHECK FOR MSD OF ZERO. JNZ ELSD ;IF NOT, PRINT IT. STA TEMP ;SAVE MSD. LDA BREHUN ;GET HUNDREDS COUNT. ORA A ;CHECK FOR ZERO. LDA TEMP ;GET MSD BACK. JNZ ELSD ;JUMP IF HUNDREDS > 0. XRA A ;PRINT NOTHING. ELSD: STA RECM ;INSERT IN BUFFER. LDA BCDREC ;GET COUNT AGAIN. ANI 0FH ;MASK AGAIN. ADI '0' ;ADD ASCII FOR ZERO. STA RECL ;INSERT IN BUFFER. LDA BREHUN ;GET HUNDREDS COUNT. ORA A ;CHECK FOR ZERO. JZ FINIS2 ;SKIP IF ZERO. ANI 0FH ;MASK OUT UPPER NYBBLE. ADI '0' ;ADD 30 HEX. STA RECH ;INSERT IN BUFFER. FINIS2: LXI H,RECMSG ;GET ERROR MESSAGE. CALL CPRINT ;PRINT IT. FINIS1: LXI H,QMSG ;GET ENDING MESSAGE. CALL CPRINT ;PRINT MESSAGE. CALL CONIN ;INPUT Y OR N. ANI 0DFH ;MAKE UPPER CASE. CPI 'Y' ;CHECK FOR Y. JZ RSTART ;START AGAIN IF Y. LXI H,GMSG ;GET MESSAGE. CALL CPRINT ;PRINT IT. CALL INTDRN ;INTERROGATE DRIVE NUMBER. RET ;GO BACK TO CPM. CONIN: MVI C,CREAD ;SET C FOR CONSOLE READ. CALL DOS ;INPUT CHARACTER. RET ;RETURN FROM CONIN. CONOUT: MVI C,CWRITE ;SET C FOR CONSOLE WRITE. CALL DOS ;OUTPUT CHARACTER. RET ;RETURN FROM CONOUT. CONST: MVI C,CSTAT ;SET C FOR STATUS CHECK. CALL DOS ;DO IT. ANI 1 ;LOOK AT LSB. RZ ;RETURN IF ZERO. CALL CONIN ;GET CHARACTER. ANI 7FH ;MASK OUT MSB. CPI 3 ;CHECK FOR CONTROL C. JNZ CTLD ;JUMP IF NOT. LXI H,AMSG ;IF CONTROL C, CALL CPRINT ;PRINT MESSAGE AND CALL INTDRN ;QUERY DRIVE NUMBER. JMP 0 ;WARM BOOT. CTLD: CPI 4 ;CHECK FOR CONTROL D. RNZ ;RETURN IF NOT. LXI H,AMSG ;IF CONTROL D, CALL CPRINT ;PRINT MESSAGE AND INX SP ;NEUTRALIZE LAST INX SP ;CALL AND JMP FINIS ;DO QUIT ROUTINE. CPRINT: PUSH D ;SAVE D AND E. XCHG ;MESSAGE ADDRESS IN D AND E. MVI C,CPB ;SET C FOR PRINT BUFFER. CALL DOS ;PRINT CONSOLE BUFFER. POP D ;RESTORE D AND E. RET ;RETURN FROM CPRINT. INTDRN: MVI C,DRINT ;CODE FOR DRIVE QUERY. CALL DOS ;GET LOGED IN DRIVE. MOV A,E ;PUT IN A. CALL SELD ;SELECT IT. RET ;RETURN FROM INTDRN. SELECT: LDA DRIVE ;GET DRIVE FOR TEST. SUI 'A' ;SUBTRACT ASCII FOR A. STA DISKNO ;SAVE IT. SELD: CMA ;INVERT SELECT CODE. ADD A ;PUT BITS ADD A ;ONE AND TWO ADD A ;AT FOUR ADD A ;AND FIVE. ORI 2 ;SET BIT ONE TO SET LATCH. OUT DCONT ;SELECT DRIVE. RET ;RETURN FROM SELECT. IF STD ;IF STANDARD DRIVE. SETSTP: LXI H,STP+1 ;POINT TO COMMAND BYTE. CPI 'S' ;IS IT AN S? MVI M,13H ;SET FOR SLOW STEP. RZ ;RETURN. CPI 'M' ;IS IT AN M? MVI M,12H ;SET FOR MEDIUM STEP. RZ ;GO BACK. CPI 'F' ;IS IT AN F? MVI M,11H ;SET FOR FAST STEP. RET ;RETURN. ENDIF ; ;READ WITHOUT HEAD LOAD. ; READN: LDA RTCNT ;SET RETRY COUNT. STA ERCNT LDA SECT ;GET SECTOR NUMBER LXI H,DIB ;AND STARTING ADDRESS. READ2: OUT SECTP ;SET SECTOR NUMBER INTO 1771. MVI A,88H ;GET CODE FOR READ W/O HLD. JMP READE ;READ A SECTOR. ; ; READ THE SECTOR AT SECT, FROM THE PRESENT TRACK. ; USE STARTING ADDRESS AT DIB. ; READ: LDA RTCNT ;GET RETRY COUNT. RRETRY: STA ERCNT ;STORE IN ERROR CTR. LDA SECT ;GET SECTOR NUMBER. LXI H,DIB ;GET STARTING ADR. READ1: OUT SECTP ;SET SECTOR INTO 1771. MVI A,8CH ;CODE FOR READ W/O HD LD. READE: OUT DCOM ;SEND COMMAND TO 1771. RLOOP: IN WAIT ;WAIT FOR DRQ OR INTRQ. ORA A ;SET FLAGS. JP RDDONE ;DONE IF INTRQ. IN DDATA ;READ A DATA BYTE FROM DISK. MOV M,A ;PUT BYTE INTO MEMORY. INX H ;INCREMENT MEMORY POINTER. JMP RLOOP ;KEEP READING. RDDONE: LXI H,HLNHL ;GET HLNHL ADDRESS. MVI M,0 ;SET TO ZERO. IN DSTAT ;READ DISK STATUS. ANI 9DH ;LOOK AT ERROR BITS. RZ ;RETURN IF NONE. CHECK: CALL ERCHK ;CHECK FOR SEEK ERROR. LXI H,RECNT ;GET RD ERR COUNT ADDR. INR M ;ONE MORE ERROR. LDA BCDREC ;GET BCD READ ERROR COUNT. ADI 1 ;ADD ONE TO READ ERROR COUNT. DAA ;DECIMAL ADJUST. STA BCDREC ;SAVE IT. JNC LDER ;SKIP IF NO CARRY. LDA BREHUN ;GET HUNDREDS COUNT. ADI 1 ;ADD ONE TO COUNT. DAA ;DECIMAL ADJUST. STA BREHUN ;SAVE IT. LDER: LDA ERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. JNZ RRETRY ;TRY TO READ AGAIN. LXI H,RDMSG ;PRINT "READ ". ERMSG: CALL CPRINT ;PRINT ORIGIN MESSAGE. ERMSG1: MOV A,D ;GET ERROR BITS. ANI 80H ;IF BIT 7 HIGH, LXI H,NRMSG ;"NOT READY". CNZ CPRINT MOV A,D ;GET ERROR BITS. ANI 10H ;IF BIT 4 IS HIGH, LXI H,RNMSG ;PRINT "RECORD NOT FOUND" CNZ CPRINT MOV A,D ;GET ERROR BITS. ANI 8 ;IF BIT 3 IS HIGH, LXI H,CRCMSG ;PRINT "CRC ERROR". CNZ CPRINT MOV A,D ;GET ERROR BITS. ANI 4 ;IF BIT 2 IS HIGH, LXI H,LDMSG ;PRINT "LOST DATA". CNZ CPRINT MOV A,D ;GET ERROR BITS. ANI 1 ;IF BIT 1 IS HIGH, LXI H,BSYMSG ;PRINT "BUSY". CNZ CPRINT PERMSG: LXI H,ERRMSG ;PRINT "ERROR." CALL CPRINT JMP ETS ;JUMP TO ERROR PRINT ROUTINE. ; ; ERCHK - CHECK FOR RECORD NOT FOUND ERROR. ; ERCHK: MOV D,A ;SAVE ERROR BITS IN D. ANI 10H ;IF RECORD NOT FOUND, JNZ CHKSK ;DO A CHECK ON SEEK. MOV A,D ;OTHERWISE RESTORE BITS ORA A ;SET FLAGS, RET ;AND RETURN. ;CHECK FOR SEEK TO CORRECT TRACK, ;AND CHANGE IF NECESSARY. CHKSK: MVI A,0C4H ;SEND COMMAND TO 1771 OUT DCOM ;TO READ ADDRESS. IN WAIT ;WAIT FOR DRQ OR INTRQ. IN DDATA ;READ THE TRACK ADDRESS. MOV B,A ;SAVE IN REGISTER B. CHKS2: IN WAIT ;WAIT FOR INTRQ. JM CHKS2 ;NOT IF DRQ. MOV A,B ;UPDATE TRACK REGITER. OUT TRACK LDA TRK ;GET REQUIRED TRACK NO. CALL SEEK ;MOVE THE HEAD TO IT. MOV A,D ;GET ERROR BITS. CHKS3: ORA A ;SET FLAGS. RET ;RETURN FROM ERCHK. ; ; WRITE THE SECTOR AT SECT ONTO THE PRESENT TRACK. ; DO NOT LOAD HEAD FIRST, THOUGH. ; WRITEN: LDA RTCNT ;SET RETRY COUNT. STA ERCNT LDA SECT ;GET SECTOR AND LXI H,DIB ;STARTING ADD´RESS. OUT SECTP ;SET SECTOR NUMBER INTO 1771. MVI A,0A8H ;GET CODE FOR WRITE W/O HLD. OUT DCOM ;SEND TO 1771. JMP WLOOP ;DO REST IN REGULAR ROUTINE. ; ; WRITE THE SECTOR AT SECT, ON THE PRESENT TRACK. ; WRITE: LDA RTCNT ;GET RETRY COUNT. WRETRY: STA ERCNT ;STORE IN ERROR COUNTER. LDA SECT ;GET SECTOR NUMBER. LXI H,DIB ;GET STARTING ADR. WRITE1: OUT SECTP ;SET THE SECTOR INTO 1771. MVI A,0ACH ;SET UP 1771 FOR WRITE. OUT DCOM WLOOP: IN WAIT ;WAIT FOR READY. ORA A ;SET FLAGS. JP WDONE ;HOP OUT WHEN DONE. MOV A,M ;GET BYTE FROM MEM. OUT DDATA ;WRITE ONTO DISK. INX H ;INCREMENT MEM PTR. JMP WLOOP ;KEEP WRITING. WDONE: IN DSTAT ;READ DISK STATUS. ANI 0FDH ;LOOK AT THESE BITS. PROCER: RZ ;RETURN IF NO ERR. CALL ERCHK ;CHECK/CORRECT SEEK ERR. LXI H,WECNT ;GET ADR OF WRITE ERR CTR. INR M ;ONE MORE WRITE ERROR. LDA ERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. JNZ WRETRY ;TRY TO WRITE AGAIN. WERR0: LXI H,WTMSG ;PRINT "WRITE ". CALL CPRINT MOV A,D ;GET ERROR BITS. ANI 40H ;LOOK AT BIT 6. LXI H,WPMSG ;PRINT "PROTECT ". CNZ CPRINT MOV A,D ;GET ERROR BITS. ANI 20H ;LOOK AT BIT 5. LXI H,WFMSG ;PRINT "FAULT ". CNZ CPRINT JMP ERMSG1 ;DO COMMON MESSAGES. ; ; MOVE THE HEAD TO THE TRACK IN REGISTER A. ; SEEK: PUSH B ;SAVE B&C. MOV B,A ;SAVE DESTINATION TRACK. LDA RTCNT ;GET RETRY COUNT. SRETRY: STA SERCNT ;STORE IN ERROR COUNTER. IN TRACK ;READ PRESENT TRACK NO. MOV C,A ;SAVE IN C. MOV A,C ;DELAY. CMP B ;SAME AS NEW TRACK NO.? MOV A,B ;RESTORE A FROM B. JNZ NOTHR ;JUMP IF NOT THERE. THERE: POP B ;RESTORE B&C. ORA A ;RESET FLAGS. RET ;RETURN FROM SEEK. NOTHR: IF STD ;IF NOT FAST SEEK, OUT DDATA ;TRACK TO DATA REGISTER. BUSY: IN DSTAT ;READ DISK STATUS. RRC ;LOOK AT BIT 0. JC BUSY ;WAIT TILL NOT BUSY. STP: MVI A,12H ;SEEK COMMAND. ORI 4 ;VERIFY ON LAST TRACK. OUT DCOM ;ISSUE SEEK COMMAND. IN WAIT ;WAIT FOR INTRQ. IN DSTAT ;READ STATUS. ANI 91H ;LOOK AT BITS. JZ THERE ;OK IF ZERO. ENDIF IF FAST ;IF FAST SEEK, MVI A,40H ;IF CARRY = 1, JC SDIR ;STEP IN. MVI A,60H ;OTHERWISE, OUT. SDIR: OUT DCOM ;ISSUE STEP DIRECTION. MVI A,20 ;DELAY LOOP COUNT. DLOOP: DCR A ;DECREMENT COUNTER. JNZ DLOOP MOV A,C ;GET PRESENT TRACK. SUB B ;FIGURE TRACKS TO STEP. JP STEP ;IF NEGATIVE, CMA ;FIGURE THE INR A ;TWO'S COMPLEMENT. STEP: MOV C,A ;GET DIFFERENCE. MVI A,1 ;PERSCI STEP COMMAND. STEP1: OUT DCONT ;STEP PERSCI (E-14). DCR C ;COUNT THE STEP. JNZ STEP1 ;STEP UNTIL C = 0. IN WAIT ;CLEAR 1771. IN DSTAT MOV A,B ;GET DEST. TRACK. OUT TRACK ;UPDATE TRACK REG. LDA DISKNO ;GET DISK NUMBER. RLC!RLC!RLC!RLC ;SHIFT LEFT 4 BITS. ANI 30H ;LOOK AT BITS 4 AND 5. CMA ;INVERT. MOV B,A ;SAVE IN B. ANI 72H ;MAKE COMMAND TO OUT DCONT ;SWITCH WAIT FOR IN WAIT ;SEEK COMPLETE. MOV A,B ;RESTORE ORIG. BITS. ANI 0F2H ;SWITCH WAIT BACK. OUT DCONT XRA A ;MAKE GOOD RETURN. POP B ;RESTORE B&C. RET ENDIF IF STD ;IF NOT FAST SEEK, PUSH H ;SAVE H&L. LXI H,SECNT ;GET ADR OF SEEK ERR CTR. INR M ;ONE MORE SEEK ERROR. POP H ;RESTORE H&L. LDA ERCNT ;GET ERROR COUNT. DCR A ;DECREMENT COUNT. JNZ SRETRY ;RETRY SEEK. POP B ;RESTORE B&C. LXI H,SKMSG ;PRINT "SEEK ". IN DSTAT ;READ DISK STATUS. ANI 91H ;LOOK AT ERROR BITS. MOV D,A ;PUT IN REG D. CALL ERMSG ;DO ERROR MESSAGES. STC ;SET CARRY FLAG. RET ;RETURN FROM SEEK. ENDIF ; ; MESSAGES. ; NRMSG: DB 'NOT READY $' RNMSG: DB 'RECORD NOT FOUND $' CRCMSG: DB 'CRC $' LDMSG: DB 'LOST DATA $' BSYMSG: DB 'BUSY $' WPMSG: DB 'PROTECT $' WFMSG: DB 'FAULT $' ERRMSG: DB 'ERROR. $' RDMSG: DB 13,10,'READ $' WTMSG: DB 13,10,'WRITE $' SKMSG: DB 13,10,'SEEK $' HEMSG: DB 13,10,'HOME $' TSMSG: DB 13,10,'TRACK ' TRKM: DB 0 TRKL: DB 0 SMSG: DB ' SECTOR ' SECM: DB 0 SECL: DB 0 CRLF: DB 13,10,36 OMSG: DB 13,10,'TARBELL DISK DIAGNOSTIC ' DB 13,10 IF STD DB 'STANDARD ' ENDIF IF FAST DB 'FAST SEEK ' ENDIF DB 'VERSION 1.3 ',13,10,36 SELMSG: DB 13,10,'SELECT DRIVE. (A/B/C/D) $' REMSG: DB 13,10,'HOW MANY RETRYS? (0-9) $' STPMSG: DB 13,10,'SELECT STEP RATE. (S/M/F) $' LSMSG: DB 13,10,'FULL TRACK SEEK? (Y/N) $' RMSG: DB 13,10,'TO START TEST TYPE RETURN. $' RECMSG: DB 13,10 RECH: DB 0 RECM: DB 0 RECL: DB 0 DB ' READ ERRORS DETECTED. ',13,10,36 QMSG: DB 13,10,7,'REPEAT TEST? (Y/N) $' AMSG: DB 13,10,'ABORTING TEST. ',13,10,36 GMSG: DB 13,10,10,36 ; HECNT: DB 0 ;HOME ERROR COUNT. RECNT: DB 0 ;READ ERROR COUNT. WECNT: DB 0 ;WRITE ERROR COUNT. SECNT: DB 0 ;SEEK ERROR COUNT. BCDREC: DB 0 ;BCD READ ERROR COUNT. BREHUN: DB 0 ;HUNDREDS OF READ ERRORS. ; TRTAB: DW 0,0 ;TRACK TABLE. NODSKS: DB 0 ;NUMBER OF DISKS. DRIVE: DB 0 ;DRIVE. DISKNO: DB 0 ;DISK NUMBER. TRK: DB 0 ;TRACK NUMBER. SECT: DB 0 ;SECTOR NUMBER. BCDTRK: DB 0 ;TRACK NUMBER IN BCD. BCDSEC: DB 0 ;SECTOR NUMBER IN BCD. RTCNT: DB 0 ;RETRY COUNT. ERCNT: DB 0 ;ERROR COUNT FOR RETRIES. SERCNT: DB 0 ;SEEK RETRY COUNTER. HLNHL: DB 0 ;READ ERROR FLAG. LST: DB 0 ;LONG SEEK FLAG. OT: DB 0 ;LST OUTER TRACK. IT: DB 0 ;LST INNER TRACK. OTIT: DB 0 ;OTIT. TEMP: DB 0 ;TEMPORARY STORAGE. DIB: DS 128 ;DISK INPUT BUFFER. END