home *** CD-ROM | disk | FTP | other *** search
/ ProfitPress Mega CDROM2 …eeware (MSDOS)(1992)(Eng) / ProfitPress-MegaCDROM2.B6I / UTILITY / DISK / FHARD101.ZIP / VHPREP.ASM < prev    next >
Encoding:
Assembly Source File  |  1990-07-17  |  19.6 KB  |  745 lines

  1.  
  2.     title    Prepare VHARD floppies
  3.     subttl    Prologue
  4.     page    60,132
  5.  
  6. comment    {
  7.  
  8. ******************************************************************************
  9.  
  10. File VHPREP.ASM
  11.  
  12. Author:
  13.     Aaron L. Brenner
  14.  
  15.     BIX mail address albrenner
  16.     GEnie address A.BRENNER
  17.  
  18.     This program is hereby released to the public domain.
  19.  
  20. Purpose:
  21.     Prepare floppy diskettes for use with VHARD.
  22.  
  23.     This consists of the following:
  24.  
  25.     1) Format the floppies to 10 sectors per track, 40 tracks (resulting
  26.        in a capacity of 800K per diskette).
  27.     2) Write the VHARD boot sector to each disk containing, along with
  28.        boot code, a disk ID and number.
  29.     3) Write a DOS boot sector, 2 FATs, and root directory to the first
  30.        disk.
  31.  
  32.     All disk operations are performed through VHARDCTL, the character
  33.     device driver installed with VHARD.
  34.  
  35. Errorlevel returned:
  36.     0        All is well
  37.     1        VHARD.SYS is not installed
  38.  
  39. Revision history:
  40. 1.00    07/11/90    ALB    Created.
  41.  
  42. ******************************************************************************
  43.  
  44. endcomment {
  45.  
  46.     subttl    Included files
  47.     page
  48.  
  49.     include    dd_defs.inc
  50.     include    vhard.inc
  51.  
  52.     subttl    Program data and stack
  53.     page
  54.  
  55. vhprep_data    segment    para
  56.  
  57. ID_to_use    db    8 dup(' ')    ; ID to use for the diskettes
  58. disk_num    db    0ffh        ; Number for each diskette
  59. track_buf    db    512 * 10 dup(0)    ; Track buffer for reading and writing
  60. drive_num    db    0        ; The drive assigned to VHARD
  61. vhard_vnum    dw    0        ; Version of VHARD
  62. VHARD_BPB    DOS_BPB <>        ; BPB gotten from VHARD
  63.  
  64.         dw    81h        ; Pointer to our command tail
  65. our_PSP        dw    0        ; Our PSP segment
  66.  
  67. ;
  68. ; This block is used to pass commands to VHPREP
  69. ;
  70. command_blk    VH_CMD <>
  71.  
  72. vhctl_name    db    'VHARDCTL',0    ; Name of control driver for VHARD
  73. vhctl_handle    dw    0        ; Handle for VHARDCTL
  74. not_installed    db    13,10,'The VHARD driver is not installed.',13,10,'$'
  75. insert_disk    db    13,10,'Put a blank diskette in drive A:, then press'
  76.         db    ' a key $'
  77. label_disk    db    'Label this diskette $'
  78. disk_bad    db    7,13,10,'This diskette is unusable!',13,10,'$'
  79. crlf_str    db    13,10,'$'
  80.  
  81. err_prefix    db    7,'Error: $'
  82.  
  83. err0        db    'spurious error message$'
  84. err1        db    'drive/adapter failed or no disk in drive$'
  85. err2        db    'seek operation failed$'
  86. err3        db    'disk adapter failed$'
  87. err4        db    'CRC error$'
  88. err5        db    'attempt to DMA across segment boundary$'
  89. err6        db    'DMA overrun$'
  90. err7        db    'sector not found$'
  91. err8        db    'diskette is write-protected$'
  92. err9        db    'address mark not found$'
  93. err10        db    'invalid BIOS command$'
  94. err11        db    'internal command error$'
  95. err0ff        db    'unknown BIOS error code$'
  96.  
  97. error_msgs    dw    err0, err1, err2, err3, err4, err5, err6, err7, err8
  98.         dw    err9, err10, err11, err0, err0, err0ff
  99.  
  100. vhprep_data    ends
  101.  
  102.  
  103. vhprep_stack    segment    word    stack
  104.  
  105.     dw    256 dup(0)
  106.  
  107. vhprep_stack    ends
  108.  
  109.  
  110. ;*****************************************************************************
  111. ;
  112. ; This gets written to the actual boot sector of each diskette. As you can
  113. ; see, it just spits out a message, waits for a key, then tries to IPL again.
  114. ;
  115. ;*****************************************************************************
  116. boot_code_seg    segment    para
  117.  
  118. assume    cs:boot_code_seg, ds:boot_code_seg
  119.  
  120.     org    0
  121. boot_code    proc    near
  122.  
  123.     jmp    short boot_msg_disp    ; Jump to message display code
  124.     db    17 dup(?)        ; Place keeper for disk ID & number
  125. boot_msg_disp:
  126.     cld                ; Make sure of direction
  127.     call    do_display        ; Do the display
  128.     db    7,'This is NOT a bootable diskette!',13,10
  129.     db    'Put a different disk in the drive, and press a key to'
  130.     db    ' try again',13,10,0
  131. do_display:
  132.     pop    si            ; Point to the string to display
  133. ddsp_l1:
  134.     lods    byte ptr cs:[si]    ; Get a byte
  135.     or    al,al            ; End of string yet?
  136.     jz    ddsp_l2            ; Yep - just hang up now
  137.     mov    ah,14            ; BIOS "Write TTY" function
  138.     int    10h            ;
  139.     jmp    short ddsp_l1        ; Loop back for the rest
  140. ddsp_l2:
  141.     sub    ah,ah            ; Get a key
  142.     int    16h            ;
  143.     int    19h            ; Try to IPL again
  144.     jmp    $            ; Hang up now
  145.  
  146. boot_code_end    label    byte
  147.  
  148. boot_code    endp
  149.  
  150. boot_code_seg    ends
  151.  
  152.  
  153.     subttl    Start of program code
  154.     page
  155.  
  156. vhprep_code    segment
  157.  
  158. assume    cs:vhprep_code, ds:vhprep_data, es:vhprep_data, ss:vhprep_stack
  159.  
  160.  
  161. start    proc
  162.  
  163.     call    initialize        ; Set things up
  164.     call    do_prep            ; Do the preparation
  165.     call    terminate        ; Do program cleanup
  166.     mov    ax,4c00h        ;
  167.     int    21h            ;
  168.  
  169. start    endp
  170.  
  171.  
  172. ;*****************************************************************************
  173. ;
  174. ; Program initialization.
  175. ;
  176. ; Make sure the VHARDCTL driver is present, and get driver info from it.
  177. ;
  178. ;*****************************************************************************
  179. initialize    proc    near
  180.  
  181.     mov    ax,vhprep_data        ; Get our data segment
  182.     mov    ds,ax            ;
  183.     mov    our_PSP,es        ; Save our PSP segment
  184.     mov    es,ax            ;
  185.     mov    dx,offset vhctl_name    ; Try to open VHARDCTL, read/write
  186.     mov    ax,3d02h        ;
  187.     int    21h            ;
  188.     jnc    init_l1            ; If it opened, make sure it's a dev
  189. init_noway:
  190.     mov    dx,offset not_installed    ; Complain that it isn't there
  191.     mov    ah,9            ;
  192.     int    21h            ;
  193.     mov    ax,4c01h        ; Exit with errorlevel of 1
  194.     int    21h            ;
  195. init_l1:
  196.     mov    vhctl_handle,ax        ; Save the handle for other ops
  197.     mov    bx,ax            ; Get the handle for IOCTL call
  198.     mov    ax,4400h        ; Get info on this guy
  199.     int    21h            ;
  200.     test    dl,80h            ; Is this a device?
  201.     jz    init_noway        ; Nope - no way we're doing anything
  202.     mov    command_blk.VC_cmd_code,CMD_GETDATA
  203.     mov    word ptr command_blk.VC_buffer[0],offset drive_num
  204.     mov    word ptr command_blk.VC_buffer[2],ds
  205.     mov    ax,4403h        ; Get data from VHARDCTL
  206.     mov    dx,offset command_blk    ;
  207.     mov    cx,size VH_CMD        ;
  208.     int    21h            ;
  209.     call    get_cmdline_parms    ; Get a parameters from the cmd line
  210.     cmp    byte ptr ID_to_use[0],' '; Did they supply an ID?
  211.     jne    init_exit        ; Yep - don't change it
  212.     mov    ah,0            ; Get timer count from BIOS
  213.     int    1ah            ; Returns CX:DX
  214.     mov    ax,'HV'            ; Set up disk ID
  215.     mov    word ptr ID_to_use[0],ax;
  216.     mov    ax,cx            ; Use the time as part of the ID
  217.     mov    di,offset ID_to_use[2]    ;
  218.     call    store2digits        ;
  219.     mov    al,dh            ;
  220.     call    store2digits        ;
  221.     mov    al,dl            ;
  222.     call    store2digits        ;
  223. init_exit:
  224.     ret                ; Return to Main
  225.  
  226. initialize    endp
  227.  
  228.  
  229. ;*****************************************************************************
  230. ;
  231. ; Get any command line parameters
  232. ;
  233. ; The only parameters allowed are a disk ID and a disk number.
  234. ;
  235. ;*****************************************************************************
  236. get_cmdline_parms    proc    near
  237.  
  238.     push    es            ; Save it for this
  239.     les    si,dword ptr our_PSP[-2]; Point to the command tail
  240.     call    skip_spaces        ; Skip any whitespace
  241.     mov    cx,8            ; Max to copy
  242.     mov    di,offset ID_to_use    ;
  243. gcmp_l1:
  244.     lods    byte ptr es:[si]    ; Get a byte
  245.     cmp    al,' '            ; Whitespace?
  246.     je    gcmp_l3            ; Yep - stop copying
  247.     cmp    al,9            ;
  248.     je    gcmp_l3            ;
  249.     cmp    al,0dh            ; End of it?
  250.     je    gcmp_exit        ; Yep - exit
  251.     cmp    al,'a'            ; Lower case?
  252.     jb    gcmp_l2            ; No - never mind
  253.     cmp    al,'z'            ;
  254.     ja    gcmp_l2            ;
  255.     xor    al,20h            ; Make it upper case
  256. gcmp_l2:
  257.     jcxz    gcmp_l1            ; Don't store if ID is full
  258.     mov    [di],al            ; Save the byte
  259.     inc    di            ; Point to next spot
  260.     dec    cx            ; Knock off the count
  261.     jmp    gcmp_l1            ; Loop back
  262. gcmp_l3:
  263.     call    skip_spaces        ; Skip any other whitespace
  264.     sub    bl,bl            ; Clear accumulator
  265. gcmp_l4:
  266.     lods    byte ptr es:[si]    ; Pick up a byte
  267.     cmp    al,'0'            ; Valid digit?
  268.     jb    gcmp_l5            ; Nope - stop now
  269.     cmp    al,'9'            ;
  270.     ja    gcmp_l5            ;
  271.     sub    al,'0'            ; Make digit binary
  272.     mov    bh,bl            ; Multiply current value by 10
  273.     shl    bh,1            ;  by (BL * 2) + (BL * 8)
  274.     shl    bl,1            ;
  275.     shl    bl,1            ;
  276.     shl    bl,1            ;
  277.     add    bl,al            ; Add in new digit
  278.     jmp    short gcmp_l4        ; Loop back
  279. gcmp_l5:
  280.     cmp    bl,12            ; Make sure it's legal
  281.     ja    gcmp_exit        ;
  282.     mov    disk_num,bl        ; Save the number
  283. gcmp_exit:
  284.     pop    es            ;
  285.     ret                ; Return to initialization
  286.  
  287. get_cmdline_parms    endp
  288.  
  289.  
  290. ;*****************************************************************************
  291. ;
  292. ; Skip whitespace characters at ES:SI
  293. ;
  294. ;*****************************************************************************
  295. skip_spaces    proc    near
  296.  
  297. sksp_l1:
  298.     mov    al,es:[si]        ; Get a byte
  299.     cmp    al,' '            ; Whitespace?
  300.     je    sksp_l2            ; Yep - skip it
  301.     cmp    al,9            ;
  302.     jne    sksp_exit        ; No - exit now
  303. sksp_l2:
  304.     inc    si            ; Skip this character
  305.     jmp    short sksp_l1        ; Loop back
  306. sksp_exit:
  307.     ret                ; Return to caller
  308.  
  309. skip_spaces    endp
  310.  
  311.  
  312. ;*****************************************************************************
  313. ;
  314. ; Convert AL to 2 hex digits, storing them at DI.
  315. ;
  316. ;*****************************************************************************
  317. store2digits    proc    near
  318.  
  319.     push    ax            ; Save it for a second
  320.     mov    cl,4            ; Move high nybble down
  321.     shr    al,cl            ;
  322.     call    store_nybble        ; Store it as ASCII
  323.     pop    ax            ; Get low nybble back
  324. store_nybble:
  325.     and    al,0fh            ; Just keep low nybble
  326.     add    al,90h            ; Convert to ASCII hex
  327.     daa                ;
  328.     adc    al,40h            ;
  329.     daa                ;
  330.     stosb                ; Store digit
  331.     ret                ; Return to caller
  332.  
  333. store2digits    endp
  334.  
  335.  
  336. ;*****************************************************************************
  337. ;
  338. ; Take care of any cleanup prior to returning to DOS.
  339. ; All we do is close the handle for VHARDCTL.
  340. ;
  341. ;*****************************************************************************
  342. terminate    proc    near
  343.  
  344.     mov    bx,vhctl_handle        ; Get the handle
  345.     mov    ah,3eh            ; Close it
  346.     int    21h            ;
  347.     ret                ; Return to Main
  348.  
  349. terminate    endp
  350.  
  351.  
  352. ;*****************************************************************************
  353. ;
  354. ; Do the actual preparation
  355. ;
  356. ; Format disk 0, writing a DOS boot sector, 2 copies of the FAT, and an
  357. ; empty root directory (empty except for a volume label that is the disk ID).
  358. ;
  359. ; Once disk 0 is taken care of, just format the rest of the disks.
  360. ;
  361. ;*****************************************************************************
  362. do_prep        proc    near
  363.  
  364.     cmp    disk_num,0ffh        ; Did they specify a disk?
  365.     je    dopr_l2            ; No - do all disks
  366.     cmp    disk_num,0        ; Is it the first disk?
  367.     jne    dopr_l1            ; No - do a normal disk
  368.     call    do_first_disk        ; Do just the first disk
  369.     jmp    short dopr_exit        ; Exit
  370. dopr_l1:
  371.     call    do_one_disk        ; Just do this disk
  372.     jmp    short dopr_exit        ;
  373. dopr_l2:
  374.     mov    disk_num,0        ;
  375.     call    do_first_disk        ; Set up the first disk
  376.     mov    cx,12            ; 12 more to do
  377.     mov    disk_num,1        ; Starting with disk 1
  378. dopr_l3:
  379.     call    do_one_disk        ; Do this disk
  380.     inc    disk_num        ; Set for next one
  381.     loop    dopr_l3            ; Loop for all 12 disks
  382. dopr_exit:
  383.     ret                ; Return to Main
  384.     
  385. do_prep        endp
  386.  
  387.  
  388. ;*****************************************************************************
  389. ;
  390. ; Prepare the first diskette. This requires special treatment because it also
  391. ; contains the DOS boot sector, 2 copies of a FAT, and a root directory.
  392. ;
  393. ;*****************************************************************************
  394. do_first_disk    proc    near
  395.  
  396. dfdk_l1:
  397.     call    format_disk        ; Format the first disk
  398.     call    copy_boot_sect        ; Copy the boot sector to track buf
  399.     mov    di,offset track_buf[512].DBS_BPB
  400.     mov    si,offset VHARD_BPB
  401.     mov    cx,size DOS_BPB
  402.     rep    movsb
  403.     mov    word ptr track_buf[512 * 2],0fffch    ; Set up 2 empty FATs
  404.     mov    track_buf[(512 * 2) + 2],0ffh        ;
  405.     mov    word ptr track_buf[6 * 512],0fffch    ;
  406.     mov    track_buf[(6 * 512) + 2],0ffh        ;
  407.     sub    ax,ax            ;
  408.     call    write_track        ; Write it
  409.     jc    dfdk_err        ; If unable, complain
  410.     call    clear_track_buf        ; Wipe it clean
  411.     mov    di,offset track_buf    ; Point to first root dir entry
  412.     mov    si,offset ID_to_use    ; Use the disk ID as the vol label
  413.     mov    cx,4            ;
  414.     rep    movsw            ;
  415.     mov    al,' '            ; Fill it out with spaces
  416.     stosb                ;
  417.     stosb                ;
  418.     stosb                ;
  419.     mov    al,8            ; Attribute byte for volume label
  420.     stosb                ;
  421.     mov    cx,5            ; Fill 10 reserved bytes w/0
  422.     sub    al,al            ;
  423.     rep    stosw            ;
  424.     mov    ah,2ch            ; Get time from DOS
  425.     int    21h            ;
  426.     mov    ah,ch            ; Get the hour
  427.     shl    ah,1            ; Put it in the high 5 bits
  428.     shl    ah,1            ;
  429.     shl    ah,1            ;
  430.     mov    ch,0            ; Make the minutes a word
  431.     mov    bx,cx            ; Into a temp register
  432.     mov    cl,5            ; Move the minutes into middle 6 bits
  433.     shl    bx,cl            ;
  434.     or    ax,bx            ; Add to time
  435.     shr    dh,1            ; Make seconds 2-sec intervals
  436.     or    al,dh            ; Finish with that
  437.     stosw                ; Put the timestamp into the dir entry
  438.     mov    ah,2ah            ; Get the date from DOS
  439.     int    21h            ;
  440.     sub    cx,1980            ; Make the year the way DOS wants
  441.     mov    ax,cx            ;
  442.     mov    cl,7            ; Move to high 7 bits
  443.     ror    ax,cl            ;
  444.     mov    bl,dh            ; Get the month
  445.     sub    bh,bh            ;  as a word
  446.     mov    cl,5            ; Put it in the middle
  447.     shl    bx,cl            ;
  448.     or    ax,bx            ; Add to date
  449.     or    al,dl            ; Add the days
  450.     stosw                ; Put it in the dir entry
  451.     mov    ax,100h            ; Write track 0, head 1
  452.     call    write_track        ;
  453.     jc    dfdk_err
  454.     call    show_label        ; Tell 'em how to label it
  455. dfdk_exit:
  456.     ret                ; Return to caller
  457. ;
  458. dfdk_err:
  459.     call    report_error        ; Complain about the error
  460.     mov    dx,offset disk_bad    ; Let 'em know the disk is bad
  461.     mov    ah,9            ;
  462.     int    21h            ;
  463.     jmp    dfdk_l1
  464.  
  465. do_first_disk    endp
  466.  
  467.  
  468. ;*****************************************************************************
  469. ;
  470. ; Prepare a disk other than the first one. Just format it and write a boot
  471. ; sector.
  472. ;
  473. ;*****************************************************************************
  474. do_one_disk    proc    near
  475.  
  476. dodk_l1:
  477.     call    format_disk        ; Format this disk
  478.     call    copy_boot_sect        ; Copy the boot sector to track_buf
  479.     mov    al,0            ; Write this track
  480.     call    write_track        ;
  481.     jnc    dodk_exit        ;
  482.     call    report_error        ; Complain about the error
  483.     mov    dx,offset disk_bad    ; Let 'em know the disk is bad
  484.     mov    ah,9            ;
  485.     int    21h            ;
  486.     jmp    short dodk_l1
  487. dodk_exit:
  488.     call    show_label        ; Tell 'em what the label is
  489.     ret                ; Return to caller
  490.  
  491. do_one_disk    endp
  492.  
  493.  
  494. ;*****************************************************************************
  495. ;
  496. ; Copy the boot sector into the first sector of the track buffer
  497. ;
  498. ;*****************************************************************************
  499. copy_boot_sect    proc    near
  500.  
  501.     save    cx, si, di
  502.     call    clear_track_buf        ; Wipe out our track buffer
  503.     push    ds            ; Save Our Segment
  504.     mov    cx,boot_code_seg    ; Point to our boot code
  505.     mov    ds,cx            ;
  506.  
  507. assume    ds:boot_code_seg
  508.  
  509.     mov    si,offset boot_code    ; Point to the boot code
  510.     mov    cx,offset boot_code_end    ; Number of bytes to copy
  511.     mov    di,offset track_buf    ; Where to put it
  512.     rep    movsb            ; Copy boot code to track buffer
  513.     pop    ds            ; Get our segment back
  514.  
  515. assume    ds:vhprep_data
  516.  
  517.     mov    si,offset ID_to_use    ; Point to disk ID
  518.     mov    di,offset track_buf.BS_disk_id
  519.     mov    cx,4            ;
  520.     rep    movsw            ; Copy disk ID to boot sector
  521.     mov    cl,disk_num        ; Copy disk # to boot sector
  522.     mov    track_buf.BS_disk_num,cl;
  523.     sub    ax,ax            ; Write track 0/head 0
  524.     call    write_track        ;
  525.     restore
  526.     ret                ; Return to caller
  527.  
  528. copy_boot_sect    endp
  529.  
  530.  
  531. ;*****************************************************************************
  532. ;
  533. ; Fill the track buffer with 0s.
  534. ;
  535. ;*****************************************************************************
  536. clear_track_buf    proc    near
  537.  
  538.     save    ax, cx, di
  539.     mov    cx,512 * 5        ; Number of words to clear
  540.     mov    di,offset track_buf    ; What to clear
  541.     sub    ax,ax            ; Fill with 0
  542.     cld                ; Make sure of direction
  543.     rep    stosw            ; Fill the buffer
  544.     restore
  545.     ret                ; Return to caller
  546.  
  547. clear_track_buf    endp
  548.  
  549.  
  550. ;*****************************************************************************
  551. ;
  552. ; Prompt for a disk, then format all tracks.
  553. ;
  554. ;*****************************************************************************
  555. format_disk    proc    near
  556.  
  557.     save    ax, cx, dx
  558. fmtd_l1:
  559.     mov    dx,offset insert_disk    ; Display the prompt
  560.     mov    ah,9            ;
  561.     int    21h            ;
  562.     mov    ax,0c08h        ; Get a key
  563.     int    21h            ;
  564.     or    al,al            ; Fn key?
  565.     jnz    fmtd_l2            ; Nope - continue
  566.     mov    ah,8            ; Read the second character
  567.     int    21h            ;
  568. fmtd_l2:
  569.     mov    dx,offset crlf_str    ; Newline
  570.     mov    ah,9            ;
  571.     int    21h            ;
  572.     sub    ax,ax            ; Start with track 0
  573. ;    inc    ah            ;
  574.     mov    cx,40            ; 40 tracks to do
  575. fmtd_l3:
  576.     call    format_track        ; Format head 0 of the track
  577.     jc    fmtd_err        ; Complain on error
  578.     xor    ah,1            ; Other head
  579.     call    format_track        ;
  580.     jc    fmtd_err        ; Complain on error
  581.     xor    ah,1            ; Head 0 again
  582.     inc    al            ; Next cylinder
  583.     loop    fmtd_l3            ; Loop for the whole disk
  584.     restore
  585.     ret                ; Return to caller
  586. fmtd_err:
  587. ;
  588. ; An error occurred during the format. Report the error, let them know the
  589. ; disk is unusable, then prompt for another.
  590. ;
  591.     call    report_error        ; Report the error
  592.     mov    dx,offset disk_bad    ; Let 'em know the disk is bad
  593.     mov    ah,9            ;
  594.     int    21h            ;
  595.     jmp    fmtd_l1            ; Try with another disk
  596.  
  597. format_disk    endp
  598.  
  599.  
  600. ;*****************************************************************************
  601. ;
  602. ; Issue a format command for the track in AL/head in AH
  603. ;
  604. ;*****************************************************************************
  605. format_track    proc    near
  606.  
  607.     save    ax, bx, cx, dx, di
  608. ;
  609. ; Before we can do the format, we need to set up the track buffer with the
  610. ; array of format parameters. Each entry in the array is 4 bytes, structured:
  611. ;    byte 0        track
  612. ;    byte 1        head
  613. ;    byte 2        sector
  614. ;    byte 3        sector size (2 in this case)
  615. ;
  616.     mov    di,offset track_buf    ; Point to the buffer
  617.     mov    cx,10            ; 10 entries
  618.     mov    bx,201h            ; Starting with sector 1
  619. fmtt_l1:
  620.     stosb                ; Store the track
  621.     mov    [di],ah            ; Store the head
  622.     inc    di            ;
  623.     mov    [di],bl            ; Now the sector number
  624.     inc    bl            ;
  625.     inc    di            ;
  626.     mov    byte ptr[di],2        ; Sector size
  627.     inc    di            ;
  628.     loop    fmtt_l1            ; Loop for all entries
  629.     mov    command_blk.VC_cmd_code,CMD_FORMAT    ; Command code
  630.     ror    ah,1            ; Put the head in the high bit
  631.     or    al,ah            ; Add to track number
  632.     mov    command_blk.VC_track,al    ; Pass it in the command block
  633.     mov    word ptr command_blk.VC_buffer[0],offset track_buf
  634.     mov    word ptr command_blk.VC_buffer[2],ds
  635.     mov    dx,offset command_blk    ; Point to the block
  636.     mov    ax,4403h        ; IOCTL Write to the VHARDCTL device
  637.     mov    bx,vhctl_handle
  638.     mov    cx,size VH_CMD
  639.     int    21h
  640.     cmp    command_blk.VC_status,STS_OK + 1    ; Get the status
  641.     cmc                ; Set CF to 1 if error
  642.     restore
  643.     ret                ; Return to caller
  644.  
  645. format_track    endp
  646.  
  647.  
  648. ;*****************************************************************************
  649. ;
  650. ; Write track_buf to the track in AL/head in AH
  651. ;
  652. ;*****************************************************************************
  653. write_track    proc    near
  654.  
  655.     save    ax, bx, cx, dx
  656.     mov    command_blk.VC_cmd_code,CMD_WRITE
  657.     ror    ah,1
  658.     or    al,ah
  659.     mov    command_blk.VC_track,al
  660.     mov    word ptr command_blk.VC_buffer[0],offset track_buf
  661.     mov    word ptr command_blk.VC_buffer[2],ds
  662.     mov    dx,offset command_blk
  663.     mov    ax,4403h
  664.     mov    bx,vhctl_handle
  665.     mov    cx,size VH_CMD
  666.     int    21h
  667.     cmp    command_blk.VC_status,STS_OK + 1
  668.     cmc
  669.     restore
  670.     ret
  671.  
  672. write_track    endp
  673.  
  674. ;*****************************************************************************
  675. ;
  676. ; Report an error based on the status byte in the command block.
  677. ;
  678. ;*****************************************************************************
  679. report_error    proc    near
  680.  
  681.     save    ax, bx, dx
  682.     mov    dx,offset err_prefix    ; Display the error message prefix
  683.     mov    ah,9            ;
  684.     int    21h            ;
  685.     mov    bl,command_blk.VC_status; Get returned status
  686.     sub    bh,bh            ; Make it a word
  687.     shl    bx,1            ; Make it a word offset
  688.     mov    dx,error_msgs[bx]    ; Get the appropriate error message
  689.     mov    ah,9            ;
  690.     int    21h            ;
  691.     mov    dx,offset crlf_str    ; Newline
  692.     mov    ah,9            ;
  693.     int    21h            ;
  694.     restore
  695.     ret                ; Return to caller
  696.  
  697. report_error    endp
  698.  
  699.  
  700. ;*****************************************************************************
  701. ;
  702. ; Tell the user what label to put on this diskette
  703. ;
  704. ;*****************************************************************************
  705. show_label    proc    near
  706.  
  707.     save    ax, bx, cx, dx
  708.     mov    dx,offset label_disk    ; Tell them to label the disk
  709.     mov    ah,9            ;
  710.     int    21h            ;
  711.     mov    dx,offset ID_to_use    ; Tell them what to label it with
  712.     mov    cx,8            ;
  713.     mov    bx,1            ;
  714.     mov    ah,40h            ; Use IOCTL Write to do it
  715.     int    21h            ;
  716.     mov    ah,2            ;
  717.     mov    dl,' '            ;
  718.     int    21h            ;
  719.     mov    ah,2            ;
  720.     mov    dl,'#'            ;
  721.     int    21h            ;
  722.     mov    al,disk_num        ; Display the disk number
  723.     aam                ;
  724.     or    ax,3030h        ;
  725.     push    ax            ;
  726.     mov    dl,ah            ;
  727.     mov    ah,2            ;
  728.     int    21h            ;
  729.     pop    dx            ;
  730.     mov    ah,2            ;
  731.     int    21h            ;
  732.     mov    dx,offset crlf_str    ; Finish off with a newline
  733.     mov    ah,9            ;
  734.     int    21h            ;
  735.     restore
  736.     ret                ; Return to caller
  737.  
  738. show_label    endp
  739.  
  740.  
  741. vhprep_code    ends
  742.  
  743.  
  744.     end    start
  745.