ReactOS  0.4.13-dev-257-gfabbd7c
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)
 
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)
 
VOID DiskStopFloppyMotor (VOID)
 
BOOLEAN DiskGetExtendedDriveParameters (UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize)
 
BOOLEAN PcDiskGetDriveGeometry (UCHAR DriveNumber, PGEOMETRY Geometry)
 
ULONG PcDiskGetCacheableBlockCount (UCHAR DriveNumber)
 
BOOLEAN PcDiskGetBootPath (OUT PCHAR BootPath, IN ULONG Size)
 

Typedef Documentation

◆ PI386_CDROM_SPEC_PACKET

◆ PI386_DISK_ADDRESS_PACKET

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( DISK  )

◆ DiskGetExtendedDriveParameters()

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

Definition at line 422 of file pcdisk.c.

423 {
424  REGS RegsIn, RegsOut;
426 
427  TRACE("DiskGetExtendedDriveParameters()\n");
428 
429  if (!DiskInt13ExtensionsSupported(DriveNumber))
430  return FALSE;
431 
432  /* Initialize transfer buffer */
433  *Ptr = BufferSize;
434 
435  /*
436  * BIOS Int 13h, function 48h - Get drive parameters
437  * AH = 48h
438  * DL = drive (bit 7 set for hard disk)
439  * DS:SI = result buffer
440  * Return:
441  * CF set on error
442  * AH = status (07h)
443  * CF clear if successful
444  * AH = 00h
445  * DS:SI -> result buffer
446  */
447  RegsIn.b.ah = 0x48;
448  RegsIn.b.dl = DriveNumber;
449  RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
450  RegsIn.w.si = BIOSCALLBUFOFFSET;
451 
452  /* Get drive parameters */
453  Int386(0x13, &RegsIn, &RegsOut);
454  if (!INT386_SUCCESS(RegsOut))
455  return FALSE;
456 
458 
459 #if DBG
460  TRACE("size of buffer: %x\n", Ptr[0]);
461  TRACE("information flags: %x\n", Ptr[1]);
462  TRACE("number of physical cylinders on drive: %u\n", *(PULONG)&Ptr[2]);
463  TRACE("number of physical heads on drive: %u\n", *(PULONG)&Ptr[4]);
464  TRACE("number of physical sectors per track: %u\n", *(PULONG)&Ptr[6]);
465  TRACE("total number of sectors on drive: %I64u\n", *(unsigned long long*)&Ptr[8]);
466  TRACE("bytes per sector: %u\n", Ptr[12]);
467  if (Ptr[0] >= 0x1e)
468  {
469  TRACE("EED configuration parameters: %x:%x\n", Ptr[13], Ptr[14]);
470  if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
471  {
472  PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[13] << 4) + Ptr[14]);
473  TRACE("SpecPtr: %x\n", SpecPtr);
474  TRACE("physical I/O port base address: %x\n", *(PUSHORT)&SpecPtr[0]);
475  TRACE("disk-drive control port address: %x\n", *(PUSHORT)&SpecPtr[2]);
476  TRACE("drive flags: %x\n", SpecPtr[4]);
477  TRACE("proprietary information: %x\n", SpecPtr[5]);
478  TRACE("IRQ for drive: %u\n", SpecPtr[6]);
479  TRACE("sector count for multi-sector transfers: %u\n", SpecPtr[7]);
480  TRACE("DMA control: %x\n", SpecPtr[8]);
481  TRACE("programmed I/O control: %x\n", SpecPtr[9]);
482  TRACE("drive options: %x\n", *(PUSHORT)&SpecPtr[10]);
483  }
484  }
485  if (Ptr[0] >= 0x42)
486  {
487  TRACE("signature: %x\n", Ptr[15]);
488  }
489 #endif
490 
491  return TRUE;
492 }
#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:140
unsigned char ah
Definition: pcbios.h:112
uint32_t ULONG_PTR
Definition: typedefs.h:63
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:120
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
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:143
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
Definition: pcdisk.c:293
unsigned int * PULONG
Definition: retypes.h:1
unsigned short si
Definition: pcbios.h:96
Definition: pcbios.h:138
unsigned short * PUSHORT
Definition: retypes.h:2
WORDREGS w
Definition: pcbios.h:142
unsigned short ds
Definition: pcbios.h:80

Referenced by PcDiskGetDriveGeometry(), and PcGetHarddiskConfigurationData().

◆ DiskInt13ExtensionsSupported()

static BOOLEAN DiskInt13ExtensionsSupported ( UCHAR  DriveNumber)
static

Definition at line 293 of file pcdisk.c.

294 {
295  static UCHAR LastDriveNumber = 0xff;
296  static BOOLEAN LastSupported;
297  REGS RegsIn, RegsOut;
298 
299  TRACE("DiskInt13ExtensionsSupported()\n");
300 
301  if (DriveNumber == LastDriveNumber)
302  {
303  TRACE("Using cached value %s for drive 0x%x\n",
304  LastSupported ? "TRUE" : "FALSE", DriveNumber);
305  return LastSupported;
306  }
307 
308  /*
309  * Some BIOSes report that extended disk access functions are not supported
310  * when booting from a CD (e.g. Phoenix BIOS v6.00PG and Insyde BIOS shipping
311  * with Intel Macs). Therefore we just return TRUE if we're booting from a CD -
312  * we can assume that all El Torito capable BIOSes support INT 13 extensions.
313  * We simply detect whether we're booting from CD by checking whether the drive
314  * number is >= 0x8A. It's 0x90 on the Insyde BIOS, and 0x9F on most other BIOSes.
315  */
316  if (DriveNumber >= 0x8A)
317  {
318  LastSupported = TRUE;
319  return TRUE;
320  }
321 
322  LastDriveNumber = DriveNumber;
323 
324  /*
325  * IBM/MS INT 13 Extensions - INSTALLATION CHECK
326  * AH = 41h
327  * BX = 55AAh
328  * DL = drive (80h-FFh)
329  * Return:
330  * CF set on error (extensions not supported)
331  * AH = 01h (invalid function)
332  * CF clear if successful
333  * BX = AA55h if installed
334  * AH = major version of extensions
335  * 01h = 1.x
336  * 20h = 2.0 / EDD-1.0
337  * 21h = 2.1 / EDD-1.1
338  * 30h = EDD-3.0
339  * AL = internal use
340  * CX = API subset support bitmap
341  * DH = extension version (v2.0+ ??? -- not present in 1.x)
342  *
343  * Bitfields for IBM/MS INT 13 Extensions API support bitmap
344  * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
345  * Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
346  * Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
347  * extended drive parameter table is valid
348  * Bits 3-15 reserved
349  */
350  RegsIn.b.ah = 0x41;
351  RegsIn.w.bx = 0x55AA;
352  RegsIn.b.dl = DriveNumber;
353 
354  /* Reset the disk controller */
355  Int386(0x13, &RegsIn, &RegsOut);
356 
357  if (!INT386_SUCCESS(RegsOut))
358  {
359  /* CF set on error (extensions not supported) */
360  LastSupported = FALSE;
361  return FALSE;
362  }
363 
364  if (RegsOut.w.bx != 0xAA55)
365  {
366  /* BX = AA55h if installed */
367  LastSupported = FALSE;
368  return FALSE;
369  }
370 
371  if (!(RegsOut.w.cx & 0x0001))
372  {
373  /*
374  * CX = API subset support bitmap.
375  * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported.
376  */
377  DbgPrint("Suspicious API subset support bitmap 0x%x on device 0x%lx\n",
378  RegsOut.w.cx, DriveNumber);
379  LastSupported = FALSE;
380  return FALSE;
381  }
382 
383  LastSupported = TRUE;
384  return TRUE;
385 }
#define TRUE
Definition: types.h:120
#define DbgPrint
Definition: loader.c:25
unsigned short cx
Definition: pcbios.h:93
unsigned char ah
Definition: pcbios.h:112
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:120
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
unsigned char BOOLEAN
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char UCHAR
Definition: xmlstorage.h:181
BYTEREGS b
Definition: pcbios.h:143
unsigned short bx
Definition: pcbios.h:92
Definition: pcbios.h:138
WORDREGS w
Definition: pcbios.h:142

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

◆ DiskResetController()

BOOLEAN DiskResetController ( UCHAR  DriveNumber)

Definition at line 79 of file pcdisk.c.

80 {
81  REGS RegsIn, RegsOut;
82 
83  WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
84 
85  /*
86  * BIOS Int 13h, function 0 - Reset disk system
87  * AH = 00h
88  * DL = drive (if bit 7 is set both hard disks and floppy disks reset)
89  * Return:
90  * AH = status
91  * CF clear if successful
92  * CF set on error
93  */
94  RegsIn.b.ah = 0x00;
95  RegsIn.b.dl = DriveNumber;
96 
97  /* Reset the disk controller */
98  Int386(0x13, &RegsIn, &RegsOut);
99 
100  return INT386_SUCCESS(RegsOut);
101 }
#define WARN(fmt,...)
Definition: debug.h:111
unsigned char ah
Definition: pcbios.h:112
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:120
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
BYTEREGS b
Definition: pcbios.h:143
Definition: pcbios.h:138

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

◆ DiskStopFloppyMotor()

VOID DiskStopFloppyMotor ( VOID  )

Definition at line 417 of file pcdisk.c.

418 {
419  WRITE_PORT_UCHAR((PUCHAR)0x3F2, 0);
420 }
unsigned char * PUCHAR
Definition: retypes.h:3
void WRITE_PORT_UCHAR(PUCHAR Address, UCHAR Value)
Definition: mach.c:539

◆ PcDiskGetBootPath()

BOOLEAN PcDiskGetBootPath ( OUT PCHAR  BootPath,
IN ULONG  Size 
)

Definition at line 578 of file pcdisk.c.

579 {
580  // FIXME: Keep it there, or put it in DiskGetBootPath?
581  // Or, abstract the notion of network booting to make
582  // sense for other platforms than the PC (and this idea
583  // already exists), then we would need to check whether
584  // we were booting from network (and: PC --> PXE, etc...)
585  // and if so, set the correct ARC path. But then this new
586  // logic could be moved back to DiskGetBootPath...
587 
588  if (*FrldrBootPath)
589  {
590  /* Copy back the buffer */
591  if (Size < strlen(FrldrBootPath) + 1)
592  return FALSE;
594  return TRUE;
595  }
596 
597  // FIXME! FIXME! Do this in some drive recognition procedure!!!!
598  if (PxeInit())
599  {
600  strcpy(BootPath, "net(0)");
601  return TRUE;
602  }
603  return DiskGetBootPath(BootPath, Size);
604 }
#define TRUE
Definition: types.h:120
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
char * strncpy(char *DstString, const char *SrcString, ACPI_SIZE Count)
Definition: utclib.c:427
BOOLEAN PxeInit(VOID)
Definition: pxe.c:371
BOOLEAN DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
Definition: disk.c:102
CHAR FrldrBootPath[MAX_PATH]
Definition: disk.c:27
IN PVOID IN PVOID IN USHORT IN USHORT Size
Definition: pci.h:359
char * strcpy(char *DstString, const char *SrcString)
Definition: utclib.c:388
char BootPath[0x100]
Definition: mach.c:35

Referenced by PcMachInit().

◆ PcDiskGetCacheableBlockCount()

ULONG PcDiskGetCacheableBlockCount ( UCHAR  DriveNumber)

Definition at line 555 of file pcdisk.c.

556 {
557  GEOMETRY Geometry;
558 
559  /* If LBA is supported then the block size will be 64 sectors (32k)
560  * If not then the block size is the size of one track. */
561  if (DiskInt13ExtensionsSupported(DriveNumber))
562  {
563  return 64;
564  }
565  /* Get the disk geometry. If this fails then we will
566  * just return 1 sector to be safe. */
567  else if (! PcDiskGetDriveGeometry(DriveNumber, &Geometry))
568  {
569  return 1;
570  }
571  else
572  {
573  return Geometry.Sectors;
574  }
575 }
BOOLEAN PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
Definition: pcdisk.c:495
ULONG Sectors
Definition: disk.h:28
static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
Definition: pcdisk.c:293
Definition: disk.h:24

Referenced by PcMachInit().

◆ PcDiskGetDriveGeometry()

BOOLEAN PcDiskGetDriveGeometry ( UCHAR  DriveNumber,
PGEOMETRY  Geometry 
)

Definition at line 495 of file pcdisk.c.

496 {
497  EXTENDED_GEOMETRY ExtGeometry;
498  REGS RegsIn, RegsOut;
499  ULONG Cylinders;
500 
501  TRACE("DiskGetDriveGeometry()\n");
502 
503  /* Try to get the extended geometry first */
504  ExtGeometry.Size = sizeof(ExtGeometry);
505  if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
506  {
507  Geometry->Cylinders = ExtGeometry.Cylinders;
508  Geometry->Heads = ExtGeometry.Heads;
509  Geometry->Sectors = ExtGeometry.SectorsPerTrack;
510  Geometry->BytesPerSector = ExtGeometry.BytesPerSector;
511  return TRUE;
512  }
513 
514  /*
515  * BIOS Int 13h, function 08h - Get drive parameters
516  * AH = 08h
517  * DL = drive (bit 7 set for hard disk)
518  * ES:DI = 0000h:0000h to guard against BIOS bugs
519  * Return:
520  * CF set on error
521  * AH = status (07h)
522  * CF clear if successful
523  * AH = 00h
524  * AL = 00h on at least some BIOSes
525  * BL = drive type (AT/PS2 floppies only)
526  * CH = low eight bits of maximum cylinder number
527  * CL = maximum sector number (bits 5-0)
528  * high two bits of maximum cylinder number (bits 7-6)
529  * DH = maximum head number
530  * DL = number of drives
531  * ES:DI -> drive parameter table (floppies only)
532  */
533  RegsIn.b.ah = 0x08;
534  RegsIn.b.dl = DriveNumber;
535  RegsIn.w.es = 0x0000;
536  RegsIn.w.di = 0x0000;
537 
538  /* Get drive parameters */
539  Int386(0x13, &RegsIn, &RegsOut);
540  if (!INT386_SUCCESS(RegsOut))
541  return FALSE;
542 
543  Cylinders = (RegsOut.b.cl & 0xC0) << 2;
544  Cylinders += RegsOut.b.ch;
545  Cylinders++;
546  Geometry->Cylinders = Cylinders;
547  Geometry->Heads = RegsOut.b.dh + 1;
548  Geometry->Sectors = RegsOut.b.cl & 0x3F;
549  Geometry->BytesPerSector = 512; /* Just assume 512 bytes per sector */
550 
551  return TRUE;
552 }
#define TRUE
Definition: types.h:120
ULONG Cylinders
Definition: disk.h:26
unsigned short es
Definition: pcbios.h:101
unsigned char ah
Definition: pcbios.h:112
ULONG Cylinders
Definition: disk.h:41
unsigned char dh
Definition: pcbios.h:121
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:120
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
ULONG SectorsPerTrack
Definition: disk.h:43
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize)
Definition: pcdisk.c:422
ULONG Sectors
Definition: disk.h:28
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:118
unsigned char cl
Definition: pcbios.h:117
BYTEREGS b
Definition: pcbios.h:143
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:138
unsigned short di
Definition: pcbios.h:97
WORDREGS w
Definition: pcbios.h:142
ULONG Heads
Definition: disk.h:27

Referenced by PcDiskGetCacheableBlockCount(), and PcMachInit().

◆ PcDiskReadLogicalSectors()

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

Definition at line 387 of file pcdisk.c.

388 {
389  BOOLEAN ExtensionsSupported;
390 
391  TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n",
392  DriveNumber, SectorNumber, SectorCount, Buffer);
393 
394  /*
395  * Check to see if it is a fixed disk drive.
396  * If so then check to see if Int13 extensions work.
397  * If they do then use them, otherwise default back to BIOS calls.
398  */
399  ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
400 
401  if ((DriveNumber >= 0x80) && ExtensionsSupported)
402  {
403  TRACE("Using Int 13 Extensions for read. DiskInt13ExtensionsSupported(%d) = %s\n", DriveNumber, ExtensionsSupported ? "TRUE" : "FALSE");
404 
405  /* LBA is easy, nothing to calculate. Just do the read. */
406  return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
407  }
408  else
409  {
410  /* LBA is not supported default to the CHS calls */
411  return PcDiskReadLogicalSectorsCHS(DriveNumber, SectorNumber, SectorCount, Buffer);
412  }
413 
414  return TRUE;
415 }
#define TRUE
Definition: types.h:120
static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: pcdisk.c:103
unsigned char BOOLEAN
Definition: bufpool.h:45
#define TRACE(s)
Definition: solgame.cpp:4
static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
Definition: pcdisk.c:293
ULONG SectorCount
Definition: part_xbox.c:32
static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
Definition: pcdisk.c:166

Referenced by PcMachInit().

◆ PcDiskReadLogicalSectorsCHS()

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

Definition at line 166 of file pcdisk.c.

167 {
168  UCHAR PhysicalSector;
169  UCHAR PhysicalHead;
170  ULONG PhysicalTrack;
171  GEOMETRY DriveGeometry;
172  ULONG NumberOfSectorsToRead;
173  REGS RegsIn, RegsOut;
174  ULONG RetryCount;
175 
176  TRACE("PcDiskReadLogicalSectorsCHS()\n");
177 
178  /* Get the drive geometry */
179  if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
180  DriveGeometry.Sectors == 0 ||
181  DriveGeometry.Heads == 0)
182  {
183  return FALSE;
184  }
185 
186  while (SectorCount)
187  {
188  /*
189  * Calculate the physical disk offsets.
190  * Note: DriveGeometry.Sectors < 64
191  */
192  PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors);
193  PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads);
194  PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads);
195 
196  /* Calculate how many sectors we need to read this round */
197  if (PhysicalSector > 1)
198  {
199  if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
200  NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
201  else
202  NumberOfSectorsToRead = SectorCount;
203  }
204  else
205  {
206  if (SectorCount >= DriveGeometry.Sectors)
207  NumberOfSectorsToRead = DriveGeometry.Sectors;
208  else
209  NumberOfSectorsToRead = SectorCount;
210  }
211 
212  /* Make sure the read is within the geometry boundaries */
213  if ((PhysicalHead >= DriveGeometry.Heads) ||
214  (PhysicalTrack >= DriveGeometry.Cylinders) ||
215  ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
216  (PhysicalSector > DriveGeometry.Sectors))
217  {
218  DiskError("Disk read exceeds drive geometry limits.", 0);
219  return FALSE;
220  }
221 
222  /*
223  * BIOS Int 13h, function 2 - Read Disk Sectors
224  * AH = 02h
225  * AL = number of sectors to read (must be nonzero)
226  * CH = low eight bits of cylinder number
227  * CL = sector number 1-63 (bits 0-5)
228  * high two bits of cylinder (bits 6-7, hard disk only)
229  * DH = head number
230  * DL = drive number (bit 7 set for hard disk)
231  * ES:BX -> data buffer
232  * Return:
233  * CF set on error
234  * if AH = 11h (corrected ECC error), AL = burst length
235  * CF clear if successful
236  * AH = status
237  * AL = number of sectors transferred
238  * (only valid if CF set for some BIOSes)
239  */
240  RegsIn.b.ah = 0x02;
241  RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
242  RegsIn.b.ch = (PhysicalTrack & 0xFF);
243  RegsIn.b.cl = (UCHAR)(PhysicalSector + ((PhysicalTrack & 0x300) >> 2));
244  RegsIn.b.dh = PhysicalHead;
245  RegsIn.b.dl = DriveNumber;
246  RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
247  RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;
248 
249  /* Perform the read. Retry 3 times. */
250  for (RetryCount=0; RetryCount<3; RetryCount++)
251  {
252  Int386(0x13, &RegsIn, &RegsOut);
253 
254  /* If it worked break out */
255  if (INT386_SUCCESS(RegsOut))
256  {
257  break;
258  }
259  /* If it was a corrected ECC error then the data is still good */
260  else if (RegsOut.b.ah == 0x11)
261  {
262  break;
263  }
264  /* If it failed the do the next retry */
265  else
266  {
267  DiskResetController(DriveNumber);
268  continue;
269  }
270  }
271 
272  /* If we retried 3 times then fail */
273  if (RetryCount >= 3)
274  {
275  ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x\n", RegsOut.b.ah);
276  return FALSE;
277  }
278 
279  // I have learned that not all BIOSes return
280  // the sector read count in the AL register (at least mine doesn't)
281  // even if the sectors were read correctly. So instead
282  // of checking the sector read count we will rely solely
283  // on the carry flag being set on error
284 
285  Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead * DriveGeometry.BytesPerSector));
286  SectorCount -= NumberOfSectorsToRead;
287  SectorNumber += NumberOfSectorsToRead;
288  }
289 
290  return TRUE;
291 }
BOOLEAN DiskResetController(UCHAR DriveNumber)
Definition: pcdisk.c:79
#define TRUE
Definition: types.h:120
ULONG Cylinders
Definition: disk.h:26
unsigned short es
Definition: pcbios.h:101
unsigned char ah
Definition: pcbios.h:112
unsigned char dh
Definition: pcbios.h:121
uint32_t ULONG_PTR
Definition: typedefs.h:63
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:120
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
#define MachDiskGetDriveGeometry(Drive, Geom)
Definition: machine.h:122
ULONG Sectors
Definition: disk.h:28
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:118
unsigned char UCHAR
Definition: xmlstorage.h:181
unsigned char cl
Definition: pcbios.h:117
BYTEREGS b
Definition: pcbios.h:143
unsigned char al
Definition: pcbios.h:111
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:92
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:138
#define ULONG_PTR
Definition: config.h:101
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
Definition: disk.c:38
WORDREGS w
Definition: pcbios.h:142
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 103 of file pcdisk.c.

104 {
105  REGS RegsIn, RegsOut;
106  ULONG RetryCount;
108 
109  TRACE("PcDiskReadLogicalSectorsLBA() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer);
110  ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
111 
112  /* Setup disk address packet */
113  RtlZeroMemory(Packet, sizeof(*Packet));
114  Packet->PacketSize = sizeof(*Packet);
115  Packet->Reserved = 0;
116  Packet->LBABlockCount = (USHORT)SectorCount;
117  ASSERT(Packet->LBABlockCount == SectorCount);
118  Packet->TransferBufferOffset = ((ULONG_PTR)Buffer) & 0x0F;
119  Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4);
120  Packet->LBAStartBlock = SectorNumber;
121 
122  /*
123  * BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
124  * Return:
125  * CF clear if successful
126  * AH = 00h
127  * CF set on error
128  * AH = error code
129  * Disk address packet's block count field set to the
130  * number of blocks successfully transferred.
131  */
132  RegsIn.b.ah = 0x42; // Subfunction 42h
133  RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk)
134  RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
135  RegsIn.w.si = BIOSCALLBUFOFFSET;
136 
137  /* Retry 3 times */
138  for (RetryCount=0; RetryCount<3; RetryCount++)
139  {
140  Int386(0x13, &RegsIn, &RegsOut);
141 
142  /* If it worked return TRUE */
143  if (INT386_SUCCESS(RegsOut))
144  {
145  return TRUE;
146  }
147  /* If it was a corrected ECC error then the data is still good */
148  else if (RegsOut.b.ah == 0x11)
149  {
150  return TRUE;
151  }
152  /* If it failed then do the next retry */
153  else
154  {
155  DiskResetController(DriveNumber);
156  continue;
157  }
158  }
159 
160  /* If we get here then the read failed */
161  ERR("Disk Read Failed in LBA mode: %x (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n", RegsOut.b.ah, DriveNumber, SectorNumber, SectorCount);
162 
163  return FALSE;
164 }
BOOLEAN DiskResetController(UCHAR DriveNumber)
Definition: pcdisk.c:79
#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:140
unsigned char ah
Definition: pcbios.h:112
uint32_t ULONG_PTR
Definition: typedefs.h:63
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:120
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define INT386_SUCCESS(regs)
Definition: pcbios.h:159
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:143
ULONG SectorCount
Definition: part_xbox.c:32
#define ERR(fmt,...)
Definition: debug.h:109
unsigned short USHORT
Definition: pedump.c:61
unsigned short si
Definition: pcbios.h:96
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:138
#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:142
unsigned short ds
Definition: pcbios.h:80

Referenced by PcDiskReadLogicalSectors().