ReactOS  0.4.14-dev-49-gfb4591c
pcdisk.c File Reference
#include <freeldr.h>
#include <debug.h>
#include <pshpack2.h>
#include <poppack.h>
Include dependency graph for pcdisk.c:

Go to the source code of this file.

Classes

struct  I386_DISK_ADDRESS_PACKET
 
struct  I386_CDROM_SPEC_PACKET
 

Typedefs

typedef struct I386_DISK_ADDRESS_PACKETPI386_DISK_ADDRESS_PACKET
 
typedef struct I386_CDROM_SPEC_PACKETPI386_CDROM_SPEC_PACKET
 

Functions

 DBG_DEFAULT_CHANNEL (DISK)
 
LONG DiskReportError (BOOLEAN bShowError)
 
static PCSTR DiskGetErrorCodeString (ULONG ErrorCode)
 
static VOID DiskError (PCSTR ErrorString, ULONG ErrorCode)
 
BOOLEAN DiskResetController (UCHAR DriveNumber)
 
static BOOLEAN PcDiskReadLogicalSectorsLBA (UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
 
static BOOLEAN PcDiskReadLogicalSectorsCHS (UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
 
static BOOLEAN DiskInt13ExtensionsSupported (UCHAR DriveNumber)
 
BOOLEAN PcDiskReadLogicalSectors (UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
 
BOOLEAN DiskGetExtendedDriveParameters (UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize)
 
BOOLEAN PcDiskGetDriveGeometry (UCHAR DriveNumber, PGEOMETRY Geometry)
 
ULONG PcDiskGetCacheableBlockCount (UCHAR DriveNumber)
 

Variables

static LONG lReportError = 0
 

Typedef Documentation

◆ PI386_CDROM_SPEC_PACKET

◆ PI386_DISK_ADDRESS_PACKET

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( DISK  )

◆ DiskError()

static VOID DiskError ( PCSTR  ErrorString,
ULONG  ErrorCode 
)
static

Definition at line 123 of file pcdisk.c.

124 {
125  CHAR ErrorCodeString[200];
126 
127  if (lReportError < 0)
128  return;
129 
130  sprintf(ErrorCodeString, "%s\n\nError Code: 0x%lx\nError: %s",
132 
133  TRACE("%s\n", ErrorCodeString);
134 
135  UiMessageBox(ErrorCodeString);
136 }
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436
char CHAR
Definition: xmlstorage.h:175
#define sprintf(buf, format,...)
Definition: sprintf.c:55
static PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
Definition: pcdisk.c:88
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:320
#define TRACE(s)
Definition: solgame.cpp:4
static LONG lReportError
Definition: pcdisk.c:78

Referenced by PcDiskReadLogicalSectorsCHS(), and PcDiskReadLogicalSectorsLBA().

◆ DiskGetErrorCodeString()

static PCSTR DiskGetErrorCodeString ( ULONG  ErrorCode)
static

Definition at line 88 of file pcdisk.c.

89 {
90  switch (ErrorCode)
91  {
92  case 0x00: return "no error";
93  case 0x01: return "bad command passed to driver";
94  case 0x02: return "address mark not found or bad sector";
95  case 0x03: return "diskette write protect error";
96  case 0x04: return "sector not found";
97  case 0x05: return "fixed disk reset failed";
98  case 0x06: return "diskette changed or removed";
99  case 0x07: return "bad fixed disk parameter table";
100  case 0x08: return "DMA overrun";
101  case 0x09: return "DMA access across 64k boundary";
102  case 0x0A: return "bad fixed disk sector flag";
103  case 0x0B: return "bad fixed disk cylinder";
104  case 0x0C: return "unsupported track/invalid media";
105  case 0x0D: return "invalid number of sectors on fixed disk format";
106  case 0x0E: return "fixed disk controlled data address mark detected";
107  case 0x0F: return "fixed disk DMA arbitration level out of range";
108  case 0x10: return "ECC/CRC error on disk read";
109  case 0x11: return "recoverable fixed disk data error, data fixed by ECC";
110  case 0x20: return "controller error (NEC for floppies)";
111  case 0x40: return "seek failure";
112  case 0x80: return "time out, drive not ready";
113  case 0xAA: return "fixed disk drive not ready";
114  case 0xBB: return "fixed disk undefined error";
115  case 0xCC: return "fixed disk write fault on selected drive";
116  case 0xE0: return "fixed disk status error/Error reg = 0";
117  case 0xFF: return "sense operation failed";
118 
119  default: return "unknown error code";
120  }
121 }
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436

Referenced by DiskError(), PcDiskReadLogicalSectorsCHS(), and PcDiskReadLogicalSectorsLBA().

◆ DiskGetExtendedDriveParameters()

BOOLEAN DiskGetExtendedDriveParameters ( UCHAR  DriveNumber,
PVOID  Buffer,
USHORT  BufferSize 
)

Definition at line 493 of file pcdisk.c.

494 {
495  REGS RegsIn, RegsOut;
497 
498  TRACE("DiskGetExtendedDriveParameters()\n");
499 
500  if (!DiskInt13ExtensionsSupported(DriveNumber))
501  return FALSE;
502 
503  /* Initialize transfer buffer */
504  *Ptr = BufferSize;
505 
506  /*
507  * BIOS Int 13h, function 48h - Get drive parameters
508  * AH = 48h
509  * DL = drive (bit 7 set for hard disk)
510  * DS:SI = result buffer
511  * Return:
512  * CF set on error
513  * AH = status (07h)
514  * CF clear if successful
515  * AH = 00h
516  * DS:SI -> result buffer
517  */
518  RegsIn.b.ah = 0x48;
519  RegsIn.b.dl = DriveNumber;
520  RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
521  RegsIn.w.si = BIOSCALLBUFOFFSET;
522 
523  /* Get drive parameters */
524  Int386(0x13, &RegsIn, &RegsOut);
525  if (!INT386_SUCCESS(RegsOut))
526  return FALSE;
527 
529 
530 #if DBG
531  TRACE("size of buffer: %x\n", Ptr[0]);
532  TRACE("information flags: %x\n", Ptr[1]);
533  TRACE("number of physical cylinders on drive: %u\n", *(PULONG)&Ptr[2]);
534  TRACE("number of physical heads on drive: %u\n", *(PULONG)&Ptr[4]);
535  TRACE("number of physical sectors per track: %u\n", *(PULONG)&Ptr[6]);
536  TRACE("total number of sectors on drive: %I64u\n", *(unsigned long long*)&Ptr[8]);
537  TRACE("bytes per sector: %u\n", Ptr[12]);
538  if (Ptr[0] >= 0x1e)
539  {
540  TRACE("EED configuration parameters: %x:%x\n", Ptr[13], Ptr[14]);
541  if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
542  {
543  PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[13] << 4) + Ptr[14]);
544  TRACE("SpecPtr: %x\n", SpecPtr);
545  TRACE("physical I/O port base address: %x\n", *(PUSHORT)&SpecPtr[0]);
546  TRACE("disk-drive control port address: %x\n", *(PUSHORT)&SpecPtr[2]);
547  TRACE("drive flags: %x\n", SpecPtr[4]);
548  TRACE("proprietary information: %x\n", SpecPtr[5]);
549  TRACE("IRQ for drive: %u\n", SpecPtr[6]);
550  TRACE("sector count for multi-sector transfers: %u\n", SpecPtr[7]);
551  TRACE("DMA control: %x\n", SpecPtr[8]);
552  TRACE("programmed I/O control: %x\n", SpecPtr[9]);
553  TRACE("drive options: %x\n", *(PUSHORT)&SpecPtr[10]);
554  }
555  }
556  if (Ptr[0] >= 0x42)
557  {
558  TRACE("signature: %x\n", Ptr[15]);
559  }
560 #endif
561 
562  return TRUE;
563 }
#define TRUE
Definition: types.h:120
#define BIOSCALLBUFFER
Definition: x86common.h:12
unsigned char * PUCHAR
Definition: retypes.h:3
_Must_inspect_result_ _In_ PFSRTL_PER_STREAM_CONTEXT Ptr
Definition: fsrtlfuncs.h:898
DWORDREGS x
Definition: pcbios.h:148
unsigned char ah
Definition: pcbios.h:120
uint32_t ULONG_PTR
Definition: typedefs.h:63
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:128
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define INT386_SUCCESS(regs)
Definition: pcbios.h:167
Definition: bufpool.h:45
#define TRACE(s)
Definition: solgame.cpp:4
#define BufferSize
Definition: classpnp.h:419
#define BIOSCALLBUFOFFSET
Definition: x86common.h:22
BYTEREGS b
Definition: pcbios.h:151
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
Definition: pcdisk.c:362
unsigned int * PULONG
Definition: retypes.h:1
unsigned short si
Definition: pcbios.h:104
Definition: pcbios.h:146
unsigned short * PUSHORT
Definition: retypes.h:2
WORDREGS w
Definition: pcbios.h:150
unsigned short ds
Definition: pcbios.h:88

Referenced by PcDiskGetDriveGeometry(), and PcGetHarddiskConfigurationData().

◆ DiskInt13ExtensionsSupported()

static BOOLEAN DiskInt13ExtensionsSupported ( UCHAR  DriveNumber)
static

Definition at line 362 of file pcdisk.c.

363 {
364  static UCHAR LastDriveNumber = 0xff;
365  static BOOLEAN LastSupported;
366  REGS RegsIn, RegsOut;
367 
368  TRACE("DiskInt13ExtensionsSupported()\n");
369 
370  if (DriveNumber == LastDriveNumber)
371  {
372  TRACE("Using cached value %s for drive 0x%x\n",
373  LastSupported ? "TRUE" : "FALSE", DriveNumber);
374  return LastSupported;
375  }
376 
377  /*
378  * Some BIOSes report that extended disk access functions are not supported
379  * when booting from a CD (e.g. Phoenix BIOS v6.00PG and Insyde BIOS shipping
380  * with Intel Macs). Therefore we just return TRUE if we're booting from a CD -
381  * we can assume that all El Torito capable BIOSes support INT 13 extensions.
382  * We simply detect whether we're booting from CD by checking whether the drive
383  * number is >= 0x8A. It's 0x90 on the Insyde BIOS, and 0x9F on most other BIOSes.
384  */
385  if (DriveNumber >= 0x8A)
386  {
387  LastSupported = TRUE;
388  return TRUE;
389  }
390 
391  LastDriveNumber = DriveNumber;
392 
393  /*
394  * IBM/MS INT 13 Extensions - INSTALLATION CHECK
395  * AH = 41h
396  * BX = 55AAh
397  * DL = drive (80h-FFh)
398  * Return:
399  * CF set on error (extensions not supported)
400  * AH = 01h (invalid function)
401  * CF clear if successful
402  * BX = AA55h if installed
403  * AH = major version of extensions
404  * 01h = 1.x
405  * 20h = 2.0 / EDD-1.0
406  * 21h = 2.1 / EDD-1.1
407  * 30h = EDD-3.0
408  * AL = internal use
409  * CX = API subset support bitmap
410  * DH = extension version (v2.0+ ??? -- not present in 1.x)
411  *
412  * Bitfields for IBM/MS INT 13 Extensions API support bitmap
413  * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
414  * Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
415  * Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
416  * extended drive parameter table is valid
417  * Bits 3-15 reserved
418  */
419  RegsIn.b.ah = 0x41;
420  RegsIn.w.bx = 0x55AA;
421  RegsIn.b.dl = DriveNumber;
422 
423  /* Reset the disk controller */
424  Int386(0x13, &RegsIn, &RegsOut);
425 
426  if (!INT386_SUCCESS(RegsOut))
427  {
428  /* CF set on error (extensions not supported) */
429  LastSupported = FALSE;
430  return FALSE;
431  }
432 
433  if (RegsOut.w.bx != 0xAA55)
434  {
435  /* BX = AA55h if installed */
436  LastSupported = FALSE;
437  return FALSE;
438  }
439 
440  if (!(RegsOut.w.cx & 0x0001))
441  {
442  /*
443  * CX = API subset support bitmap.
444  * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported.
445  */
446  DbgPrint("Suspicious API subset support bitmap 0x%x on device 0x%lx\n",
447  RegsOut.w.cx, DriveNumber);
448  LastSupported = FALSE;
449  return FALSE;
450  }
451 
452  LastSupported = TRUE;
453  return TRUE;
454 }
#define TRUE
Definition: types.h:120
#define DbgPrint
Definition: loader.c:25
unsigned short cx
Definition: pcbios.h:101
unsigned char ah
Definition: pcbios.h:120
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:128
#define INT386_SUCCESS(regs)
Definition: pcbios.h:167
unsigned char BOOLEAN
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char UCHAR
Definition: xmlstorage.h:181
BYTEREGS b
Definition: pcbios.h:151
unsigned short bx
Definition: pcbios.h:100
Definition: pcbios.h:146
WORDREGS w
Definition: pcbios.h:150

Referenced by DiskGetExtendedDriveParameters(), PcDiskGetCacheableBlockCount(), and PcDiskReadLogicalSectors().

◆ DiskReportError()

LONG DiskReportError ( BOOLEAN  bShowError)

Definition at line 80 of file pcdisk.c.

81 {
82  /* Set the reference count */
83  if (bShowError) ++lReportError;
84  else --lReportError;
85  return lReportError;
86 }
static LONG lReportError
Definition: pcdisk.c:78

Referenced by EnumerateHarddisks(), and GetHarddiskInformation().

◆ DiskResetController()

BOOLEAN DiskResetController ( UCHAR  DriveNumber)

Definition at line 140 of file pcdisk.c.

141 {
142  REGS RegsIn, RegsOut;
143 
144  WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
145 
146  /*
147  * BIOS Int 13h, function 0 - Reset disk system
148  * AH = 00h
149  * DL = drive (if bit 7 is set both hard disks and floppy disks reset)
150  * Return:
151  * AH = status
152  * CF clear if successful
153  * CF set on error
154  */
155  RegsIn.b.ah = 0x00;
156  RegsIn.b.dl = DriveNumber;
157 
158  /* Reset the disk controller */
159  Int386(0x13, &RegsIn, &RegsOut);
160 
161  return INT386_SUCCESS(RegsOut);
162 }
#define WARN(fmt,...)
Definition: debug.h:111
unsigned char ah
Definition: pcbios.h:120
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:128
#define INT386_SUCCESS(regs)
Definition: pcbios.h:167
BYTEREGS b
Definition: pcbios.h:151
Definition: pcbios.h:146

Referenced by DetectBiosFloppyPeripheral(), PcDiskReadLogicalSectorsCHS(), and PcDiskReadLogicalSectorsLBA().

◆ PcDiskGetCacheableBlockCount()

ULONG PcDiskGetCacheableBlockCount ( UCHAR  DriveNumber)

Definition at line 626 of file pcdisk.c.

627 {
628  GEOMETRY Geometry;
629 
630  /* If LBA is supported then the block size will be 64 sectors (32k)
631  * If not then the block size is the size of one track. */
632  if (DiskInt13ExtensionsSupported(DriveNumber))
633  {
634  return 64;
635  }
636  /* Get the disk geometry. If this fails then we will
637  * just return 1 sector to be safe. */
638  else if (!PcDiskGetDriveGeometry(DriveNumber, &Geometry))
639  {
640  return 1;
641  }
642  else
643  {
644  return Geometry.Sectors;
645  }
646 }
BOOLEAN PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
Definition: pcdisk.c:566
ULONG Sectors
Definition: disk.h:28
static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
Definition: pcdisk.c:362
Definition: disk.h:24

Referenced by PcMachInit().

◆ PcDiskGetDriveGeometry()

BOOLEAN PcDiskGetDriveGeometry ( UCHAR  DriveNumber,
PGEOMETRY  Geometry 
)

Definition at line 566 of file pcdisk.c.

567 {
568  EXTENDED_GEOMETRY ExtGeometry;
569  REGS RegsIn, RegsOut;
570  ULONG Cylinders;
571 
572  TRACE("DiskGetDriveGeometry()\n");
573 
574  /* Try to get the extended geometry first */
575  ExtGeometry.Size = sizeof(ExtGeometry);
576  if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
577  {
578  Geometry->Cylinders = ExtGeometry.Cylinders;
579  Geometry->Heads = ExtGeometry.Heads;
580  Geometry->Sectors = ExtGeometry.SectorsPerTrack;
581  Geometry->BytesPerSector = ExtGeometry.BytesPerSector;
582  return TRUE;
583  }
584 
585  /*
586  * BIOS Int 13h, function 08h - Get drive parameters
587  * AH = 08h
588  * DL = drive (bit 7 set for hard disk)
589  * ES:DI = 0000h:0000h to guard against BIOS bugs
590  * Return:
591  * CF set on error
592  * AH = status (07h)
593  * CF clear if successful
594  * AH = 00h
595  * AL = 00h on at least some BIOSes
596  * BL = drive type (AT/PS2 floppies only)
597  * CH = low eight bits of maximum cylinder number
598  * CL = maximum sector number (bits 5-0)
599  * high two bits of maximum cylinder number (bits 7-6)
600  * DH = maximum head number
601  * DL = number of drives
602  * ES:DI -> drive parameter table (floppies only)
603  */
604  RegsIn.b.ah = 0x08;
605  RegsIn.b.dl = DriveNumber;
606  RegsIn.w.es = 0x0000;
607  RegsIn.w.di = 0x0000;
608 
609  /* Get drive parameters */
610  Int386(0x13, &RegsIn, &RegsOut);
611  if (!INT386_SUCCESS(RegsOut))
612  return FALSE;
613 
614  Cylinders = (RegsOut.b.cl & 0xC0) << 2;
615  Cylinders += RegsOut.b.ch;
616  Cylinders++;
617  Geometry->Cylinders = Cylinders;
618  Geometry->Heads = RegsOut.b.dh + 1;
619  Geometry->Sectors = RegsOut.b.cl & 0x3F;
620  Geometry->BytesPerSector = 512; /* Just assume 512 bytes per sector */
621 
622  return TRUE;
623 }
#define TRUE
Definition: types.h:120
ULONG Cylinders
Definition: disk.h:26
unsigned short es
Definition: pcbios.h:109
unsigned char ah
Definition: pcbios.h:120
ULONG Cylinders
Definition: disk.h:41
unsigned char dh
Definition: pcbios.h:129
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:128
#define INT386_SUCCESS(regs)
Definition: pcbios.h:167
ULONG SectorsPerTrack
Definition: disk.h:43
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize)
Definition: pcdisk.c:493
ULONG Sectors
Definition: disk.h:28
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:126
unsigned char cl
Definition: pcbios.h:125
BYTEREGS b
Definition: pcbios.h:151
USHORT Size
Definition: disk.h:39
ULONG BytesPerSector
Definition: disk.h:29
USHORT BytesPerSector
Definition: disk.h:45
ULONG Heads
Definition: disk.h:42
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:146
unsigned short di
Definition: pcbios.h:105
WORDREGS w
Definition: pcbios.h:150
ULONG Heads
Definition: disk.h:27

Referenced by PcDiskGetCacheableBlockCount(), PcDiskReadLogicalSectorsCHS(), PcGetHarddiskConfigurationData(), and PcMachInit().

◆ PcDiskReadLogicalSectors()

BOOLEAN PcDiskReadLogicalSectors ( UCHAR  DriveNumber,
ULONGLONG  SectorNumber,
ULONG  SectorCount,
PVOID  Buffer 
)

Definition at line 456 of file pcdisk.c.

457 {
458  BOOLEAN ExtensionsSupported;
459 
460  TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n",
461  DriveNumber, SectorNumber, SectorCount, Buffer);
462 
463  /*
464  * Check to see if it is a fixed disk drive.
465  * If so then check to see if Int13 extensions work.
466  * If they do then use them, otherwise default back to BIOS calls.
467  */
468  ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
469 
470  if ((DriveNumber >= 0x80) && ExtensionsSupported)
471  {
472  TRACE("Using Int 13 Extensions for read. DiskInt13ExtensionsSupported(%d) = %s\n", DriveNumber, ExtensionsSupported ? "TRUE" : "FALSE");
473 
474  /* LBA is easy, nothing to calculate. Just do the read. */
475  return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
476  }
477  else
478  {
479  /* LBA is not supported default to the CHS calls */
480  return PcDiskReadLogicalSectorsCHS(DriveNumber, SectorNumber, SectorCount, Buffer);
481  }
482 
483  return TRUE;
484 }
#define TRUE
Definition: types.h:120
static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: pcdisk.c:164
unsigned char BOOLEAN
Definition: bufpool.h:45
#define TRACE(s)
Definition: solgame.cpp:4
static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
Definition: pcdisk.c:362
ULONG SectorCount
Definition: part_xbox.c:32
static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: pcdisk.c:230

Referenced by PcMachInit().

◆ PcDiskReadLogicalSectorsCHS()

static BOOLEAN PcDiskReadLogicalSectorsCHS ( UCHAR  DriveNumber,
ULONGLONG  SectorNumber,
ULONG  SectorCount,
PVOID  Buffer 
)
static

Definition at line 230 of file pcdisk.c.

231 {
232  UCHAR PhysicalSector;
233  UCHAR PhysicalHead;
234  ULONG PhysicalTrack;
235  GEOMETRY DriveGeometry;
236  ULONG NumberOfSectorsToRead;
237  REGS RegsIn, RegsOut;
238  ULONG RetryCount;
239 
240  TRACE("PcDiskReadLogicalSectorsCHS()\n");
241 
242  /* Get the drive geometry */
243  //
244  // TODO: Cache this information for the given drive.
245  //
246  if (!PcDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
247  DriveGeometry.Sectors == 0 || DriveGeometry.Heads == 0)
248  {
249  return FALSE;
250  }
251 
252  while (SectorCount)
253  {
254  /*
255  * Calculate the physical disk offsets.
256  * Note: DriveGeometry.Sectors < 64
257  */
258  PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors);
259  PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads);
260  PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads);
261 
262  /* Calculate how many sectors we need to read this round */
263  if (PhysicalSector > 1)
264  {
265  if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
266  NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
267  else
268  NumberOfSectorsToRead = SectorCount;
269  }
270  else
271  {
272  if (SectorCount >= DriveGeometry.Sectors)
273  NumberOfSectorsToRead = DriveGeometry.Sectors;
274  else
275  NumberOfSectorsToRead = SectorCount;
276  }
277 
278  /* Make sure the read is within the geometry boundaries */
279  if ((PhysicalHead >= DriveGeometry.Heads) ||
280  (PhysicalTrack >= DriveGeometry.Cylinders) ||
281  ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
282  (PhysicalSector > DriveGeometry.Sectors))
283  {
284  DiskError("Disk read exceeds drive geometry limits.", 0);
285  return FALSE;
286  }
287 
288  /*
289  * BIOS Int 13h, function 2 - Read Disk Sectors
290  * AH = 02h
291  * AL = number of sectors to read (must be nonzero)
292  * CH = low eight bits of cylinder number
293  * CL = sector number 1-63 (bits 0-5)
294  * high two bits of cylinder (bits 6-7, hard disk only)
295  * DH = head number
296  * DL = drive number (bit 7 set for hard disk)
297  * ES:BX -> data buffer
298  * Return:
299  * CF set on error
300  * if AH = 11h (corrected ECC error), AL = burst length
301  * CF clear if successful
302  * AH = status
303  * AL = number of sectors transferred
304  * (only valid if CF set for some BIOSes)
305  */
306  RegsIn.b.ah = 0x02;
307  RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
308  RegsIn.b.ch = (PhysicalTrack & 0xFF);
309  RegsIn.b.cl = (UCHAR)(PhysicalSector + ((PhysicalTrack & 0x300) >> 2));
310  RegsIn.b.dh = PhysicalHead;
311  RegsIn.b.dl = DriveNumber;
312  RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
313  RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;
314 
315  /* Perform the read. Retry 3 times. */
316  for (RetryCount=0; RetryCount<3; RetryCount++)
317  {
318  Int386(0x13, &RegsIn, &RegsOut);
319 
320  /* If it worked break out */
321  if (INT386_SUCCESS(RegsOut))
322  {
323  break;
324  }
325  /* If it was a corrected ECC error then the data is still good */
326  else if (RegsOut.b.ah == 0x11)
327  {
328  break;
329  }
330  /* If it failed the do the next retry */
331  else
332  {
333  DiskResetController(DriveNumber);
334  continue;
335  }
336  }
337 
338  /* If we retried 3 times then fail */
339  if (RetryCount >= 3)
340  {
341  DiskError("Disk Read Failed in CHS mode, after retrying 3 times", RegsOut.b.ah);
342  ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n",
343  RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
344  DriveNumber, SectorNumber, SectorCount);
345  return FALSE;
346  }
347 
348  // I have learned that not all BIOSes return
349  // the sector read count in the AL register (at least mine doesn't)
350  // even if the sectors were read correctly. So instead
351  // of checking the sector read count we will rely solely
352  // on the carry flag being set on error
353 
354  Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead * DriveGeometry.BytesPerSector));
355  SectorCount -= NumberOfSectorsToRead;
356  SectorNumber += NumberOfSectorsToRead;
357  }
358 
359  return TRUE;
360 }
BOOLEAN DiskResetController(UCHAR DriveNumber)
Definition: pcdisk.c:140
#define TRUE
Definition: types.h:120
ULONG Cylinders
Definition: disk.h:26
unsigned short es
Definition: pcbios.h:109
unsigned char ah
Definition: pcbios.h:120
unsigned char dh
Definition: pcbios.h:129
uint32_t ULONG_PTR
Definition: typedefs.h:63
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:128
#define INT386_SUCCESS(regs)
Definition: pcbios.h:167
static PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
Definition: pcdisk.c:88
BOOLEAN PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
Definition: pcdisk.c:566
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
ULONG Sectors
Definition: disk.h:28
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:126
unsigned char UCHAR
Definition: xmlstorage.h:181
unsigned char cl
Definition: pcbios.h:125
BYTEREGS b
Definition: pcbios.h:151
unsigned char al
Definition: pcbios.h:119
ULONG SectorCount
Definition: part_xbox.c:32
#define ERR(fmt,...)
Definition: debug.h:109
ULONG BytesPerSector
Definition: disk.h:29
unsigned short USHORT
Definition: pedump.c:61
Definition: disk.h:24
unsigned short bx
Definition: pcbios.h:100
static VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
Definition: pcdisk.c:123
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:146
#define ULONG_PTR
Definition: config.h:101
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
WORDREGS w
Definition: pcbios.h:150
ULONG Heads
Definition: disk.h:27

Referenced by PcDiskReadLogicalSectors().

◆ PcDiskReadLogicalSectorsLBA()

static BOOLEAN PcDiskReadLogicalSectorsLBA ( UCHAR  DriveNumber,
ULONGLONG  SectorNumber,
ULONG  SectorCount,
PVOID  Buffer 
)
static

Definition at line 164 of file pcdisk.c.

165 {
166  REGS RegsIn, RegsOut;
167  ULONG RetryCount;
169 
170  TRACE("PcDiskReadLogicalSectorsLBA() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer);
171  ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
172 
173  /* Setup disk address packet */
174  RtlZeroMemory(Packet, sizeof(*Packet));
175  Packet->PacketSize = sizeof(*Packet);
176  Packet->Reserved = 0;
177  Packet->LBABlockCount = (USHORT)SectorCount;
178  ASSERT(Packet->LBABlockCount == SectorCount);
179  Packet->TransferBufferOffset = ((ULONG_PTR)Buffer) & 0x0F;
180  Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4);
181  Packet->LBAStartBlock = SectorNumber;
182 
183  /*
184  * BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
185  * Return:
186  * CF clear if successful
187  * AH = 00h
188  * CF set on error
189  * AH = error code
190  * Disk address packet's block count field set to the
191  * number of blocks successfully transferred.
192  */
193  RegsIn.b.ah = 0x42; // Subfunction 42h
194  RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk)
195  RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
196  RegsIn.w.si = BIOSCALLBUFOFFSET;
197 
198  /* Retry 3 times */
199  for (RetryCount=0; RetryCount<3; RetryCount++)
200  {
201  Int386(0x13, &RegsIn, &RegsOut);
202 
203  /* If it worked return TRUE */
204  if (INT386_SUCCESS(RegsOut))
205  {
206  return TRUE;
207  }
208  /* If it was a corrected ECC error then the data is still good */
209  else if (RegsOut.b.ah == 0x11)
210  {
211  return TRUE;
212  }
213  /* If it failed then do the next retry */
214  else
215  {
216  DiskResetController(DriveNumber);
217  continue;
218  }
219  }
220 
221  /* If we get here then the read failed */
222  DiskError("Disk Read Failed in LBA mode", RegsOut.b.ah);
223  ERR("Disk Read Failed in LBA mode: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n",
224  RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
225  DriveNumber, SectorNumber, SectorCount);
226 
227  return FALSE;
228 }
BOOLEAN DiskResetController(UCHAR DriveNumber)
Definition: pcdisk.c:140
#define TRUE
Definition: types.h:120
_In_ NDIS_HANDLE _In_ PNDIS_PACKET Packet
Definition: ndis.h:1548
#define BIOSCALLBUFFER
Definition: x86common.h:12
struct I386_DISK_ADDRESS_PACKET * PI386_DISK_ADDRESS_PACKET
DWORDREGS x
Definition: pcbios.h:148
unsigned char ah
Definition: pcbios.h:120
uint32_t ULONG_PTR
Definition: typedefs.h:63
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:128
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define INT386_SUCCESS(regs)
Definition: pcbios.h:167
static PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
Definition: pcdisk.c:88
Definition: bufpool.h:45
#define TRACE(s)
Definition: solgame.cpp:4
#define BIOSCALLBUFOFFSET
Definition: x86common.h:22
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
BYTEREGS b
Definition: pcbios.h:151
ULONG SectorCount
Definition: part_xbox.c:32
#define ERR(fmt,...)
Definition: debug.h:109
unsigned short USHORT
Definition: pedump.c:61
static VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
Definition: pcdisk.c:123
unsigned short si
Definition: pcbios.h:104
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:146
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:261
#define ULONG_PTR
Definition: config.h:101
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
WORDREGS w
Definition: pcbios.h:150
unsigned short ds
Definition: pcbios.h:88

Referenced by PcDiskReadLogicalSectors().

Variable Documentation

◆ lReportError

LONG lReportError = 0
static

Definition at line 78 of file pcdisk.c.

Referenced by DiskError(), and DiskReportError().