Retro video games delivered to your door every month!
Click above to get retro games delivered to your door ever month!
X-Hacker.org- Microsoft C 6.0 - <b>_bios_disk() disk i/o services, floppy and hard disks</b> http://www.X-Hacker.org [<<Previous Entry] [^^Up^^] [Next Entry>>] [Menu] [About The Guide]
 _bios_disk()            Disk I/O Services, Floppy and Hard Disks

 #include   <bios.h>

 unsigned   _bios_disk(service, disk_info);
  unsigned service;      ROM-BIOS disk service requested.

         Declared in dos.h, struct diskinfo_t holds values put into
         registers before a call to ROM-BIOS. See more detailed
         description of structure members just before Notes, below.

          struct diskinfo_t {
          unsigned drive;   Drive Number
          unsigned head;    Head Number
          unsigned track;   Track Number
          unsigned sector;  Start sector number
          unsigned nsectors;  Number of sectors to read, write, or compare
          void far *buffer; Memory location to write to, read to, or compare
          } *disk_info;

    _bios_disk() uses ROM-BIOS interrupt 13h (0x13) to provide six
    standard BIOS disk services common to all PC models. The 'service'
    argument, defined by one of the six manifest constants described
    below, selects the specific service desired. The disk_info argument
    points to a structure holding values for placement into the registers
    before the interrupt is called.

 ------------------------------- Services -------------------------------
 Specifies the  ROM-BIOS service requested. The standard services 0h-5h are
 supported by _bios_disk(). Specify the service desired by using one of
 the following manifest constants defined in bios.h:

 -------------------------------------------------------------------
 _DISK_RESET    Resets the fixed disk or diskette controller and drive,
                forcing recalibration of the read/write head by
                positioning it on a certain track. This is used after
                another disk operation returns a serious error, to
                prepare the drive for retrying the operation.  For this
                service, the disk_info argument is ignored.

 -------------------------------------------------------------------
 _DISK_STATUS   Returns the status of the most recent fixed or floppy
                disk operation. Using this service it is possible to
                diagnose the outcomes of the following read, write, and
                format services, as well the outcomes of the MS-DOS disk
                services. This permits detailed disk error-checking
                routines to be included in C programs.  For this service
                the disk_info argument is ignored.

                Status values are returned in the high-order 8 bits of
                the 2-byte return-value:

                    Value   Meaning                             Drive
                    --------------------------------------------------
                    FFh    Sense operation failed             (fixed)
                    E0h    Status error                       (fixed)
                    CCh    Write fault                        (fixed)
                    BBh    Undefined error                    (fixed)
                    AAh    Drive not ready                    (fixed)
                    80h    Drive not ready                    (floppy)
                    80H    Timeout                            (fixed)
                    40h    Seek failure
                    20h    Controller failure
                    11h    ECC corrected data error           (fixed)
                    10h    CRC or ECC data error
                    0Fh    DMA arbitration level out of range (fixed)
                    0Eh    Control data address mark detected (fixed)
                    0Dh    Invalid number sectors on format   (fixed)
                    0Ch    Media type not found               (floppy)
                    0Bh    Bad track found                    (fixed)
                    0Ah    Bad sector flag detected           (fixed)
                    09h    Attempt to DMA across a 64K boundary
                    08h    DMA overrun
                    07h    Drive parameter activity failed    (fixed)
                    06h    Diskette change line active        (floppy)
                    05h    Reset failed                       (fixed)
                    04h    Sector not found
                    03h    Attempt to write on write-protected disk
                    02h    Address mark not found
                    01h    Invalid command
                    00h    No error

 -------------------------------------------------------------------
  _DISK_READ    Reads one or more sectors from a fixed or floppy disk
                into memory. The fields of the structure that disk_info
                points to determines what is read: it reads the specified
                number of sectors (nsectors) starting at the specified
                location (head, track, and sector) from the specified
                disk (drive) into the specified memory location (buffer).
                The sectors read must all be on the same track and same
                side (head) for diskettes, while a hard disk can read at
                most 128 sectors at one time.

                This service returns the status value in the high-order
                byte (see _DISK_STATUS codes above) and the number of
                sectors read in the low-order byte. The low-order byte
                may not give the correct number of sectors, even though
                no error has occurred.

 -------------------------------------------------------------------
 _DISK_WRITE    Writes one or more sectors from memory to a fixed or
                floppy disk.  The fields of the structure that disk_info
                points to determines what is written: it writes the
                specified number of sectors (nsectors) from the specified
                memory location (buffer) to the specified disk location
                (drive, head, track, sector). The sectors written must
                all be on the same track and same side (head) for
                diskettes, while a hard disk can write at most 128
                sectors at one time.

                This service returns the status value in the high-order
                byte (see _DISK_STATUS codes above) and the number of
                sectors written in the low-order byte. The low-order byte
                may not give the correct number of sectors, even though
                no error has occurred.

 -------------------------------------------------------------------
 _DISK_VERIFY   Verifies one or more fixed disk or diskette sectors. The
                verification process consists of checking that the
                sectors can be found and read (checking address fields)
                and that the Cyclic Redundancy Check (CRC) is correct.
                The fields of the structure that disk_info points to
                determines what is verified: it verifies the specified
                number of sectors (nsectors) beginning at the specified
                disk location (drive, head, track, sector). No memory
                area is needed for this service.  The sectors written
                must all be on the same track and same side (head) for
                diskettes, while a hard disk can write at most 255
                sectors at one time.

                This service returns the status value in the high-order
                byte (see _DISK_STATUS codes above) and the number of
                sectors verified in the low-order byte. The low-order
                byte may not give the correct number of sectors, even
                though no error has occurred.

 -------------------------------------------------------------------
 _DISK_FORMAT   Formats the track specified (drive, head, track) by
                initializing each sector on the track with sector address
                and size information. The desired sector address and size
                information must be located in memory at the location pointed
                to by buffer. The value in nsectors specifies either the
                number of sectors to format (for diskettes) or the interleave
                (for hard disks).

  Interleave    "Interleaving" is the process of putting logically
                contiguous sectors in physically noncontiguous locations,
                in order to increase disk performance.  Below is outlined
                the different ways of changing the interleave factor
                depending on the type of media (fixed disk or diskette)
                and the machine type.

                The address and size list (buffer) varies depending
                on what type of machine and type of disk (fixed or
                diskette) the formatting process will occur on. Also
                the interleave factor is specified differently for
                the different machines and disk types. Below are the
                formats for the different types of machines and
                disks.

  Diskette      Buffer points to a list of address marks for each
                sector on the track to be formatted. Each address
                mark consists of 4 bytes. Therefore, to format a 9-
                sector track, the list must consist of 36 bytes (4 *
                9). The 4 bytes making up the address mark are
                defined as follows:

                    Byte 1 - Track number (T)
                    Byte 2 - Head number (H)
                    Byte 3 - Sector number (R), or Record number
                    Byte 4 - Sector Size (N)
                              0 - 128 bytes per sector
                              1 - 256 bytes per sector
                              2 - 512 bytes per sector
                              3 - 1024 bytes per sector

                    Note that you can change the interleave factor by
                    specifying byte 3 (sector number) in a non-sequential
                    order.

                    Standard MS-DOS diskettes are formatted with 512
                    bytes per sector (N=2) and with no interleave. Thus,
                    the address field list for a standard MS-DOS nine-
                    sector track would look like this:

                       T H R N    T H R N    T H R N ... T H R N
                       0 1 1 2    0 1 2 2    0 1 3 2     0 1 9 2

                    If there is more than one type of diskette supported
                    by the drive, _DISK_FORMAT will format the disk using
                    the maximum disk type supported by the disk drive.

               XT   The XT uses the nsectors value to specify the
                    interleave factor. The pointer buffer is not needed
                    for the XT.

    AT and XT-286   These machines use an address table (pointed to by
                    buffer), similar to the one used in diskette mode but
                    with a slight variation. The buffer must be 512 bytes
                    long. The first 2 * (sectors per track) bytes contain
                    information for each sector on the track.  For each
                    sector, there are 2 bytes in the table.  These 2
                    bytes are defined as follows:

                       Byte 1 - Sector Format state (F)
                                 00h - Good sector
                                 80h - Bad sector
                       Byte 2 - Sector number (N)

                    For example, the following table is used to format a
                    track for a fixed disk with 17 sectors per track and
                    an interleave factor of 3.

              00h  01h  00h  07h  00h  0Dh  00h  02h  00h  08h  00h  0Eh
              00h  03h  00h  09h  00h  0Fh  00h  04h  00h  0Ah  00h  10h
              00h  05h  00h  0Bh  00h  11h  00h  06h  00h  0Ch

 -------------------------------------------------------------------
   disk_info    Description of structure diskinfo_t field values.

         drive;     Drive Number: Values less than 80h specify floppy
                    disks; values greater than 80h specify fixed disks.
                    For example, 0 means the first floppy diskette, while
                    80h means the first fixed disk.

          head;     Head Number: 0 or 1 for diskettes; can be up to 15
                    for supported fixed disks.

         track;     Track Number: The track number is a ten-bit quantity
                    (0 through 1023). For diskettes it normally has a
                    value from 0 through 39. The XT hard disk normally
                    ranges from 0 to 306 and the AT 0 to 615; the PS/2
                    can be as large as 1023. Many references refer to
                    tracks as cylinders.

        sector;     Start sector number: For diskettes the sector number
                    normally ranges from 1 to 8 or 9, though high-
                    capacity diskettes will be either 15 or 18; for hard
                    disks from 1 to 17, except for some PS/2 models which
                    have 32. Note that sectors are numbered from 1,
                    unlike drives, tracks, or heads.

      nsectors;     Number of sectors to read, write, verify, or format.
                    Normally ranges from 0 to 128 or 255, depending on
                    the service selected (see services above).

        buffer;     Memory location to write to, read to, or read format
                    values from. The contents and use varies depending on
                    the service selected (see services above).

       Returns:     Different values, or nothing, depending on the
                    service selected (see services above).

         Notes:     For most disk operations the standard C stream or
                    low-level I/O routines would normally be used. The
                    BIOS interface disk services described here would
                    rarely be used except for highly specialized
                    applications, such as copy protection schemes, file
                    recovery utilities, or disk error-handling systems,
                    for example.

                    One major disadvantage to the use of the ROM-BIOS
                    disk services is that many necessary and complex
                    operations have to be explicitly coded by the
                    programmer, such as directory handling, end-of-file
                    operations, and blocking and deblocking of records.
                    These are normally handled automatically by the
                    operating system and are usually transparent to the
                    programmer. Another disadvantage is that ROM-BIOS
                    disk services are device-dependent, which means they
                    cannot access logical drives such as RAM-disks.
                    However, for the rare occasions that ROM-BIOS disk
                    services are needed, _bios_disk() provides easy
                    access to the six standard disk services available to
                    all PC-compatibles.

                    If an error is encountered reading, writing,
                    verifying, or formatting a sector, use _DISK_RESET to
                    reset the drive and retry the operation. For diskette
                    access, it is recommended that at least 3 retries be
                    attempted before an error is signalled, since the
                    error may have resulted from the diskette motor not
                    being up to speed.

                    There are 20 additional disk services that can be
                    accessed for the PS/2 (several of which also apply to
                    the XT, XT/286, and AT) using interrupt 13h. Use
                    int86() or int86x() if you wish to access these
                    services.

 Portability:   MS-DOS and PC-DOS only.

 ------------------------------ Example --------------------------------

 This program writes text to a diskette in drive A:, reads it back, and
 compares the two. Selected errors are reported to the console. The
 message is written to the absolute disk location head (side) 0, track 39,
 sector 1. To test the error-checking features put a write-protect tab on
 a diskette in the A: drive, and/or leave the drive door open, then run
 the program.

           #include <bios.h>
           #include <stdio.h>
           #include <memory.h>

           char *disk_error[] = {
                   "Please insert disk in drive A: and close drive door",
                   "Please remove write-protection from disk in drive A:",
                   "Unknown problem with disk drive A:" };

           char out_buffer[512] = {
                   "Write and read test of ROM-BIOS disk service 13h" };

           char in_buffer[512];

           main ()
           {
                   unsigned status;
                   struct diskinfo_t disk_info;
                   char *message;

                   disk_info.drive    = 0;     /* A: drive */
                   disk_info.head     = 0;     /* head (side) 0 */
                   disk_info.track    = 39;    /* track 39 */
                   disk_info.sector   = 1;     /* beginning sector */
                   disk_info.nsectors = 1;     /* write 512 bytes */
                   disk_info.buffer   = (void far *) out_buffer;

                   while (1)
                      {
                      status = _bios_disk(_DISK_WRITE, &disk_info);

                      if (status >> 8)
                         {
                         switch (status >> 8)
                            {
                            case 0x80: message = disk_error[0]; break;
                            case 0x03: message = disk_error[1]; break;
                              default: message = disk_error[2]; break;
                            }
                         _bios_disk(_DISK_RESET, &disk_info);

                         printf("\n\tWrite error:\n\n\t%s", message);
                         printf("\n\n\tPress any key when ready . . .");
                         _bios_keybrd(_KEYBRD_READ);
                         }
                      else
                         break;
                      }

                   disk_info.buffer   = (void far *) in_buffer;

                   while (2)
                      {
                      status = _bios_disk(_DISK_READ, &disk_info);

                      if (status >> 8)
                         {
                         switch (status >> 8)
                            {
                            case 0x80: message = disk_error[0]; break;
                            case 0x03: message = disk_error[1]; break;
                              default: message = disk_error[2]; break;
                            }
                         _bios_disk(_DISK_RESET, &disk_info);

                         printf("\n\tRead error:\n\n\t%s", message);
                         printf("\n\n\tPress any key when ready . . .");
                         _bios_keybrd(_KEYBRD_READ);
                         }
                      else
                         break;
                      }

                   if (memcmp(out_buffer, in_buffer, 512))
                      printf("\n\tUnsuccessful ROM-BIOS write and read");
                   else
                      printf("\n\tSuccessful ROM-BIOS write and read");


           }


See Also: int86() int86x()

Online resources provided by: http://www.X-Hacker.org --- NG 2 HTML conversion by Dave Pearson