ReactOS  0.4.15-dev-1029-g3f30b1e
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
 
struct  _PC_DISK_DRIVE
 

Typedefs

typedef struct I386_DISK_ADDRESS_PACKETPI386_DISK_ADDRESS_PACKET
 
typedef struct I386_CDROM_SPEC_PACKETPI386_CDROM_SPEC_PACKET
 
typedef struct _PC_DISK_DRIVE PC_DISK_DRIVE
 
typedef struct _PC_DISK_DRIVEPPC_DISK_DRIVE
 

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 DiskIsDriveRemovable (UCHAR DriveNumber)
 
static BOOLEAN DiskInt13ExtensionsSupported (IN UCHAR DriveNumber)
 
static BOOLEAN DiskGetExtendedDriveParameters (IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, OUT PVOID Buffer, IN USHORT BufferSize)
 
static BOOLEAN InitDriveGeometry (IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive)
 
static BOOLEAN PcDiskDriveInit (IN UCHAR DriveNumber, IN OUT PPC_DISK_DRIVE DiskDrive)
 
static PPC_DISK_DRIVE PcDiskDriveNumberToDrive (IN UCHAR DriveNumber)
 
static BOOLEAN PcDiskReadLogicalSectorsLBA (IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
static BOOLEAN PcDiskReadLogicalSectorsCHS (IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
BOOLEAN PcDiskReadLogicalSectors (IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
 
BOOLEAN PcDiskGetDriveGeometry (UCHAR DriveNumber, PGEOMETRY Geometry)
 
ULONG PcDiskGetCacheableBlockCount (UCHAR DriveNumber)
 

Variables

static USHORT LastDriveNumber = 0xFFFF
 
static PC_DISK_DRIVE PcDiskDrive
 
static LONG lReportError = 0
 

Typedef Documentation

◆ PC_DISK_DRIVE

◆ PI386_CDROM_SPEC_PACKET

◆ PI386_DISK_ADDRESS_PACKET

◆ PPC_DISK_DRIVE

Function Documentation

◆ DBG_DEFAULT_CHANNEL()

DBG_DEFAULT_CHANNEL ( DISK  )

◆ DiskError()

static VOID DiskError ( PCSTR  ErrorString,
ULONG  ErrorCode 
)
static

Definition at line 163 of file pcdisk.c.

164 {
165  CHAR ErrorCodeString[200];
166 
167  if (lReportError < 0)
168  return;
169 
170  sprintf(ErrorCodeString, "%s\n\nError Code: 0x%lx\nError: %s",
172 
173  ERR("%s\n", ErrorCodeString);
174 
175  UiMessageBox(ErrorCodeString);
176 }
_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:128
VOID UiMessageBox(PCSTR Format,...)
Definition: ui.c:320
#define ERR(fmt,...)
Definition: debug.h:110
static LONG lReportError
Definition: pcdisk.c:118

Referenced by PcDiskReadLogicalSectorsCHS(), and PcDiskReadLogicalSectorsLBA().

◆ DiskGetErrorCodeString()

static PCSTR DiskGetErrorCodeString ( ULONG  ErrorCode)
static

Definition at line 128 of file pcdisk.c.

129 {
130  switch (ErrorCode)
131  {
132  case 0x00: return "no error";
133  case 0x01: return "bad command passed to driver";
134  case 0x02: return "address mark not found or bad sector";
135  case 0x03: return "diskette write protect error";
136  case 0x04: return "sector not found";
137  case 0x05: return "fixed disk reset failed";
138  case 0x06: return "diskette changed or removed";
139  case 0x07: return "bad fixed disk parameter table";
140  case 0x08: return "DMA overrun";
141  case 0x09: return "DMA access across 64k boundary";
142  case 0x0A: return "bad fixed disk sector flag";
143  case 0x0B: return "bad fixed disk cylinder";
144  case 0x0C: return "unsupported track/invalid media";
145  case 0x0D: return "invalid number of sectors on fixed disk format";
146  case 0x0E: return "fixed disk controlled data address mark detected";
147  case 0x0F: return "fixed disk DMA arbitration level out of range";
148  case 0x10: return "ECC/CRC error on disk read";
149  case 0x11: return "recoverable fixed disk data error, data fixed by ECC";
150  case 0x20: return "controller error (NEC for floppies)";
151  case 0x40: return "seek failure";
152  case 0x80: return "time out, drive not ready";
153  case 0xAA: return "fixed disk drive not ready";
154  case 0xBB: return "fixed disk undefined error";
155  case 0xCC: return "fixed disk write fault on selected drive";
156  case 0xE0: return "fixed disk status error/Error reg = 0";
157  case 0xFF: return "sense operation failed";
158 
159  default: return "unknown error code";
160  }
161 }
_In_ NDIS_ERROR_CODE ErrorCode
Definition: ndis.h:4436

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

◆ DiskGetExtendedDriveParameters()

static BOOLEAN DiskGetExtendedDriveParameters ( IN UCHAR  DriveNumber,
IN PPC_DISK_DRIVE  DiskDrive,
OUT PVOID  Buffer,
IN USHORT  BufferSize 
)
static

Definition at line 294 of file pcdisk.c.

299 {
300  REGS RegsIn, RegsOut;
302 
303  TRACE("DiskGetExtendedDriveParameters(0x%x)\n", DriveNumber);
304 
305  if (!DiskDrive->Int13ExtensionsSupported)
306  return FALSE;
307 
308  /* Initialize transfer buffer */
309  *Ptr = BufferSize;
310 
311  /*
312  * BIOS Int 13h, function 48h - Get drive parameters
313  * AH = 48h
314  * DL = drive (bit 7 set for hard disk)
315  * DS:SI = result buffer
316  * Return:
317  * CF set on error
318  * AH = status (07h)
319  * CF clear if successful
320  * AH = 00h
321  * DS:SI -> result buffer
322  */
323  RegsIn.b.ah = 0x48;
324  RegsIn.b.dl = DriveNumber;
325  RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
326  RegsIn.w.si = BIOSCALLBUFOFFSET;
327 
328  /* Get drive parameters */
329  Int386(0x13, &RegsIn, &RegsOut);
330  if (!INT386_SUCCESS(RegsOut))
331  return FALSE;
332 
334 
335 #if DBG
336  TRACE("size of buffer: %x\n", Ptr[0]);
337  TRACE("information flags: %x\n", Ptr[1]);
338  TRACE("number of physical cylinders on drive: %u\n", *(PULONG)&Ptr[2]);
339  TRACE("number of physical heads on drive: %u\n", *(PULONG)&Ptr[4]);
340  TRACE("number of physical sectors per track: %u\n", *(PULONG)&Ptr[6]);
341  TRACE("total number of sectors on drive: %I64u\n", *(unsigned long long*)&Ptr[8]);
342  TRACE("bytes per sector: %u\n", Ptr[12]);
343  if (Ptr[0] >= 0x1e)
344  {
345  TRACE("EED configuration parameters: %x:%x\n", Ptr[13], Ptr[14]);
346  if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
347  {
348  PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[13] << 4) + Ptr[14]);
349  TRACE("SpecPtr: %x\n", SpecPtr);
350  TRACE("physical I/O port base address: %x\n", *(PUSHORT)&SpecPtr[0]);
351  TRACE("disk-drive control port address: %x\n", *(PUSHORT)&SpecPtr[2]);
352  TRACE("drive flags: %x\n", SpecPtr[4]);
353  TRACE("proprietary information: %x\n", SpecPtr[5]);
354  TRACE("IRQ for drive: %u\n", SpecPtr[6]);
355  TRACE("sector count for multi-sector transfers: %u\n", SpecPtr[7]);
356  TRACE("DMA control: %x\n", SpecPtr[8]);
357  TRACE("programmed I/O control: %x\n", SpecPtr[9]);
358  TRACE("drive options: %x\n", *(PUSHORT)&SpecPtr[10]);
359  }
360  }
361  if (Ptr[0] >= 0x42)
362  {
363  TRACE("signature: %x\n", Ptr[15]);
364  }
365 #endif
366 
367  return TRUE;
368 }
NTSYSAPI VOID NTAPI RtlCopyMemory(VOID UNALIGNED *Destination, CONST VOID UNALIGNED *Source, ULONG Length)
#define BIOSCALLBUFFER
Definition: x86common.h:12
#define TRUE
Definition: types.h:120
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:154
unsigned char ah
Definition: pcbios.h:126
uint32_t ULONG_PTR
Definition: typedefs.h:65
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:134
#define FALSE
Definition: types.h:117
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define INT386_SUCCESS(regs)
Definition: pcbios.h:173
Definition: bufpool.h:45
#define TRACE(s)
Definition: solgame.cpp:4
#define BufferSize
Definition: classpnp.h:436
#define BIOSCALLBUFOFFSET
Definition: x86common.h:22
BYTEREGS b
Definition: pcbios.h:157
unsigned int * PULONG
Definition: retypes.h:1
unsigned short si
Definition: pcbios.h:110
Definition: pcbios.h:152
unsigned short * PUSHORT
Definition: retypes.h:2
WORDREGS w
Definition: pcbios.h:156
unsigned short ds
Definition: pcbios.h:94

Referenced by InitDriveGeometry(), and PcGetHarddiskConfigurationData().

◆ DiskInt13ExtensionsSupported()

static BOOLEAN DiskInt13ExtensionsSupported ( IN UCHAR  DriveNumber)
static

Definition at line 220 of file pcdisk.c.

221 {
222  REGS RegsIn, RegsOut;
223 
224  /*
225  * Some BIOSes report that extended disk access functions are not supported
226  * when booting from a CD (e.g. Phoenix BIOS v6.00PG and Insyde BIOS shipping
227  * with Intel Macs). Therefore we just return TRUE if we're booting from a CD
228  * - we can assume that all El Torito capable BIOSes support INT 13 extensions.
229  * We simply detect whether we're booting from CD by checking whether the drive
230  * number is >= 0x8A. It's 0x90 on the Insyde BIOS, and 0x9F on most other BIOSes.
231  */
232  if (DriveNumber >= 0x8A)
233  return TRUE;
234 
235  /*
236  * IBM/MS INT 13 Extensions - INSTALLATION CHECK
237  * AH = 41h
238  * BX = 55AAh
239  * DL = drive (80h-FFh)
240  * Return:
241  * CF set on error (extensions not supported)
242  * AH = 01h (invalid function)
243  * CF clear if successful
244  * BX = AA55h if installed
245  * AH = major version of extensions
246  * 01h = 1.x
247  * 20h = 2.0 / EDD-1.0
248  * 21h = 2.1 / EDD-1.1
249  * 30h = EDD-3.0
250  * AL = internal use
251  * CX = API subset support bitmap
252  * DH = extension version (v2.0+ ??? -- not present in 1.x)
253  *
254  * Bitfields for IBM/MS INT 13 Extensions API support bitmap
255  * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
256  * Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
257  * Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
258  * extended drive parameter table is valid
259  * Bits 3-15 reserved
260  */
261  RegsIn.b.ah = 0x41;
262  RegsIn.w.bx = 0x55AA;
263  RegsIn.b.dl = DriveNumber;
264 
265  /* Reset the disk controller */
266  Int386(0x13, &RegsIn, &RegsOut);
267  if (!INT386_SUCCESS(RegsOut))
268  {
269  /* CF set on error (extensions not supported) */
270  return FALSE;
271  }
272 
273  if (RegsOut.w.bx != 0xAA55)
274  {
275  /* BX = AA55h if installed */
276  return FALSE;
277  }
278 
279  if (!(RegsOut.w.cx & 0x0001))
280  {
281  /*
282  * CX = API subset support bitmap.
283  * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported.
284  */
285  WARN("Suspicious API subset support bitmap 0x%x on device 0x%lx\n",
286  RegsOut.w.cx, DriveNumber);
287  return FALSE;
288  }
289 
290  return TRUE;
291 }
#define TRUE
Definition: types.h:120
#define WARN(fmt,...)
Definition: debug.h:112
unsigned short cx
Definition: pcbios.h:107
unsigned char ah
Definition: pcbios.h:126
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:134
#define FALSE
Definition: types.h:117
#define INT386_SUCCESS(regs)
Definition: pcbios.h:173
BYTEREGS b
Definition: pcbios.h:157
unsigned short bx
Definition: pcbios.h:106
Definition: pcbios.h:152
WORDREGS w
Definition: pcbios.h:156

Referenced by PcDiskDriveInit().

◆ DiskIsDriveRemovable()

static BOOLEAN DiskIsDriveRemovable ( UCHAR  DriveNumber)
static

Definition at line 205 of file pcdisk.c.

206 {
207  /*
208  * Hard disks use drive numbers >= 0x80 . So if the drive number
209  * indicates a hard disk then return FALSE.
210  * 0x49 is our magic ramdisk drive, so return FALSE for that too.
211  */
212  if ((DriveNumber >= 0x80) || (DriveNumber == 0x49))
213  return FALSE;
214 
215  /* The drive is a floppy diskette so return TRUE */
216  return TRUE;
217 }
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117

Referenced by PcDiskDriveInit().

◆ DiskReportError()

LONG DiskReportError ( BOOLEAN  bShowError)

Definition at line 120 of file pcdisk.c.

121 {
122  /* Set the reference count */
123  if (bShowError) ++lReportError;
124  else --lReportError;
125  return lReportError;
126 }
static LONG lReportError
Definition: pcdisk.c:118

Referenced by EnumerateHarddisks(), and GetHarddiskInformation().

◆ DiskResetController()

BOOLEAN DiskResetController ( UCHAR  DriveNumber)

Definition at line 180 of file pcdisk.c.

181 {
182  REGS RegsIn, RegsOut;
183 
184  WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
185 
186  /*
187  * BIOS Int 13h, function 0 - Reset disk system
188  * AH = 00h
189  * DL = drive (if bit 7 is set both hard disks and floppy disks reset)
190  * Return:
191  * AH = status
192  * CF clear if successful
193  * CF set on error
194  */
195  RegsIn.b.ah = 0x00;
196  RegsIn.b.dl = DriveNumber;
197 
198  /* Reset the disk controller */
199  Int386(0x13, &RegsIn, &RegsOut);
200 
201  return INT386_SUCCESS(RegsOut);
202 }
#define WARN(fmt,...)
Definition: debug.h:112
unsigned char ah
Definition: pcbios.h:126
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:134
#define INT386_SUCCESS(regs)
Definition: pcbios.h:173
BYTEREGS b
Definition: pcbios.h:157
Definition: pcbios.h:152

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

◆ InitDriveGeometry()

static BOOLEAN InitDriveGeometry ( IN UCHAR  DriveNumber,
IN PPC_DISK_DRIVE  DiskDrive 
)
static

Definition at line 371 of file pcdisk.c.

374 {
376  REGS RegsIn, RegsOut;
377  ULONG Cylinders;
378 
379  /* Get the extended geometry first */
380  DiskDrive->ExtGeometry.Size = sizeof(DiskDrive->ExtGeometry);
381  Success = DiskGetExtendedDriveParameters(DriveNumber, DiskDrive,
382  &DiskDrive->ExtGeometry,
383  DiskDrive->ExtGeometry.Size);
384  if (!Success)
385  {
386  /* Failed, zero it out */
387  RtlZeroMemory(&DiskDrive->ExtGeometry, sizeof(DiskDrive->ExtGeometry));
388  }
389  else
390  {
391  TRACE("DiskGetExtendedDriveParameters(0x%x) returned:\n"
392  "Cylinders : 0x%x\n"
393  "Heads : 0x%x\n"
394  "Sects/Track: 0x%x\n"
395  "Bytes/Sect : 0x%x\n",
396  DriveNumber,
397  DiskDrive->ExtGeometry.Cylinders,
398  DiskDrive->ExtGeometry.Heads,
399  DiskDrive->ExtGeometry.SectorsPerTrack,
400  DiskDrive->ExtGeometry.BytesPerSector);
401  }
402 
403  /* Now try the legacy geometry */
404  RtlZeroMemory(&DiskDrive->Geometry, sizeof(DiskDrive->Geometry));
405 
406  /*
407  * BIOS Int 13h, function 08h - Get drive parameters
408  * AH = 08h
409  * DL = drive (bit 7 set for hard disk)
410  * ES:DI = 0000h:0000h to guard against BIOS bugs
411  * Return:
412  * CF set on error
413  * AH = status (07h)
414  * CF clear if successful
415  * AH = 00h
416  * AL = 00h on at least some BIOSes
417  * BL = drive type (AT/PS2 floppies only)
418  * CH = low eight bits of maximum cylinder number
419  * CL = maximum sector number (bits 5-0)
420  * high two bits of maximum cylinder number (bits 7-6)
421  * DH = maximum head number
422  * DL = number of drives
423  * ES:DI -> drive parameter table (floppies only)
424  */
425  RegsIn.b.ah = 0x08;
426  RegsIn.b.dl = DriveNumber;
427  RegsIn.w.es = 0x0000;
428  RegsIn.w.di = 0x0000;
429 
430  /* Get drive parameters */
431  Int386(0x13, &RegsIn, &RegsOut);
432  if (!INT386_SUCCESS(RegsOut))
433  {
434  /* We failed, return the result of the previous call (extended geometry) */
435  return Success;
436  }
437  /* OR it with the old result, so that we return TRUE whenever either call succeeded */
438  Success |= TRUE;
439 
440  Cylinders = (RegsOut.b.cl & 0xC0) << 2;
441  Cylinders += RegsOut.b.ch;
442  Cylinders++;
443  DiskDrive->Geometry.Cylinders = Cylinders;
444  DiskDrive->Geometry.Heads = RegsOut.b.dh + 1;
445  DiskDrive->Geometry.Sectors = RegsOut.b.cl & 0x3F;
446  DiskDrive->Geometry.BytesPerSector = 512; /* Just assume 512 bytes per sector */
447 
448  TRACE("Regular Int13h(0x%x) returned:\n"
449  "Cylinders : 0x%x\n"
450  "Heads : 0x%x\n"
451  "Sects/Track: 0x%x (original 0x%x)\n"
452  "Bytes/Sect : 0x%x\n",
453  DriveNumber,
454  DiskDrive->Geometry.Cylinders,
455  DiskDrive->Geometry.Heads,
456  DiskDrive->Geometry.Sectors, RegsOut.b.cl,
457  DiskDrive->Geometry.BytesPerSector);
458 
459  return Success;
460 }
#define TRUE
Definition: types.h:120
unsigned short es
Definition: pcbios.h:115
unsigned char ah
Definition: pcbios.h:126
unsigned char dh
Definition: pcbios.h:135
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:134
#define INT386_SUCCESS(regs)
Definition: pcbios.h:173
unsigned char BOOLEAN
#define TRACE(s)
Definition: solgame.cpp:4
unsigned char ch
Definition: pcbios.h:132
unsigned char cl
Definition: pcbios.h:131
BYTEREGS b
Definition: pcbios.h:157
static BOOLEAN DiskGetExtendedDriveParameters(IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, OUT PVOID Buffer, IN USHORT BufferSize)
Definition: pcdisk.c:294
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:152
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
unsigned short di
Definition: pcbios.h:111
WORDREGS w
Definition: pcbios.h:156

Referenced by PcDiskDriveInit().

◆ PcDiskDriveInit()

static BOOLEAN PcDiskDriveInit ( IN UCHAR  DriveNumber,
IN OUT PPC_DISK_DRIVE  DiskDrive 
)
static

Definition at line 463 of file pcdisk.c.

466 {
467  DiskDrive->IsRemovable = DiskIsDriveRemovable(DriveNumber);
468 
469  /*
470  * Check to see if it is a fixed disk drive.
471  * If so then check to see if INT 13h extensions work.
472  * If they do then use them, otherwise default back to BIOS calls.
473  */
474  DiskDrive->Int13ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
475 
476  if (!InitDriveGeometry(DriveNumber, DiskDrive))
477  return FALSE;
478 
479  TRACE("\n"
480  "DriveNumber: 0x%x\n"
481  "IsRemovable = %s\n"
482  "Int13ExtensionsSupported = %s\n",
483  DriveNumber,
484  DiskDrive->IsRemovable ? "TRUE" : "FALSE",
485  DiskDrive->Int13ExtensionsSupported ? "TRUE" : "FALSE");
486 
487  return TRUE;
488 }
#define TRUE
Definition: types.h:120
static BOOLEAN DiskInt13ExtensionsSupported(IN UCHAR DriveNumber)
Definition: pcdisk.c:220
#define FALSE
Definition: types.h:117
static BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber)
Definition: pcdisk.c:205
#define TRACE(s)
Definition: solgame.cpp:4
static BOOLEAN InitDriveGeometry(IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive)
Definition: pcdisk.c:371

Referenced by PcDiskDriveNumberToDrive().

◆ PcDiskDriveNumberToDrive()

static PPC_DISK_DRIVE PcDiskDriveNumberToDrive ( IN UCHAR  DriveNumber)
inlinestatic

Definition at line 492 of file pcdisk.c.

493 {
494 #ifdef CACHE_MULTI_DRIVES
495  PPC_DISK_DRIVE DiskDrive;
496 
497  ASSERT((0 <= DriveNumber) && (DriveNumber < RTL_NUMBER_OF(PcDiskDrive)));
498 
499  /* Retrieve a slot */
500  DiskDrive = &PcDiskDrive[DriveNumber];
501 
502  /* If the drive has not been initialized before... */
503  if (!DiskDrive->Initialized)
504  {
505  /* ... try to initialize it now. */
506  if (!PcDiskDriveInit(DriveNumber, DiskDrive))
507  {
508  /*
509  * If we failed, there is no drive at this number
510  * and flag it as such (set its high bit).
511  */
512  DiskDrive->Initialized |= 0x80;
513  return NULL;
514  }
515  DiskDrive->Initialized = TRUE;
516  }
517  else if (DiskDrive->Initialized & 0x80)
518  {
519  /*
520  * The disk failed to be initialized previously, reset its flag to give
521  * it chance to be initialized again later, but just fail for the moment.
522  */
523  DiskDrive->Initialized = FALSE;
524  return NULL;
525  }
526 
527  return DiskDrive;
528 #else
529  static PC_DISK_DRIVE NewDiskDrive;
530 
531  ASSERT((0 <= DriveNumber) && (DriveNumber <= 0xFF));
532 
533  /* Update cached information */
534 
535  /* If the drive has not been accessed last before... */
536  if ((USHORT)DriveNumber != LastDriveNumber)
537  {
538  /* ... try to (re-)initialize and cache it now. */
539  RtlZeroMemory(&NewDiskDrive, sizeof(NewDiskDrive));
540  if (!PcDiskDriveInit(DriveNumber, &NewDiskDrive))
541  {
542  /*
543  * If we failed, there is no drive at this number.
544  * Keep the last-accessed valid drive cached.
545  */
546  return NULL;
547  }
548  /* We succeeded, cache the drive data */
549  PcDiskDrive = NewDiskDrive;
550  LastDriveNumber = (USHORT)DriveNumber;
551  }
552 
553  return &PcDiskDrive;
554 #endif /* CACHE_MULTI_DRIVES */
555 }
#define TRUE
Definition: types.h:120
static PC_DISK_DRIVE PcDiskDrive
Definition: pcdisk.c:113
#define FALSE
Definition: types.h:117
smooth NULL
Definition: ftsmooth.c:416
static BOOLEAN PcDiskDriveInit(IN UCHAR DriveNumber, IN OUT PPC_DISK_DRIVE DiskDrive)
Definition: pcdisk.c:463
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
unsigned short USHORT
Definition: pedump.c:61
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
static USHORT LastDriveNumber
Definition: pcdisk.c:112

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

◆ PcDiskGetCacheableBlockCount()

ULONG PcDiskGetCacheableBlockCount ( UCHAR  DriveNumber)

Definition at line 827 of file pcdisk.c.

828 {
829  PPC_DISK_DRIVE DiskDrive;
830 
831  DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
832  if (!DiskDrive)
833  return 1; // Unknown count.
834 
835  /*
836  * If LBA is supported then the block size will be 64 sectors (32k).
837  * If not then the block size is the size of one track.
838  */
839  if (DiskDrive->Int13ExtensionsSupported)
840  return 64;
841  else
842  return DiskDrive->Geometry.Sectors;
843 }
static PPC_DISK_DRIVE PcDiskDriveNumberToDrive(IN UCHAR DriveNumber)
Definition: pcdisk.c:492
ULONG Sectors
Definition: disk.h:28
BOOLEAN Int13ExtensionsSupported
Definition: pcdisk.c:86
GEOMETRY Geometry
Definition: pcdisk.c:82

Referenced by MachInit().

◆ PcDiskGetDriveGeometry()

BOOLEAN PcDiskGetDriveGeometry ( UCHAR  DriveNumber,
PGEOMETRY  Geometry 
)

Definition at line 798 of file pcdisk.c.

799 {
800  PPC_DISK_DRIVE DiskDrive;
801 
802  TRACE("PcDiskGetDriveGeometry(0x%x)\n", DriveNumber);
803 
804  DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
805  if (!DiskDrive)
806  return FALSE;
807 
808  /* Try to get the extended geometry first */
809  if (DiskDrive->ExtGeometry.Size == sizeof(DiskDrive->ExtGeometry))
810  {
811  /* Extended geometry has been initialized, return it */
812  Geometry->Cylinders = DiskDrive->ExtGeometry.Cylinders;
813  Geometry->Heads = DiskDrive->ExtGeometry.Heads;
814  Geometry->Sectors = DiskDrive->ExtGeometry.SectorsPerTrack;
815  Geometry->BytesPerSector = DiskDrive->ExtGeometry.BytesPerSector;
816  }
817  else
818  /* Fall back to legacy BIOS geometry */
819  {
820  *Geometry = DiskDrive->Geometry;
821  }
822 
823  return TRUE;
824 }
#define TRUE
Definition: types.h:120
ULONG Cylinders
Definition: disk.h:26
ULONG Cylinders
Definition: disk.h:41
static PPC_DISK_DRIVE PcDiskDriveNumberToDrive(IN UCHAR DriveNumber)
Definition: pcdisk.c:492
#define FALSE
Definition: types.h:117
ULONG SectorsPerTrack
Definition: disk.h:43
ULONG Sectors
Definition: disk.h:28
#define TRACE(s)
Definition: solgame.cpp:4
EXTENDED_GEOMETRY ExtGeometry
Definition: pcdisk.c:83
GEOMETRY Geometry
Definition: pcdisk.c:82
USHORT Size
Definition: disk.h:39
ULONG BytesPerSector
Definition: disk.h:29
USHORT BytesPerSector
Definition: disk.h:45
ULONG Heads
Definition: disk.h:42
ULONG Heads
Definition: disk.h:27

Referenced by MachInit(), and PcGetHarddiskConfigurationData().

◆ PcDiskReadLogicalSectors()

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

Definition at line 758 of file pcdisk.c.

763 {
764  PPC_DISK_DRIVE DiskDrive;
765 
766  TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n",
767  DriveNumber, SectorNumber, SectorCount, Buffer);
768 
769  /* 16-bit BIOS addressing limitation */
770  ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
771 
772  DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
773  if (!DiskDrive)
774  return FALSE;
775 
776  if ((DriveNumber >= 0x80) && DiskDrive->Int13ExtensionsSupported)
777  {
778  /* LBA is easy, nothing to calculate. Just do the read. */
779  TRACE("--> Using LBA\n");
780  return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
781  }
782  else
783  {
784  /* LBA is not supported, default to CHS */
785  TRACE("--> Using CHS\n");
786  return PcDiskReadLogicalSectorsCHS(DriveNumber, DiskDrive, SectorNumber, SectorCount, Buffer);
787  }
788 }
uint32_t ULONG_PTR
Definition: typedefs.h:65
static PPC_DISK_DRIVE PcDiskDriveNumberToDrive(IN UCHAR DriveNumber)
Definition: pcdisk.c:492
#define FALSE
Definition: types.h:117
Definition: bufpool.h:45
#define TRACE(s)
Definition: solgame.cpp:4
static BOOLEAN PcDiskReadLogicalSectorsLBA(IN UCHAR DriveNumber, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pcdisk.c:558
BOOLEAN Int13ExtensionsSupported
Definition: pcdisk.c:86
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
ULONG SectorCount
Definition: part_xbox.c:31
static BOOLEAN PcDiskReadLogicalSectorsCHS(IN UCHAR DriveNumber, IN PPC_DISK_DRIVE DiskDrive, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
Definition: pcdisk.c:626

Referenced by MachInit().

◆ PcDiskReadLogicalSectorsCHS()

static BOOLEAN PcDiskReadLogicalSectorsCHS ( IN UCHAR  DriveNumber,
IN PPC_DISK_DRIVE  DiskDrive,
IN ULONGLONG  SectorNumber,
IN ULONG  SectorCount,
OUT PVOID  Buffer 
)
static

Definition at line 626 of file pcdisk.c.

632 {
633  UCHAR PhysicalSector;
634  UCHAR PhysicalHead;
635  ULONG PhysicalTrack;
636  GEOMETRY DriveGeometry;
637  ULONG NumberOfSectorsToRead;
638  REGS RegsIn, RegsOut;
639  ULONG RetryCount;
640 
641  DriveGeometry = DiskDrive->Geometry;
642  if (DriveGeometry.Sectors == 0 || DriveGeometry.Heads == 0)
643  return FALSE;
644 
645  while (SectorCount > 0)
646  {
647  /*
648  * Calculate the physical disk offsets.
649  * Note: DriveGeometry.Sectors < 64
650  */
651  PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors);
652  PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads);
653  PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads);
654 
655  /* Calculate how many sectors we need to read this round */
656  if (PhysicalSector > 1)
657  {
658  if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
659  NumberOfSectorsToRead = (DriveGeometry.Sectors - (PhysicalSector - 1));
660  else
661  NumberOfSectorsToRead = SectorCount;
662  }
663  else
664  {
665  if (SectorCount >= DriveGeometry.Sectors)
666  NumberOfSectorsToRead = DriveGeometry.Sectors;
667  else
668  NumberOfSectorsToRead = SectorCount;
669  }
670 
671  /* Make sure the read is within the geometry boundaries */
672  if ((PhysicalHead >= DriveGeometry.Heads) ||
673  (PhysicalTrack >= DriveGeometry.Cylinders) ||
674  ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
675  (PhysicalSector > DriveGeometry.Sectors))
676  {
677  DiskError("Disk read exceeds drive geometry limits.", 0);
678  return FALSE;
679  }
680 
681  /*
682  * BIOS Int 13h, function 2 - Read Disk Sectors
683  * AH = 02h
684  * AL = number of sectors to read (must be nonzero)
685  * CH = low eight bits of cylinder number
686  * CL = sector number 1-63 (bits 0-5)
687  * high two bits of cylinder (bits 6-7, hard disk only)
688  * DH = head number
689  * DL = drive number (bit 7 set for hard disk)
690  * ES:BX -> data buffer
691  * Return:
692  * CF set on error
693  * if AH = 11h (corrected ECC error), AL = burst length
694  * CF clear if successful
695  * AH = status
696  * AL = number of sectors transferred
697  * (only valid if CF set for some BIOSes)
698  */
699  RegsIn.b.ah = 0x02;
700  RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
701  RegsIn.b.ch = (PhysicalTrack & 0xFF);
702  RegsIn.b.cl = (UCHAR)(PhysicalSector + ((PhysicalTrack & 0x300) >> 2));
703  RegsIn.b.dh = PhysicalHead;
704  RegsIn.b.dl = DriveNumber;
705  RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
706  RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;
707 
708  /* Perform the read. Retry 3 times. */
709  for (RetryCount = 0; RetryCount < 3; ++RetryCount)
710  {
711  Int386(0x13, &RegsIn, &RegsOut);
712 
713  /* If it worked break out */
714  if (INT386_SUCCESS(RegsOut))
715  {
716  break;
717  }
718  /* If it was a corrected ECC error then the data is still good */
719  else if (RegsOut.b.ah == 0x11)
720  {
721  break;
722  }
723  /* If it failed then do the next retry */
724  else
725  {
726  DiskResetController(DriveNumber);
727  continue;
728  }
729  }
730 
731  /* If we retried 3 times then fail */
732  if (RetryCount >= 3)
733  {
734  DiskError("Disk Read Failed in CHS mode, after retrying 3 times", RegsOut.b.ah);
735  ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n",
736  RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
737  DriveNumber, SectorNumber, SectorCount);
738  return FALSE;
739  }
740 
741  /*
742  * I have learned that not all BIOSes return
743  * the sector read count in the AL register (at least mine doesn't)
744  * even if the sectors were read correctly. So instead
745  * of checking the sector read count we will rely solely
746  * on the carry flag being set on error.
747  */
748 
749  Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead * DriveGeometry.BytesPerSector));
750  SectorCount -= NumberOfSectorsToRead;
751  SectorNumber += NumberOfSectorsToRead;
752  }
753 
754  return TRUE;
755 }
BOOLEAN DiskResetController(UCHAR DriveNumber)
Definition: pcdisk.c:180
#define TRUE
Definition: types.h:120
ULONG Cylinders
Definition: disk.h:26
unsigned short es
Definition: pcbios.h:115
unsigned char ah
Definition: pcbios.h:126
unsigned char dh
Definition: pcbios.h:135
uint32_t ULONG_PTR
Definition: typedefs.h:65
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:134
#define FALSE
Definition: types.h:117
#define INT386_SUCCESS(regs)
Definition: pcbios.h:173
static PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
Definition: pcdisk.c:128
Definition: bufpool.h:45
void * PVOID
Definition: retypes.h:9
ULONG Sectors
Definition: disk.h:28
unsigned char ch
Definition: pcbios.h:132
unsigned char UCHAR
Definition: xmlstorage.h:181
unsigned char cl
Definition: pcbios.h:131
BYTEREGS b
Definition: pcbios.h:157
unsigned char al
Definition: pcbios.h:125
ULONG SectorCount
Definition: part_xbox.c:31
#define ERR(fmt,...)
Definition: debug.h:110
ULONG BytesPerSector
Definition: disk.h:29
unsigned short USHORT
Definition: pedump.c:61
Definition: disk.h:24
unsigned short bx
Definition: pcbios.h:106
static VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
Definition: pcdisk.c:163
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:152
#define ULONG_PTR
Definition: config.h:101
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
WORDREGS w
Definition: pcbios.h:156
ULONG Heads
Definition: disk.h:27

Referenced by PcDiskReadLogicalSectors().

◆ PcDiskReadLogicalSectorsLBA()

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

Definition at line 558 of file pcdisk.c.

563 {
564  REGS RegsIn, RegsOut;
565  ULONG RetryCount;
567 
568  /* Setup disk address packet */
569  RtlZeroMemory(Packet, sizeof(*Packet));
570  Packet->PacketSize = sizeof(*Packet);
571  Packet->Reserved = 0;
572  Packet->LBABlockCount = (USHORT)SectorCount;
573  ASSERT(Packet->LBABlockCount == SectorCount);
574  Packet->TransferBufferOffset = ((ULONG_PTR)Buffer) & 0x0F;
575  Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4);
576  Packet->LBAStartBlock = SectorNumber;
577 
578  /*
579  * BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
580  * Return:
581  * CF clear if successful
582  * AH = 00h
583  * CF set on error
584  * AH = error code
585  * Disk address packet's block count field set to the
586  * number of blocks successfully transferred.
587  */
588  RegsIn.b.ah = 0x42; // Subfunction 42h
589  RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk)
590  RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
591  RegsIn.w.si = BIOSCALLBUFOFFSET;
592 
593  /* Retry 3 times */
594  for (RetryCount = 0; RetryCount < 3; ++RetryCount)
595  {
596  Int386(0x13, &RegsIn, &RegsOut);
597 
598  /* If it worked return TRUE */
599  if (INT386_SUCCESS(RegsOut))
600  {
601  return TRUE;
602  }
603  /* If it was a corrected ECC error then the data is still good */
604  else if (RegsOut.b.ah == 0x11)
605  {
606  return TRUE;
607  }
608  /* If it failed then do the next retry */
609  else
610  {
611  DiskResetController(DriveNumber);
612  continue;
613  }
614  }
615 
616  /* If we get here then the read failed */
617  DiskError("Disk Read Failed in LBA mode", RegsOut.b.ah);
618  ERR("Disk Read Failed in LBA mode: %x (%s) (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n",
619  RegsOut.b.ah, DiskGetErrorCodeString(RegsOut.b.ah),
620  DriveNumber, SectorNumber, SectorCount);
621 
622  return FALSE;
623 }
BOOLEAN DiskResetController(UCHAR DriveNumber)
Definition: pcdisk.c:180
_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
#define TRUE
Definition: types.h:120
DWORDREGS x
Definition: pcbios.h:154
unsigned char ah
Definition: pcbios.h:126
uint32_t ULONG_PTR
Definition: typedefs.h:65
int __cdecl Int386(int ivec, REGS *in, REGS *out)
unsigned char dl
Definition: pcbios.h:134
#define FALSE
Definition: types.h:117
#define BIOSCALLBUFSEGMENT
Definition: x86common.h:21
#define INT386_SUCCESS(regs)
Definition: pcbios.h:173
static PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
Definition: pcdisk.c:128
Definition: bufpool.h:45
#define BIOSCALLBUFOFFSET
Definition: x86common.h:22
ASSERT((InvokeOnSuccess||InvokeOnError||InvokeOnCancel) ?(CompletionRoutine !=NULL) :TRUE)
BYTEREGS b
Definition: pcbios.h:157
ULONG SectorCount
Definition: part_xbox.c:31
#define ERR(fmt,...)
Definition: debug.h:110
unsigned short USHORT
Definition: pedump.c:61
static VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
Definition: pcdisk.c:163
unsigned short si
Definition: pcbios.h:110
unsigned int ULONG
Definition: retypes.h:1
Definition: pcbios.h:152
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
#define ULONG_PTR
Definition: config.h:101
IN BOOLEAN OUT PSTR Buffer
Definition: progress.h:34
WORDREGS w
Definition: pcbios.h:156
unsigned short ds
Definition: pcbios.h:94

Referenced by PcDiskReadLogicalSectors().

Variable Documentation

◆ LastDriveNumber

USHORT LastDriveNumber = 0xFFFF
static

Definition at line 112 of file pcdisk.c.

Referenced by PcDiskDriveNumberToDrive().

◆ lReportError

LONG lReportError = 0
static

Definition at line 118 of file pcdisk.c.

Referenced by DiskError(), and DiskReportError().

◆ PcDiskDrive

PC_DISK_DRIVE PcDiskDrive
static

Definition at line 113 of file pcdisk.c.

Referenced by PcDiskDriveNumberToDrive().