mirror of
https://github.com/reactos/reactos.git
synced 2024-06-28 17:01:28 +00:00
[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:
parent
8c8c4f495c
commit
dde1f97a02
|
@ -123,7 +123,6 @@ if(ARCH STREQUAL "i386")
|
|||
arch/i386/hwdisk.c
|
||||
arch/i386/hwpci.c
|
||||
arch/i386/i386bug.c
|
||||
arch/i386/i386disk.c
|
||||
arch/i386/i386idt.c
|
||||
arch/i386/i386rtl.c
|
||||
arch/i386/i386vid.c
|
||||
|
@ -137,7 +136,6 @@ if(ARCH STREQUAL "i386")
|
|||
arch/i386/xboxcons.c
|
||||
arch/i386/xboxdisk.c
|
||||
arch/i386/xboxfont.c
|
||||
arch/i386/xboxhw.c
|
||||
arch/i386/xboxi2c.c
|
||||
arch/i386/xboxmem.c
|
||||
arch/i386/xboxrtc.c
|
||||
|
@ -170,7 +168,6 @@ elseif(ARCH STREQUAL "amd64")
|
|||
arch/i386/hwpci.c
|
||||
arch/i386/i386bug.c
|
||||
arch/i386/i386rtl.c
|
||||
arch/i386/i386disk.c
|
||||
arch/i386/i386vid.c
|
||||
arch/i386/machpc.c
|
||||
arch/i386/pccons.c
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -39,13 +39,19 @@ extern ULONG reactos_disk_count;
|
|||
extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[];
|
||||
|
||||
static CHAR Hex[] = "0123456789abcdef";
|
||||
|
||||
UCHAR PcBiosDiskCount = 0;
|
||||
CHAR PcDiskIdentifier[32][20];
|
||||
static CHAR PcDiskIdentifier[32][20];
|
||||
|
||||
PVOID DiskReadBuffer;
|
||||
SIZE_T DiskReadBufferSize;
|
||||
|
||||
|
||||
static ARC_STATUS DiskClose(ULONG FileId)
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
// static
|
||||
ARC_STATUS
|
||||
DiskClose(ULONG FileId)
|
||||
{
|
||||
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
||||
|
||||
|
@ -53,7 +59,9 @@ static ARC_STATUS DiskClose(ULONG FileId)
|
|||
return ESUCCESS;
|
||||
}
|
||||
|
||||
static ARC_STATUS DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
|
||||
// static
|
||||
ARC_STATUS
|
||||
DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
|
||||
{
|
||||
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
||||
|
||||
|
@ -64,7 +72,8 @@ static ARC_STATUS DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Informat
|
|||
return ESUCCESS;
|
||||
}
|
||||
|
||||
static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
||||
static ARC_STATUS
|
||||
DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
||||
{
|
||||
DISKCONTEXT* Context;
|
||||
UCHAR DriveNumber;
|
||||
|
@ -84,9 +93,12 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
|||
}
|
||||
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 */
|
||||
/*
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
@ -94,13 +106,21 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
|||
{
|
||||
if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
|
||||
return EINVAL;
|
||||
|
||||
SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
|
||||
SectorCount = PartitionTableEntry.PartitionSectorCount;
|
||||
}
|
||||
#if 0 // FIXME: Investigate
|
||||
else
|
||||
{
|
||||
SectorCount = 0; /* FIXME */
|
||||
}
|
||||
#endif
|
||||
|
||||
Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
|
||||
if (!Context)
|
||||
return ENOMEM;
|
||||
|
||||
Context->DriveNumber = DriveNumber;
|
||||
Context->SectorSize = SectorSize;
|
||||
Context->SectorOffset = SectorOffset;
|
||||
|
@ -111,7 +131,9 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
|||
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);
|
||||
UCHAR* Ptr = (UCHAR*)Buffer;
|
||||
|
@ -123,7 +145,7 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
|||
MaxSectors = DiskReadBufferSize / Context->SectorSize;
|
||||
SectorOffset = Context->SectorNumber + Context->SectorOffset;
|
||||
|
||||
ret = 1;
|
||||
ret = TRUE;
|
||||
|
||||
while (TotalSectors)
|
||||
{
|
||||
|
@ -131,11 +153,10 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
|||
if (ReadSectors > MaxSectors)
|
||||
ReadSectors = MaxSectors;
|
||||
|
||||
ret = MachDiskReadLogicalSectors(
|
||||
Context->DriveNumber,
|
||||
SectorOffset,
|
||||
ReadSectors,
|
||||
DiskReadBuffer);
|
||||
ret = MachDiskReadLogicalSectors(Context->DriveNumber,
|
||||
SectorOffset,
|
||||
ReadSectors,
|
||||
DiskReadBuffer);
|
||||
if (!ret)
|
||||
break;
|
||||
|
||||
|
@ -156,7 +177,9 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
|||
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);
|
||||
|
||||
|
@ -169,7 +192,8 @@ static ARC_STATUS DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekM
|
|||
return ESUCCESS;
|
||||
}
|
||||
|
||||
static const DEVVTBL DiskVtbl = {
|
||||
static const DEVVTBL DiskVtbl =
|
||||
{
|
||||
DiskClose,
|
||||
DiskGetFileInformation,
|
||||
DiskOpen,
|
||||
|
@ -177,6 +201,7 @@ static const DEVVTBL DiskVtbl = {
|
|||
DiskSeek,
|
||||
};
|
||||
|
||||
|
||||
PCHAR
|
||||
GetHarddiskIdentifier(
|
||||
UCHAR DriveNumber)
|
||||
|
@ -264,14 +289,13 @@ GetHarddiskInformation(
|
|||
Identifier[15] = Hex[(Signature >> 4) & 0x0F];
|
||||
Identifier[16] = Hex[Signature & 0x0F];
|
||||
Identifier[17] = '-';
|
||||
Identifier[18] = 'A';
|
||||
Identifier[18] = 'A'; // FIXME: Not always 'A' ...
|
||||
Identifier[19] = 0;
|
||||
TRACE("Identifier: %s\n", Identifier);
|
||||
}
|
||||
|
||||
|
||||
BOOLEAN
|
||||
HwInitializeBiosDisks(VOID)
|
||||
PcInitializeBootDevices(VOID)
|
||||
{
|
||||
UCHAR DiskCount, DriveNumber;
|
||||
ULONG i;
|
||||
|
@ -314,9 +338,11 @@ HwInitializeBiosDisks(VOID)
|
|||
|
||||
DiskCount++;
|
||||
DriveNumber++;
|
||||
memset(DiskReadBuffer, 0xcd, 512);
|
||||
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
|
||||
}
|
||||
DiskReportError(TRUE);
|
||||
TRACE("BIOS reports %d harddisk%s\n",
|
||||
(int)DiskCount, (DiskCount == 1) ? "" : "s");
|
||||
|
||||
/* Get the drive we're booting from */
|
||||
MachDiskGetBootPath(BootPath, sizeof(BootPath));
|
||||
|
@ -366,5 +392,5 @@ HwInitializeBiosDisks(VOID)
|
|||
TRACE("BIOS reports %d harddisk%s\n",
|
||||
(int)DiskCount, (DiskCount == 1) ? "": "s");
|
||||
|
||||
return DiskCount != 0;
|
||||
return (DiskCount != 0);
|
||||
}
|
||||
|
|
|
@ -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
|
@ -18,53 +18,513 @@
|
|||
|
||||
#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
|
||||
XboxMachInit(const char *CmdLine)
|
||||
{
|
||||
/* Set LEDs to red before anything is initialized */
|
||||
XboxSetLED("rrrr");
|
||||
/* Set LEDs to red before anything is initialized */
|
||||
XboxSetLED("rrrr");
|
||||
|
||||
/* Initialize our stuff */
|
||||
XboxMemInit();
|
||||
XboxVideoInit();
|
||||
/* Initialize our stuff */
|
||||
XboxMemInit();
|
||||
XboxVideoInit();
|
||||
|
||||
/* Setup vtbl */
|
||||
MachVtbl.ConsPutChar = XboxConsPutChar;
|
||||
MachVtbl.ConsKbHit = XboxConsKbHit;
|
||||
MachVtbl.ConsGetCh = XboxConsGetCh;
|
||||
MachVtbl.VideoClearScreen = XboxVideoClearScreen;
|
||||
MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode;
|
||||
MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize;
|
||||
MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize;
|
||||
MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor;
|
||||
MachVtbl.VideoPutChar = XboxVideoPutChar;
|
||||
MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM;
|
||||
MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed;
|
||||
MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor;
|
||||
MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor;
|
||||
MachVtbl.VideoSync = XboxVideoSync;
|
||||
MachVtbl.Beep = PcBeep;
|
||||
MachVtbl.PrepareForReactOS = XboxPrepareForReactOS;
|
||||
MachVtbl.GetMemoryMap = XboxMemGetMemoryMap;
|
||||
MachVtbl.DiskGetBootPath = DiskGetBootPath;
|
||||
MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors;
|
||||
MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry;
|
||||
MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount;
|
||||
MachVtbl.GetTime = XboxGetTime;
|
||||
MachVtbl.InitializeBootDevices = XboxInitializeBootDevices;
|
||||
MachVtbl.HwDetect = XboxHwDetect;
|
||||
MachVtbl.HwIdle = XboxHwIdle;
|
||||
/* Setup vtbl */
|
||||
MachVtbl.ConsPutChar = XboxConsPutChar;
|
||||
MachVtbl.ConsKbHit = XboxConsKbHit;
|
||||
MachVtbl.ConsGetCh = XboxConsGetCh;
|
||||
MachVtbl.VideoClearScreen = XboxVideoClearScreen;
|
||||
MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode;
|
||||
MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize;
|
||||
MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize;
|
||||
MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor;
|
||||
MachVtbl.VideoPutChar = XboxVideoPutChar;
|
||||
MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM;
|
||||
MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed;
|
||||
MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor;
|
||||
MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor;
|
||||
MachVtbl.VideoSync = XboxVideoSync;
|
||||
MachVtbl.Beep = PcBeep;
|
||||
MachVtbl.PrepareForReactOS = XboxPrepareForReactOS;
|
||||
MachVtbl.GetMemoryMap = XboxMemGetMemoryMap;
|
||||
MachVtbl.DiskGetBootPath = DiskGetBootPath;
|
||||
MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors;
|
||||
MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry;
|
||||
MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount;
|
||||
MachVtbl.GetTime = XboxGetTime;
|
||||
MachVtbl.InitializeBootDevices = PcInitializeBootDevices;
|
||||
MachVtbl.HwDetect = XboxHwDetect;
|
||||
MachVtbl.HwIdle = XboxHwIdle;
|
||||
|
||||
/* Set LEDs to orange after init */
|
||||
XboxSetLED("oooo");
|
||||
/* Set LEDs to orange after init */
|
||||
XboxSetLED("oooo");
|
||||
}
|
||||
|
||||
VOID
|
||||
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);
|
||||
DiskStopFloppyMotor();
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
|
||||
#include <freeldr.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
DBG_DEFAULT_CHANNEL(DISK);
|
||||
|
@ -25,41 +27,40 @@ DBG_DEFAULT_CHANNEL(DISK);
|
|||
#include <pshpack2.h>
|
||||
typedef struct
|
||||
{
|
||||
UCHAR PacketSize; // 00h - Size of packet (10h or 18h)
|
||||
UCHAR Reserved; // 01h - Reserved (0)
|
||||
USHORT LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD)
|
||||
USHORT TransferBufferOffset; // 04h - Transfer buffer offset (seg:off)
|
||||
USHORT TransferBufferSegment; // Transfer buffer segment (seg:off)
|
||||
ULONGLONG LBAStartBlock; // 08h - Starting absolute block number
|
||||
//ULONGLONG TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer
|
||||
// used if DWORD at 04h is FFFFh:FFFFh
|
||||
// Commented since some earlier BIOSes refuse to work with
|
||||
// such extended structure
|
||||
UCHAR PacketSize; // 00h - Size of packet (10h or 18h)
|
||||
UCHAR Reserved; // 01h - Reserved (0)
|
||||
USHORT LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD)
|
||||
USHORT TransferBufferOffset; // 04h - Transfer buffer offset (seg:off)
|
||||
USHORT TransferBufferSegment; // Transfer buffer segment (seg:off)
|
||||
ULONGLONG LBAStartBlock; // 08h - Starting absolute block number
|
||||
// ULONGLONG TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer
|
||||
// used if DWORD at 04h is FFFFh:FFFFh
|
||||
// Commented since some earlier BIOSes refuse to work with
|
||||
// such extended structure
|
||||
} I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET;
|
||||
#include <poppack.h>
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FUNCTIONS
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
static BOOLEAN PcDiskResetController(UCHAR DriveNumber)
|
||||
BOOLEAN DiskResetController(UCHAR DriveNumber)
|
||||
{
|
||||
REGS RegsIn;
|
||||
REGS RegsOut;
|
||||
REGS RegsIn, 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
|
||||
// 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
|
||||
/*
|
||||
* 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
|
||||
/* Reset the disk controller */
|
||||
Int386(0x13, &RegsIn, &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)
|
||||
{
|
||||
REGS RegsIn;
|
||||
REGS RegsOut;
|
||||
ULONG RetryCount;
|
||||
PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER);
|
||||
REGS RegsIn, RegsOut;
|
||||
ULONG RetryCount;
|
||||
PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER);
|
||||
|
||||
TRACE("PcDiskReadLogicalSectorsLBA() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer);
|
||||
ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
|
||||
|
||||
// BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
|
||||
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;
|
||||
|
||||
// Setup disk address packet
|
||||
RtlZeroMemory(Packet, sizeof(I386_DISK_ADDRESS_PACKET));
|
||||
Packet->PacketSize = sizeof(I386_DISK_ADDRESS_PACKET);
|
||||
/* Setup disk address packet */
|
||||
RtlZeroMemory(Packet, sizeof(*Packet));
|
||||
Packet->PacketSize = sizeof(*Packet);
|
||||
Packet->Reserved = 0;
|
||||
Packet->LBABlockCount = (USHORT)SectorCount;
|
||||
ASSERT(Packet->LBABlockCount == SectorCount);
|
||||
|
@ -91,39 +85,45 @@ static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNu
|
|||
Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4);
|
||||
Packet->LBAStartBlock = SectorNumber;
|
||||
|
||||
// BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
|
||||
// Return:
|
||||
// CF clear if successful
|
||||
// AH = 00h
|
||||
// CF set on error
|
||||
// AH = error code
|
||||
// disk address packet's block count field set to the
|
||||
// number of blocks successfully transferred
|
||||
/*
|
||||
* BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
|
||||
* Return:
|
||||
* CF clear if successful
|
||||
* AH = 00h
|
||||
* CF set on error
|
||||
* AH = error code
|
||||
* 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++)
|
||||
{
|
||||
Int386(0x13, &RegsIn, &RegsOut);
|
||||
|
||||
// If it worked return TRUE
|
||||
/* If it worked return TRUE */
|
||||
if (INT386_SUCCESS(RegsOut))
|
||||
{
|
||||
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)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
// If it failed then do the next retry
|
||||
/* If it failed then do the next retry */
|
||||
else
|
||||
{
|
||||
PcDiskResetController(DriveNumber);
|
||||
DiskResetController(DriveNumber);
|
||||
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);
|
||||
|
||||
return FALSE;
|
||||
|
@ -131,20 +131,17 @@ static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNu
|
|||
|
||||
static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||
{
|
||||
UCHAR PhysicalSector;
|
||||
UCHAR PhysicalHead;
|
||||
ULONG PhysicalTrack;
|
||||
GEOMETRY DriveGeometry;
|
||||
ULONG NumberOfSectorsToRead;
|
||||
REGS RegsIn;
|
||||
REGS RegsOut;
|
||||
ULONG RetryCount;
|
||||
UCHAR PhysicalSector;
|
||||
UCHAR PhysicalHead;
|
||||
ULONG PhysicalTrack;
|
||||
GEOMETRY DriveGeometry;
|
||||
ULONG NumberOfSectorsToRead;
|
||||
REGS RegsIn, RegsOut;
|
||||
ULONG RetryCount;
|
||||
|
||||
TRACE("PcDiskReadLogicalSectorsCHS()\n");
|
||||
|
||||
//
|
||||
// Get the drive geometry
|
||||
//
|
||||
/* Get the drive geometry */
|
||||
if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
|
||||
DriveGeometry.Sectors == 0 ||
|
||||
DriveGeometry.Heads == 0)
|
||||
|
@ -154,18 +151,15 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
|||
|
||||
while (SectorCount)
|
||||
{
|
||||
|
||||
//
|
||||
// Calculate the physical disk offsets
|
||||
// Note: DriveGeometry.Sectors < 64
|
||||
//
|
||||
/*
|
||||
* Calculate the physical disk offsets.
|
||||
* Note: DriveGeometry.Sectors < 64
|
||||
*/
|
||||
PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors);
|
||||
PhysicalHead = (UCHAR)((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 (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
|
||||
|
@ -181,9 +175,7 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
|||
NumberOfSectorsToRead = SectorCount;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure the read is within the geometry boundaries
|
||||
//
|
||||
/* Make sure the read is within the geometry boundaries */
|
||||
if ((PhysicalHead >= DriveGeometry.Heads) ||
|
||||
(PhysicalTrack >= DriveGeometry.Cylinders) ||
|
||||
((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
|
||||
|
@ -193,22 +185,24 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
// BIOS Int 13h, function 2 - Read Disk Sectors
|
||||
// AH = 02h
|
||||
// AL = number of sectors to read (must be nonzero)
|
||||
// CH = low eight bits of cylinder number
|
||||
// CL = sector number 1-63 (bits 0-5)
|
||||
// high two bits of cylinder (bits 6-7, hard disk only)
|
||||
// DH = head number
|
||||
// DL = drive number (bit 7 set for hard disk)
|
||||
// ES:BX -> data buffer
|
||||
// Return:
|
||||
// CF set on error
|
||||
// if AH = 11h (corrected ECC error), AL = burst length
|
||||
// CF clear if successful
|
||||
// AH = status
|
||||
// AL = number of sectors transferred
|
||||
// (only valid if CF set for some BIOSes)
|
||||
/*
|
||||
* BIOS Int 13h, function 2 - Read Disk Sectors
|
||||
* AH = 02h
|
||||
* AL = number of sectors to read (must be nonzero)
|
||||
* CH = low eight bits of cylinder number
|
||||
* CL = sector number 1-63 (bits 0-5)
|
||||
* high two bits of cylinder (bits 6-7, hard disk only)
|
||||
* DH = head number
|
||||
* DL = drive number (bit 7 set for hard disk)
|
||||
* ES:BX -> data buffer
|
||||
* Return:
|
||||
* CF set on error
|
||||
* if AH = 11h (corrected ECC error), AL = burst length
|
||||
* CF clear if successful
|
||||
* AH = status
|
||||
* AL = number of sectors transferred
|
||||
* (only valid if CF set for some BIOSes)
|
||||
*/
|
||||
RegsIn.b.ah = 0x02;
|
||||
RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
|
||||
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.bx = ((ULONG_PTR)Buffer) & 0x0F;
|
||||
|
||||
//
|
||||
// Perform the read
|
||||
// Retry 3 times
|
||||
//
|
||||
/* Perform the read. Retry 3 times. */
|
||||
for (RetryCount=0; RetryCount<3; RetryCount++)
|
||||
{
|
||||
Int386(0x13, &RegsIn, &RegsOut);
|
||||
|
||||
// If it worked break out
|
||||
/* If it worked break out */
|
||||
if (INT386_SUCCESS(RegsOut))
|
||||
{
|
||||
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)
|
||||
{
|
||||
break;
|
||||
}
|
||||
// If it failed the do the next retry
|
||||
/* If it failed the do the next retry */
|
||||
else
|
||||
{
|
||||
PcDiskResetController(DriveNumber);
|
||||
|
||||
DiskResetController(DriveNumber);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// If we retried 3 times then fail
|
||||
/* If we retried 3 times then fail */
|
||||
if (RetryCount >= 3)
|
||||
{
|
||||
ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x\n", RegsOut.b.ah);
|
||||
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)
|
||||
// even if the sectors were read correctly. So instead
|
||||
// of checking the sector read count we will rely solely
|
||||
|
@ -266,122 +256,287 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
|
||||
{
|
||||
static UCHAR LastDriveNumber = 0xff;
|
||||
static BOOLEAN LastSupported;
|
||||
REGS RegsIn, RegsOut;
|
||||
|
||||
TRACE("DiskInt13ExtensionsSupported()\n");
|
||||
|
||||
if (DriveNumber == LastDriveNumber)
|
||||
{
|
||||
TRACE("Using cached value %s for drive 0x%x\n",
|
||||
LastSupported ? "TRUE" : "FALSE", DriveNumber);
|
||||
return LastSupported;
|
||||
}
|
||||
|
||||
/*
|
||||
* Some BIOSes report that extended disk access functions are not supported
|
||||
* when booting from a CD (e.g. Phoenix BIOS v6.00PG and Insyde BIOS shipping
|
||||
* with Intel Macs). Therefore we just return TRUE if we're booting from a CD -
|
||||
* we can assume that all El Torito capable BIOSes support INT 13 extensions.
|
||||
* We simply detect whether we're booting from CD by checking whether the drive
|
||||
* number is >= 0x8A. It's 0x90 on the Insyde BIOS, and 0x9F on most other BIOSes.
|
||||
*/
|
||||
if (DriveNumber >= 0x8A)
|
||||
{
|
||||
LastSupported = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
LastDriveNumber = DriveNumber;
|
||||
|
||||
/*
|
||||
* IBM/MS INT 13 Extensions - INSTALLATION CHECK
|
||||
* AH = 41h
|
||||
* BX = 55AAh
|
||||
* DL = drive (80h-FFh)
|
||||
* Return:
|
||||
* CF set on error (extensions not supported)
|
||||
* AH = 01h (invalid function)
|
||||
* CF clear if successful
|
||||
* BX = AA55h if installed
|
||||
* AH = major version of extensions
|
||||
* 01h = 1.x
|
||||
* 20h = 2.0 / EDD-1.0
|
||||
* 21h = 2.1 / EDD-1.1
|
||||
* 30h = EDD-3.0
|
||||
* AL = internal use
|
||||
* CX = API subset support bitmap
|
||||
* DH = extension version (v2.0+ ??? -- not present in 1.x)
|
||||
*
|
||||
* Bitfields for IBM/MS INT 13 Extensions API support bitmap
|
||||
* Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
||||
* Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
|
||||
* Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
|
||||
* extended drive parameter table is valid
|
||||
* Bits 3-15 reserved
|
||||
*/
|
||||
RegsIn.b.ah = 0x41;
|
||||
RegsIn.w.bx = 0x55AA;
|
||||
RegsIn.b.dl = DriveNumber;
|
||||
|
||||
/* Reset the disk controller */
|
||||
Int386(0x13, &RegsIn, &RegsOut);
|
||||
|
||||
if (!INT386_SUCCESS(RegsOut))
|
||||
{
|
||||
/* CF set on error (extensions not supported) */
|
||||
LastSupported = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (RegsOut.w.bx != 0xAA55)
|
||||
{
|
||||
/* BX = AA55h if installed */
|
||||
LastSupported = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (!(RegsOut.w.cx & 0x0001))
|
||||
{
|
||||
/*
|
||||
* CX = API subset support bitmap.
|
||||
* Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported.
|
||||
*/
|
||||
DbgPrint("Suspicious API subset support bitmap 0x%x on device 0x%lx\n",
|
||||
RegsOut.w.cx, DriveNumber);
|
||||
LastSupported = FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
LastSupported = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||
{
|
||||
BOOLEAN 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
|
||||
// If so then check to see if Int13 extensions work
|
||||
// If they do then use them, otherwise default back to BIOS calls
|
||||
//
|
||||
/*
|
||||
* Check to see if it is a fixed disk drive.
|
||||
* If so then check to see if Int13 extensions work.
|
||||
* If they do then use them, otherwise default back to BIOS calls.
|
||||
*/
|
||||
ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
|
||||
|
||||
if ((DriveNumber >= 0x80) && ExtensionsSupported)
|
||||
{
|
||||
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);
|
||||
}
|
||||
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 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
|
||||
PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
|
||||
{
|
||||
EXTENDED_GEOMETRY ExtGeometry;
|
||||
REGS RegsIn;
|
||||
REGS RegsOut;
|
||||
ULONG Cylinders;
|
||||
EXTENDED_GEOMETRY ExtGeometry;
|
||||
REGS RegsIn, RegsOut;
|
||||
ULONG Cylinders;
|
||||
|
||||
TRACE("DiskGetDriveGeometry()\n");
|
||||
TRACE("DiskGetDriveGeometry()\n");
|
||||
|
||||
/* Try to get the extended geometry first */
|
||||
ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
|
||||
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))
|
||||
/* Try to get the extended geometry first */
|
||||
ExtGeometry.Size = sizeof(ExtGeometry);
|
||||
if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
|
||||
{
|
||||
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;
|
||||
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 */
|
||||
/*
|
||||
* 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;
|
||||
|
||||
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
|
||||
PcDiskGetCacheableBlockCount(UCHAR DriveNumber)
|
||||
{
|
||||
GEOMETRY Geometry;
|
||||
GEOMETRY Geometry;
|
||||
|
||||
/* If LBA is supported then the block size will be 64 sectors (32k)
|
||||
* If not then the block size is the size of one track */
|
||||
if (DiskInt13ExtensionsSupported(DriveNumber))
|
||||
/* If LBA is supported then the block size will be 64 sectors (32k)
|
||||
* If not then the block size is the size of one track. */
|
||||
if (DiskInt13ExtensionsSupported(DriveNumber))
|
||||
{
|
||||
return 64;
|
||||
return 64;
|
||||
}
|
||||
/* Get the disk geometry
|
||||
* If this fails then we will just return 1 sector to be safe */
|
||||
else if (! PcDiskGetDriveGeometry(DriveNumber, &Geometry))
|
||||
/* Get the disk geometry. If this fails then we will
|
||||
* just return 1 sector to be safe. */
|
||||
else if (! PcDiskGetDriveGeometry(DriveNumber, &Geometry))
|
||||
{
|
||||
return 1;
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
return Geometry.Sectors;
|
||||
return Geometry.Sectors;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,22 +36,22 @@ DBG_DEFAULT_CHANNEL(DISK);
|
|||
|
||||
static struct
|
||||
{
|
||||
ULONG SectorCountBeforePartition;
|
||||
ULONG PartitionSectorCount;
|
||||
UCHAR SystemIndicator;
|
||||
ULONG SectorCountBeforePartition;
|
||||
ULONG PartitionSectorCount;
|
||||
UCHAR SystemIndicator;
|
||||
} XboxPartitions[] =
|
||||
{
|
||||
/* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */
|
||||
{ 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store, E: */
|
||||
{ 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */
|
||||
{ 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */
|
||||
{ 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */
|
||||
{ 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */
|
||||
/* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */
|
||||
{ 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store , E: */
|
||||
{ 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */
|
||||
{ 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */
|
||||
{ 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */
|
||||
{ 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */
|
||||
};
|
||||
|
||||
#define IDE_SECTOR_BUF_SZ 512
|
||||
#define IDE_MAX_POLL_RETRIES 100000
|
||||
#define IDE_MAX_BUSY_RETRIES 50000
|
||||
#define IDE_SECTOR_BUF_SZ 512
|
||||
#define IDE_MAX_POLL_RETRIES 100000
|
||||
#define IDE_MAX_BUSY_RETRIES 50000
|
||||
|
||||
/* Control Block offsets and masks */
|
||||
#define IDE_REG_ALT_STATUS 0x0000
|
||||
|
@ -111,131 +111,131 @@ static struct
|
|||
* Each macro takes an address of the command port block, and data
|
||||
*/
|
||||
#define IDEReadError(Address) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR)))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR)))
|
||||
#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) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT)))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT)))
|
||||
#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) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM)))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM)))
|
||||
#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) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW)))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW)))
|
||||
#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) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH)))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH)))
|
||||
#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) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD)))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD)))
|
||||
#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) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS)))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS)))
|
||||
#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) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address))))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address))))
|
||||
#define IDEWriteDMACommand(Address, Data) \
|
||||
(WRITE_PORT_UCHAR((PUCHAR)((Address)), (Data)))
|
||||
(WRITE_PORT_UCHAR((PUCHAR)((Address)), (Data)))
|
||||
#define IDEReadDMAStatus(Address) \
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + 2)))
|
||||
(READ_PORT_UCHAR((PUCHAR)((Address) + 2)))
|
||||
#define IDEWriteDMAStatus(Address, Data) \
|
||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + 2), (Data)))
|
||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + 2), (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
|
||||
*/
|
||||
#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) \
|
||||
(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) \
|
||||
(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) \
|
||||
(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) \
|
||||
(READ_PORT_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT)))
|
||||
(READ_PORT_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT)))
|
||||
|
||||
/*
|
||||
* Access macros for control registers
|
||||
* Each macro takes an address of the control port blank and data
|
||||
*/
|
||||
#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) \
|
||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data)))
|
||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data)))
|
||||
|
||||
/* IDE_DRIVE_IDENTIFY */
|
||||
|
||||
typedef struct _IDE_DRIVE_IDENTIFY
|
||||
{
|
||||
USHORT ConfigBits; /*00*/
|
||||
USHORT LogicalCyls; /*01*/
|
||||
USHORT Reserved02; /*02*/
|
||||
USHORT LogicalHeads; /*03*/
|
||||
USHORT BytesPerTrack; /*04*/
|
||||
USHORT BytesPerSector; /*05*/
|
||||
USHORT SectorsPerTrack; /*06*/
|
||||
UCHAR InterSectorGap; /*07*/
|
||||
UCHAR InterSectorGapSize;
|
||||
UCHAR Reserved08H; /*08*/
|
||||
UCHAR BytesInPLO;
|
||||
USHORT VendorUniqueCnt; /*09*/
|
||||
char SerialNumber[20]; /*10*/
|
||||
USHORT ControllerType; /*20*/
|
||||
USHORT BufferSize; /*21*/
|
||||
USHORT ECCByteCnt; /*22*/
|
||||
char FirmwareRev[8]; /*23*/
|
||||
char ModelNumber[40]; /*27*/
|
||||
USHORT RWMultImplemented; /*47*/
|
||||
USHORT DWordIo; /*48*/
|
||||
USHORT Capabilities; /*49*/
|
||||
USHORT ConfigBits; /*00*/
|
||||
USHORT LogicalCyls; /*01*/
|
||||
USHORT Reserved02; /*02*/
|
||||
USHORT LogicalHeads; /*03*/
|
||||
USHORT BytesPerTrack; /*04*/
|
||||
USHORT BytesPerSector; /*05*/
|
||||
USHORT SectorsPerTrack; /*06*/
|
||||
UCHAR InterSectorGap; /*07*/
|
||||
UCHAR InterSectorGapSize;
|
||||
UCHAR Reserved08H; /*08*/
|
||||
UCHAR BytesInPLO;
|
||||
USHORT VendorUniqueCnt; /*09*/
|
||||
UCHAR SerialNumber[20]; /*10*/
|
||||
USHORT ControllerType; /*20*/
|
||||
USHORT BufferSize; /*21*/
|
||||
USHORT ECCByteCnt; /*22*/
|
||||
UCHAR FirmwareRev[8]; /*23*/
|
||||
UCHAR ModelNumber[40]; /*27*/
|
||||
USHORT RWMultImplemented; /*47*/
|
||||
USHORT DWordIo; /*48*/
|
||||
USHORT Capabilities; /*49*/
|
||||
#define IDE_DRID_STBY_SUPPORTED 0x2000
|
||||
#define IDE_DRID_IORDY_SUPPORTED 0x0800
|
||||
#define IDE_DRID_IORDY_DISABLE 0x0400
|
||||
#define IDE_DRID_LBA_SUPPORTED 0x0200
|
||||
#define IDE_DRID_DMA_SUPPORTED 0x0100
|
||||
USHORT Reserved50; /*50*/
|
||||
USHORT MinPIOTransTime; /*51*/
|
||||
USHORT MinDMATransTime; /*52*/
|
||||
USHORT TMFieldsValid; /*53*/
|
||||
USHORT TMCylinders; /*54*/
|
||||
USHORT TMHeads; /*55*/
|
||||
USHORT TMSectorsPerTrk; /*56*/
|
||||
USHORT TMCapacityLo; /*57*/
|
||||
USHORT TMCapacityHi; /*58*/
|
||||
USHORT RWMultCurrent; /*59*/
|
||||
USHORT TMSectorCountLo; /*60*/
|
||||
USHORT TMSectorCountHi; /*61*/
|
||||
USHORT DmaModes; /*62*/
|
||||
USHORT MultiDmaModes; /*63*/
|
||||
USHORT Reserved64[5]; /*64*/
|
||||
USHORT Reserved69[2]; /*69*/
|
||||
USHORT Reserved71[4]; /*71*/
|
||||
USHORT MaxQueueDepth; /*75*/
|
||||
USHORT Reserved76[4]; /*76*/
|
||||
USHORT MajorRevision; /*80*/
|
||||
USHORT MinorRevision; /*81*/
|
||||
USHORT SupportedFeatures82; /*82*/
|
||||
USHORT SupportedFeatures83; /*83*/
|
||||
USHORT SupportedFeatures84; /*84*/
|
||||
USHORT EnabledFeatures85; /*85*/
|
||||
USHORT EnabledFeatures86; /*86*/
|
||||
USHORT EnabledFeatures87; /*87*/
|
||||
USHORT UltraDmaModes; /*88*/
|
||||
USHORT Reserved89[11]; /*89*/
|
||||
USHORT Max48BitAddress[4]; /*100*/
|
||||
USHORT Reserved104[151]; /*104*/
|
||||
USHORT Checksum; /*255*/
|
||||
USHORT Reserved50; /*50*/
|
||||
USHORT MinPIOTransTime; /*51*/
|
||||
USHORT MinDMATransTime; /*52*/
|
||||
USHORT TMFieldsValid; /*53*/
|
||||
USHORT TMCylinders; /*54*/
|
||||
USHORT TMHeads; /*55*/
|
||||
USHORT TMSectorsPerTrk; /*56*/
|
||||
USHORT TMCapacityLo; /*57*/
|
||||
USHORT TMCapacityHi; /*58*/
|
||||
USHORT RWMultCurrent; /*59*/
|
||||
USHORT TMSectorCountLo; /*60*/
|
||||
USHORT TMSectorCountHi; /*61*/
|
||||
USHORT DmaModes; /*62*/
|
||||
USHORT MultiDmaModes; /*63*/
|
||||
USHORT Reserved64[5]; /*64*/
|
||||
USHORT Reserved69[2]; /*69*/
|
||||
USHORT Reserved71[4]; /*71*/
|
||||
USHORT MaxQueueDepth; /*75*/
|
||||
USHORT Reserved76[4]; /*76*/
|
||||
USHORT MajorRevision; /*80*/
|
||||
USHORT MinorRevision; /*81*/
|
||||
USHORT SupportedFeatures82; /*82*/
|
||||
USHORT SupportedFeatures83; /*83*/
|
||||
USHORT SupportedFeatures84; /*84*/
|
||||
USHORT EnabledFeatures85; /*85*/
|
||||
USHORT EnabledFeatures86; /*86*/
|
||||
USHORT EnabledFeatures87; /*87*/
|
||||
USHORT UltraDmaModes; /*88*/
|
||||
USHORT Reserved89[11]; /*89*/
|
||||
USHORT Max48BitAddress[4]; /*100*/
|
||||
USHORT Reserved104[151]; /*104*/
|
||||
USHORT Checksum; /*255*/
|
||||
} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
|
||||
|
||||
/* XboxDiskPolledRead
|
||||
|
@ -247,21 +247,20 @@ typedef struct _IDE_DRIVE_IDENTIFY
|
|||
* PASSIVE_LEVEL
|
||||
*
|
||||
* ARGUMENTS:
|
||||
* ULONG CommandPort Address of command port for drive
|
||||
* ULONG ControlPort Address of control port for drive
|
||||
* UCHAR PreComp Value to write to precomp register
|
||||
* UCHAR SectorCnt Value to write to sectorCnt register
|
||||
* UCHAR SectorNum Value to write to sectorNum register
|
||||
* UCHAR CylinderLow Value to write to CylinderLow register
|
||||
* UCHAR CylinderHigh Value to write to CylinderHigh register
|
||||
* UCHAR DrvHead Value to write to Drive/Head register
|
||||
* UCHAR Command Value to write to Command register
|
||||
* PVOID Buffer Buffer for output data
|
||||
* ULONG CommandPort Address of command port for drive
|
||||
* ULONG ControlPort Address of control port for drive
|
||||
* UCHAR PreComp Value to write to precomp register
|
||||
* UCHAR SectorCnt Value to write to sectorCnt register
|
||||
* UCHAR SectorNum Value to write to sectorNum register
|
||||
* UCHAR CylinderLow Value to write to CylinderLow register
|
||||
* UCHAR CylinderHigh Value to write to CylinderHigh register
|
||||
* UCHAR DrvHead Value to write to Drive/Head register
|
||||
* UCHAR Command Value to write to Command register
|
||||
* PVOID Buffer Buffer for output data
|
||||
*
|
||||
* RETURNS:
|
||||
* BOOLEAN: TRUE success, FALSE error
|
||||
*/
|
||||
|
||||
static BOOLEAN
|
||||
XboxDiskPolledRead(ULONG CommandPort,
|
||||
ULONG ControlPort,
|
||||
|
@ -274,300 +273,296 @@ XboxDiskPolledRead(ULONG CommandPort,
|
|||
UCHAR Command,
|
||||
PVOID Buffer)
|
||||
{
|
||||
ULONG SectorCount = 0;
|
||||
ULONG RetryCount;
|
||||
BOOLEAN Junk = FALSE;
|
||||
UCHAR Status;
|
||||
ULONG SectorCount = 0;
|
||||
ULONG RetryCount;
|
||||
BOOLEAN Junk = FALSE;
|
||||
UCHAR Status;
|
||||
|
||||
/* Wait for BUSY to clear */
|
||||
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
|
||||
/* Wait for BUSY to clear */
|
||||
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
|
||||
{
|
||||
Status = IDEReadStatus(CommandPort);
|
||||
if (!(Status & IDE_SR_BUSY))
|
||||
Status = IDEReadStatus(CommandPort);
|
||||
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;
|
||||
}
|
||||
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)
|
||||
if (Status & IDE_SR_ERR)
|
||||
{
|
||||
TRACE("Buffer size exceeded!\n");
|
||||
Junk = TRUE;
|
||||
IDEWriteDriveControl(ControlPort, 0);
|
||||
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
|
||||
XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||
{
|
||||
ULONG StartSector;
|
||||
UCHAR Count;
|
||||
ULONG StartSector;
|
||||
UCHAR Count;
|
||||
|
||||
if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f))
|
||||
if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f))
|
||||
{
|
||||
/* Xbox has only 1 IDE controller and no floppy */
|
||||
WARN("Invalid drive number\n");
|
||||
return FALSE;
|
||||
/* Xbox has only 1 IDE controller and no floppy */
|
||||
WARN("Invalid drive number\n");
|
||||
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");
|
||||
return FALSE;
|
||||
FIXME("48bit LBA required but not implemented\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
StartSector = (ULONG) SectorNumber;
|
||||
while (0 < SectorCount)
|
||||
StartSector = (ULONG) SectorNumber;
|
||||
while (0 < SectorCount)
|
||||
{
|
||||
Count = (SectorCount <= 255 ? (UCHAR)SectorCount : 255);
|
||||
if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
|
||||
XBOX_IDE_CONTROL_PORT,
|
||||
0, Count,
|
||||
StartSector & 0xff,
|
||||
(StartSector >> 8) & 0xff,
|
||||
(StartSector >> 16) & 0xff,
|
||||
((StartSector >> 24) & 0x0f) | IDE_DH_LBA |
|
||||
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
|
||||
IDE_CMD_READ,
|
||||
Count = (SectorCount <= 255 ? (UCHAR)SectorCount : 255);
|
||||
if (!XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
|
||||
XBOX_IDE_CONTROL_PORT,
|
||||
0, Count,
|
||||
StartSector & 0xff,
|
||||
(StartSector >> 8) & 0xff,
|
||||
(StartSector >> 16) & 0xff,
|
||||
((StartSector >> 24) & 0x0f) | IDE_DH_LBA |
|
||||
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
|
||||
IDE_CMD_READ,
|
||||
Buffer))
|
||||
{
|
||||
return FALSE;
|
||||
return FALSE;
|
||||
}
|
||||
SectorCount -= Count;
|
||||
Buffer = (PVOID) ((PCHAR) Buffer + Count * IDE_SECTOR_BUF_SZ);
|
||||
SectorCount -= Count;
|
||||
Buffer = (PVOID) ((PCHAR) Buffer + Count * IDE_SECTOR_BUF_SZ);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
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 */
|
||||
|
||||
if (1 <= PartitionNumber && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) &&
|
||||
MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData))
|
||||
/*
|
||||
* 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 (*((PULONG) SectorData) == XBOX_SIGNATURE)
|
||||
if (*((PULONG) SectorData) == XBOX_SIGNATURE)
|
||||
{
|
||||
memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY));
|
||||
PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator;
|
||||
PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition;
|
||||
PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount;
|
||||
return TRUE;
|
||||
memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY));
|
||||
PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator;
|
||||
PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition;
|
||||
PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
/* No magic Xbox partitions. Maybe there's a MBR */
|
||||
return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry);
|
||||
/* No magic Xbox partitions. Maybe there's a MBR */
|
||||
return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry);
|
||||
}
|
||||
|
||||
BOOLEAN
|
||||
XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
|
||||
{
|
||||
IDE_DRIVE_IDENTIFY DrvParms;
|
||||
ULONG i;
|
||||
BOOLEAN Atapi;
|
||||
IDE_DRIVE_IDENTIFY DrvParms;
|
||||
ULONG i;
|
||||
BOOLEAN Atapi;
|
||||
|
||||
Atapi = FALSE; /* FIXME */
|
||||
/* Get the Drive Identify block from drive or die */
|
||||
if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
|
||||
XBOX_IDE_CONTROL_PORT,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
|
||||
(Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
|
||||
(PUCHAR) &DrvParms))
|
||||
Atapi = FALSE; /* FIXME */
|
||||
/* Get the Drive Identify block from drive or die */
|
||||
if (!XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
|
||||
XBOX_IDE_CONTROL_PORT,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
|
||||
(Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
|
||||
(PUCHAR) &DrvParms))
|
||||
{
|
||||
ERR("XboxDiskPolledRead() failed\n");
|
||||
return FALSE;
|
||||
ERR("XboxDiskPolledRead() failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
Geometry->Cylinders = DrvParms.LogicalCyls;
|
||||
Geometry->Heads = DrvParms.LogicalHeads;
|
||||
Geometry->Sectors = DrvParms.SectorsPerTrack;
|
||||
Geometry->Cylinders = DrvParms.LogicalCyls;
|
||||
Geometry->Heads = DrvParms.LogicalHeads;
|
||||
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 */
|
||||
Geometry->BytesPerSector = 512;
|
||||
/* LBA ATA drives always have a sector size of 512 */
|
||||
Geometry->BytesPerSector = 512;
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
TRACE("BytesPerSector %d\n", DrvParms.BytesPerSector);
|
||||
if (DrvParms.BytesPerSector == 0)
|
||||
TRACE("BytesPerSector %d\n", DrvParms.BytesPerSector);
|
||||
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;
|
||||
break;
|
||||
Geometry->BytesPerSector = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
TRACE("Cylinders %d\n", Geometry->Cylinders);
|
||||
TRACE("Heads %d\n", Geometry->Heads);
|
||||
TRACE("Sectors %d\n", Geometry->Sectors);
|
||||
TRACE("BytesPerSector %d\n", Geometry->BytesPerSector);
|
||||
TRACE("Cylinders %d\n", Geometry->Cylinders);
|
||||
TRACE("Heads %d\n", Geometry->Heads);
|
||||
TRACE("Sectors %d\n", Geometry->Sectors);
|
||||
TRACE("BytesPerSector %d\n", Geometry->BytesPerSector);
|
||||
|
||||
return TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
ULONG
|
||||
XboxDiskGetCacheableBlockCount(UCHAR DriveNumber)
|
||||
{
|
||||
/* 64 seems a nice number, it is used by the machpc code for LBA devices */
|
||||
return 64;
|
||||
/* 64 seems a nice number, it is used by the machpc code for LBA devices */
|
||||
return 64;
|
||||
}
|
||||
|
||||
/* EOF */
|
||||
|
|
|
@ -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 */
|
|
@ -19,29 +19,30 @@
|
|||
|
||||
#ifndef _M_ARM
|
||||
#include <freeldr.h>
|
||||
|
||||
#define NDEBUG
|
||||
#include <debug.h>
|
||||
|
||||
DBG_DEFAULT_CHANNEL(DISK);
|
||||
|
||||
static BOOLEAN bReportError = TRUE;
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// FUNCTIONS
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
VOID DiskReportError (BOOLEAN bError)
|
||||
VOID DiskReportError(BOOLEAN bError)
|
||||
{
|
||||
bReportError = bError;
|
||||
}
|
||||
|
||||
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
|
||||
{
|
||||
CHAR ErrorCodeString[200];
|
||||
CHAR ErrorCodeString[200];
|
||||
|
||||
if (bReportError == FALSE)
|
||||
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);
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
// Hard disks use drive numbers >= 0x80
|
||||
// So if the drive number indicates a hard disk
|
||||
// then return FALSE
|
||||
// 0x49 is our magic ramdisk drive, so return FALSE for that too
|
||||
/*
|
||||
* Hard disks use drive numbers >= 0x80 . So if the drive number
|
||||
* indicates a hard disk then return FALSE.
|
||||
* 0x49 is our magic ramdisk drive, so return FALSE for that too.
|
||||
*/
|
||||
if ((DriveNumber >= 0x80) || (DriveNumber == 0x49))
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
// Drive is a floppy diskette so return TRUE
|
||||
/* The drive is a floppy diskette so return TRUE */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
@ -191,10 +188,4 @@ DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
|
|||
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
|
||||
|
|
|
@ -49,6 +49,9 @@ VOID PcPrepareForReactOS(IN BOOLEAN Setup);
|
|||
|
||||
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 PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer);
|
||||
BOOLEAN PcDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
|
||||
typedef struct _GEOMETRY
|
||||
{
|
||||
ULONG Cylinders; // Number of cylinders on the disk
|
||||
ULONG Heads; // Number of heads on the disk
|
||||
ULONG Sectors; // Number of sectors per track
|
||||
ULONG BytesPerSector; // Number of bytes per sector
|
||||
ULONG Cylinders; // Number of cylinders on the disk
|
||||
ULONG Heads; // Number of heads on the disk
|
||||
ULONG Sectors; // Number of sectors per track
|
||||
ULONG BytesPerSector; // Number of bytes per sector
|
||||
|
||||
} GEOMETRY, *PGEOMETRY;
|
||||
|
||||
|
@ -36,14 +36,15 @@ typedef struct _GEOMETRY
|
|||
#include <pshpack1.h>
|
||||
typedef struct _EXTENDED_GEOMETRY
|
||||
{
|
||||
USHORT Size;
|
||||
USHORT Flags;
|
||||
ULONG Cylinders;
|
||||
ULONG Heads;
|
||||
ULONG SectorsPerTrack;
|
||||
ULONGLONG Sectors;
|
||||
USHORT BytesPerSector;
|
||||
ULONG PDPTE;
|
||||
USHORT Size;
|
||||
USHORT Flags;
|
||||
ULONG Cylinders;
|
||||
ULONG Heads;
|
||||
ULONG SectorsPerTrack;
|
||||
ULONGLONG Sectors;
|
||||
USHORT BytesPerSector;
|
||||
ULONG PDPTE;
|
||||
|
||||
} EXTENDED_GEOMETRY, *PEXTENDED_GEOMETRY;
|
||||
|
||||
//
|
||||
|
@ -51,16 +52,17 @@ typedef struct _EXTENDED_GEOMETRY
|
|||
//
|
||||
typedef struct _PARTITION_TABLE_ENTRY
|
||||
{
|
||||
UCHAR BootIndicator; // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only)
|
||||
UCHAR StartHead; // Beginning head number
|
||||
UCHAR StartSector; // Beginning sector (2 high bits of cylinder #)
|
||||
UCHAR StartCylinder; // Beginning cylinder# (low order bits of cylinder #)
|
||||
UCHAR SystemIndicator; // System indicator
|
||||
UCHAR EndHead; // Ending head number
|
||||
UCHAR EndSector; // Ending sector (2 high bits of cylinder #)
|
||||
UCHAR EndCylinder; // Ending cylinder# (low order bits of cylinder #)
|
||||
ULONG SectorCountBeforePartition; // Number of sectors preceding the partition
|
||||
ULONG PartitionSectorCount; // Number of sectors in the partition
|
||||
UCHAR BootIndicator; // 0x00 - non-bootable partition,
|
||||
// 0x80 - bootable partition (one partition only)
|
||||
UCHAR StartHead; // Beginning head number
|
||||
UCHAR StartSector; // Beginning sector (2 high bits of cylinder #)
|
||||
UCHAR StartCylinder; // Beginning cylinder# (low order bits of cylinder #)
|
||||
UCHAR SystemIndicator; // System indicator
|
||||
UCHAR EndHead; // Ending head number
|
||||
UCHAR EndSector; // Ending sector (2 high bits of cylinder #)
|
||||
UCHAR EndCylinder; // Ending cylinder# (low order bits of cylinder #)
|
||||
ULONG SectorCountBeforePartition; // Number of sectors preceding the partition
|
||||
ULONG PartitionSectorCount; // Number of sectors in the partition
|
||||
|
||||
} PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY;
|
||||
|
||||
|
@ -69,11 +71,11 @@ typedef struct _PARTITION_TABLE_ENTRY
|
|||
//
|
||||
typedef struct _MASTER_BOOT_RECORD
|
||||
{
|
||||
UCHAR MasterBootRecordCodeAndData[0x1b8]; /* 0x000 */
|
||||
ULONG Signature; /* 0x1B8 */
|
||||
USHORT Reserved; /* 0x1BC */
|
||||
PARTITION_TABLE_ENTRY PartitionTable[4]; /* 0x1BE */
|
||||
USHORT MasterBootRecordMagic; /* 0x1FE */
|
||||
UCHAR MasterBootRecordCodeAndData[0x1b8]; /* 0x000 */
|
||||
ULONG Signature; /* 0x1B8 */
|
||||
USHORT Reserved; /* 0x1BC */
|
||||
PARTITION_TABLE_ENTRY PartitionTable[4]; /* 0x1BE */
|
||||
USHORT MasterBootRecordMagic; /* 0x1FE */
|
||||
|
||||
} MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD;
|
||||
#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)
|
||||
|
||||
BOOLEAN DiskResetController(UCHAR DriveNumber);
|
||||
BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber);
|
||||
//VOID DiskStopFloppyMotor(VOID);
|
||||
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize);
|
||||
|
||||
VOID DiskStopFloppyMotor(VOID);
|
||||
#endif // defined __i386__ || defined(_M_AMD64)
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -124,12 +121,10 @@ BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHOR
|
|||
// FreeLoader Disk Functions
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
VOID DiskReportError (BOOLEAN bError);
|
||||
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode);
|
||||
PCSTR DiskGetErrorCodeString(ULONG ErrorCode);
|
||||
BOOLEAN DiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); // Implemented in i386disk.c
|
||||
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
|
||||
VOID DiskStopFloppyMotor(VOID); // Implemented in i386disk.c
|
||||
VOID DiskReportError (BOOLEAN bError);
|
||||
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode);
|
||||
PCSTR DiskGetErrorCodeString(ULONG ErrorCode);
|
||||
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
|
||||
extern UCHAR FrldrBootDrive;
|
||||
extern ULONG FrldrBootPartition;
|
||||
extern PVOID DiskReadBuffer;
|
||||
|
@ -143,10 +138,13 @@ BOOLEAN DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size);
|
|||
// Fixed Disk Partition Management Functions
|
||||
//
|
||||
///////////////////////////////////////////////////////////////////////////////////////
|
||||
BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, ULONG *ActivePartition);
|
||||
BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, 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 DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord);
|
||||
BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, ULONG *ActivePartition);
|
||||
BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, 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 DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord);
|
||||
|
||||
/*
|
||||
* SCSI support (disk/scsiport.c)
|
||||
*/
|
||||
ULONG LoadBootDeviceDriver(VOID);
|
||||
|
|
Loading…
Reference in a new issue