disk_io.cpp
上传用户:yingdiyu
上传日期:2007-01-06
资源大小:116k
文件大小:7k
源码类别:

磁盘编程

开发平台:

Others

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