home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 December
/
simtel1292_SIMTEL_1292_Walnut_Creek.iso
/
msdos
/
dskutl
/
verdisk.asm
< prev
next >
Wrap
Assembly Source File
|
1985-07-13
|
13KB
|
362 lines
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