home *** CD-ROM | disk | FTP | other *** search
- PAGE 60,132
- ; USE BIOS DISK VERIFY FUNCTION TO CHECK INTEGRITY OF DISKETTES.
- ; RICH WINKEL 6/8/85
-
- ; verdisk.asm 11 Jul 85 Craig Milo Rogers at USC/ISI
- ; Enhanced this program to support hard disks, too. I have
- ; to assume that the hard disks start with DOS device "C:". The
- ; error analysis needs more work... the original program seemed to
- ; think that the error byte was bit-encoded, which it isn't. Check
- ; the IBM-PC/AT's Technical Reference for the latest and greatest
- ; list of potential error codes. Also, this program does NOT support
- ; IBM's 8-in. diskettes.
-
- CR EQU 0DH ;CARRIAGE RETURN
- LF EQU 0AH ;LINE FEED
-
- FLPNUM EQU 2 ; Number of floppies before hard disk.
-
-
- ; Assume this program is run as a .COM file.
-
- VERDISK SEGMENT
- ASSUME CS:VERDISK,DS:VERDISK
-
- ORG 5CH
- FCB1 DB ? ; First FCB in the PSP.
-
-
- ORG 100H ; Start of program execution.
- MAIN PROC NEAR
- JMP START ; Skip past the data area.
-
- ; Floppy disk parameter table:
- ; Disk type: DS8S, SS8S, DS9S, SS9S, DS15S (quad density)
- DSKIDT DW 0FFH, 0FEH, 0FDH, 0FCH, 0F9H ; Disk ID bytes.
- DSKIDL EQU ($-DSKIDT)/2
- SIDES DW 1, 0, 1, 0, 1 ; Sides per disk.
- TRACKS DW 39, 39, 39, 39, 79 ; Tracks per side.
- SECTORS DW 8, 8, 9, 9, 15 ; Sectors per track.
-
- HRDID DB 0F8H ; Hard (fixed) disk ID.
-
- ; EACH DISK ERR MESSAGE MUST BE 16 BYTES LONG!
- DSKMSGS DB CR,LF,'Timeout $';TIMEOUT 80H
- DB CR,LF,'Drive seek $';DRIVE SEEK 40H
- DB CR,LF,'Controller $';CONTROLLER ERROR 20H
- DB CR,LF,'CRC $';CRC 10H
- DB CR,LF,'Bad Sector $';DMA or Bad Sector 08H
- DB CR,LF,'Sector NF $';MISSING SECTOR 04H
- DB CR,LF,'Addr mark NF $';MISSING ADDRESS MARK 02H
- DB CR,LF,'VERDISK $';BAD CMD SHOULD NEVER HAPPEN 01H
- ;
- EM1 DB 'Invalid drive specified.$'
- EM2 DB 'Error: disk not supported, or invalid FAT ID found.$'
- IMSG1 DB 'Verifying $'
- IMSG2 DB ' side(s), $'
- IMSG3 DB ' tracks, $'
- IMSG4 DB ' sectors per track:$'
- PIDMSG DB 'error at side, track, sector: $'
- RETRYM1 DB '; OK on retry $'
- RETRYM2 DB '; still bad after 5 retries$'
- DONEMSG1 DB CR,LF,'No disk errors found.$'
- DONEMSG2 DB CR,LF,'Verdisk done.$'
- DEATHCRY DB CR,LF,'Verdisk terminating!!$'
-
- VERDRV DB ? ;DRIVE TO VERIFY
- NUMSIDES DB ? ;NUMBER OF SIDES
- NUMTRKS DW ? ;NUMBER OF TRACKS
- NUMSECT DB ? ;NUMBER OF SECTORS
-
- CURTRK DW ? ; Current track.
-
- RC DB 0 ;RETURN CODE FOR DOS
-
-
- START: CMP AL,0FFH ;DRIVE SPEC INVALID??
- JNZ LL1
- MOV DX,OFFSET EM1 ;THEN COMPLAIN
- CALL PRSTR
- MOV AX,4C08H ;INDICATE COMMAND ERR IN RC
- INT 21H
- LL1: MOV DL,FCB1 ;GET DISK ID IF SPECIFIED
- DEC DL
- JNS L1 ;JUMP IF DRIVE SPECIFIED
- MOV AH,19H ;OTHERWISE, GET CURRENT DRIVE AND
- INT 21H ;USE THAT
- MOV DL,AL ;PUT IT IN DL
- L1: MOV VERDRV,DL ;SAVE DRIVE TO VERIFY
-
- INC DL ; Convert drive to 1's origin.
- MOV AH,1CH ; Get FAT ID byte loc in DS:BX.
- INT 21H
-
- MOV AL,[BX] ; Get the FAT ID byte in AL.
- XOR AH,AH ; Zero-extend into AH.
-
- MOV DX,CS ; Restore our DS pointer.
- MOV DS,DX
- MOV DI,OFFSET DSKIDT; Point to disk ID table.
- MOV CX,DSKIDL ; Length of table.
- CLD ; Clear direction flag,
- REPNE SCASW ; Scan for a match.
- JE GOTFLP ; (found it)
-
- CMP AL,HRDID ; Is this a hard disk?
- JNE UNKNWN ; (nope)
-
- ; We are looking at a hard disk.
-
- GOTHRD: MOV AL,VERDRV ; Get drive number.
- SUB AL,FLPNUM ; Subtract number of floppies.
- ADD AL,80H ; Convert to hard disk unit number.
- MOV VERDRV,AL ; Save for future use.
- MOV DL,AL ; Copy unit number for BIOS call.
- MOV AH,08H ; Return drive parms function.
- INT 13H ; Call Fixed Disk BIOS.
- JC UNKNWN ; (not a hard disk after all)
- MOV NUMSIDES,DH ; Get the number of heads.
- MOV AL,CL ; Get the number of sectors.
- AND AL,03FH ; Clear cylinder bits.
- MOV NUMSECT,AL ; Save the number of sectors.
- MOV AL,CH ; Get the number of cylinders.
- MOV AH,CL ; Get high 2 bits.
- MOV CL,6 ; Shift count to extract high 2 bits.
- SHR AH,CL ; Extract them.
- MOV NUMTRKS,AX ; Save the number of cylinders.
- JMP SHOSIZ ; Go print disk size.
-
-
- ; We ar looking at a floppy disk. Get the number of tracks,
- ; etc. from our table.
-
- GOTFLP: SUB DI,OFFSET DSKIDT+2 ; Adjust for offset within table.
- MOV AX,SIDES[DI] ; Get the number of sides per disk.
- MOV NUMSIDES,AL ; Save in NUMSIDES.
- MOV AX,TRACKS[DI] ; Get the number of tracks per side.
- MOV NUMTRKS,AX ; Store in NUMTRKS.
- MOV AX,SECTORS[DI] ; Get the number of sectors per track.
- MOV NUMSECT,AL ; Store in NUMSECT.
- JMP SHOSIZ ; Go print disk size.
-
-
- ; The disk type is unknown, give up:
-
- UNKNWN: MOV DX,OFFSET EM2 ;COMPLAIN IF NO MATCH
- CALL PRSTR
- MOV AX,4C04H ;INDICATE SEVERE ERROR.
- INT 21H ;BACK TO DOS
-
-
- ; Tell the user how big the disk is:
-
- SHOSIZ: MOV DX,OFFSET IMSG1 ;PRINT DISK INFO MSG
- CALL PRSTR ; 'Verifying'
- MOV AL,NUMSIDES ; Get number of sides (heads) per cylinder.
- INC AL ; Convert to 1's origin.
- CALL BASE10PR0 ;PRINT IT
- MOV DX,OFFSET IMSG2
- CALL PRSTR ; 'sides,'
- MOV AX,NUMTRKS ; Get the number of tracks per side.
- INC AX ; Convert to 1's origin.
- CALL BASE10PR ;PRINT IT
- MOV DX,OFFSET IMSG3
- CALL PRSTR ; 'tracks,'
- MOV AL,NUMSECT ; Get the number of sectors per track.
- CALL BASE10PR0 ;PRINT IT
- MOV DX,OFFSET IMSG4
- CALL PRSTR ; 'sectors per track:'
-
- MOV DL,VERDRV ;GET DRIVE NUMBER
- MOV CURTRK,0 ; Start with track 0.
- ;
- ; MAIN LOOP
- ; DRIVE=DL, SIDE=DH, TRACK=CH, SECTOR=CL, NUMBER OF SECTORS TO VER=AL
- LOOP0: MOV DH,0H ;START ON SIDE 0
- LOOP1: MOV AL,BYTE PTR CURTRK+1; Get track number high bits.
- MOV CL,6 ; Number of bits to shift.
- SHL AL,CL ; Move high bits into position.
- OR AL,01H ; Start with sector 1.
- MOV CL,AL ; Copy into proper register.
- MOV CH,BYTE PTR CURTRK; Get track number low bits.
- MOV AL,NUMSECT ; Verify NUMSECT sectors.
- MOV AH,04H
- INT 13H ;DO THE OPERATION
- OR AH,AH ;CHECK FOR ZERO RC
- JNZ BADVER ;NO, THEN COMPLAIN
-
- L3: INC DH ;NEXT SIDE
- CMP DH,NUMSIDES ; Are we done with this cylinder?
- JLE LOOP1 ;NO, THEN BACK FOR MORE
-
- MOV AH,0BH ;CHECK FOR CTRL-BREAK
- INT 21H ;VIA INPUT STATUS CALL.
-
- INC CURTRK ;INCREMENT TRACK
- MOV AX,CURTRK ; Get new track number.
- CMP AX,NUMTRKS ;CHECK FOR LAST TRACK
- JLE LOOP0 ;GO BACK FOR MORE
- ;
- ; DONE, SO EXIT
- MOV BL,RC ;CHECK RC
- OR BL,BL
- JNZ DOS
- MOV DX,OFFSET DONEMSG1 ; 'NO DISK ERRORS FOUND.'
- CALL PRSTR
- DOS: MOV DX,OFFSET DONEMSG2 ; 'VERDISK DONE'
- CALL PRSTR
- MOV AH,4CH
- MOV AL,BL ;GET RETURN CODE FLAGS
- INT 21H
- ;
- ; BADVER USES CL, BL & AX.
- BADVER: MOV AX,0401H ;TEST TRACK ONE SECTOR AT A TIME
- INT 13H ;DO IT
- OR AH,AH ;CHECK FOR ERROR
- JNZ L5
- L4: INC CL ;INC SECTOR NUMBER
- PUSH CX ; Save sector and track.
- AND CL,03FH ; Mask out track bits
- CMP CL,NUMSECT ; CHECK FOR LAST SECTOR
- POP CX ; Restore track and sector.
- JLE BADVER ;GO DO ANOTHER
- JMP L3
- ;
- L5: OR RC,01H ;INDICATE DISK ERR IN RC
- CALL PRERR
- MOV BL,'1' ;TRY A FEW RETRIES
- RETRY: MOV AX,0401H
- INT 13H
- OR AH,AH
- JZ RETRYSUC ;THAT ONE WAS OK, SO PRT MSG & LEAVE
- INC BL ;ELSE CHECK COUNTER
- CMP BL,'5'
- JLE RETRY ;TRY AGAIN
- PUSH DX ;ELSE PRINT MSG & LEAVE
- MOV DX,OFFSET RETRYM2
- CALL PRSTR
- POP DX
- OR RC,02H ;INDICATE NON-RECOVERABLE ERR IN RC
- JMP L4
- ;
- RETRYSUC:PUSH DX
- MOV DX,OFFSET RETRYM1
- CALL PRSTR
- MOV DL,BL
- CALL PRCHAR
- POP DX
- JMP L4
- ;
- ; PRINT SIDE, TRACK, SECTOR & ERROR
- ; SIDE=DH, TRACK=CH, SECTOR=CL
- ; CX, DX, AX, BL, DI ARE USED; CX & DX ARE RESTORED.
- PRERR: PUSH CX ;SAVE THEM REGS
- PUSH DX
- PUSH CX ;SAVE EM AGAIN
- PUSH DX
- MOV BL,AH ;DISK STATUS FLAGS TO BL
- MOV BH,AH ;DISK STATUS FLAGS TO BH
- MOV CX,8H ;CHECK ON 8 BITS
- LOOP2: OR BL,BL ;SET CPU FLAGS
- JS L6 ;JUMP IF HI BIT IS 1
- JZ L7 ;JUMP IF NO 1'S LEFT
- SHL BL,1
- LOOP LOOP2 ;DO THE SAME FOR EVERY BIT
- JMP SHORT L7
- ;
- L6: MOV DX,08H ;CALC OFFSET OF MSG; EACH MSG IS
- SUB DX,CX ;16 BYTES LONG
- SHL DX,1 ;MULT BY 16
- SHL DX,1
- SHL DX,1
- SHL DX,1
- ADD DX,OFFSET DSKMSGS
- CALL PRSTR ;PRINT IT
- ;***** SHL BL,1
- ;***** LOOP LOOP2 ;DO THE SAME FOR EVERY BIT
-
-
- L7: MOV DX,OFFSET PIDMSG ;PREFACE TO SIDE, TRK, SECTOR ID MSG
- CALL PRSTR
- POP AX ;RECOVER SIDE IN AH
- MOV AL,AH ; Move it into AL.
- CALL BASE10PR0 ;PRINT IT
- MOV DL,',' ;PRINT A COMMA
- CALL PRCHAR
- POP AX ;RECOVER TRACK AND SECTOR
- PUSH AX ; Save it again.
- XCHG AH,AL ; Properly order high and low parts.
- MOV CL,6 ; Shift count for upper track bits.
- SHR AH,CL ; Reposition high 2 bits of track count.
- CALL BASE10PR ; Print the track number.
- MOV DL,','
- CALL PRCHAR ;PRINT A COMMA
- POP AX ; Recover sector number (and sector).
- AND AL,03FH ; Mask out sector number high bits.
- CALL BASE10PR0 ;PRINT IT
- POP DX ;RECOVER SIDE, TRK, SECTOR POINTERS
- POP CX
- TEST BH,0A1H ;TST FOR TMOUT, NEC, WP OR BAD CMD
- JNZ L8
- TEST BH,40H ; Test for bad seek.
- JNZ L9
- RET
- ;
- L8: MOV DX,OFFSET DEATHCRY ;SOMETHING WEIRD HAPPENING ..
- CALL PRSTR
- MOV AX,4C04H ;INDICATE SEVERE ERROR.
- OR AL,RC ;ADD ON ANY OTHERS
- INT 21H ;GO WHILE THE GOIN'S GOOD
- ;
- L9: MOV AH,0H ;RESET DISK DRIVES IF SEEK ERR
- INT 13H
- RET
- ;
- BASE10PR0: ; Number to print in AL.
- XOR AH,AH ; Zero-extend it.
- BASE10PR: ; Number to print in AX.
- PUSH BX ; Save temp reg.
- XOR BL,BL ; Leading zeros flag.
- MOV CX,10000 ; Start with 10000's digit.
-
- BLOOP: XOR DX,DX ; Clear the number extension.
- DIV CX
- PUSH DX ; Save remainder.
- CMP AL,BL ; Leading zero?
- JE BSKIP ; (yup)
- MOV BL,0FFH ; Mark no more leading zeros.
- OR AL,30H ; Convert to ASCII.
- MOV DL,AL ; Put in DL.
- MOV AH,02H ;PRINT DL
- INT 21H
-
- BSKIP: MOV AX,CX ; Get the current digit divisor.
- XOR DX,DX ; Zero-extend to 32 bits.
- MOV CX,10 ; Divide divisor by 10.
- DIV CX
- MOV CX,AX ; Save divisor for next decimal digit.
- POP AX ; Restore the remainder.
- CMP CX,1 ; Final digit?
- JNE BLOOP ; (nope)
-
- OR AL,30H ; Convert final digit to ASCII.
- MOV DL,AL ; Put in DL.
- MOV AH,02H ; Print DL.
- INT 21H
-
- POP BX ; Restore temp reg.
- RET ; All done.
- ;
- PRSTR: MOV AH,09
- INT 21H
- RET
- ;
- PRCHAR: MOV AH,02
- INT 21H
- RET
- ;
- MAIN ENDP
- VERDISK ENDS
- END MAIN
-
-