home *** CD-ROM | disk | FTP | other *** search
/ Simtel MSDOS - Coast to Coast / simteldosarchivecoasttocoast.iso / diskutil / verdisk.asm < prev    next >
Assembly Source File  |  1994-03-04  |  13KB  |  362 lines

  1. PAGE 60,132
  2. ; USE BIOS DISK VERIFY FUNCTION TO CHECK INTEGRITY OF DISKETTES.
  3. ; RICH WINKEL  6/8/85
  4.  
  5. ; verdisk.asm  11 Jul 85  Craig Milo Rogers at USC/ISI
  6. ;    Enhanced this program to support hard disks, too.  I have
  7. ; to assume that the hard disks start with DOS device "C:".  The
  8. ; error analysis needs more work... the original program seemed to
  9. ; think that the error byte was bit-encoded, which it isn't.  Check
  10. ; the IBM-PC/AT's Technical Reference for the latest and greatest
  11. ; list of potential error codes.  Also, this program does NOT support
  12. ; IBM's 8-in. diskettes.
  13.  
  14. CR      EQU     0DH             ;CARRIAGE RETURN
  15. LF      EQU     0AH             ;LINE FEED
  16.  
  17. FLPNUM    EQU    2        ; Number of floppies before hard disk.
  18.  
  19.  
  20. ;    Assume this program is run as a .COM file.
  21.  
  22. VERDISK SEGMENT
  23.         ASSUME CS:VERDISK,DS:VERDISK
  24.  
  25.         ORG 5CH
  26. FCB1    DB ?                    ; First FCB in the PSP.
  27.  
  28.  
  29.         ORG 100H        ; Start of program execution.
  30. MAIN    PROC    NEAR
  31.         JMP     START        ; Skip past the data area.
  32.  
  33. ;    Floppy disk parameter table:
  34. ; Disk type:    DS8S, SS8S, DS9S, SS9S, DS15S (quad density)
  35. DSKIDT  DW      0FFH, 0FEH, 0FDH, 0FCH, 0F9H    ; Disk ID bytes.
  36. DSKIDL  EQU     ($-DSKIDT)/2
  37. SIDES   DW        1,    0,    1,    0,    1    ; Sides per disk.
  38. TRACKS  DW       39,   39,   39,   39,   79    ; Tracks per side.
  39. SECTORS    DW        8,    8,    9,    9,   15    ; Sectors per track.
  40.  
  41. HRDID    DB    0F8H        ; Hard (fixed) disk ID.
  42.  
  43. ; EACH DISK ERR MESSAGE MUST BE 16 BYTES LONG!
  44. DSKMSGS DB      CR,LF,'Timeout      $';TIMEOUT                       80H
  45.         DB      CR,LF,'Drive seek   $';DRIVE SEEK                    40H
  46.         DB      CR,LF,'Controller   $';CONTROLLER ERROR              20H
  47.         DB      CR,LF,'CRC          $';CRC                           10H
  48.         DB      CR,LF,'Bad Sector   $';DMA or Bad Sector             08H
  49.         DB      CR,LF,'Sector NF    $';MISSING SECTOR                04H
  50.         DB      CR,LF,'Addr mark NF $';MISSING ADDRESS MARK          02H
  51.         DB      CR,LF,'VERDISK      $';BAD CMD SHOULD NEVER HAPPEN   01H
  52. ;
  53. EM1     DB      'Invalid drive specified.$'
  54. EM2     DB      'Error: disk not supported, or invalid FAT ID found.$'
  55. IMSG1   DB      'Verifying $'
  56. IMSG2   DB      ' side(s), $'
  57. IMSG3   DB      ' tracks, $'
  58. IMSG4   DB      ' sectors per track:$'
  59. PIDMSG  DB      'error at side, track, sector: $'
  60. RETRYM1 DB      '; OK on retry $'
  61. RETRYM2 DB      '; still bad after 5 retries$'
  62. DONEMSG1 DB     CR,LF,'No disk errors found.$'
  63. DONEMSG2 DB     CR,LF,'Verdisk done.$'
  64. DEATHCRY DB     CR,LF,'Verdisk terminating!!$'
  65.  
  66. VERDRV  DB      ?               ;DRIVE TO VERIFY
  67. NUMSIDES DB     ?               ;NUMBER OF SIDES
  68. NUMTRKS DW      ?               ;NUMBER OF TRACKS
  69. NUMSECT DB      ?               ;NUMBER OF SECTORS
  70.  
  71. CURTRK    DW    ?        ; Current track.
  72.  
  73. RC      DB      0               ;RETURN CODE FOR DOS
  74.  
  75.  
  76. START:  CMP     AL,0FFH         ;DRIVE SPEC INVALID??
  77.         JNZ     LL1
  78.         MOV     DX,OFFSET EM1   ;THEN COMPLAIN
  79.         CALL    PRSTR
  80.         MOV     AX,4C08H        ;INDICATE COMMAND ERR IN RC
  81.         INT     21H
  82. LL1:    MOV     DL,FCB1         ;GET DISK ID IF SPECIFIED
  83.         DEC     DL
  84.         JNS     L1              ;JUMP IF DRIVE SPECIFIED
  85.         MOV     AH,19H          ;OTHERWISE, GET CURRENT DRIVE AND
  86.         INT     21H             ;USE THAT
  87.         MOV     DL,AL           ;PUT IT IN DL
  88. L1:     MOV     VERDRV,DL       ;SAVE DRIVE TO VERIFY
  89.  
  90.         INC     DL              ; Convert drive to 1's origin.
  91.         MOV     AH,1CH          ; Get FAT ID byte loc in DS:BX.
  92.         INT     21H
  93.  
  94.         MOV     AL,[BX]         ; Get the FAT ID byte in AL.
  95.     XOR    AH,AH        ; Zero-extend into AH.
  96.  
  97.         MOV     DX,CS        ; Restore our DS pointer.
  98.         MOV     DS,DX
  99.         MOV     DI,OFFSET DSKIDT; Point to disk ID table.
  100.         MOV     CX,DSKIDL       ; Length of table.
  101.         CLD                     ; Clear direction flag,
  102.         REPNE   SCASW           ; Scan for a match.
  103.          JE     GOTFLP        ;   (found it)
  104.  
  105.     CMP    AL,HRDID    ; Is this a hard disk?
  106.      JNE    UNKNWN        ;   (nope)
  107.  
  108. ;    We are looking at a hard disk.
  109.  
  110. GOTHRD:    MOV    AL,VERDRV    ; Get drive number.
  111.     SUB    AL,FLPNUM    ; Subtract number of floppies.
  112.     ADD    AL,80H        ; Convert to hard disk unit number.
  113.     MOV    VERDRV,AL    ; Save for future use.
  114.     MOV    DL,AL        ; Copy unit number for BIOS call.
  115.     MOV    AH,08H        ; Return drive parms function.
  116.     INT    13H        ; Call Fixed Disk BIOS.
  117.      JC    UNKNWN        ;   (not a hard disk after all)
  118.     MOV    NUMSIDES,DH    ; Get the number of heads.
  119.     MOV    AL,CL        ; Get the number of sectors.
  120.     AND    AL,03FH        ; Clear cylinder bits.
  121.     MOV    NUMSECT,AL    ; Save the number of sectors.
  122.     MOV    AL,CH        ; Get the number of cylinders.
  123.     MOV    AH,CL        ; Get high 2 bits.
  124.     MOV    CL,6        ; Shift count to extract high 2 bits.
  125.     SHR    AH,CL        ; Extract them.
  126.     MOV    NUMTRKS,AX    ; Save the number of cylinders.
  127.     JMP    SHOSIZ        ; Go print disk size.
  128.  
  129.  
  130. ;    We ar looking at a floppy disk.  Get the number of tracks,
  131. ; etc. from our table.
  132.  
  133. GOTFLP:    SUB     DI,OFFSET DSKIDT+2 ; Adjust for offset within table.
  134.         MOV     AX,SIDES[DI]    ; Get the number of sides per disk.
  135.         MOV     NUMSIDES,AL     ; Save in NUMSIDES.
  136.         MOV     AX,TRACKS[DI]   ; Get the number of tracks per side.
  137.         MOV     NUMTRKS,AX      ; Store in NUMTRKS.
  138.         MOV     AX,SECTORS[DI]  ; Get the number of sectors per track.
  139.         MOV     NUMSECT,AL      ; Store in NUMSECT.
  140.     JMP    SHOSIZ        ; Go print disk size.
  141.  
  142.  
  143. ;    The disk type is unknown, give up:
  144.  
  145. UNKNWN: MOV     DX,OFFSET EM2   ;COMPLAIN IF NO MATCH
  146.         CALL    PRSTR
  147.         MOV     AX,4C04H        ;INDICATE SEVERE ERROR.
  148.         INT     21H             ;BACK TO DOS
  149.  
  150.  
  151. ;    Tell the user how big the disk is:
  152.  
  153. SHOSIZ:    MOV     DX,OFFSET IMSG1 ;PRINT DISK INFO MSG
  154.         CALL    PRSTR           ; 'Verifying'
  155.     MOV    AL,NUMSIDES    ; Get number of sides (heads) per cylinder.
  156.         INC     AL              ; Convert to 1's origin.
  157.         CALL    BASE10PR0       ;PRINT IT
  158.         MOV     DX,OFFSET IMSG2
  159.         CALL    PRSTR           ; 'sides,'
  160.     MOV    AX,NUMTRKS    ; Get the number of tracks per side.
  161.         INC     AX        ; Convert to 1's origin.
  162.         CALL    BASE10PR        ;PRINT IT
  163.         MOV     DX,OFFSET IMSG3
  164.         CALL    PRSTR           ; 'tracks,'
  165.     MOV    AL,NUMSECT    ; Get the number of sectors per track.
  166.         CALL    BASE10PR0       ;PRINT IT
  167.         MOV     DX,OFFSET IMSG4
  168.         CALL    PRSTR           ; 'sectors per track:'
  169.  
  170.         MOV     DL,VERDRV       ;GET DRIVE NUMBER
  171.     MOV    CURTRK,0    ; Start with track 0.
  172. ;
  173. ; MAIN LOOP
  174. ; DRIVE=DL, SIDE=DH, TRACK=CH, SECTOR=CL, NUMBER OF SECTORS TO VER=AL
  175. LOOP0:    MOV     DH,0H           ;START ON SIDE 0
  176. LOOP1:    MOV    AL,BYTE PTR CURTRK+1; Get track number high bits.
  177.     MOV    CL,6        ; Number of bits to shift.
  178.     SHL    AL,CL        ; Move high bits into position.
  179.     OR    AL,01H        ; Start with sector 1.
  180.     MOV    CL,AL        ; Copy into proper register.
  181.     MOV    CH,BYTE PTR CURTRK; Get track number low bits.
  182.     MOV     AL,NUMSECT    ; Verify NUMSECT sectors.
  183.         MOV     AH,04H
  184.         INT     13H             ;DO THE OPERATION
  185.         OR      AH,AH           ;CHECK FOR ZERO RC
  186.         JNZ     BADVER          ;NO, THEN COMPLAIN
  187.  
  188. L3:     INC     DH              ;NEXT SIDE
  189.         CMP     DH,NUMSIDES    ; Are we done with this cylinder?
  190.         JLE     LOOP1           ;NO, THEN BACK FOR MORE
  191.  
  192.         MOV     AH,0BH          ;CHECK FOR CTRL-BREAK
  193.         INT     21H             ;VIA INPUT STATUS CALL.
  194.  
  195.         INC     CURTRK        ;INCREMENT TRACK
  196.     MOV    AX,CURTRK    ; Get new track number.
  197.         CMP     AX,NUMTRKS      ;CHECK FOR LAST TRACK
  198.         JLE     LOOP0           ;GO BACK FOR MORE
  199. ;
  200. ; DONE, SO EXIT
  201.         MOV     BL,RC              ;CHECK RC
  202.         OR      BL,BL
  203.         JNZ     DOS
  204.         MOV     DX,OFFSET DONEMSG1 ; 'NO DISK ERRORS FOUND.'
  205.         CALL    PRSTR
  206. DOS:    MOV     DX,OFFSET DONEMSG2 ; 'VERDISK DONE'
  207.         CALL    PRSTR
  208.         MOV     AH,4CH
  209.         MOV     AL,BL           ;GET RETURN CODE FLAGS
  210.         INT     21H
  211. ;
  212. ; BADVER USES CL, BL & AX.
  213. BADVER: MOV     AX,0401H        ;TEST TRACK ONE SECTOR AT A TIME
  214.         INT     13H             ;DO IT
  215.         OR      AH,AH           ;CHECK FOR ERROR
  216.         JNZ     L5
  217. L4:     INC     CL              ;INC SECTOR NUMBER
  218.     PUSH    CX        ; Save sector and track.
  219.     AND    CL,03FH        ; Mask out track bits
  220.         CMP     CL,NUMSECT    ; CHECK FOR LAST SECTOR
  221.     POP    CX        ; Restore track and sector.
  222.         JLE     BADVER          ;GO DO ANOTHER
  223.         JMP     L3
  224. ;
  225. L5:     OR      RC,01H          ;INDICATE DISK ERR IN RC
  226.         CALL    PRERR
  227.         MOV     BL,'1'          ;TRY A FEW RETRIES
  228. RETRY:  MOV     AX,0401H
  229.         INT     13H
  230.         OR      AH,AH
  231.         JZ      RETRYSUC        ;THAT ONE WAS OK, SO PRT MSG & LEAVE
  232.         INC     BL              ;ELSE CHECK COUNTER
  233.         CMP     BL,'5'
  234.         JLE     RETRY           ;TRY AGAIN
  235.         PUSH    DX              ;ELSE PRINT MSG & LEAVE
  236.         MOV     DX,OFFSET RETRYM2
  237.         CALL    PRSTR
  238.         POP     DX
  239.         OR      RC,02H          ;INDICATE NON-RECOVERABLE ERR IN RC
  240.         JMP     L4
  241. ;
  242. RETRYSUC:PUSH   DX
  243.         MOV     DX,OFFSET RETRYM1
  244.         CALL    PRSTR
  245.         MOV     DL,BL
  246.         CALL    PRCHAR
  247.         POP     DX
  248.         JMP     L4
  249. ;
  250. ; PRINT SIDE, TRACK, SECTOR & ERROR
  251. ; SIDE=DH, TRACK=CH, SECTOR=CL
  252. ; CX, DX, AX, BL, DI ARE USED; CX & DX ARE RESTORED.
  253. PRERR:  PUSH    CX              ;SAVE THEM REGS
  254.         PUSH    DX
  255.         PUSH    CX              ;SAVE EM AGAIN
  256.         PUSH    DX
  257.         MOV     BL,AH           ;DISK STATUS FLAGS TO BL
  258.         MOV     BH,AH           ;DISK STATUS FLAGS TO BH
  259.         MOV     CX,8H           ;CHECK ON 8 BITS
  260. LOOP2:  OR      BL,BL           ;SET CPU FLAGS
  261.         JS      L6              ;JUMP IF HI BIT IS 1
  262.         JZ      L7              ;JUMP IF NO 1'S LEFT
  263.         SHL     BL,1
  264.         LOOP    LOOP2           ;DO THE SAME FOR EVERY BIT
  265.         JMP     SHORT L7
  266. ;
  267. L6:     MOV     DX,08H          ;CALC OFFSET OF MSG; EACH MSG IS
  268.         SUB     DX,CX           ;16 BYTES LONG
  269.         SHL     DX,1            ;MULT BY 16
  270.         SHL     DX,1
  271.         SHL     DX,1
  272.         SHL     DX,1
  273.         ADD     DX,OFFSET DSKMSGS
  274.         CALL    PRSTR           ;PRINT IT
  275. ;*****    SHL     BL,1
  276. ;*****    LOOP    LOOP2           ;DO THE SAME FOR EVERY BIT
  277.  
  278.  
  279. L7:     MOV     DX,OFFSET PIDMSG ;PREFACE TO SIDE, TRK, SECTOR ID MSG
  280.         CALL    PRSTR
  281.         POP     AX              ;RECOVER SIDE IN AH
  282.     MOV    AL,AH        ; Move it into AL.
  283.         CALL    BASE10PR0       ;PRINT IT
  284.         MOV     DL,','          ;PRINT A COMMA
  285.         CALL    PRCHAR
  286.         POP     AX              ;RECOVER TRACK AND SECTOR
  287.     PUSH    AX        ; Save it again.
  288.     XCHG    AH,AL        ; Properly order high and low parts.
  289.     MOV    CL,6        ; Shift count for upper track bits.
  290.     SHR    AH,CL        ; Reposition high 2 bits of track count.
  291.         CALL    BASE10PR        ; Print the track number.
  292.         MOV     DL,','
  293.         CALL    PRCHAR          ;PRINT A COMMA
  294.         POP     AX              ; Recover sector number (and sector).
  295.     AND    AL,03FH        ; Mask out sector number high bits.
  296.         CALL    BASE10PR0       ;PRINT IT
  297.         POP     DX              ;RECOVER SIDE, TRK, SECTOR POINTERS
  298.         POP     CX
  299.         TEST    BH,0A1H         ;TST FOR TMOUT, NEC, WP OR BAD CMD
  300.         JNZ     L8
  301.         TEST    BH,40H        ; Test for bad seek.
  302.         JNZ     L9
  303.         RET
  304. ;
  305. L8:     MOV     DX,OFFSET DEATHCRY ;SOMETHING WEIRD HAPPENING ..
  306.         CALL    PRSTR
  307.         MOV     AX,4C04H           ;INDICATE SEVERE ERROR.
  308.         OR      AL,RC              ;ADD ON ANY OTHERS
  309.         INT     21H                ;GO WHILE THE GOIN'S GOOD
  310. ;
  311. L9:     MOV     AH,0H           ;RESET DISK DRIVES IF SEEK ERR
  312.         INT     13H
  313.         RET
  314. ;
  315. BASE10PR0:            ; Number to print in AL.
  316.     XOR    AH,AH        ; Zero-extend it.
  317. BASE10PR:            ; Number to print in AX.
  318.     PUSH    BX        ; Save temp reg.
  319.     XOR    BL,BL        ; Leading zeros flag.
  320.     MOV    CX,10000    ; Start with 10000's digit.
  321.  
  322. BLOOP:    XOR    DX,DX        ; Clear the number extension.
  323.     DIV    CX
  324.     PUSH    DX        ; Save remainder.
  325.     CMP    AL,BL        ; Leading zero?
  326.      JE    BSKIP        ;   (yup)
  327.     MOV    BL,0FFH        ; Mark no more leading zeros.
  328.     OR    AL,30H        ; Convert to ASCII.
  329.     MOV    DL,AL        ; Put in DL.
  330.         MOV     AH,02H          ;PRINT DL
  331.         INT     21H
  332.  
  333. BSKIP:    MOV    AX,CX        ; Get the current digit divisor.
  334.     XOR    DX,DX        ; Zero-extend to 32 bits.
  335.     MOV    CX,10        ; Divide divisor by 10.
  336.     DIV    CX
  337.     MOV    CX,AX        ; Save divisor for next decimal digit.
  338.     POP    AX        ; Restore the remainder.
  339.     CMP    CX,1        ; Final digit?
  340.      JNE    BLOOP        ;   (nope)
  341.  
  342.     OR    AL,30H        ; Convert final digit to ASCII.
  343.     MOV    DL,AL        ; Put in DL.
  344.         MOV     AH,02H          ; Print DL.
  345.         INT     21H
  346.  
  347.     POP    BX        ; Restore temp reg.
  348.     RET            ; All done.
  349. ;
  350. PRSTR:  MOV     AH,09
  351.         INT     21H
  352.         RET
  353. ;
  354. PRCHAR: MOV     AH,02
  355.         INT     21H
  356.         RET
  357. ;
  358. MAIN    ENDP
  359. VERDISK ENDS
  360.         END     MAIN
  361.  
  362.