home *** CD-ROM | disk | FTP | other *** search
/ PC World 1999 August / PCWorld_1999-08_cd.bin / dosutils / fips20 / source / disk_io.cpp < prev    next >
C/C++ Source or Header  |  1997-12-20  |  7KB  |  268 lines

  1. /*
  2.     FIPS - the First nondestructive Interactive Partition Splitting program
  3.  
  4.     Module disk_io.cpp
  5.  
  6.     RCS - Header:
  7.     $Header: c:/daten/fips/source/main/RCS/disk_io.cpp 1.4 1995/01/19 00:00:51 schaefer Exp schaefer $
  8.  
  9.     Copyright (C) 1993 Arno Schaefer
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.  
  26.     Report problems and direct all questions to:
  27.  
  28.     schaefer@rbg.informatik.th-darmstadt.de
  29. */
  30.  
  31. #include "disk_io.h"
  32. #include <dos.h>
  33. #include <bios.h>
  34.  
  35. #define DISK_INT 0x13
  36.  
  37. #define RESET_DISK 0
  38. #define READ_SECTOR 2
  39. #define WRITE_SECTOR 3
  40. #define VERIFY_SECTOR 4
  41. #define GET_DRIVE_PARAMS 8
  42. #define GET_DISK_TYPE 0x15
  43.  
  44.  
  45. /* ----------------------------------------------------------------------- */
  46. /* Bios call to get the number of drives attached                          */
  47. /* ----------------------------------------------------------------------- */
  48.  
  49. int get_no_of_drives (void)
  50. {
  51.     union REGS regs;
  52.  
  53.     regs.h.ah = GET_DRIVE_PARAMS;
  54.     regs.h.dl = 0x80;
  55.     int86 (DISK_INT, ®s, ®s);
  56.  
  57.     if (regs.h.ah != 0) return (1); // will be checked again
  58.     return (regs.h.dl);
  59. }
  60.  
  61.  
  62. /* ----------------------------------------------------------------------- */
  63. /* Calculates physical sector number (Head, Cylinder, Sector).             */
  64. /* Log_sector is absolute logical sector number (0 = master boot record).  */
  65. /* ----------------------------------------------------------------------- */
  66.  
  67. physical_sector_no::physical_sector_no
  68. (
  69.     dword logical_sector,
  70.     const drive_geometry &geometry
  71. )
  72. {
  73.     cylinder =
  74.         logical_sector
  75.         / (geometry.heads * geometry.sectors);
  76.  
  77.     head =
  78.     (
  79.         logical_sector
  80.         - (cylinder * geometry.heads * geometry.sectors)
  81.     )
  82.     / geometry.sectors;
  83.  
  84.     sector =
  85.         logical_sector
  86.         - (cylinder * geometry.heads * geometry.sectors)
  87.         - (head * geometry.sectors)
  88.         + 1;
  89. }
  90.  
  91.  
  92. /* ----------------------------------------------------------------------- */
  93. /* Bios call get_drive_geometry, returns error status in var errorcode     */
  94. /* ----------------------------------------------------------------------- */
  95.  
  96. void physical_drive::get_geometry (void)
  97. {
  98.     union REGS regs;
  99.  
  100.     regs.h.ah = GET_DRIVE_PARAMS;
  101.     regs.h.dl = number;
  102.     int86 (DISK_INT, ®s, ®s);
  103.  
  104.     if ((errorcode = regs.h.ah) != 0) return;
  105.  
  106.     geometry.heads = (dword) regs.h.dh + 1;
  107.     geometry.sectors = (dword) regs.h.cl & 0x3f;
  108.     geometry.cylinders =
  109.     (
  110.         (dword) regs.h.ch
  111.         | (((dword) regs.h.cl << 2) & 0x300)
  112.     ) + 1;
  113. }
  114.  
  115.  
  116. /* ----------------------------------------------------------------------- */
  117. /* Bios call reset_drive, returns error status in var errorcode            */
  118. /* ----------------------------------------------------------------------- */
  119.  
  120. void physical_drive::reset (void)
  121. {
  122.     union REGS regs;
  123.  
  124.     regs.h.ah = RESET_DISK;
  125.     regs.h.dl = number;
  126.     int86 (DISK_INT, ®s, ®s);
  127.  
  128.     errorcode = regs.h.ah;
  129. }
  130.  
  131.  
  132. /* ----------------------------------------------------------------------- */
  133. /* Initialization physical_drive, requires drive number.                   */
  134. /* Calls get_drive_geometry, errorcode contains return status              */
  135. /* ----------------------------------------------------------------------- */
  136.  
  137. physical_drive::physical_drive (int number)
  138. {
  139.     physical_drive::number = number;
  140.     get_geometry ();
  141. };
  142.  
  143.  
  144. /* ----------------------------------------------------------------------- */
  145. /* Initialization physical_drive with physical_drive object                */
  146. /* ----------------------------------------------------------------------- */
  147.  
  148. physical_drive::physical_drive (physical_drive &pd)
  149. {
  150.     number = pd.number;
  151.     errorcode = pd.errorcode;
  152.     geometry = pd.geometry;
  153. }
  154.  
  155.  
  156. /* ----------------------------------------------------------------------- */
  157. /* Assignment operator for physical drive                                  */
  158. /* ----------------------------------------------------------------------- */
  159.  
  160. void physical_drive::operator= (physical_drive &pd)
  161. {
  162.     number = pd.number;
  163.     errorcode = pd.errorcode;
  164.     geometry = pd.geometry;
  165. }
  166.  
  167.  
  168. /* ----------------------------------------------------------------------- */
  169. /* Read sector                                                             */
  170. /* ----------------------------------------------------------------------- */
  171.  
  172. int physical_drive::read_sector (struct sector *sector, dword sector_number)
  173. {
  174.     physical_sector_no p (sector_number, geometry);
  175.  
  176.     boolean done = false;
  177.  
  178.     for (int i=0; i<3; i++)
  179.     {
  180.         if (biosdisk
  181.         (
  182.             READ_SECTOR,
  183.             number,
  184.             p.head,
  185.             p.cylinder,
  186.             p.sector,
  187.             1,
  188.             sector->data
  189.         ) == 0)
  190.         {
  191.             done=true;
  192.             break;
  193.         }
  194.  
  195.         reset ();
  196.     }
  197.  
  198.     if (!done) return (-1);
  199.     return 0;
  200. }
  201.  
  202.  
  203. /* ----------------------------------------------------------------------- */
  204. /* Write sector with verify                                                */
  205. /* ----------------------------------------------------------------------- */
  206.  
  207. int physical_drive::write_sector (struct sector *sector, dword sector_number)
  208. {
  209.     physical_sector_no p (sector_number,geometry);
  210.  
  211.     boolean done = false;
  212.  
  213.     for (int i=0; i<3; i++)
  214.     {
  215.         if (biosdisk
  216.         (
  217.             WRITE_SECTOR,
  218.             number,
  219.             p.head,
  220.             p.cylinder,
  221.             p.sector,
  222.             1,
  223.             sector->data
  224.         ) == 0)
  225.         {
  226.             done=true;
  227.             break;
  228.         }
  229.  
  230.         reset ();
  231.     }
  232.  
  233.     if (!done) return (-1);
  234.  
  235.     if (biosdisk
  236.     (
  237.         VERIFY_SECTOR,
  238.         number,
  239.         p.head,
  240.         p.cylinder,
  241.         p.sector,
  242.         1,
  243.         sector->data
  244.  
  245.     ) != 0) return (-1);
  246.  
  247.     return 0;
  248. }
  249.  
  250.  
  251. /* ----------------------------------------------------------------------- */
  252. /* Bios call get_disk_type - returns 0 if drive not present.               */
  253. /* Valid drive numbers: 0 - 255, result: 1 - floppy without disk change    */
  254. /* detection, 2 - floppy with disk change detection, 3 - harddisk          */
  255. /* ----------------------------------------------------------------------- */
  256.  
  257. int get_disk_type (int drive_number)
  258. {
  259.     union REGS regs;
  260.  
  261.     regs.h.ah = GET_DISK_TYPE;
  262.     regs.h.dl = drive_number;
  263.     int86 (DISK_INT, ®s, ®s);
  264.  
  265.     if (regs.x.cflag) return 0;
  266.     return (regs.h.ah);                     // disk type
  267. }
  268.