[FREELDR]: More local changes merging, part 2/x:

- Move the HW detection code specific to the PC architecture from hardware.c to machpc.c, keeping in hardware.c the code that is shared between PC and XBOX.
- Move what remained of i386disk.c into pcdisk.c (specific to PC architecture) + code formatting.
- Move what remained of xboxhw.c into machxbox.c (specific to XBOX architecture); we discover that some code related to disk management is actually shared with PC architecture (in hwdisk.c): hwdisk.c therefore contains disk-management routines common to both PC & XBOX.
- xboxdisk.c: Code formatting only.
- Cleanup in disk.c/disk.h

svn path=/trunk/; revision=73616
This commit is contained in:
Hermès Bélusca-Maïto 2017-01-28 23:47:35 +00:00
parent 8c8c4f495c
commit dde1f97a02
12 changed files with 2628 additions and 2771 deletions

View file

@ -123,7 +123,6 @@ if(ARCH STREQUAL "i386")
arch/i386/hwdisk.c arch/i386/hwdisk.c
arch/i386/hwpci.c arch/i386/hwpci.c
arch/i386/i386bug.c arch/i386/i386bug.c
arch/i386/i386disk.c
arch/i386/i386idt.c arch/i386/i386idt.c
arch/i386/i386rtl.c arch/i386/i386rtl.c
arch/i386/i386vid.c arch/i386/i386vid.c
@ -137,7 +136,6 @@ if(ARCH STREQUAL "i386")
arch/i386/xboxcons.c arch/i386/xboxcons.c
arch/i386/xboxdisk.c arch/i386/xboxdisk.c
arch/i386/xboxfont.c arch/i386/xboxfont.c
arch/i386/xboxhw.c
arch/i386/xboxi2c.c arch/i386/xboxi2c.c
arch/i386/xboxmem.c arch/i386/xboxmem.c
arch/i386/xboxrtc.c arch/i386/xboxrtc.c
@ -170,7 +168,6 @@ elseif(ARCH STREQUAL "amd64")
arch/i386/hwpci.c arch/i386/hwpci.c
arch/i386/i386bug.c arch/i386/i386bug.c
arch/i386/i386rtl.c arch/i386/i386rtl.c
arch/i386/i386disk.c
arch/i386/i386vid.c arch/i386/i386vid.c
arch/i386/machpc.c arch/i386/machpc.c
arch/i386/pccons.c arch/i386/pccons.c

File diff suppressed because it is too large Load diff

View file

@ -39,13 +39,19 @@ extern ULONG reactos_disk_count;
extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[]; extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[];
static CHAR Hex[] = "0123456789abcdef"; static CHAR Hex[] = "0123456789abcdef";
UCHAR PcBiosDiskCount = 0; UCHAR PcBiosDiskCount = 0;
CHAR PcDiskIdentifier[32][20]; static CHAR PcDiskIdentifier[32][20];
PVOID DiskReadBuffer; PVOID DiskReadBuffer;
SIZE_T DiskReadBufferSize; SIZE_T DiskReadBufferSize;
static ARC_STATUS DiskClose(ULONG FileId) /* FUNCTIONS *****************************************************************/
// static
ARC_STATUS
DiskClose(ULONG FileId)
{ {
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId); DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
@ -53,7 +59,9 @@ static ARC_STATUS DiskClose(ULONG FileId)
return ESUCCESS; return ESUCCESS;
} }
static ARC_STATUS DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information) // static
ARC_STATUS
DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
{ {
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId); DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
@ -64,7 +72,8 @@ static ARC_STATUS DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Informat
return ESUCCESS; return ESUCCESS;
} }
static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId) static ARC_STATUS
DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
{ {
DISKCONTEXT* Context; DISKCONTEXT* Context;
UCHAR DriveNumber; UCHAR DriveNumber;
@ -84,9 +93,12 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
} }
else else
{ {
/* This is either a floppy disk device (DrivePartition == 0) or /*
* a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but * This is either a floppy disk device (DrivePartition == 0) or
* it doesn't matter which one because they both have 512 bytes per sector */ * a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF)
* but it doesn't matter which one because they both have 512 bytes
* per sector.
*/
SectorSize = 512; SectorSize = 512;
} }
@ -94,13 +106,21 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
{ {
if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry)) if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
return EINVAL; return EINVAL;
SectorOffset = PartitionTableEntry.SectorCountBeforePartition; SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
SectorCount = PartitionTableEntry.PartitionSectorCount; SectorCount = PartitionTableEntry.PartitionSectorCount;
} }
#if 0 // FIXME: Investigate
else
{
SectorCount = 0; /* FIXME */
}
#endif
Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT); Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
if (!Context) if (!Context)
return ENOMEM; return ENOMEM;
Context->DriveNumber = DriveNumber; Context->DriveNumber = DriveNumber;
Context->SectorSize = SectorSize; Context->SectorSize = SectorSize;
Context->SectorOffset = SectorOffset; Context->SectorOffset = SectorOffset;
@ -111,7 +131,9 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
return ESUCCESS; return ESUCCESS;
} }
static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count) // static
ARC_STATUS
DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
{ {
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId); DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
UCHAR* Ptr = (UCHAR*)Buffer; UCHAR* Ptr = (UCHAR*)Buffer;
@ -123,7 +145,7 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
MaxSectors = DiskReadBufferSize / Context->SectorSize; MaxSectors = DiskReadBufferSize / Context->SectorSize;
SectorOffset = Context->SectorNumber + Context->SectorOffset; SectorOffset = Context->SectorNumber + Context->SectorOffset;
ret = 1; ret = TRUE;
while (TotalSectors) while (TotalSectors)
{ {
@ -131,11 +153,10 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
if (ReadSectors > MaxSectors) if (ReadSectors > MaxSectors)
ReadSectors = MaxSectors; ReadSectors = MaxSectors;
ret = MachDiskReadLogicalSectors( ret = MachDiskReadLogicalSectors(Context->DriveNumber,
Context->DriveNumber, SectorOffset,
SectorOffset, ReadSectors,
ReadSectors, DiskReadBuffer);
DiskReadBuffer);
if (!ret) if (!ret)
break; break;
@ -156,7 +177,9 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
return (!ret) ? EIO : ESUCCESS; return (!ret) ? EIO : ESUCCESS;
} }
static ARC_STATUS DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode) // static
ARC_STATUS
DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
{ {
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId); DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
@ -169,7 +192,8 @@ static ARC_STATUS DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekM
return ESUCCESS; return ESUCCESS;
} }
static const DEVVTBL DiskVtbl = { static const DEVVTBL DiskVtbl =
{
DiskClose, DiskClose,
DiskGetFileInformation, DiskGetFileInformation,
DiskOpen, DiskOpen,
@ -177,6 +201,7 @@ static const DEVVTBL DiskVtbl = {
DiskSeek, DiskSeek,
}; };
PCHAR PCHAR
GetHarddiskIdentifier( GetHarddiskIdentifier(
UCHAR DriveNumber) UCHAR DriveNumber)
@ -264,14 +289,13 @@ GetHarddiskInformation(
Identifier[15] = Hex[(Signature >> 4) & 0x0F]; Identifier[15] = Hex[(Signature >> 4) & 0x0F];
Identifier[16] = Hex[Signature & 0x0F]; Identifier[16] = Hex[Signature & 0x0F];
Identifier[17] = '-'; Identifier[17] = '-';
Identifier[18] = 'A'; Identifier[18] = 'A'; // FIXME: Not always 'A' ...
Identifier[19] = 0; Identifier[19] = 0;
TRACE("Identifier: %s\n", Identifier); TRACE("Identifier: %s\n", Identifier);
} }
BOOLEAN BOOLEAN
HwInitializeBiosDisks(VOID) PcInitializeBootDevices(VOID)
{ {
UCHAR DiskCount, DriveNumber; UCHAR DiskCount, DriveNumber;
ULONG i; ULONG i;
@ -314,9 +338,11 @@ HwInitializeBiosDisks(VOID)
DiskCount++; DiskCount++;
DriveNumber++; DriveNumber++;
memset(DiskReadBuffer, 0xcd, 512); memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
} }
DiskReportError(TRUE); DiskReportError(TRUE);
TRACE("BIOS reports %d harddisk%s\n",
(int)DiskCount, (DiskCount == 1) ? "" : "s");
/* Get the drive we're booting from */ /* Get the drive we're booting from */
MachDiskGetBootPath(BootPath, sizeof(BootPath)); MachDiskGetBootPath(BootPath, sizeof(BootPath));
@ -366,5 +392,5 @@ HwInitializeBiosDisks(VOID)
TRACE("BIOS reports %d harddisk%s\n", TRACE("BIOS reports %d harddisk%s\n",
(int)DiskCount, (DiskCount == 1) ? "": "s"); (int)DiskCount, (DiskCount == 1) ? "": "s");
return DiskCount != 0; return (DiskCount != 0);
} }

View file

@ -1,220 +0,0 @@
/*
* FreeLoader
* Copyright (C) 1998-2003 Brian Palmer <brianp@sginet.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <freeldr.h>
#define NDEBUG
#include <debug.h>
DBG_DEFAULT_CHANNEL(DISK);
/////////////////////////////////////////////////////////////////////////////////////////////
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////
BOOLEAN DiskResetController(UCHAR DriveNumber)
{
REGS RegsIn;
REGS RegsOut;
WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
// BIOS Int 13h, function 0 - Reset disk system
// AH = 00h
// DL = drive (if bit 7 is set both hard disks and floppy disks reset)
// Return:
// AH = status
// CF clear if successful
// CF set on error
RegsIn.b.ah = 0x00;
RegsIn.b.dl = DriveNumber;
// Reset the disk controller
Int386(0x13, &RegsIn, &RegsOut);
return INT386_SUCCESS(RegsOut);
}
BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
{
static UCHAR LastDriveNumber = 0xff;
static BOOLEAN LastSupported;
REGS RegsIn;
REGS RegsOut;
TRACE("PcDiskInt13ExtensionsSupported()\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;
}
VOID DiskStopFloppyMotor(VOID)
{
WRITE_PORT_UCHAR((PUCHAR)0x3F2, 0);
}
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize)
{
REGS RegsIn;
REGS RegsOut;
PUSHORT Ptr = (PUSHORT)(BIOSCALLBUFFER);
TRACE("DiskGetExtendedDriveParameters()\n");
if (!DiskInt13ExtensionsSupported(DriveNumber))
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)
{
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;
}
/* EOF */

File diff suppressed because it is too large Load diff

View file

@ -18,53 +18,513 @@
#include <freeldr.h> #include <freeldr.h>
#define NDEBUG
#include <debug.h>
DBG_DEFAULT_CHANNEL(HWDETECT);
static CHAR Hex[] = "0123456789ABCDEF";
extern ULONG reactos_disk_count;
extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[];
typedef struct tagDISKCONTEXT
{
UCHAR DriveNumber;
ULONG SectorSize;
ULONGLONG SectorOffset;
ULONGLONG SectorCount;
ULONGLONG SectorNumber;
} DISKCONTEXT;
// NOTE: Similar to hardware.c!PcGetHarddiskConfigurationData(),
// but without extended geometry support.
static
PCM_PARTIAL_RESOURCE_LIST
XboxGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
//EXTENDED_GEOMETRY ExtGeometry;
GEOMETRY Geometry;
ULONG Size;
//
// Initialize returned size
//
*pSize = 0;
/* Set 'Configuration Data' value */
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
if (PartialResourceList == NULL)
{
ERR("Failed to allocate a full resource descriptor\n");
return NULL;
}
memset(PartialResourceList, 0, Size);
PartialResourceList->Version = 1;
PartialResourceList->Revision = 1;
PartialResourceList->Count = 1;
PartialResourceList->PartialDescriptors[0].Type =
CmResourceTypeDeviceSpecific;
// PartialResourceList->PartialDescriptors[0].ShareDisposition =
// PartialResourceList->PartialDescriptors[0].Flags =
PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
/* Get pointer to geometry data */
DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
/* Get the disk geometry */
//ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
{
DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
DiskGeometry->SectorsPerTrack = Geometry.Sectors;
DiskGeometry->NumberOfHeads = Geometry.Heads;
}
else
{
ERR("Reading disk geometry failed\n");
FrLdrHeapFree(PartialResourceList, TAG_HW_RESOURCE_LIST);
return NULL;
}
TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
DriveNumber,
DiskGeometry->NumberOfCylinders,
DiskGeometry->NumberOfHeads,
DiskGeometry->SectorsPerTrack,
DiskGeometry->BytesPerSector);
//
// Return configuration data
//
*pSize = Size;
return PartialResourceList;
}
#define GetHarddiskConfigurationData XboxGetHarddiskConfigurationData
extern ARC_STATUS
DiskClose(ULONG FileId);
extern ARC_STATUS
DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information);
static
ARC_STATUS
DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
{
DISKCONTEXT* Context;
ULONG DrivePartition, SectorSize;
UCHAR DriveNumber;
ULONGLONG SectorOffset = 0;
ULONGLONG SectorCount = 0;
PARTITION_TABLE_ENTRY PartitionTableEntry;
CHAR FileName[1];
if (!DissectArcPath(Path, FileName, &DriveNumber, &DrivePartition))
return EINVAL;
if (DrivePartition == 0xff)
{
/* This is a CD-ROM device */
SectorSize = 2048;
}
else
{
/* This is either a floppy disk device (DrivePartition == 0) or
* a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
* it doesn't matter which one because they both have 512 bytes per sector */
SectorSize = 512;
}
if (DrivePartition != 0xff && DrivePartition != 0)
{
if (!XboxDiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
return EINVAL;
SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
SectorCount = PartitionTableEntry.PartitionSectorCount;
}
else
{
SectorCount = 0; /* FIXME */
}
Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
if (!Context)
return ENOMEM;
Context->DriveNumber = DriveNumber;
Context->SectorSize = SectorSize;
Context->SectorOffset = SectorOffset;
Context->SectorCount = SectorCount;
Context->SectorNumber = 0;
FsSetDeviceSpecific(*FileId, Context);
return ESUCCESS;
}
extern ARC_STATUS
DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count);
extern ARC_STATUS
DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode);
static const DEVVTBL DiskVtbl =
{
DiskClose,
DiskGetFileInformation,
DiskOpen,
DiskRead,
DiskSeek,
};
static
VOID
GetHarddiskIdentifier(PCHAR Identifier,
UCHAR DriveNumber)
{
PMASTER_BOOT_RECORD Mbr;
PULONG Buffer;
ULONG i;
ULONG Checksum;
ULONG Signature;
CHAR ArcName[MAX_PATH];
PARTITION_TABLE_ENTRY PartitionTableEntry;
/* Read the MBR */
if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
{
ERR("Reading MBR failed\n");
return;
}
Buffer = (ULONG*)DiskReadBuffer;
Mbr = (PMASTER_BOOT_RECORD)DiskReadBuffer;
Signature = Mbr->Signature;
TRACE("Signature: %x\n", Signature);
/* Calculate the MBR checksum */
Checksum = 0;
for (i = 0; i < 512 / sizeof(ULONG); i++)
{
Checksum += Buffer[i];
}
Checksum = ~Checksum + 1;
TRACE("Checksum: %x\n", Checksum);
/* Fill out the ARC disk block */
reactos_arc_disk_info[reactos_disk_count].DiskSignature.Signature = Signature;
reactos_arc_disk_info[reactos_disk_count].DiskSignature.CheckSum = Checksum;
sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count);
strcpy(reactos_arc_disk_info[reactos_disk_count].ArcName, ArcName);
reactos_arc_disk_info[reactos_disk_count].DiskSignature.ArcName =
reactos_arc_disk_info[reactos_disk_count].ArcName;
reactos_disk_count++;
sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(0)", DriveNumber - 0x80);
FsRegisterDevice(ArcName, &DiskVtbl);
/* Add partitions */
i = 1;
DiskReportError(FALSE);
while (XboxDiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry))
{
if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED)
{
sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(%lu)", DriveNumber - 0x80, i);
FsRegisterDevice(ArcName, &DiskVtbl);
}
i++;
}
DiskReportError(TRUE);
/* Convert checksum and signature to identifier string */
Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
Identifier[7] = Hex[Checksum & 0x0F];
Identifier[8] = '-';
Identifier[9] = Hex[(Signature >> 28) & 0x0F];
Identifier[10] = Hex[(Signature >> 24) & 0x0F];
Identifier[11] = Hex[(Signature >> 20) & 0x0F];
Identifier[12] = Hex[(Signature >> 16) & 0x0F];
Identifier[13] = Hex[(Signature >> 12) & 0x0F];
Identifier[14] = Hex[(Signature >> 8) & 0x0F];
Identifier[15] = Hex[(Signature >> 4) & 0x0F];
Identifier[16] = Hex[Signature & 0x0F];
Identifier[17] = '-';
Identifier[18] = 'A';
Identifier[19] = 0;
TRACE("Identifier: %s\n", Identifier);
}
static
VOID
DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
PCONFIGURATION_COMPONENT_DATA BusKey)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCM_INT13_DRIVE_PARAMETER Int13Drives;
GEOMETRY Geometry;
PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey;
UCHAR DiskCount;
ULONG i;
ULONG Size;
BOOLEAN Changed;
/* Count the number of visible drives */
DiskReportError(FALSE);
DiskCount = 0;
/* There are some really broken BIOSes out there. There are even BIOSes
* that happily report success when you ask them to read from non-existent
* harddisks. So, we set the buffer to known contents first, then try to
* read. If the BIOS reports success but the buffer contents haven't
* changed then we fail anyway */
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, DiskReadBuffer))
{
Changed = FALSE;
for (i = 0; ! Changed && i < DiskReadBufferSize; i++)
{
Changed = ((PUCHAR)DiskReadBuffer)[i] != 0xcd;
}
if (! Changed)
{
TRACE("BIOS reports success for disk %d but data didn't change\n",
(int)DiskCount);
break;
}
DiskCount++;
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
}
DiskReportError(TRUE);
TRACE("BIOS reports %d harddisk%s\n",
(int)DiskCount, (DiskCount == 1) ? "" : "s");
//DetectBiosFloppyController(BusKey);
/* Allocate resource descriptor */
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
if (PartialResourceList == NULL)
{
ERR("Failed to allocate resource descriptor\n");
return;
}
/* Initialize resource descriptor */
memset(PartialResourceList, 0, Size);
PartialResourceList->Version = 1;
PartialResourceList->Revision = 1;
PartialResourceList->Count = 1;
PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
PartialResourceList->PartialDescriptors[0].Flags = 0;
PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
/* Get harddisk Int13 geometry data */
Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
for (i = 0; i < DiskCount; i++)
{
if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
{
Int13Drives[i].DriveSelect = 0x80 + i;
Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
Int13Drives[i].SectorsPerTrack = (USHORT)Geometry.Sectors;
Int13Drives[i].MaxHeads = (USHORT)Geometry.Heads - 1;
Int13Drives[i].NumberDrives = DiskCount;
TRACE(
"Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
0x80 + i,
Geometry.Cylinders - 1,
Geometry.Heads - 1,
Geometry.Sectors,
Geometry.BytesPerSector);
}
}
FldrCreateComponentKey(BusKey,
ControllerClass,
DiskController,
Output | Input,
0,
0xFFFFFFFF,
NULL,
PartialResourceList,
Size,
&ControllerKey);
TRACE("Created key: DiskController\\0\n");
/* Create and fill subkey for each harddisk */
for (i = 0; i < DiskCount; i++)
{
CHAR Identifier[20];
/* Get disk values */
PartialResourceList = GetHarddiskConfigurationData(0x80 + i, &Size);
GetHarddiskIdentifier(Identifier, 0x80 + i);
/* Create disk key */
FldrCreateComponentKey(ControllerKey,
PeripheralClass,
DiskPeripheral,
Output | Input,
0,
0xFFFFFFFF,
Identifier,
PartialResourceList,
Size,
&DiskKey);
}
}
BOOLEAN
XboxInitializeBootDevices(VOID)
{
// Emulate old behavior
return XboxHwDetect() != NULL;
}
static
VOID
DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCONFIGURATION_COMPONENT_DATA BusKey;
ULONG Size;
/* Set 'Configuration Data' value */
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
if (PartialResourceList == NULL)
{
TRACE("Failed to allocate resource descriptor\n");
return;
}
/* Initialize resource descriptor */
memset(PartialResourceList, 0, Size);
PartialResourceList->Version = 1;
PartialResourceList->Revision = 1;
PartialResourceList->Count = 0;
/* Create new bus key */
FldrCreateComponentKey(SystemKey,
AdapterClass,
MultiFunctionAdapter,
0x0,
0x0,
0xFFFFFFFF,
"ISA",
PartialResourceList,
Size,
&BusKey);
/* Increment bus number */
(*BusNumber)++;
/* Detect ISA/BIOS devices */
DetectBiosDisks(SystemKey, BusKey);
/* FIXME: Detect more ISA devices */
}
PCONFIGURATION_COMPONENT_DATA
XboxHwDetect(VOID)
{
PCONFIGURATION_COMPONENT_DATA SystemKey;
ULONG BusNumber = 0;
TRACE("DetectHardware()\n");
/* Create the 'System' key */
FldrCreateSystemKey(&SystemKey);
/* TODO: Build actual xbox's hardware configuration tree */
DetectIsaBios(SystemKey, &BusNumber);
TRACE("DetectHardware() Done\n");
return SystemKey;
}
VOID XboxHwIdle(VOID)
{
/* UNIMPLEMENTED */
}
/******************************************************************************/
VOID VOID
XboxMachInit(const char *CmdLine) XboxMachInit(const char *CmdLine)
{ {
/* Set LEDs to red before anything is initialized */ /* Set LEDs to red before anything is initialized */
XboxSetLED("rrrr"); XboxSetLED("rrrr");
/* Initialize our stuff */ /* Initialize our stuff */
XboxMemInit(); XboxMemInit();
XboxVideoInit(); XboxVideoInit();
/* Setup vtbl */ /* Setup vtbl */
MachVtbl.ConsPutChar = XboxConsPutChar; MachVtbl.ConsPutChar = XboxConsPutChar;
MachVtbl.ConsKbHit = XboxConsKbHit; MachVtbl.ConsKbHit = XboxConsKbHit;
MachVtbl.ConsGetCh = XboxConsGetCh; MachVtbl.ConsGetCh = XboxConsGetCh;
MachVtbl.VideoClearScreen = XboxVideoClearScreen; MachVtbl.VideoClearScreen = XboxVideoClearScreen;
MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode; MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode;
MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize; MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize;
MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize; MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize;
MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor; MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor;
MachVtbl.VideoPutChar = XboxVideoPutChar; MachVtbl.VideoPutChar = XboxVideoPutChar;
MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM; MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM;
MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed; MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed;
MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor; MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor;
MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor; MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor;
MachVtbl.VideoSync = XboxVideoSync; MachVtbl.VideoSync = XboxVideoSync;
MachVtbl.Beep = PcBeep; MachVtbl.Beep = PcBeep;
MachVtbl.PrepareForReactOS = XboxPrepareForReactOS; MachVtbl.PrepareForReactOS = XboxPrepareForReactOS;
MachVtbl.GetMemoryMap = XboxMemGetMemoryMap; MachVtbl.GetMemoryMap = XboxMemGetMemoryMap;
MachVtbl.DiskGetBootPath = DiskGetBootPath; MachVtbl.DiskGetBootPath = DiskGetBootPath;
MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors; MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors;
MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry; MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry;
MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount; MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount;
MachVtbl.GetTime = XboxGetTime; MachVtbl.GetTime = XboxGetTime;
MachVtbl.InitializeBootDevices = XboxInitializeBootDevices; MachVtbl.InitializeBootDevices = PcInitializeBootDevices;
MachVtbl.HwDetect = XboxHwDetect; MachVtbl.HwDetect = XboxHwDetect;
MachVtbl.HwIdle = XboxHwIdle; MachVtbl.HwIdle = XboxHwIdle;
/* Set LEDs to orange after init */ /* Set LEDs to orange after init */
XboxSetLED("oooo"); XboxSetLED("oooo");
} }
VOID VOID
XboxPrepareForReactOS(IN BOOLEAN Setup) XboxPrepareForReactOS(IN BOOLEAN Setup)
{ {
// /* On XBOX, prepare video and turn off the floppy motor */
// On XBOX, prepare video and turn off the floppy motor
//
XboxVideoPrepareForReactOS(Setup); XboxVideoPrepareForReactOS(Setup);
DiskStopFloppyMotor(); DiskStopFloppyMotor();
} }
/* EOF */

View file

@ -18,6 +18,8 @@
*/ */
#include <freeldr.h> #include <freeldr.h>
#define NDEBUG
#include <debug.h> #include <debug.h>
DBG_DEFAULT_CHANNEL(DISK); DBG_DEFAULT_CHANNEL(DISK);
@ -25,41 +27,40 @@ DBG_DEFAULT_CHANNEL(DISK);
#include <pshpack2.h> #include <pshpack2.h>
typedef struct typedef struct
{ {
UCHAR PacketSize; // 00h - Size of packet (10h or 18h) UCHAR PacketSize; // 00h - Size of packet (10h or 18h)
UCHAR Reserved; // 01h - Reserved (0) UCHAR Reserved; // 01h - Reserved (0)
USHORT LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD) USHORT LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD)
USHORT TransferBufferOffset; // 04h - Transfer buffer offset (seg:off) USHORT TransferBufferOffset; // 04h - Transfer buffer offset (seg:off)
USHORT TransferBufferSegment; // Transfer buffer segment (seg:off) USHORT TransferBufferSegment; // Transfer buffer segment (seg:off)
ULONGLONG LBAStartBlock; // 08h - Starting absolute block number ULONGLONG LBAStartBlock; // 08h - Starting absolute block number
//ULONGLONG TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer // ULONGLONG TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer
// used if DWORD at 04h is FFFFh:FFFFh // used if DWORD at 04h is FFFFh:FFFFh
// Commented since some earlier BIOSes refuse to work with // Commented since some earlier BIOSes refuse to work with
// such extended structure // such extended structure
} I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET; } I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET;
#include <poppack.h> #include <poppack.h>
///////////////////////////////////////////////////////////////////////////////////////////// /* FUNCTIONS *****************************************************************/
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////
static BOOLEAN PcDiskResetController(UCHAR DriveNumber) BOOLEAN DiskResetController(UCHAR DriveNumber)
{ {
REGS RegsIn; REGS RegsIn, RegsOut;
REGS RegsOut;
WARN("PcDiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber); WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
// BIOS Int 13h, function 0 - Reset disk system /*
// AH = 00h * BIOS Int 13h, function 0 - Reset disk system
// DL = drive (if bit 7 is set both hard disks and floppy disks reset) * AH = 00h
// Return: * DL = drive (if bit 7 is set both hard disks and floppy disks reset)
// AH = status * Return:
// CF clear if successful * AH = status
// CF set on error * CF clear if successful
* CF set on error
*/
RegsIn.b.ah = 0x00; RegsIn.b.ah = 0x00;
RegsIn.b.dl = DriveNumber; RegsIn.b.dl = DriveNumber;
// Reset the disk controller /* Reset the disk controller */
Int386(0x13, &RegsIn, &RegsOut); Int386(0x13, &RegsIn, &RegsOut);
return INT386_SUCCESS(RegsOut); return INT386_SUCCESS(RegsOut);
@ -67,23 +68,16 @@ static BOOLEAN PcDiskResetController(UCHAR DriveNumber)
static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer) static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{ {
REGS RegsIn; REGS RegsIn, RegsOut;
REGS RegsOut; ULONG RetryCount;
ULONG RetryCount; PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER);
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); TRACE("PcDiskReadLogicalSectorsLBA() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer);
ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF); ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
// BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ /* Setup disk address packet */
RegsIn.b.ah = 0x42; // Subfunction 42h RtlZeroMemory(Packet, sizeof(*Packet));
RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk) Packet->PacketSize = sizeof(*Packet);
RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
RegsIn.w.si = BIOSCALLBUFOFFSET;
// Setup disk address packet
RtlZeroMemory(Packet, sizeof(I386_DISK_ADDRESS_PACKET));
Packet->PacketSize = sizeof(I386_DISK_ADDRESS_PACKET);
Packet->Reserved = 0; Packet->Reserved = 0;
Packet->LBABlockCount = (USHORT)SectorCount; Packet->LBABlockCount = (USHORT)SectorCount;
ASSERT(Packet->LBABlockCount == SectorCount); ASSERT(Packet->LBABlockCount == SectorCount);
@ -91,39 +85,45 @@ static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNu
Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4); Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4);
Packet->LBAStartBlock = SectorNumber; Packet->LBAStartBlock = SectorNumber;
// BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ /*
// Return: * BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
// CF clear if successful * Return:
// AH = 00h * CF clear if successful
// CF set on error * AH = 00h
// AH = error code * CF set on error
// disk address packet's block count field set to the * AH = error code
// number of blocks successfully transferred * Disk address packet's block count field set to the
* number of blocks successfully transferred.
*/
RegsIn.b.ah = 0x42; // Subfunction 42h
RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk)
RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
RegsIn.w.si = BIOSCALLBUFOFFSET;
// Retry 3 times /* Retry 3 times */
for (RetryCount=0; RetryCount<3; RetryCount++) for (RetryCount=0; RetryCount<3; RetryCount++)
{ {
Int386(0x13, &RegsIn, &RegsOut); Int386(0x13, &RegsIn, &RegsOut);
// If it worked return TRUE /* If it worked return TRUE */
if (INT386_SUCCESS(RegsOut)) if (INT386_SUCCESS(RegsOut))
{ {
return TRUE; return TRUE;
} }
// If it was a corrected ECC error then the data is still good /* If it was a corrected ECC error then the data is still good */
else if (RegsOut.b.ah == 0x11) else if (RegsOut.b.ah == 0x11)
{ {
return TRUE; return TRUE;
} }
// If it failed then do the next retry /* If it failed then do the next retry */
else else
{ {
PcDiskResetController(DriveNumber); DiskResetController(DriveNumber);
continue; continue;
} }
} }
// If we get here then the read failed /* If we get here then the read failed */
ERR("Disk Read Failed in LBA mode: %x (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n", RegsOut.b.ah, DriveNumber, SectorNumber, SectorCount); ERR("Disk Read Failed in LBA mode: %x (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n", RegsOut.b.ah, DriveNumber, SectorNumber, SectorCount);
return FALSE; return FALSE;
@ -131,20 +131,17 @@ static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNu
static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer) static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{ {
UCHAR PhysicalSector; UCHAR PhysicalSector;
UCHAR PhysicalHead; UCHAR PhysicalHead;
ULONG PhysicalTrack; ULONG PhysicalTrack;
GEOMETRY DriveGeometry; GEOMETRY DriveGeometry;
ULONG NumberOfSectorsToRead; ULONG NumberOfSectorsToRead;
REGS RegsIn; REGS RegsIn, RegsOut;
REGS RegsOut; ULONG RetryCount;
ULONG RetryCount;
TRACE("PcDiskReadLogicalSectorsCHS()\n"); TRACE("PcDiskReadLogicalSectorsCHS()\n");
// /* Get the drive geometry */
// Get the drive geometry
//
if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) || if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
DriveGeometry.Sectors == 0 || DriveGeometry.Sectors == 0 ||
DriveGeometry.Heads == 0) DriveGeometry.Heads == 0)
@ -154,18 +151,15 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
while (SectorCount) while (SectorCount)
{ {
/*
// * Calculate the physical disk offsets.
// Calculate the physical disk offsets * Note: DriveGeometry.Sectors < 64
// Note: DriveGeometry.Sectors < 64 */
//
PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors); PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors);
PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads); PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads);
PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads); PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads);
// /* Calculate how many sectors we need to read this round */
// Calculate how many sectors we need to read this round
//
if (PhysicalSector > 1) if (PhysicalSector > 1)
{ {
if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1))) if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
@ -181,9 +175,7 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
NumberOfSectorsToRead = SectorCount; NumberOfSectorsToRead = SectorCount;
} }
// /* Make sure the read is within the geometry boundaries */
// Make sure the read is within the geometry boundaries
//
if ((PhysicalHead >= DriveGeometry.Heads) || if ((PhysicalHead >= DriveGeometry.Heads) ||
(PhysicalTrack >= DriveGeometry.Cylinders) || (PhysicalTrack >= DriveGeometry.Cylinders) ||
((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) || ((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
@ -193,22 +185,24 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
return FALSE; return FALSE;
} }
// BIOS Int 13h, function 2 - Read Disk Sectors /*
// AH = 02h * BIOS Int 13h, function 2 - Read Disk Sectors
// AL = number of sectors to read (must be nonzero) * AH = 02h
// CH = low eight bits of cylinder number * AL = number of sectors to read (must be nonzero)
// CL = sector number 1-63 (bits 0-5) * CH = low eight bits of cylinder number
// high two bits of cylinder (bits 6-7, hard disk only) * CL = sector number 1-63 (bits 0-5)
// DH = head number * high two bits of cylinder (bits 6-7, hard disk only)
// DL = drive number (bit 7 set for hard disk) * DH = head number
// ES:BX -> data buffer * DL = drive number (bit 7 set for hard disk)
// Return: * ES:BX -> data buffer
// CF set on error * Return:
// if AH = 11h (corrected ECC error), AL = burst length * CF set on error
// CF clear if successful * if AH = 11h (corrected ECC error), AL = burst length
// AH = status * CF clear if successful
// AL = number of sectors transferred * AH = status
// (only valid if CF set for some BIOSes) * AL = number of sectors transferred
* (only valid if CF set for some BIOSes)
*/
RegsIn.b.ah = 0x02; RegsIn.b.ah = 0x02;
RegsIn.b.al = (UCHAR)NumberOfSectorsToRead; RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
RegsIn.b.ch = (PhysicalTrack & 0xFF); RegsIn.b.ch = (PhysicalTrack & 0xFF);
@ -218,41 +212,37 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4); RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F; RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;
// /* Perform the read. Retry 3 times. */
// Perform the read
// Retry 3 times
//
for (RetryCount=0; RetryCount<3; RetryCount++) for (RetryCount=0; RetryCount<3; RetryCount++)
{ {
Int386(0x13, &RegsIn, &RegsOut); Int386(0x13, &RegsIn, &RegsOut);
// If it worked break out /* If it worked break out */
if (INT386_SUCCESS(RegsOut)) if (INT386_SUCCESS(RegsOut))
{ {
break; break;
} }
// If it was a corrected ECC error then the data is still good /* If it was a corrected ECC error then the data is still good */
else if (RegsOut.b.ah == 0x11) else if (RegsOut.b.ah == 0x11)
{ {
break; break;
} }
// If it failed the do the next retry /* If it failed the do the next retry */
else else
{ {
PcDiskResetController(DriveNumber); DiskResetController(DriveNumber);
continue; continue;
} }
} }
// If we retried 3 times then fail /* If we retried 3 times then fail */
if (RetryCount >= 3) if (RetryCount >= 3)
{ {
ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x\n", RegsOut.b.ah); ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x\n", RegsOut.b.ah);
return FALSE; return FALSE;
} }
// I have learned that not all bioses return // I have learned that not all BIOSes return
// the sector read count in the AL register (at least mine doesn't) // the sector read count in the AL register (at least mine doesn't)
// even if the sectors were read correctly. So instead // even if the sectors were read correctly. So instead
// of checking the sector read count we will rely solely // of checking the sector read count we will rely solely
@ -266,122 +256,287 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
return TRUE; 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(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{ {
BOOLEAN ExtensionsSupported; BOOLEAN ExtensionsSupported;
TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer); 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 * Check to see if it is a fixed disk drive.
// If so then check to see if Int13 extensions work * If so then check to see if Int13 extensions work.
// If they do then use them, otherwise default back to BIOS calls * If they do then use them, otherwise default back to BIOS calls.
// */
ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber); ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
if ((DriveNumber >= 0x80) && ExtensionsSupported) if ((DriveNumber >= 0x80) && ExtensionsSupported)
{ {
TRACE("Using Int 13 Extensions for read. DiskInt13ExtensionsSupported(%d) = %s\n", DriveNumber, ExtensionsSupported ? "TRUE" : "FALSE"); TRACE("Using Int 13 Extensions for read. DiskInt13ExtensionsSupported(%d) = %s\n", DriveNumber, ExtensionsSupported ? "TRUE" : "FALSE");
// /* LBA is easy, nothing to calculate. Just do the read. */
// LBA is easy, nothing to calculate
// Just do the read
//
return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer); return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
} }
else else
{ {
// LBA is not supported default to the CHS calls /* LBA is not supported default to the CHS calls */
return PcDiskReadLogicalSectorsCHS(DriveNumber, SectorNumber, SectorCount, Buffer); return PcDiskReadLogicalSectorsCHS(DriveNumber, SectorNumber, SectorCount, Buffer);
} }
return TRUE; return TRUE;
} }
VOID DiskStopFloppyMotor(VOID)
{
WRITE_PORT_UCHAR((PUCHAR)0x3F2, 0);
}
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize)
{
REGS RegsIn, RegsOut;
PUSHORT Ptr = (PUSHORT)(BIOSCALLBUFFER);
TRACE("DiskGetExtendedDriveParameters()\n");
if (!DiskInt13ExtensionsSupported(DriveNumber))
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)
{
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;
}
BOOLEAN BOOLEAN
PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry) PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
{ {
EXTENDED_GEOMETRY ExtGeometry; EXTENDED_GEOMETRY ExtGeometry;
REGS RegsIn; REGS RegsIn, RegsOut;
REGS RegsOut; ULONG Cylinders;
ULONG Cylinders;
TRACE("DiskGetDriveGeometry()\n"); TRACE("DiskGetDriveGeometry()\n");
/* Try to get the extended geometry first */ /* Try to get the extended geometry first */
ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY); ExtGeometry.Size = sizeof(ExtGeometry);
if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size)) if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
{
Geometry->Cylinders = ExtGeometry.Cylinders;
Geometry->Heads = ExtGeometry.Heads;
Geometry->Sectors = ExtGeometry.SectorsPerTrack;
Geometry->BytesPerSector = ExtGeometry.BytesPerSector;
return TRUE;
}
/* 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))
{ {
return FALSE; Geometry->Cylinders = ExtGeometry.Cylinders;
Geometry->Heads = ExtGeometry.Heads;
Geometry->Sectors = ExtGeometry.SectorsPerTrack;
Geometry->BytesPerSector = ExtGeometry.BytesPerSector;
return TRUE;
} }
Cylinders = (RegsOut.b.cl & 0xC0) << 2; /*
Cylinders += RegsOut.b.ch; * BIOS Int 13h, function 08h - Get drive parameters
Cylinders++; * AH = 08h
Geometry->Cylinders = Cylinders; * DL = drive (bit 7 set for hard disk)
Geometry->Heads = RegsOut.b.dh + 1; * ES:DI = 0000h:0000h to guard against BIOS bugs
Geometry->Sectors = RegsOut.b.cl & 0x3F; * Return:
Geometry->BytesPerSector = 512; /* Just assume 512 bytes per sector */ * 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;
return TRUE; /* 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 ULONG
PcDiskGetCacheableBlockCount(UCHAR DriveNumber) PcDiskGetCacheableBlockCount(UCHAR DriveNumber)
{ {
GEOMETRY Geometry; GEOMETRY Geometry;
/* 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 not then the block size is the size of one track. */
if (DiskInt13ExtensionsSupported(DriveNumber)) if (DiskInt13ExtensionsSupported(DriveNumber))
{ {
return 64; return 64;
} }
/* Get the disk geometry /* Get the disk geometry. If this fails then we will
* If this fails then we will just return 1 sector to be safe */ * just return 1 sector to be safe. */
else if (! PcDiskGetDriveGeometry(DriveNumber, &Geometry)) else if (! PcDiskGetDriveGeometry(DriveNumber, &Geometry))
{ {
return 1; return 1;
} }
else else
{ {
return Geometry.Sectors; return Geometry.Sectors;
} }
} }

View file

@ -36,22 +36,22 @@ DBG_DEFAULT_CHANNEL(DISK);
static struct static struct
{ {
ULONG SectorCountBeforePartition; ULONG SectorCountBeforePartition;
ULONG PartitionSectorCount; ULONG PartitionSectorCount;
UCHAR SystemIndicator; UCHAR SystemIndicator;
} XboxPartitions[] = } XboxPartitions[] =
{ {
/* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */ /* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */
{ 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store, E: */ { 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store , E: */
{ 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */ { 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */
{ 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */ { 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */
{ 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */ { 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */
{ 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */ { 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */
}; };
#define IDE_SECTOR_BUF_SZ 512 #define IDE_SECTOR_BUF_SZ 512
#define IDE_MAX_POLL_RETRIES 100000 #define IDE_MAX_POLL_RETRIES 100000
#define IDE_MAX_BUSY_RETRIES 50000 #define IDE_MAX_BUSY_RETRIES 50000
/* Control Block offsets and masks */ /* Control Block offsets and masks */
#define IDE_REG_ALT_STATUS 0x0000 #define IDE_REG_ALT_STATUS 0x0000
@ -111,131 +111,131 @@ static struct
* Each macro takes an address of the command port block, and data * Each macro takes an address of the command port block, and data
*/ */
#define IDEReadError(Address) \ #define IDEReadError(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR))) (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR)))
#define IDEWritePrecomp(Address, Data) \ #define IDEWritePrecomp(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_PRECOMP), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_PRECOMP), (Data)))
#define IDEReadSectorCount(Address) \ #define IDEReadSectorCount(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT))) (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT)))
#define IDEWriteSectorCount(Address, Data) \ #define IDEWriteSectorCount(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT), (Data)))
#define IDEReadSectorNum(Address) \ #define IDEReadSectorNum(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM))) (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM)))
#define IDEWriteSectorNum(Address, Data) \ #define IDEWriteSectorNum(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM), (Data)))
#define IDEReadCylinderLow(Address) \ #define IDEReadCylinderLow(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW))) (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW)))
#define IDEWriteCylinderLow(Address, Data) \ #define IDEWriteCylinderLow(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW), (Data)))
#define IDEReadCylinderHigh(Address) \ #define IDEReadCylinderHigh(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH))) (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH)))
#define IDEWriteCylinderHigh(Address, Data) \ #define IDEWriteCylinderHigh(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH), (Data)))
#define IDEReadDriveHead(Address) \ #define IDEReadDriveHead(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD))) (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD)))
#define IDEWriteDriveHead(Address, Data) \ #define IDEWriteDriveHead(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD), (Data)))
#define IDEReadStatus(Address) \ #define IDEReadStatus(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS))) (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS)))
#define IDEWriteCommand(Address, Data) \ #define IDEWriteCommand(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_COMMAND), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_COMMAND), (Data)))
#define IDEReadDMACommand(Address) \ #define IDEReadDMACommand(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address)))) (READ_PORT_UCHAR((PUCHAR)((Address))))
#define IDEWriteDMACommand(Address, Data) \ #define IDEWriteDMACommand(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address)), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address)), (Data)))
#define IDEReadDMAStatus(Address) \ #define IDEReadDMAStatus(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + 2))) (READ_PORT_UCHAR((PUCHAR)((Address) + 2)))
#define IDEWriteDMAStatus(Address, Data) \ #define IDEWriteDMAStatus(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + 2), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + 2), (Data)))
#define IDEWritePRDTable(Address, Data) \ #define IDEWritePRDTable(Address, Data) \
(WRITE_PORT_ULONG((PULONG)((Address) + 4), (Data))) (WRITE_PORT_ULONG((PULONG)((Address) + 4), (Data)))
/* /*
* Data block read and write commands * Data block read and write commands
*/ */
#define IDEReadBlock(Address, Buffer, Count) \ #define IDEReadBlock(Address, Buffer, Count) \
(READ_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) (READ_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2))
#define IDEWriteBlock(Address, Buffer, Count) \ #define IDEWriteBlock(Address, Buffer, Count) \
(WRITE_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2)) (WRITE_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2))
#define IDEReadBlock32(Address, Buffer, Count) \ #define IDEReadBlock32(Address, Buffer, Count) \
(READ_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4)) (READ_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4))
#define IDEWriteBlock32(Address, Buffer, Count) \ #define IDEWriteBlock32(Address, Buffer, Count) \
(WRITE_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4)) (WRITE_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4))
#define IDEReadWord(Address) \ #define IDEReadWord(Address) \
(READ_PORT_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT))) (READ_PORT_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT)))
/* /*
* Access macros for control registers * Access macros for control registers
* Each macro takes an address of the control port blank and data * Each macro takes an address of the control port blank and data
*/ */
#define IDEReadAltStatus(Address) \ #define IDEReadAltStatus(Address) \
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ALT_STATUS))) (READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ALT_STATUS)))
#define IDEWriteDriveControl(Address, Data) \ #define IDEWriteDriveControl(Address, Data) \
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data))) (WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data)))
/* IDE_DRIVE_IDENTIFY */ /* IDE_DRIVE_IDENTIFY */
typedef struct _IDE_DRIVE_IDENTIFY typedef struct _IDE_DRIVE_IDENTIFY
{ {
USHORT ConfigBits; /*00*/ USHORT ConfigBits; /*00*/
USHORT LogicalCyls; /*01*/ USHORT LogicalCyls; /*01*/
USHORT Reserved02; /*02*/ USHORT Reserved02; /*02*/
USHORT LogicalHeads; /*03*/ USHORT LogicalHeads; /*03*/
USHORT BytesPerTrack; /*04*/ USHORT BytesPerTrack; /*04*/
USHORT BytesPerSector; /*05*/ USHORT BytesPerSector; /*05*/
USHORT SectorsPerTrack; /*06*/ USHORT SectorsPerTrack; /*06*/
UCHAR InterSectorGap; /*07*/ UCHAR InterSectorGap; /*07*/
UCHAR InterSectorGapSize; UCHAR InterSectorGapSize;
UCHAR Reserved08H; /*08*/ UCHAR Reserved08H; /*08*/
UCHAR BytesInPLO; UCHAR BytesInPLO;
USHORT VendorUniqueCnt; /*09*/ USHORT VendorUniqueCnt; /*09*/
char SerialNumber[20]; /*10*/ UCHAR SerialNumber[20]; /*10*/
USHORT ControllerType; /*20*/ USHORT ControllerType; /*20*/
USHORT BufferSize; /*21*/ USHORT BufferSize; /*21*/
USHORT ECCByteCnt; /*22*/ USHORT ECCByteCnt; /*22*/
char FirmwareRev[8]; /*23*/ UCHAR FirmwareRev[8]; /*23*/
char ModelNumber[40]; /*27*/ UCHAR ModelNumber[40]; /*27*/
USHORT RWMultImplemented; /*47*/ USHORT RWMultImplemented; /*47*/
USHORT DWordIo; /*48*/ USHORT DWordIo; /*48*/
USHORT Capabilities; /*49*/ USHORT Capabilities; /*49*/
#define IDE_DRID_STBY_SUPPORTED 0x2000 #define IDE_DRID_STBY_SUPPORTED 0x2000
#define IDE_DRID_IORDY_SUPPORTED 0x0800 #define IDE_DRID_IORDY_SUPPORTED 0x0800
#define IDE_DRID_IORDY_DISABLE 0x0400 #define IDE_DRID_IORDY_DISABLE 0x0400
#define IDE_DRID_LBA_SUPPORTED 0x0200 #define IDE_DRID_LBA_SUPPORTED 0x0200
#define IDE_DRID_DMA_SUPPORTED 0x0100 #define IDE_DRID_DMA_SUPPORTED 0x0100
USHORT Reserved50; /*50*/ USHORT Reserved50; /*50*/
USHORT MinPIOTransTime; /*51*/ USHORT MinPIOTransTime; /*51*/
USHORT MinDMATransTime; /*52*/ USHORT MinDMATransTime; /*52*/
USHORT TMFieldsValid; /*53*/ USHORT TMFieldsValid; /*53*/
USHORT TMCylinders; /*54*/ USHORT TMCylinders; /*54*/
USHORT TMHeads; /*55*/ USHORT TMHeads; /*55*/
USHORT TMSectorsPerTrk; /*56*/ USHORT TMSectorsPerTrk; /*56*/
USHORT TMCapacityLo; /*57*/ USHORT TMCapacityLo; /*57*/
USHORT TMCapacityHi; /*58*/ USHORT TMCapacityHi; /*58*/
USHORT RWMultCurrent; /*59*/ USHORT RWMultCurrent; /*59*/
USHORT TMSectorCountLo; /*60*/ USHORT TMSectorCountLo; /*60*/
USHORT TMSectorCountHi; /*61*/ USHORT TMSectorCountHi; /*61*/
USHORT DmaModes; /*62*/ USHORT DmaModes; /*62*/
USHORT MultiDmaModes; /*63*/ USHORT MultiDmaModes; /*63*/
USHORT Reserved64[5]; /*64*/ USHORT Reserved64[5]; /*64*/
USHORT Reserved69[2]; /*69*/ USHORT Reserved69[2]; /*69*/
USHORT Reserved71[4]; /*71*/ USHORT Reserved71[4]; /*71*/
USHORT MaxQueueDepth; /*75*/ USHORT MaxQueueDepth; /*75*/
USHORT Reserved76[4]; /*76*/ USHORT Reserved76[4]; /*76*/
USHORT MajorRevision; /*80*/ USHORT MajorRevision; /*80*/
USHORT MinorRevision; /*81*/ USHORT MinorRevision; /*81*/
USHORT SupportedFeatures82; /*82*/ USHORT SupportedFeatures82; /*82*/
USHORT SupportedFeatures83; /*83*/ USHORT SupportedFeatures83; /*83*/
USHORT SupportedFeatures84; /*84*/ USHORT SupportedFeatures84; /*84*/
USHORT EnabledFeatures85; /*85*/ USHORT EnabledFeatures85; /*85*/
USHORT EnabledFeatures86; /*86*/ USHORT EnabledFeatures86; /*86*/
USHORT EnabledFeatures87; /*87*/ USHORT EnabledFeatures87; /*87*/
USHORT UltraDmaModes; /*88*/ USHORT UltraDmaModes; /*88*/
USHORT Reserved89[11]; /*89*/ USHORT Reserved89[11]; /*89*/
USHORT Max48BitAddress[4]; /*100*/ USHORT Max48BitAddress[4]; /*100*/
USHORT Reserved104[151]; /*104*/ USHORT Reserved104[151]; /*104*/
USHORT Checksum; /*255*/ USHORT Checksum; /*255*/
} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY; } IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
/* XboxDiskPolledRead /* XboxDiskPolledRead
@ -247,21 +247,20 @@ typedef struct _IDE_DRIVE_IDENTIFY
* PASSIVE_LEVEL * PASSIVE_LEVEL
* *
* ARGUMENTS: * ARGUMENTS:
* ULONG CommandPort Address of command port for drive * ULONG CommandPort Address of command port for drive
* ULONG ControlPort Address of control port for drive * ULONG ControlPort Address of control port for drive
* UCHAR PreComp Value to write to precomp register * UCHAR PreComp Value to write to precomp register
* UCHAR SectorCnt Value to write to sectorCnt register * UCHAR SectorCnt Value to write to sectorCnt register
* UCHAR SectorNum Value to write to sectorNum register * UCHAR SectorNum Value to write to sectorNum register
* UCHAR CylinderLow Value to write to CylinderLow register * UCHAR CylinderLow Value to write to CylinderLow register
* UCHAR CylinderHigh Value to write to CylinderHigh register * UCHAR CylinderHigh Value to write to CylinderHigh register
* UCHAR DrvHead Value to write to Drive/Head register * UCHAR DrvHead Value to write to Drive/Head register
* UCHAR Command Value to write to Command register * UCHAR Command Value to write to Command register
* PVOID Buffer Buffer for output data * PVOID Buffer Buffer for output data
* *
* RETURNS: * RETURNS:
* BOOLEAN: TRUE success, FALSE error * BOOLEAN: TRUE success, FALSE error
*/ */
static BOOLEAN static BOOLEAN
XboxDiskPolledRead(ULONG CommandPort, XboxDiskPolledRead(ULONG CommandPort,
ULONG ControlPort, ULONG ControlPort,
@ -274,300 +273,296 @@ XboxDiskPolledRead(ULONG CommandPort,
UCHAR Command, UCHAR Command,
PVOID Buffer) PVOID Buffer)
{ {
ULONG SectorCount = 0; ULONG SectorCount = 0;
ULONG RetryCount; ULONG RetryCount;
BOOLEAN Junk = FALSE; BOOLEAN Junk = FALSE;
UCHAR Status; UCHAR Status;
/* Wait for BUSY to clear */ /* Wait for BUSY to clear */
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++) for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
{ {
Status = IDEReadStatus(CommandPort); Status = IDEReadStatus(CommandPort);
if (!(Status & IDE_SR_BUSY)) if (!(Status & IDE_SR_BUSY))
break;
StallExecutionProcessor(10);
}
TRACE("status=0x%x\n", Status);
TRACE("waited %d usecs for busy to clear\n", RetryCount * 10);
if (RetryCount >= IDE_MAX_BUSY_RETRIES)
{
WARN("Drive is BUSY for too long\n");
return FALSE;
}
/* Write Drive/Head to select drive */
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
StallExecutionProcessor(500);
/* Disable interrupts */
IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
StallExecutionProcessor(500);
/* Issue command to drive */
if (DrvHead & IDE_DH_LBA)
{
TRACE("READ:DRV=%d:LBA=1:BLK=%d:SC=0x%x:CM=0x%x\n",
DrvHead & IDE_DH_DRV1 ? 1 : 0,
((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
SectorCnt,
Command);
}
else
{
TRACE("READ:DRV=%d:LBA=0:CH=0x%x:CL=0x%x:HD=0x%x:SN=0x%x:SC=0x%x:CM=0x%x\n",
DrvHead & IDE_DH_DRV1 ? 1 : 0,
CylinderHigh,
CylinderLow,
DrvHead & 0x0f,
SectorNum,
SectorCnt,
Command);
}
/* Setup command parameters */
IDEWritePrecomp(CommandPort, PreComp);
IDEWriteSectorCount(CommandPort, SectorCnt);
IDEWriteSectorNum(CommandPort, SectorNum);
IDEWriteCylinderHigh(CommandPort, CylinderHigh);
IDEWriteCylinderLow(CommandPort, CylinderLow);
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
/* Issue the command */
IDEWriteCommand(CommandPort, Command);
StallExecutionProcessor(50);
/* Wait for DRQ or error */
for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
{
Status = IDEReadStatus(CommandPort);
if (!(Status & IDE_SR_BUSY))
{ {
break; if (Status & IDE_SR_ERR)
}
StallExecutionProcessor(10);
}
TRACE("status=0x%x\n", Status);
TRACE("waited %d usecs for busy to clear\n", RetryCount * 10);
if (RetryCount >= IDE_MAX_BUSY_RETRIES)
{
WARN("Drive is BUSY for too long\n");
return FALSE;
}
/* Write Drive/Head to select drive */
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
StallExecutionProcessor(500);
/* Disable interrupts */
IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
StallExecutionProcessor(500);
/* Issue command to drive */
if (DrvHead & IDE_DH_LBA)
{
TRACE("READ:DRV=%d:LBA=1:BLK=%d:SC=0x%x:CM=0x%x\n",
DrvHead & IDE_DH_DRV1 ? 1 : 0,
((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
SectorCnt,
Command);
}
else
{
TRACE("READ:DRV=%d:LBA=0:CH=0x%x:CL=0x%x:HD=0x%x:SN=0x%x:SC=0x%x:CM=0x%x\n",
DrvHead & IDE_DH_DRV1 ? 1 : 0,
CylinderHigh,
CylinderLow,
DrvHead & 0x0f,
SectorNum,
SectorCnt,
Command);
}
/* Setup command parameters */
IDEWritePrecomp(CommandPort, PreComp);
IDEWriteSectorCount(CommandPort, SectorCnt);
IDEWriteSectorNum(CommandPort, SectorNum);
IDEWriteCylinderHigh(CommandPort, CylinderHigh);
IDEWriteCylinderLow(CommandPort, CylinderLow);
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
/* Issue the command */
IDEWriteCommand(CommandPort, Command);
StallExecutionProcessor(50);
/* wait for DRQ or error */
for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
{
Status = IDEReadStatus(CommandPort);
if (!(Status & IDE_SR_BUSY))
{
if (Status & IDE_SR_ERR)
{
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return FALSE;
}
if (Status & IDE_SR_DRQ)
{
break;
}
else
{
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return FALSE;
}
}
StallExecutionProcessor(10);
}
/* timed out */
if (RetryCount >= IDE_MAX_POLL_RETRIES)
{
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return FALSE;
}
while (1)
{
/* Read data into buffer */
if (Junk == FALSE)
{
IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
Buffer = (PVOID)((ULONG_PTR)Buffer + IDE_SECTOR_BUF_SZ);
}
else
{
UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
}
SectorCount++;
/* Check for error or more sectors to read */
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
{
Status = IDEReadStatus(CommandPort);
if (!(Status & IDE_SR_BUSY))
{
if (Status & IDE_SR_ERR)
{
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return FALSE;
}
if (Status & IDE_SR_DRQ)
{
if (SectorCount >= SectorCnt)
{ {
TRACE("Buffer size exceeded!\n"); IDEWriteDriveControl(ControlPort, 0);
Junk = TRUE; StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return FALSE;
} }
break;
}
else
{
if (SectorCount > SectorCnt)
{
TRACE("Read %lu sectors of junk!\n",
SectorCount - SectorCnt);
}
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return TRUE; if (Status & IDE_SR_DRQ)
} {
break;
}
else
{
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return FALSE;
}
} }
StallExecutionProcessor(10);
} }
/* Timed out */
if (RetryCount >= IDE_MAX_POLL_RETRIES)
{
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return FALSE;
}
while (1)
{
/* Read data into buffer */
if (Junk == FALSE)
{
IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
Buffer = (PVOID)((ULONG_PTR)Buffer + IDE_SECTOR_BUF_SZ);
}
else
{
UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
}
SectorCount++;
/* Check for error or more sectors to read */
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
{
Status = IDEReadStatus(CommandPort);
if (!(Status & IDE_SR_BUSY))
{
if (Status & IDE_SR_ERR)
{
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return FALSE;
}
if (Status & IDE_SR_DRQ)
{
if (SectorCount >= SectorCnt)
{
TRACE("Buffer size exceeded!\n");
Junk = TRUE;
}
break;
}
else
{
if (SectorCount > SectorCnt)
{
TRACE("Read %lu sectors of junk!\n",
SectorCount - SectorCnt);
}
IDEWriteDriveControl(ControlPort, 0);
StallExecutionProcessor(50);
IDEReadStatus(CommandPort);
return TRUE;
}
}
}
} }
} }
BOOLEAN BOOLEAN
XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer) XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
{ {
ULONG StartSector; ULONG StartSector;
UCHAR Count; UCHAR Count;
if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f)) if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f))
{ {
/* Xbox has only 1 IDE controller and no floppy */ /* Xbox has only 1 IDE controller and no floppy */
WARN("Invalid drive number\n"); WARN("Invalid drive number\n");
return FALSE; return FALSE;
} }
if (UINT64_C(0) != ((SectorNumber + SectorCount) & UINT64_C(0xfffffffff0000000))) if (UINT64_C(0) != ((SectorNumber + SectorCount) & UINT64_C(0xfffffffff0000000)))
{ {
FIXME("48bit LBA required but not implemented\n"); FIXME("48bit LBA required but not implemented\n");
return FALSE; return FALSE;
} }
StartSector = (ULONG) SectorNumber; StartSector = (ULONG) SectorNumber;
while (0 < SectorCount) while (0 < SectorCount)
{ {
Count = (SectorCount <= 255 ? (UCHAR)SectorCount : 255); Count = (SectorCount <= 255 ? (UCHAR)SectorCount : 255);
if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT, if (!XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
XBOX_IDE_CONTROL_PORT, XBOX_IDE_CONTROL_PORT,
0, Count, 0, Count,
StartSector & 0xff, StartSector & 0xff,
(StartSector >> 8) & 0xff, (StartSector >> 8) & 0xff,
(StartSector >> 16) & 0xff, (StartSector >> 16) & 0xff,
((StartSector >> 24) & 0x0f) | IDE_DH_LBA | ((StartSector >> 24) & 0x0f) | IDE_DH_LBA |
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1), (0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
IDE_CMD_READ, IDE_CMD_READ,
Buffer)) Buffer))
{ {
return FALSE; return FALSE;
} }
SectorCount -= Count; SectorCount -= Count;
Buffer = (PVOID) ((PCHAR) Buffer + Count * IDE_SECTOR_BUF_SZ); Buffer = (PVOID) ((PCHAR) Buffer + Count * IDE_SECTOR_BUF_SZ);
} }
return TRUE; return TRUE;
} }
BOOLEAN BOOLEAN
XboxDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry) XboxDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
{ {
UCHAR SectorData[IDE_SECTOR_BUF_SZ]; UCHAR SectorData[IDE_SECTOR_BUF_SZ];
/* This is the Xbox, chances are that there is a Xbox-standard partitionless /*
* disk in it so let's check that first */ * This is the Xbox, chances are that there is a Xbox-standard
* partitionless disk in it so let's check that first.
if (1 <= PartitionNumber && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) && */
MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData)) if (1 <= PartitionNumber && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) &&
MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData))
{ {
if (*((PULONG) SectorData) == XBOX_SIGNATURE) if (*((PULONG) SectorData) == XBOX_SIGNATURE)
{ {
memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY)); memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY));
PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator; PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator;
PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition; PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition;
PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount; PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount;
return TRUE; return TRUE;
} }
} }
/* No magic Xbox partitions. Maybe there's a MBR */ /* No magic Xbox partitions. Maybe there's a MBR */
return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry); return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry);
} }
BOOLEAN BOOLEAN
XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry) XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
{ {
IDE_DRIVE_IDENTIFY DrvParms; IDE_DRIVE_IDENTIFY DrvParms;
ULONG i; ULONG i;
BOOLEAN Atapi; BOOLEAN Atapi;
Atapi = FALSE; /* FIXME */ Atapi = FALSE; /* FIXME */
/* Get the Drive Identify block from drive or die */ /* Get the Drive Identify block from drive or die */
if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT, if (!XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
XBOX_IDE_CONTROL_PORT, XBOX_IDE_CONTROL_PORT,
0, 0,
1, 1,
0, 0,
0, 0,
0, 0,
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1), (0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
(Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV), (Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
(PUCHAR) &DrvParms)) (PUCHAR) &DrvParms))
{ {
ERR("XboxDiskPolledRead() failed\n"); ERR("XboxDiskPolledRead() failed\n");
return FALSE; return FALSE;
} }
Geometry->Cylinders = DrvParms.LogicalCyls; Geometry->Cylinders = DrvParms.LogicalCyls;
Geometry->Heads = DrvParms.LogicalHeads; Geometry->Heads = DrvParms.LogicalHeads;
Geometry->Sectors = DrvParms.SectorsPerTrack; Geometry->Sectors = DrvParms.SectorsPerTrack;
if (! Atapi && 0 != (DrvParms.Capabilities & IDE_DRID_LBA_SUPPORTED)) if (! Atapi && 0 != (DrvParms.Capabilities & IDE_DRID_LBA_SUPPORTED))
{ {
/* LBA ATA drives always have a sector size of 512 */ /* LBA ATA drives always have a sector size of 512 */
Geometry->BytesPerSector = 512; Geometry->BytesPerSector = 512;
} }
else else
{ {
TRACE("BytesPerSector %d\n", DrvParms.BytesPerSector); TRACE("BytesPerSector %d\n", DrvParms.BytesPerSector);
if (DrvParms.BytesPerSector == 0) if (DrvParms.BytesPerSector == 0)
{ {
Geometry->BytesPerSector = 512; Geometry->BytesPerSector = 512;
} }
else else
{ {
for (i = 1 << 15; i; i /= 2) for (i = 1 << 15; i; i /= 2)
{ {
if (0 != (DrvParms.BytesPerSector & i)) if ((DrvParms.BytesPerSector & i) != 0)
{ {
Geometry->BytesPerSector = i; Geometry->BytesPerSector = i;
break; break;
} }
} }
} }
} }
TRACE("Cylinders %d\n", Geometry->Cylinders); TRACE("Cylinders %d\n", Geometry->Cylinders);
TRACE("Heads %d\n", Geometry->Heads); TRACE("Heads %d\n", Geometry->Heads);
TRACE("Sectors %d\n", Geometry->Sectors); TRACE("Sectors %d\n", Geometry->Sectors);
TRACE("BytesPerSector %d\n", Geometry->BytesPerSector); TRACE("BytesPerSector %d\n", Geometry->BytesPerSector);
return TRUE; return TRUE;
} }
ULONG ULONG
XboxDiskGetCacheableBlockCount(UCHAR DriveNumber) XboxDiskGetCacheableBlockCount(UCHAR DriveNumber)
{ {
/* 64 seems a nice number, it is used by the machpc code for LBA devices */ /* 64 seems a nice number, it is used by the machpc code for LBA devices */
return 64; return 64;
} }
/* EOF */ /* EOF */

View file

@ -1,531 +0,0 @@
/*
* FreeLoader
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include <freeldr.h>
#define NDEBUG
#include <debug.h>
DBG_DEFAULT_CHANNEL(HWDETECT);
static CHAR Hex[] = "0123456789ABCDEF";
//static unsigned int delay_count = 1;
extern ULONG reactos_disk_count;
extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[];
static
PCM_PARTIAL_RESOURCE_LIST
GetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
//EXTENDED_GEOMETRY ExtGeometry;
GEOMETRY Geometry;
ULONG Size;
//
// Initialize returned size
//
*pSize = 0;
/* Set 'Configuration Data' value */
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
if (PartialResourceList == NULL)
{
ERR("Failed to allocate a full resource descriptor\n");
return NULL;
}
memset(PartialResourceList, 0, Size);
PartialResourceList->Version = 1;
PartialResourceList->Revision = 1;
PartialResourceList->Count = 1;
PartialResourceList->PartialDescriptors[0].Type =
CmResourceTypeDeviceSpecific;
// PartialResourceList->PartialDescriptors[0].ShareDisposition =
// PartialResourceList->PartialDescriptors[0].Flags =
PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
/* Get pointer to geometry data */
DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
/* Get the disk geometry */
//ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
{
DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
DiskGeometry->SectorsPerTrack = Geometry.Sectors;
DiskGeometry->NumberOfHeads = Geometry.Heads;
}
else
{
ERR("Reading disk geometry failed\n");
FrLdrHeapFree(PartialResourceList, TAG_HW_RESOURCE_LIST);
return NULL;
}
TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
DriveNumber,
DiskGeometry->NumberOfCylinders,
DiskGeometry->NumberOfHeads,
DiskGeometry->SectorsPerTrack,
DiskGeometry->BytesPerSector);
//
// Return configuration data
//
*pSize = Size;
return PartialResourceList;
}
typedef struct tagDISKCONTEXT
{
UCHAR DriveNumber;
ULONG SectorSize;
ULONGLONG SectorOffset;
ULONGLONG SectorCount;
ULONGLONG SectorNumber;
} DISKCONTEXT;
static
ARC_STATUS
DiskClose(ULONG FileId)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
FrLdrTempFree(Context, TAG_HW_DISK_CONTEXT);
return ESUCCESS;
}
static
ARC_STATUS
DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
RtlZeroMemory(Information, sizeof(FILEINFORMATION));
Information->EndingAddress.QuadPart = (Context->SectorOffset + Context->SectorCount) * Context->SectorSize;
Information->CurrentAddress.QuadPart = (Context->SectorOffset + Context->SectorNumber) * Context->SectorSize;
return ESUCCESS;
}
static
ARC_STATUS
DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
{
DISKCONTEXT* Context;
ULONG DrivePartition, SectorSize;
UCHAR DriveNumber;
ULONGLONG SectorOffset = 0;
ULONGLONG SectorCount = 0;
PARTITION_TABLE_ENTRY PartitionTableEntry;
CHAR FileName[1];
if (!DissectArcPath(Path, FileName, &DriveNumber, &DrivePartition))
return EINVAL;
if (DrivePartition == 0xff)
{
/* This is a CD-ROM device */
SectorSize = 2048;
}
else
{
/* This is either a floppy disk device (DrivePartition == 0) or
* a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
* it doesn't matter which one because they both have 512 bytes per sector */
SectorSize = 512;
}
if (DrivePartition != 0xff && DrivePartition != 0)
{
if (!XboxDiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
return EINVAL;
SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
SectorCount = PartitionTableEntry.PartitionSectorCount;
}
else
{
SectorCount = 0; /* FIXME */
}
Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
if (!Context)
return ENOMEM;
Context->DriveNumber = DriveNumber;
Context->SectorSize = SectorSize;
Context->SectorOffset = SectorOffset;
Context->SectorCount = SectorCount;
Context->SectorNumber = 0;
FsSetDeviceSpecific(*FileId, Context);
return ESUCCESS;
}
static
ARC_STATUS
DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
UCHAR* Ptr = (UCHAR*)Buffer;
ULONG i, Length, Sectors;
BOOLEAN ret;
*Count = 0;
i = 0;
while (N > 0)
{
Length = N;
if (Length > DiskReadBufferSize)
Length = DiskReadBufferSize;
Sectors = (Length + Context->SectorSize - 1) / Context->SectorSize;
ret = MachDiskReadLogicalSectors(
Context->DriveNumber,
Context->SectorNumber + Context->SectorOffset + i,
Sectors,
DiskReadBuffer);
if (!ret)
return EIO;
RtlCopyMemory(Ptr, DiskReadBuffer, Length);
Ptr += Length;
*Count += Length;
N -= Length;
i += Sectors;
}
return ESUCCESS;
}
static
ARC_STATUS
DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
{
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
if (SeekMode != SeekAbsolute)
return EINVAL;
if (Position->LowPart & (Context->SectorSize - 1))
return EINVAL;
/* FIXME: take HighPart into account */
Context->SectorNumber = Position->LowPart / Context->SectorSize;
return ESUCCESS;
}
static const DEVVTBL DiskVtbl =
{
DiskClose,
DiskGetFileInformation,
DiskOpen,
DiskRead,
DiskSeek,
};
static
VOID
GetHarddiskIdentifier(PCHAR Identifier,
UCHAR DriveNumber)
{
PMASTER_BOOT_RECORD Mbr;
PULONG Buffer;
ULONG i;
ULONG Checksum;
ULONG Signature;
CHAR ArcName[MAX_PATH];
PARTITION_TABLE_ENTRY PartitionTableEntry;
/* Read the MBR */
if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
{
ERR("Reading MBR failed\n");
return;
}
Buffer = (ULONG*)DiskReadBuffer;
Mbr = (PMASTER_BOOT_RECORD)DiskReadBuffer;
Signature = Mbr->Signature;
TRACE("Signature: %x\n", Signature);
/* Calculate the MBR checksum */
Checksum = 0;
for (i = 0; i < 512 / sizeof(ULONG); i++)
{
Checksum += Buffer[i];
}
Checksum = ~Checksum + 1;
TRACE("Checksum: %x\n", Checksum);
/* Fill out the ARC disk block */
reactos_arc_disk_info[reactos_disk_count].DiskSignature.Signature = Signature;
reactos_arc_disk_info[reactos_disk_count].DiskSignature.CheckSum = Checksum;
sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count);
strcpy(reactos_arc_disk_info[reactos_disk_count].ArcName, ArcName);
reactos_arc_disk_info[reactos_disk_count].DiskSignature.ArcName =
reactos_arc_disk_info[reactos_disk_count].ArcName;
reactos_disk_count++;
sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(0)", DriveNumber - 0x80);
FsRegisterDevice(ArcName, &DiskVtbl);
/* Add partitions */
i = 1;
DiskReportError(FALSE);
while (XboxDiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry))
{
if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED)
{
sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(%lu)", DriveNumber - 0x80, i);
FsRegisterDevice(ArcName, &DiskVtbl);
}
i++;
}
DiskReportError(TRUE);
/* Convert checksum and signature to identifier string */
Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
Identifier[7] = Hex[Checksum & 0x0F];
Identifier[8] = '-';
Identifier[9] = Hex[(Signature >> 28) & 0x0F];
Identifier[10] = Hex[(Signature >> 24) & 0x0F];
Identifier[11] = Hex[(Signature >> 20) & 0x0F];
Identifier[12] = Hex[(Signature >> 16) & 0x0F];
Identifier[13] = Hex[(Signature >> 12) & 0x0F];
Identifier[14] = Hex[(Signature >> 8) & 0x0F];
Identifier[15] = Hex[(Signature >> 4) & 0x0F];
Identifier[16] = Hex[Signature & 0x0F];
Identifier[17] = '-';
Identifier[18] = 'A';
Identifier[19] = 0;
TRACE("Identifier: %s\n", Identifier);
}
static
VOID
DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
PCONFIGURATION_COMPONENT_DATA BusKey)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCM_INT13_DRIVE_PARAMETER Int13Drives;
GEOMETRY Geometry;
PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey;
UCHAR DiskCount;
ULONG i;
ULONG Size;
BOOLEAN Changed;
/* Count the number of visible drives */
DiskReportError(FALSE);
DiskCount = 0;
/* There are some really broken BIOSes out there. There are even BIOSes
* that happily report success when you ask them to read from non-existent
* harddisks. So, we set the buffer to known contents first, then try to
* read. If the BIOS reports success but the buffer contents haven't
* changed then we fail anyway */
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, DiskReadBuffer))
{
Changed = FALSE;
for (i = 0; ! Changed && i < DiskReadBufferSize; i++)
{
Changed = ((PUCHAR)DiskReadBuffer)[i] != 0xcd;
}
if (! Changed)
{
TRACE("BIOS reports success for disk %d but data didn't change\n",
(int)DiskCount);
break;
}
DiskCount++;
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
}
DiskReportError(TRUE);
TRACE("BIOS reports %d harddisk%s\n",
(int)DiskCount, (DiskCount == 1) ? "" : "s");
//DetectBiosFloppyController(BusKey);
/* Allocate resource descriptor */
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
if (PartialResourceList == NULL)
{
ERR("Failed to allocate resource descriptor\n");
return;
}
/* Initialize resource descriptor */
memset(PartialResourceList, 0, Size);
PartialResourceList->Version = 1;
PartialResourceList->Revision = 1;
PartialResourceList->Count = 1;
PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
PartialResourceList->PartialDescriptors[0].Flags = 0;
PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
/* Get harddisk Int13 geometry data */
Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
for (i = 0; i < DiskCount; i++)
{
if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
{
Int13Drives[i].DriveSelect = 0x80 + i;
Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
Int13Drives[i].SectorsPerTrack = (USHORT)Geometry.Sectors;
Int13Drives[i].MaxHeads = (USHORT)Geometry.Heads - 1;
Int13Drives[i].NumberDrives = DiskCount;
TRACE(
"Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
0x80 + i,
Geometry.Cylinders - 1,
Geometry.Heads - 1,
Geometry.Sectors,
Geometry.BytesPerSector);
}
}
FldrCreateComponentKey(BusKey,
ControllerClass,
DiskController,
Output | Input,
0,
0xFFFFFFFF,
NULL,
PartialResourceList,
Size,
&ControllerKey);
TRACE("Created key: DiskController\\0\n");
/* Create and fill subkey for each harddisk */
for (i = 0; i < DiskCount; i++)
{
CHAR Identifier[20];
/* Get disk values */
PartialResourceList = GetHarddiskConfigurationData(0x80 + i, &Size);
GetHarddiskIdentifier(Identifier, 0x80 + i);
/* Create disk key */
FldrCreateComponentKey(ControllerKey,
PeripheralClass,
DiskPeripheral,
Output | Input,
0,
0xFFFFFFFF,
Identifier,
PartialResourceList,
Size,
&DiskKey);
}
}
static
VOID
DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
{
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
PCONFIGURATION_COMPONENT_DATA BusKey;
ULONG Size;
/* Set 'Configuration Data' value */
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
if (PartialResourceList == NULL)
{
TRACE(
"Failed to allocate resource descriptor\n");
return;
}
/* Initialize resource descriptor */
memset(PartialResourceList, 0, Size);
PartialResourceList->Version = 1;
PartialResourceList->Revision = 1;
PartialResourceList->Count = 0;
/* Create new bus key */
FldrCreateComponentKey(SystemKey,
AdapterClass,
MultiFunctionAdapter,
0x0,
0x0,
0xFFFFFFFF,
"ISA",
PartialResourceList,
Size,
&BusKey);
/* Increment bus number */
(*BusNumber)++;
/* Detect ISA/BIOS devices */
DetectBiosDisks(SystemKey, BusKey);
/* FIXME: Detect more ISA devices */
}
PCONFIGURATION_COMPONENT_DATA
XboxHwDetect(VOID)
{
PCONFIGURATION_COMPONENT_DATA SystemKey;
ULONG BusNumber = 0;
TRACE("DetectHardware()\n");
/* Create the 'System' key */
FldrCreateSystemKey(&SystemKey);
/* TODO: Build actual xbox's hardware configuration tree */
DetectIsaBios(SystemKey, &BusNumber);
TRACE("DetectHardware() Done\n");
return SystemKey;
}
BOOLEAN
XboxInitializeBootDevices(VOID)
{
// Emulate old behavior
return XboxHwDetect() != NULL;
}
VOID XboxHwIdle(VOID)
{
/* UNIMPLEMENTED */
}
/* EOF */

View file

@ -19,29 +19,30 @@
#ifndef _M_ARM #ifndef _M_ARM
#include <freeldr.h> #include <freeldr.h>
#define NDEBUG
#include <debug.h> #include <debug.h>
DBG_DEFAULT_CHANNEL(DISK); DBG_DEFAULT_CHANNEL(DISK);
static BOOLEAN bReportError = TRUE; static BOOLEAN bReportError = TRUE;
///////////////////////////////////////////////////////////////////////////////////////////// /* FUNCTIONS *****************************************************************/
// FUNCTIONS
/////////////////////////////////////////////////////////////////////////////////////////////
VOID DiskReportError (BOOLEAN bError) VOID DiskReportError(BOOLEAN bError)
{ {
bReportError = bError; bReportError = bError;
} }
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode) VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
{ {
CHAR ErrorCodeString[200]; CHAR ErrorCodeString[200];
if (bReportError == FALSE) if (bReportError == FALSE)
return; return;
sprintf(ErrorCodeString, "%s\n\nError Code: 0x%lx\nError: %s", ErrorString, ErrorCode, DiskGetErrorCodeString(ErrorCode)); sprintf(ErrorCodeString, "%s\n\nError Code: 0x%lx\nError: %s",
ErrorString, ErrorCode, DiskGetErrorCodeString(ErrorCode));
TRACE("%s\n", ErrorCodeString); TRACE("%s\n", ErrorCodeString);
@ -83,21 +84,17 @@ PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
} }
} }
// This function is in arch/i386/i386disk.c
//BOOLEAN DiskReadLogicalSectors(ULONG DriveNumber, U64 SectorNumber, ULONG SectorCount, PVOID Buffer)
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber) BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber)
{ {
// Hard disks use drive numbers >= 0x80 /*
// So if the drive number indicates a hard disk * Hard disks use drive numbers >= 0x80 . So if the drive number
// then return FALSE * indicates a hard disk then return FALSE.
// 0x49 is our magic ramdisk drive, so return FALSE for that too * 0x49 is our magic ramdisk drive, so return FALSE for that too.
*/
if ((DriveNumber >= 0x80) || (DriveNumber == 0x49)) if ((DriveNumber >= 0x80) || (DriveNumber == 0x49))
{
return FALSE; return FALSE;
}
// Drive is a floppy diskette so return TRUE /* The drive is a floppy diskette so return TRUE */
return TRUE; return TRUE;
} }
@ -191,10 +188,4 @@ DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
return TRUE; return TRUE;
} }
// This function is in arch/i386/i386disk.c
//VOID DiskStopFloppyMotor(VOID)
// This function is in arch/i386/i386disk.c
//ULONG DiskGetCacheableBlockCount(UCHAR DriveNumber)
#endif #endif

View file

@ -49,6 +49,9 @@ VOID PcPrepareForReactOS(IN BOOLEAN Setup);
PFREELDR_MEMORY_DESCRIPTOR PcMemGetMemoryMap(ULONG *MemoryMapSize); PFREELDR_MEMORY_DESCRIPTOR PcMemGetMemoryMap(ULONG *MemoryMapSize);
BOOLEAN DiskResetController(UCHAR DriveNumber);
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize);
BOOLEAN PcDiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size); BOOLEAN PcDiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size);
BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer);
BOOLEAN PcDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOLEAN PcDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);

View file

@ -23,10 +23,10 @@
typedef struct _GEOMETRY typedef struct _GEOMETRY
{ {
ULONG Cylinders; // Number of cylinders on the disk ULONG Cylinders; // Number of cylinders on the disk
ULONG Heads; // Number of heads on the disk ULONG Heads; // Number of heads on the disk
ULONG Sectors; // Number of sectors per track ULONG Sectors; // Number of sectors per track
ULONG BytesPerSector; // Number of bytes per sector ULONG BytesPerSector; // Number of bytes per sector
} GEOMETRY, *PGEOMETRY; } GEOMETRY, *PGEOMETRY;
@ -36,14 +36,15 @@ typedef struct _GEOMETRY
#include <pshpack1.h> #include <pshpack1.h>
typedef struct _EXTENDED_GEOMETRY typedef struct _EXTENDED_GEOMETRY
{ {
USHORT Size; USHORT Size;
USHORT Flags; USHORT Flags;
ULONG Cylinders; ULONG Cylinders;
ULONG Heads; ULONG Heads;
ULONG SectorsPerTrack; ULONG SectorsPerTrack;
ULONGLONG Sectors; ULONGLONG Sectors;
USHORT BytesPerSector; USHORT BytesPerSector;
ULONG PDPTE; ULONG PDPTE;
} EXTENDED_GEOMETRY, *PEXTENDED_GEOMETRY; } EXTENDED_GEOMETRY, *PEXTENDED_GEOMETRY;
// //
@ -51,16 +52,17 @@ typedef struct _EXTENDED_GEOMETRY
// //
typedef struct _PARTITION_TABLE_ENTRY typedef struct _PARTITION_TABLE_ENTRY
{ {
UCHAR BootIndicator; // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only) UCHAR BootIndicator; // 0x00 - non-bootable partition,
UCHAR StartHead; // Beginning head number // 0x80 - bootable partition (one partition only)
UCHAR StartSector; // Beginning sector (2 high bits of cylinder #) UCHAR StartHead; // Beginning head number
UCHAR StartCylinder; // Beginning cylinder# (low order bits of cylinder #) UCHAR StartSector; // Beginning sector (2 high bits of cylinder #)
UCHAR SystemIndicator; // System indicator UCHAR StartCylinder; // Beginning cylinder# (low order bits of cylinder #)
UCHAR EndHead; // Ending head number UCHAR SystemIndicator; // System indicator
UCHAR EndSector; // Ending sector (2 high bits of cylinder #) UCHAR EndHead; // Ending head number
UCHAR EndCylinder; // Ending cylinder# (low order bits of cylinder #) UCHAR EndSector; // Ending sector (2 high bits of cylinder #)
ULONG SectorCountBeforePartition; // Number of sectors preceding the partition UCHAR EndCylinder; // Ending cylinder# (low order bits of cylinder #)
ULONG PartitionSectorCount; // Number of sectors in the partition ULONG SectorCountBeforePartition; // Number of sectors preceding the partition
ULONG PartitionSectorCount; // Number of sectors in the partition
} PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY; } PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY;
@ -69,11 +71,11 @@ typedef struct _PARTITION_TABLE_ENTRY
// //
typedef struct _MASTER_BOOT_RECORD typedef struct _MASTER_BOOT_RECORD
{ {
UCHAR MasterBootRecordCodeAndData[0x1b8]; /* 0x000 */ UCHAR MasterBootRecordCodeAndData[0x1b8]; /* 0x000 */
ULONG Signature; /* 0x1B8 */ ULONG Signature; /* 0x1B8 */
USHORT Reserved; /* 0x1BC */ USHORT Reserved; /* 0x1BC */
PARTITION_TABLE_ENTRY PartitionTable[4]; /* 0x1BE */ PARTITION_TABLE_ENTRY PartitionTable[4]; /* 0x1BE */
USHORT MasterBootRecordMagic; /* 0x1FE */ USHORT MasterBootRecordMagic; /* 0x1FE */
} MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD; } MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD;
#include <poppack.h> #include <poppack.h>
@ -107,16 +109,11 @@ typedef struct _MASTER_BOOT_RECORD
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
// //
// i386 BIOS Disk Functions (i386disk.c) // PC x86/64 BIOS Disk Functions (pcdisk.c)
// //
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
#if defined(__i386__) || defined(_M_AMD64) #if defined(__i386__) || defined(_M_AMD64)
VOID DiskStopFloppyMotor(VOID);
BOOLEAN DiskResetController(UCHAR DriveNumber);
BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber);
//VOID DiskStopFloppyMotor(VOID);
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize);
#endif // defined __i386__ || defined(_M_AMD64) #endif // defined __i386__ || defined(_M_AMD64)
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
@ -124,12 +121,10 @@ BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHOR
// FreeLoader Disk Functions // FreeLoader Disk Functions
// //
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
VOID DiskReportError (BOOLEAN bError); VOID DiskReportError (BOOLEAN bError);
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode); VOID DiskError(PCSTR ErrorString, ULONG ErrorCode);
PCSTR DiskGetErrorCodeString(ULONG ErrorCode); PCSTR DiskGetErrorCodeString(ULONG ErrorCode);
BOOLEAN DiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); // Implemented in i386disk.c BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
VOID DiskStopFloppyMotor(VOID); // Implemented in i386disk.c
extern UCHAR FrldrBootDrive; extern UCHAR FrldrBootDrive;
extern ULONG FrldrBootPartition; extern ULONG FrldrBootPartition;
extern PVOID DiskReadBuffer; extern PVOID DiskReadBuffer;
@ -143,10 +138,13 @@ BOOLEAN DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size);
// Fixed Disk Partition Management Functions // Fixed Disk Partition Management Functions
// //
/////////////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////////////
BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, ULONG *ActivePartition); BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, ULONG *ActivePartition);
BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
BOOLEAN DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOLEAN DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
BOOLEAN DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry); BOOLEAN DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord); BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord);
/*
* SCSI support (disk/scsiport.c)
*/
ULONG LoadBootDeviceDriver(VOID); ULONG LoadBootDeviceDriver(VOID);