https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7c93350e05f7105afd6fe…
commit 7c93350e05f7105afd6fedc8498d68c9a8841e31
Author: disean <di.sean(a)protonmail.com>
AuthorDate: Tue Jan 14 09:08:53 2020 +0600
Commit: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org>
CommitDate: Tue Jan 14 04:08:53 2020 +0100
[FREELDR] Cache INT13h drive data in pcdisk.c (#2097)
* [FREELDR] Cache the drive geometry in the PcDiskReadLogicalSectorsCHS()
Speed up the loading time a bit.
* [FREELDR] Generalize the cache to all the geometry data + INT 13h
extensions-supported status.
The data structure used is "PC_DISK_DRIVE".
- Adapt the associated functions;
- Make DiskGetExtendedDriveParameters() private to pcdisk.c
- Introduce PcDiskDriveNumberToDrive(), that is similar to the XBOX
function XboxDiskDriveNumberToDeviceUnit(), that retrieves a valid
pointer to the cached disk corresponding to the given BIOS DriveNumber.
If needed the cached data gets initialized.
- Make XboxDiskDriveNumberToDeviceUnit() simpler by just returning the
pointer to the corresponding drive, of NULL if there is none.
Co-authored-by: Hermès BÉLUSCA - MAÏTO <hermes.belusca-maito(a)reactos.org>
---
boot/freeldr/freeldr/arch/i386/hwdisk.c | 2 +
boot/freeldr/freeldr/arch/i386/machpc.c | 7 +-
boot/freeldr/freeldr/arch/i386/pcdisk.c | 731 ++++++++++++++++----------
boot/freeldr/freeldr/arch/i386/xboxdisk.c | 52 +-
boot/freeldr/freeldr/include/arch/pc/machpc.h | 2 +-
5 files changed, 498 insertions(+), 296 deletions(-)
diff --git a/boot/freeldr/freeldr/arch/i386/hwdisk.c
b/boot/freeldr/freeldr/arch/i386/hwdisk.c
index 7aec1c3db99..cf23c60ac21 100644
--- a/boot/freeldr/freeldr/arch/i386/hwdisk.c
+++ b/boot/freeldr/freeldr/arch/i386/hwdisk.c
@@ -396,6 +396,8 @@ EnumerateHarddisks(OUT PBOOLEAN BootDriveReported)
return DiskCount;
}
+// FIXME: Copied from pcdisk.c
+// Actually this function is REALLY PC-specific!!
static BOOLEAN
DiskIsDriveRemovable(UCHAR DriveNumber)
{
diff --git a/boot/freeldr/freeldr/arch/i386/machpc.c
b/boot/freeldr/freeldr/arch/i386/machpc.c
index 712a0575b44..95253971c02 100644
--- a/boot/freeldr/freeldr/arch/i386/machpc.c
+++ b/boot/freeldr/freeldr/arch/i386/machpc.c
@@ -105,7 +105,7 @@ PcGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
- EXTENDED_GEOMETRY ExtGeometry;
+ // EXTENDED_GEOMETRY ExtGeometry;
GEOMETRY Geometry;
ULONG Size;
@@ -139,6 +139,7 @@ PcGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) +
sizeof(CM_PARTIAL_RESOURCE_LIST));
/* Get the disk geometry */
+#if 0 // This is somehow replaced by what PcDiskGetDriveGeometry() does internally.
ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
{
@@ -147,7 +148,9 @@ PcGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
DiskGeometry->SectorsPerTrack = ExtGeometry.SectorsPerTrack;
DiskGeometry->NumberOfHeads = ExtGeometry.Heads;
}
- else if (PcDiskGetDriveGeometry(DriveNumber, &Geometry))
+ else
+#endif
+ if (PcDiskGetDriveGeometry(DriveNumber, &Geometry))
{
DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
diff --git a/boot/freeldr/freeldr/arch/i386/pcdisk.c
b/boot/freeldr/freeldr/arch/i386/pcdisk.c
index f9fc4f0c1ba..37058bced70 100644
--- a/boot/freeldr/freeldr/arch/i386/pcdisk.c
+++ b/boot/freeldr/freeldr/arch/i386/pcdisk.c
@@ -24,6 +24,9 @@
#include <debug.h>
DBG_DEFAULT_CHANNEL(DISK);
+/* Enable this line if you want to support multi-drive caching (increases FreeLdr size!)
*/
+// #define CACHE_MULTI_DRIVES
+
#include <pshpack2.h>
typedef struct
@@ -73,6 +76,43 @@ typedef struct
#include <poppack.h>
+typedef struct _PC_DISK_DRIVE
+{
+ /* Disk geometry (legacy BIOS and INT13 extended) */
+ GEOMETRY Geometry;
+ EXTENDED_GEOMETRY ExtGeometry;
+
+ /* TRUE when INT 13h extensions are supported */
+ BOOLEAN Int13ExtensionsSupported;
+
+ /*
+ * 'IsRemovable' flag: TRUE when the drive is removable (e.g. floppy,
CD-ROM...).
+ * In that case some of the cached information might need to be refreshed regularly.
+ */
+ BOOLEAN IsRemovable;
+
+#ifdef CACHE_MULTI_DRIVES
+ /*
+ * 'Initialized' flag: if TRUE then the drive has been initialized;
+ * if FALSE then it needs to be initialized; if its high bit is set
+ * then there has been an error; don't try to use it.
+ */
+ BOOLEAN Initialized;
+#endif
+} PC_DISK_DRIVE, *PPC_DISK_DRIVE;
+
+#ifdef CACHE_MULTI_DRIVES
+/* Cache of all possible PC disk drives */
+// Maximum number of disks is 0x100, indexed from 0x00 to 0xFF.
+static PC_DISK_DRIVE PcDiskDrive[0x100];
+#else
+/* Cached data for the last-accessed PC disk drive */
+// We use a USHORT so that we can initialize it with a drive number that cannot exist
+// on the system (they are <= 0xFF), therefore forcing drive caching on first access.
+static USHORT LastDriveNumber = 0xFFFF;
+static PC_DISK_DRIVE PcDiskDrive;
+#endif /* CACHE_MULTI_DRIVES */
+
/* DISK IO ERROR SUPPORT *****************************************************/
static LONG lReportError = 0; // >= 0: display errors; < 0: hide errors.
@@ -130,7 +170,7 @@ static VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
sprintf(ErrorCodeString, "%s\n\nError Code: 0x%lx\nError: %s",
ErrorString, ErrorCode, DiskGetErrorCodeString(ErrorCode));
- TRACE("%s\n", ErrorCodeString);
+ ERR("%s\n", ErrorCodeString);
UiMessageBox(ErrorCodeString);
}
@@ -161,15 +201,370 @@ BOOLEAN DiskResetController(UCHAR DriveNumber)
return INT386_SUCCESS(RegsOut);
}
-static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNumber,
ULONG SectorCount, PVOID Buffer)
+static BOOLEAN
+DiskIsDriveRemovable(UCHAR DriveNumber)
+{
+ /*
+ * Hard disks use drive numbers >= 0x80 . So if the drive number
+ * indicates a hard disk then return FALSE.
+ * 0x49 is our magic ramdisk drive, so return FALSE for that too.
+ */
+ if ((DriveNumber >= 0x80) || (DriveNumber == 0x49))
+ return FALSE;
+
+ /* The drive is a floppy diskette so return TRUE */
+ return TRUE;
+}
+
+static BOOLEAN
+DiskInt13ExtensionsSupported(IN UCHAR DriveNumber)
+{
+ REGS RegsIn, RegsOut;
+
+ /*
+ * Some BIOSes report that extended disk access functions are not supported
+ * when booting from a CD (e.g. Phoenix BIOS v6.00PG and Insyde BIOS shipping
+ * with Intel Macs). Therefore we just return TRUE if we're booting from a CD
+ * - we can assume that all El Torito capable BIOSes support INT 13 extensions.
+ * We simply detect whether we're booting from CD by checking whether the drive
+ * number is >= 0x8A. It's 0x90 on the Insyde BIOS, and 0x9F on most other
BIOSes.
+ */
+ if (DriveNumber >= 0x8A)
+ return TRUE;
+
+ /*
+ * IBM/MS INT 13 Extensions - INSTALLATION CHECK
+ * AH = 41h
+ * BX = 55AAh
+ * DL = drive (80h-FFh)
+ * Return:
+ * CF set on error (extensions not supported)
+ * AH = 01h (invalid function)
+ * CF clear if successful
+ * BX = AA55h if installed
+ * AH = major version of extensions
+ * 01h = 1.x
+ * 20h = 2.0 / EDD-1.0
+ * 21h = 2.1 / EDD-1.1
+ * 30h = EDD-3.0
+ * AL = internal use
+ * CX = API subset support bitmap
+ * DH = extension version (v2.0+ ??? -- not present in 1.x)
+ *
+ * Bitfields for IBM/MS INT 13 Extensions API support bitmap
+ * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
+ * Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h)
supported
+ * Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
+ * extended drive parameter table is valid
+ * Bits 3-15 reserved
+ */
+ RegsIn.b.ah = 0x41;
+ RegsIn.w.bx = 0x55AA;
+ RegsIn.b.dl = DriveNumber;
+
+ /* Reset the disk controller */
+ Int386(0x13, &RegsIn, &RegsOut);
+ if (!INT386_SUCCESS(RegsOut))
+ {
+ /* CF set on error (extensions not supported) */
+ return FALSE;
+ }
+
+ if (RegsOut.w.bx != 0xAA55)
+ {
+ /* BX = AA55h if installed */
+ return FALSE;
+ }
+
+ if (!(RegsOut.w.cx & 0x0001))
+ {
+ /*
+ * CX = API subset support bitmap.
+ * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported.
+ */
+ WARN("Suspicious API subset support bitmap 0x%x on device 0x%lx\n",
+ RegsOut.w.cx, DriveNumber);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static BOOLEAN
+DiskGetExtendedDriveParameters(
+ IN UCHAR DriveNumber,
+ IN PPC_DISK_DRIVE DiskDrive,
+ OUT PVOID Buffer,
+ IN USHORT BufferSize)
+{
+ REGS RegsIn, RegsOut;
+ PUSHORT Ptr = (PUSHORT)(BIOSCALLBUFFER);
+
+ TRACE("DiskGetExtendedDriveParameters(0x%x)\n", DriveNumber);
+
+ if (!DiskDrive->Int13ExtensionsSupported)
+ return FALSE;
+
+ /* Initialize transfer buffer */
+ *Ptr = BufferSize;
+
+ /*
+ * BIOS Int 13h, function 48h - Get drive parameters
+ * AH = 48h
+ * DL = drive (bit 7 set for hard disk)
+ * DS:SI = result buffer
+ * Return:
+ * CF set on error
+ * AH = status (07h)
+ * CF clear if successful
+ * AH = 00h
+ * DS:SI -> result buffer
+ */
+ RegsIn.b.ah = 0x48;
+ RegsIn.b.dl = DriveNumber;
+ RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
+ RegsIn.w.si = BIOSCALLBUFOFFSET;
+
+ /* Get drive parameters */
+ Int386(0x13, &RegsIn, &RegsOut);
+ if (!INT386_SUCCESS(RegsOut))
+ return FALSE;
+
+ RtlCopyMemory(Buffer, Ptr, BufferSize);
+
+#if DBG
+ TRACE("size of buffer: %x\n", Ptr[0]);
+ TRACE("information flags: %x\n", Ptr[1]);
+ TRACE("number of physical cylinders on drive: %u\n",
*(PULONG)&Ptr[2]);
+ TRACE("number of physical heads on drive: %u\n",
*(PULONG)&Ptr[4]);
+ TRACE("number of physical sectors per track: %u\n",
*(PULONG)&Ptr[6]);
+ TRACE("total number of sectors on drive: %I64u\n", *(unsigned long
long*)&Ptr[8]);
+ TRACE("bytes per sector: %u\n", Ptr[12]);
+ if (Ptr[0] >= 0x1e)
+ {
+ TRACE("EED configuration parameters: %x:%x\n", Ptr[13],
Ptr[14]);
+ if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
+ {
+ PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[13] << 4) + Ptr[14]);
+ TRACE("SpecPtr: %x\n", SpecPtr);
+ TRACE("physical I/O port base address: %x\n",
*(PUSHORT)&SpecPtr[0]);
+ TRACE("disk-drive control port address: %x\n",
*(PUSHORT)&SpecPtr[2]);
+ TRACE("drive flags: %x\n",
SpecPtr[4]);
+ TRACE("proprietary information: %x\n",
SpecPtr[5]);
+ TRACE("IRQ for drive: %u\n",
SpecPtr[6]);
+ TRACE("sector count for multi-sector transfers: %u\n",
SpecPtr[7]);
+ TRACE("DMA control: %x\n",
SpecPtr[8]);
+ TRACE("programmed I/O control: %x\n",
SpecPtr[9]);
+ TRACE("drive options: %x\n",
*(PUSHORT)&SpecPtr[10]);
+ }
+ }
+ if (Ptr[0] >= 0x42)
+ {
+ TRACE("signature: %x\n", Ptr[15]);
+ }
+#endif
+
+ return TRUE;
+}
+
+static BOOLEAN
+InitDriveGeometry(
+ IN UCHAR DriveNumber,
+ IN PPC_DISK_DRIVE DiskDrive)
+{
+ BOOLEAN Success;
+ REGS RegsIn, RegsOut;
+ ULONG Cylinders;
+
+ /* Get the extended geometry first */
+ DiskDrive->ExtGeometry.Size = sizeof(DiskDrive->ExtGeometry);
+ Success = DiskGetExtendedDriveParameters(DriveNumber, DiskDrive,
+ &DiskDrive->ExtGeometry,
+ DiskDrive->ExtGeometry.Size);
+ if (!Success)
+ {
+ /* Failed, zero it out */
+ RtlZeroMemory(&DiskDrive->ExtGeometry,
sizeof(DiskDrive->ExtGeometry));
+ }
+ else
+ {
+ TRACE("DiskGetExtendedDriveParameters(0x%x) returned:\n"
+ "Cylinders : 0x%x\n"
+ "Heads : 0x%x\n"
+ "Sects/Track: 0x%x\n"
+ "Bytes/Sect : 0x%x\n",
+ DriveNumber,
+ DiskDrive->ExtGeometry.Cylinders,
+ DiskDrive->ExtGeometry.Heads,
+ DiskDrive->ExtGeometry.SectorsPerTrack,
+ DiskDrive->ExtGeometry.BytesPerSector);
+ }
+
+ /* Now try the legacy geometry */
+ RtlZeroMemory(&DiskDrive->Geometry, sizeof(DiskDrive->Geometry));
+
+ /*
+ * BIOS Int 13h, function 08h - Get drive parameters
+ * AH = 08h
+ * DL = drive (bit 7 set for hard disk)
+ * ES:DI = 0000h:0000h to guard against BIOS bugs
+ * Return:
+ * CF set on error
+ * AH = status (07h)
+ * CF clear if successful
+ * AH = 00h
+ * AL = 00h on at least some BIOSes
+ * BL = drive type (AT/PS2 floppies only)
+ * CH = low eight bits of maximum cylinder number
+ * CL = maximum sector number (bits 5-0)
+ * high two bits of maximum cylinder number (bits 7-6)
+ * DH = maximum head number
+ * DL = number of drives
+ * ES:DI -> drive parameter table (floppies only)
+ */
+ RegsIn.b.ah = 0x08;
+ RegsIn.b.dl = DriveNumber;
+ RegsIn.w.es = 0x0000;
+ RegsIn.w.di = 0x0000;
+
+ /* Get drive parameters */
+ Int386(0x13, &RegsIn, &RegsOut);
+ if (!INT386_SUCCESS(RegsOut))
+ {
+ /* We failed, return the result of the previous call (extended geometry) */
+ return Success;
+ }
+ /* OR it with the old result, so that we return TRUE whenever either call succeeded
*/
+ Success |= TRUE;
+
+ Cylinders = (RegsOut.b.cl & 0xC0) << 2;
+ Cylinders += RegsOut.b.ch;
+ Cylinders++;
+ DiskDrive->Geometry.Cylinders = Cylinders;
+ DiskDrive->Geometry.Heads = RegsOut.b.dh + 1;
+ DiskDrive->Geometry.Sectors = RegsOut.b.cl & 0x3F;
+ DiskDrive->Geometry.BytesPerSector = 512; /* Just assume 512 bytes per sector
*/
+
+ TRACE("Regular Int13h(0x%x) returned:\n"
+ "Cylinders : 0x%x\n"
+ "Heads : 0x%x\n"
+ "Sects/Track: 0x%x (original 0x%x)\n"
+ "Bytes/Sect : 0x%x\n",
+ DriveNumber,
+ DiskDrive->Geometry.Cylinders,
+ DiskDrive->Geometry.Heads,
+ DiskDrive->Geometry.Sectors, RegsOut.b.cl,
+ DiskDrive->Geometry.BytesPerSector);
+
+ return Success;
+}
+
+static BOOLEAN
+PcDiskDriveInit(
+ IN UCHAR DriveNumber,
+ IN OUT PPC_DISK_DRIVE DiskDrive)
+{
+ DiskDrive->IsRemovable = DiskIsDriveRemovable(DriveNumber);
+
+ /*
+ * Check to see if it is a fixed disk drive.
+ * If so then check to see if INT 13h extensions work.
+ * If they do then use them, otherwise default back to BIOS calls.
+ */
+ DiskDrive->Int13ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
+
+ if (!InitDriveGeometry(DriveNumber, DiskDrive))
+ return FALSE;
+
+ TRACE("\n"
+ "DriveNumber: 0x%x\n"
+ "IsRemovable = %s\n"
+ "Int13ExtensionsSupported = %s\n",
+ DriveNumber,
+ DiskDrive->IsRemovable ? "TRUE" : "FALSE",
+ DiskDrive->Int13ExtensionsSupported ? "TRUE" :
"FALSE");
+
+ return TRUE;
+}
+
+static inline
+PPC_DISK_DRIVE
+PcDiskDriveNumberToDrive(IN UCHAR DriveNumber)
+{
+#ifdef CACHE_MULTI_DRIVES
+ PPC_DISK_DRIVE DiskDrive;
+
+ ASSERT((0 <= DriveNumber) && (DriveNumber <
RTL_NUMBER_OF(PcDiskDrive)));
+
+ /* Retrieve a slot */
+ DiskDrive = &PcDiskDrive[DriveNumber];
+
+ /* If the drive has not been initialized before... */
+ if (!DiskDrive->Initialized)
+ {
+ /* ... try to initialize it now. */
+ if (!PcDiskDriveInit(DriveNumber, DiskDrive))
+ {
+ /*
+ * If we failed, there is no drive at this number
+ * and flag it as such (set its high bit).
+ */
+ DiskDrive->Initialized |= 0x80;
+ return NULL;
+ }
+ DiskDrive->Initialized = TRUE;
+ }
+ else if (DiskDrive->Initialized & 0x80)
+ {
+ /*
+ * The disk failed to be initialized previously, reset its flag to give
+ * it chance to be initialized again later, but just fail for the moment.
+ */
+ DiskDrive->Initialized = FALSE;
+ return NULL;
+ }
+
+ return DiskDrive;
+#else
+ static PC_DISK_DRIVE NewDiskDrive;
+
+ ASSERT((0 <= DriveNumber) && (DriveNumber <= 0xFF));
+
+ /* Update cached information */
+
+ /* If the drive has not been accessed last before... */
+ if ((USHORT)DriveNumber != LastDriveNumber)
+ {
+ /* ... try to (re-)initialize and cache it now. */
+ RtlZeroMemory(&NewDiskDrive, sizeof(NewDiskDrive));
+ if (!PcDiskDriveInit(DriveNumber, &NewDiskDrive))
+ {
+ /*
+ * If we failed, there is no drive at this number.
+ * Keep the last-accessed valid drive cached.
+ */
+ return NULL;
+ }
+ /* We succeeded, cache the drive data */
+ PcDiskDrive = NewDiskDrive;
+ LastDriveNumber = (USHORT)DriveNumber;
+ }
+
+ return &PcDiskDrive;
+#endif /* CACHE_MULTI_DRIVES */
+}
+
+static BOOLEAN
+PcDiskReadLogicalSectorsLBA(
+ IN UCHAR DriveNumber,
+ IN ULONGLONG SectorNumber,
+ IN ULONG SectorCount,
+ OUT PVOID Buffer)
{
REGS RegsIn, RegsOut;
ULONG RetryCount;
PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER);
- TRACE("PcDiskReadLogicalSectorsLBA() DriveNumber: 0x%x SectorNumber: %I64d
SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer);
- ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
-
/* Setup disk address packet */
RtlZeroMemory(Packet, sizeof(*Packet));
Packet->PacketSize = sizeof(*Packet);
@@ -196,7 +591,7 @@ static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber,
ULONGLONG SectorNu
RegsIn.w.si = BIOSCALLBUFOFFSET;
/* Retry 3 times */
- for (RetryCount=0; RetryCount<3; RetryCount++)
+ for (RetryCount = 0; RetryCount < 3; ++RetryCount)
{
Int386(0x13, &RegsIn, &RegsOut);
@@ -227,7 +622,13 @@ static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber,
ULONGLONG SectorNu
return FALSE;
}
-static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber,
ULONG SectorCount, PVOID Buffer)
+static BOOLEAN
+PcDiskReadLogicalSectorsCHS(
+ IN UCHAR DriveNumber,
+ IN PPC_DISK_DRIVE DiskDrive,
+ IN ULONGLONG SectorNumber,
+ IN ULONG SectorCount,
+ OUT PVOID Buffer)
{
UCHAR PhysicalSector;
UCHAR PhysicalHead;
@@ -237,19 +638,11 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber,
ULONGLONG SectorNu
REGS RegsIn, RegsOut;
ULONG RetryCount;
- TRACE("PcDiskReadLogicalSectorsCHS()\n");
-
- /* Get the drive geometry */
- //
- // TODO: Cache this information for the given drive.
- //
- if (!PcDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
- DriveGeometry.Sectors == 0 || DriveGeometry.Heads == 0)
- {
+ DriveGeometry = DiskDrive->Geometry;
+ if (DriveGeometry.Sectors == 0 || DriveGeometry.Heads == 0)
return FALSE;
- }
- while (SectorCount)
+ while (SectorCount > 0)
{
/*
* Calculate the physical disk offsets.
@@ -313,7 +706,7 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber,
ULONGLONG SectorNu
RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;
/* Perform the read. Retry 3 times. */
- for (RetryCount=0; RetryCount<3; RetryCount++)
+ for (RetryCount = 0; RetryCount < 3; ++RetryCount)
{
Int386(0x13, &RegsIn, &RegsOut);
@@ -327,7 +720,7 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber,
ULONGLONG SectorNu
{
break;
}
- /* If it failed the do the next retry */
+ /* If it failed then do the next retry */
else
{
DiskResetController(DriveNumber);
@@ -345,11 +738,13 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber,
ULONGLONG SectorNu
return FALSE;
}
- // I have learned that not all BIOSes return
- // the sector read count in the AL register (at least mine doesn't)
- // even if the sectors were read correctly. So instead
- // of checking the sector read count we will rely solely
- // on the carry flag being set on error
+ /*
+ * I have learned that not all BIOSes return
+ * the sector read count in the AL register (at least mine doesn't)
+ * even if the sectors were read correctly. So instead
+ * of checking the sector read count we will rely solely
+ * on the carry flag being set on error.
+ */
Buffer = (PVOID)((ULONG_PTR)Buffer + (NumberOfSectorsToRead *
DriveGeometry.BytesPerSector));
SectorCount -= NumberOfSectorsToRead;
@@ -359,128 +754,37 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber,
ULONGLONG SectorNu
return TRUE;
}
-static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
-{
- static UCHAR LastDriveNumber = 0xff;
- static BOOLEAN LastSupported;
- REGS RegsIn, RegsOut;
-
- TRACE("DiskInt13ExtensionsSupported()\n");
-
- if (DriveNumber == LastDriveNumber)
- {
- TRACE("Using cached value %s for drive 0x%x\n",
- LastSupported ? "TRUE" : "FALSE", DriveNumber);
- return LastSupported;
- }
-
- /*
- * Some BIOSes report that extended disk access functions are not supported
- * when booting from a CD (e.g. Phoenix BIOS v6.00PG and Insyde BIOS shipping
- * with Intel Macs). Therefore we just return TRUE if we're booting from a CD -
- * we can assume that all El Torito capable BIOSes support INT 13 extensions.
- * We simply detect whether we're booting from CD by checking whether the drive
- * number is >= 0x8A. It's 0x90 on the Insyde BIOS, and 0x9F on most other
BIOSes.
- */
- if (DriveNumber >= 0x8A)
- {
- LastSupported = TRUE;
- return TRUE;
- }
-
- LastDriveNumber = DriveNumber;
-
- /*
- * IBM/MS INT 13 Extensions - INSTALLATION CHECK
- * AH = 41h
- * BX = 55AAh
- * DL = drive (80h-FFh)
- * Return:
- * CF set on error (extensions not supported)
- * AH = 01h (invalid function)
- * CF clear if successful
- * BX = AA55h if installed
- * AH = major version of extensions
- * 01h = 1.x
- * 20h = 2.0 / EDD-1.0
- * 21h = 2.1 / EDD-1.1
- * 30h = EDD-3.0
- * AL = internal use
- * CX = API subset support bitmap
- * DH = extension version (v2.0+ ??? -- not present in 1.x)
- *
- * Bitfields for IBM/MS INT 13 Extensions API support bitmap
- * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
- * Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h)
supported
- * Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
- * extended drive parameter table is valid
- * Bits 3-15 reserved
- */
- RegsIn.b.ah = 0x41;
- RegsIn.w.bx = 0x55AA;
- RegsIn.b.dl = DriveNumber;
-
- /* Reset the disk controller */
- Int386(0x13, &RegsIn, &RegsOut);
-
- if (!INT386_SUCCESS(RegsOut))
- {
- /* CF set on error (extensions not supported) */
- LastSupported = FALSE;
- return FALSE;
- }
-
- if (RegsOut.w.bx != 0xAA55)
- {
- /* BX = AA55h if installed */
- LastSupported = FALSE;
- return FALSE;
- }
-
- if (!(RegsOut.w.cx & 0x0001))
- {
- /*
- * CX = API subset support bitmap.
- * Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported.
- */
- DbgPrint("Suspicious API subset support bitmap 0x%x on device
0x%lx\n",
- RegsOut.w.cx, DriveNumber);
- LastSupported = FALSE;
- return FALSE;
- }
-
- LastSupported = TRUE;
- return TRUE;
-}
-
-BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG
SectorCount, PVOID Buffer)
+BOOLEAN
+PcDiskReadLogicalSectors(
+ IN UCHAR DriveNumber,
+ IN ULONGLONG SectorNumber,
+ IN ULONG SectorCount,
+ OUT PVOID Buffer)
{
- BOOLEAN ExtensionsSupported;
+ PPC_DISK_DRIVE DiskDrive;
TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d
SectorCount: %d Buffer: 0x%x\n",
DriveNumber, SectorNumber, SectorCount, Buffer);
- /*
- * Check to see if it is a fixed disk drive.
- * If so then check to see if Int13 extensions work.
- * If they do then use them, otherwise default back to BIOS calls.
- */
- ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
+ /* 16-bit BIOS addressing limitation */
+ ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
- if ((DriveNumber >= 0x80) && ExtensionsSupported)
- {
- TRACE("Using Int 13 Extensions for read. DiskInt13ExtensionsSupported(%d) =
%s\n", DriveNumber, ExtensionsSupported ? "TRUE" : "FALSE");
+ DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
+ if (!DiskDrive)
+ return FALSE;
+ if ((DriveNumber >= 0x80) && DiskDrive->Int13ExtensionsSupported)
+ {
/* LBA is easy, nothing to calculate. Just do the read. */
+ TRACE("--> Using LBA\n");
return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount,
Buffer);
}
else
{
- /* LBA is not supported default to the CHS calls */
- return PcDiskReadLogicalSectorsCHS(DriveNumber, SectorNumber, SectorCount,
Buffer);
+ /* LBA is not supported, default to CHS */
+ TRACE("--> Using CHS\n");
+ return PcDiskReadLogicalSectorsCHS(DriveNumber, DiskDrive, SectorNumber,
SectorCount, Buffer);
}
-
- return TRUE;
}
#if defined(__i386__) || defined(_M_AMD64)
@@ -490,159 +794,52 @@ VOID __cdecl DiskStopFloppyMotor(VOID)
}
#endif // defined __i386__ || defined(_M_AMD64)
-BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT
BufferSize)
+BOOLEAN
+PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
{
- REGS RegsIn, RegsOut;
- PUSHORT Ptr = (PUSHORT)(BIOSCALLBUFFER);
+ PPC_DISK_DRIVE DiskDrive;
- TRACE("DiskGetExtendedDriveParameters()\n");
+ TRACE("PcDiskGetDriveGeometry(0x%x)\n", DriveNumber);
- if (!DiskInt13ExtensionsSupported(DriveNumber))
+ DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
+ if (!DiskDrive)
return FALSE;
- /* Initialize transfer buffer */
- *Ptr = BufferSize;
-
- /*
- * BIOS Int 13h, function 48h - Get drive parameters
- * AH = 48h
- * DL = drive (bit 7 set for hard disk)
- * DS:SI = result buffer
- * Return:
- * CF set on error
- * AH = status (07h)
- * CF clear if successful
- * AH = 00h
- * DS:SI -> result buffer
- */
- RegsIn.b.ah = 0x48;
- RegsIn.b.dl = DriveNumber;
- RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
- RegsIn.w.si = BIOSCALLBUFOFFSET;
-
- /* Get drive parameters */
- Int386(0x13, &RegsIn, &RegsOut);
- if (!INT386_SUCCESS(RegsOut))
- return FALSE;
-
- memcpy(Buffer, Ptr, BufferSize);
-
-#if DBG
- TRACE("size of buffer: %x\n", Ptr[0]);
- TRACE("information flags: %x\n", Ptr[1]);
- TRACE("number of physical cylinders on drive: %u\n",
*(PULONG)&Ptr[2]);
- TRACE("number of physical heads on drive: %u\n",
*(PULONG)&Ptr[4]);
- TRACE("number of physical sectors per track: %u\n",
*(PULONG)&Ptr[6]);
- TRACE("total number of sectors on drive: %I64u\n", *(unsigned long
long*)&Ptr[8]);
- TRACE("bytes per sector: %u\n", Ptr[12]);
- if (Ptr[0] >= 0x1e)
+ /* Try to get the extended geometry first */
+ if (DiskDrive->ExtGeometry.Size == sizeof(DiskDrive->ExtGeometry))
{
- TRACE("EED configuration parameters: %x:%x\n", Ptr[13],
Ptr[14]);
- if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
- {
- PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[13] << 4) + Ptr[14]);
- TRACE("SpecPtr: %x\n", SpecPtr);
- TRACE("physical I/O port base address: %x\n",
*(PUSHORT)&SpecPtr[0]);
- TRACE("disk-drive control port address: %x\n",
*(PUSHORT)&SpecPtr[2]);
- TRACE("drive flags: %x\n", SpecPtr[4]);
- TRACE("proprietary information: %x\n", SpecPtr[5]);
- TRACE("IRQ for drive: %u\n", SpecPtr[6]);
- TRACE("sector count for multi-sector transfers: %u\n", SpecPtr[7]);
- TRACE("DMA control: %x\n", SpecPtr[8]);
- TRACE("programmed I/O control: %x\n", SpecPtr[9]);
- TRACE("drive options: %x\n",
*(PUSHORT)&SpecPtr[10]);
- }
+ /* Extended geometry has been initialized, return it */
+ Geometry->Cylinders = DiskDrive->ExtGeometry.Cylinders;
+ Geometry->Heads = DiskDrive->ExtGeometry.Heads;
+ Geometry->Sectors = DiskDrive->ExtGeometry.SectorsPerTrack;
+ Geometry->BytesPerSector = DiskDrive->ExtGeometry.BytesPerSector;
}
- if (Ptr[0] >= 0x42)
+ else
+ /* Fall back to legacy BIOS geometry */
{
- TRACE("signature: %x\n", Ptr[15]);
+ *Geometry = DiskDrive->Geometry;
}
-#endif
return TRUE;
}
-BOOLEAN
-PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
+ULONG
+PcDiskGetCacheableBlockCount(UCHAR DriveNumber)
{
- EXTENDED_GEOMETRY ExtGeometry;
- REGS RegsIn, RegsOut;
- ULONG Cylinders;
-
- TRACE("DiskGetDriveGeometry()\n");
+ PPC_DISK_DRIVE DiskDrive;
- /* Try to get the extended geometry first */
- ExtGeometry.Size = sizeof(ExtGeometry);
- if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
- {
- Geometry->Cylinders = ExtGeometry.Cylinders;
- Geometry->Heads = ExtGeometry.Heads;
- Geometry->Sectors = ExtGeometry.SectorsPerTrack;
- Geometry->BytesPerSector = ExtGeometry.BytesPerSector;
- return TRUE;
- }
+ DiskDrive = PcDiskDriveNumberToDrive(DriveNumber);
+ if (!DiskDrive)
+ return 1; // Unknown count.
/*
- * BIOS Int 13h, function 08h - Get drive parameters
- * AH = 08h
- * DL = drive (bit 7 set for hard disk)
- * ES:DI = 0000h:0000h to guard against BIOS bugs
- * Return:
- * CF set on error
- * AH = status (07h)
- * CF clear if successful
- * AH = 00h
- * AL = 00h on at least some BIOSes
- * BL = drive type (AT/PS2 floppies only)
- * CH = low eight bits of maximum cylinder number
- * CL = maximum sector number (bits 5-0)
- * high two bits of maximum cylinder number (bits 7-6)
- * DH = maximum head number
- * DL = number of drives
- * ES:DI -> drive parameter table (floppies only)
+ * If LBA is supported then the block size will be 64 sectors (32k).
+ * If not then the block size is the size of one track.
*/
- RegsIn.b.ah = 0x08;
- RegsIn.b.dl = DriveNumber;
- RegsIn.w.es = 0x0000;
- RegsIn.w.di = 0x0000;
-
- /* Get drive parameters */
- Int386(0x13, &RegsIn, &RegsOut);
- if (!INT386_SUCCESS(RegsOut))
- return FALSE;
-
- Cylinders = (RegsOut.b.cl & 0xC0) << 2;
- Cylinders += RegsOut.b.ch;
- Cylinders++;
- Geometry->Cylinders = Cylinders;
- Geometry->Heads = RegsOut.b.dh + 1;
- Geometry->Sectors = RegsOut.b.cl & 0x3F;
- Geometry->BytesPerSector = 512; /* Just assume 512 bytes per sector */
-
- return TRUE;
-}
-
-ULONG
-PcDiskGetCacheableBlockCount(UCHAR DriveNumber)
-{
- GEOMETRY Geometry;
-
- /* If LBA is supported then the block size will be 64 sectors (32k)
- * If not then the block size is the size of one track. */
- if (DiskInt13ExtensionsSupported(DriveNumber))
- {
+ if (DiskDrive->Int13ExtensionsSupported)
return 64;
- }
- /* Get the disk geometry. If this fails then we will
- * just return 1 sector to be safe. */
- else if (!PcDiskGetDriveGeometry(DriveNumber, &Geometry))
- {
- return 1;
- }
else
- {
- return Geometry.Sectors;
- }
+ return DiskDrive->Geometry.Sectors;
}
/* EOF */
diff --git a/boot/freeldr/freeldr/arch/i386/xboxdisk.c
b/boot/freeldr/freeldr/arch/i386/xboxdisk.c
index 26a00e1136c..06e7e2d6691 100644
--- a/boot/freeldr/freeldr/arch/i386/xboxdisk.c
+++ b/boot/freeldr/freeldr/arch/i386/xboxdisk.c
@@ -58,44 +58,42 @@ XboxDiskInit(BOOLEAN Init)
}
}
-static
-inline
-BOOLEAN
-XboxDiskDriveNumberToDeviceUnit(UCHAR DriveNumber, PDEVICE_UNIT *DeviceUnit)
+static inline
+PDEVICE_UNIT
+XboxDiskDriveNumberToDeviceUnit(UCHAR DriveNumber)
{
/* Xbox has only 1 IDE controller and no floppy */
if (DriveNumber < 0x80 || (DriveNumber & 0x0F) >= 2)
- return FALSE;
+ return NULL;
if (!AtaInitialized)
XboxDiskInit(TRUE);
/* HDD */
if ((DriveNumber == 0x80) && HardDrive)
- {
- *DeviceUnit = HardDrive;
- return TRUE;
- }
+ return HardDrive;
/* CD */
- if ((DriveNumber & 0xF0) > 0x80 && CdDrive)
- {
- *DeviceUnit = CdDrive;
- return TRUE;
- }
+ if (((DriveNumber & 0xF0) > 0x80) && CdDrive)
+ return CdDrive;
- return FALSE;
+ return NULL;
}
BOOLEAN
-XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount,
PVOID Buffer)
+XboxDiskReadLogicalSectors(
+ IN UCHAR DriveNumber,
+ IN ULONGLONG SectorNumber,
+ IN ULONG SectorCount,
+ OUT PVOID Buffer)
{
- PDEVICE_UNIT DeviceUnit = NULL;
+ PDEVICE_UNIT DeviceUnit;
TRACE("XboxDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d
SectorCount: %d Buffer: 0x%x\n",
DriveNumber, SectorNumber, SectorCount, Buffer);
- if (!XboxDiskDriveNumberToDeviceUnit(DriveNumber, &DeviceUnit))
+ DeviceUnit = XboxDiskDriveNumberToDeviceUnit(DriveNumber);
+ if (!DeviceUnit)
return FALSE;
return AtaAtapiReadLogicalSectorsLBA(DeviceUnit, SectorNumber, SectorCount, Buffer);
@@ -104,11 +102,12 @@ XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG
SectorNumber, ULONG Sect
BOOLEAN
XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
{
- PDEVICE_UNIT DeviceUnit = NULL;
+ PDEVICE_UNIT DeviceUnit;
TRACE("XboxDiskGetDriveGeometry(0x%x)\n", DriveNumber);
- if (!XboxDiskDriveNumberToDeviceUnit(DriveNumber, &DeviceUnit))
+ DeviceUnit = XboxDiskDriveNumberToDeviceUnit(DriveNumber);
+ if (!DeviceUnit)
return FALSE;
Geometry->Cylinders = DeviceUnit->Cylinders;
@@ -122,15 +121,14 @@ XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
ULONG
XboxDiskGetCacheableBlockCount(UCHAR DriveNumber)
{
- PDEVICE_UNIT DeviceUnit = NULL;
+ PDEVICE_UNIT DeviceUnit;
- TRACE("XboxDiskGetCacheableBlockCount(0x%x)\n", DriveNumber);
-
- if (!XboxDiskDriveNumberToDeviceUnit(DriveNumber, &DeviceUnit))
- return 0;
+ DeviceUnit = XboxDiskDriveNumberToDeviceUnit(DriveNumber);
+ if (!DeviceUnit)
+ return 1; // Unknown count.
/*
- * If LBA is supported then the block size will be 64 sectors (32k)
+ * If LBA is supported then the block size will be 64 sectors (32k).
* If not then the block size is the size of one track.
*/
if (DeviceUnit->Flags & ATA_DEVICE_LBA)
@@ -138,3 +136,5 @@ XboxDiskGetCacheableBlockCount(UCHAR DriveNumber)
else
return DeviceUnit->Sectors;
}
+
+/* EOF */
diff --git a/boot/freeldr/freeldr/include/arch/pc/machpc.h
b/boot/freeldr/freeldr/include/arch/pc/machpc.h
index d5d8bebce1d..b76e55e776a 100644
--- a/boot/freeldr/freeldr/include/arch/pc/machpc.h
+++ b/boot/freeldr/freeldr/include/arch/pc/machpc.h
@@ -60,7 +60,7 @@ extern ULONG FrldrBootPartition;
LONG DiskReportError(BOOLEAN bShowError);
BOOLEAN DiskResetController(UCHAR DriveNumber);
-BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT
BufferSize);
+// BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT
BufferSize);
BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG
SectorCount, PVOID Buffer);
BOOLEAN PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY DriveGeometry);