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/hwdisk.c
|
||||||
arch/i386/hwpci.c
|
arch/i386/hwpci.c
|
||||||
arch/i386/i386bug.c
|
arch/i386/i386bug.c
|
||||||
arch/i386/i386disk.c
|
|
||||||
arch/i386/i386idt.c
|
arch/i386/i386idt.c
|
||||||
arch/i386/i386rtl.c
|
arch/i386/i386rtl.c
|
||||||
arch/i386/i386vid.c
|
arch/i386/i386vid.c
|
||||||
|
@ -137,7 +136,6 @@ if(ARCH STREQUAL "i386")
|
||||||
arch/i386/xboxcons.c
|
arch/i386/xboxcons.c
|
||||||
arch/i386/xboxdisk.c
|
arch/i386/xboxdisk.c
|
||||||
arch/i386/xboxfont.c
|
arch/i386/xboxfont.c
|
||||||
arch/i386/xboxhw.c
|
|
||||||
arch/i386/xboxi2c.c
|
arch/i386/xboxi2c.c
|
||||||
arch/i386/xboxmem.c
|
arch/i386/xboxmem.c
|
||||||
arch/i386/xboxrtc.c
|
arch/i386/xboxrtc.c
|
||||||
|
@ -170,7 +168,6 @@ elseif(ARCH STREQUAL "amd64")
|
||||||
arch/i386/hwpci.c
|
arch/i386/hwpci.c
|
||||||
arch/i386/i386bug.c
|
arch/i386/i386bug.c
|
||||||
arch/i386/i386rtl.c
|
arch/i386/i386rtl.c
|
||||||
arch/i386/i386disk.c
|
|
||||||
arch/i386/i386vid.c
|
arch/i386/i386vid.c
|
||||||
arch/i386/machpc.c
|
arch/i386/machpc.c
|
||||||
arch/i386/pccons.c
|
arch/i386/pccons.c
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -39,13 +39,19 @@ extern ULONG reactos_disk_count;
|
||||||
extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[];
|
extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[];
|
||||||
|
|
||||||
static CHAR Hex[] = "0123456789abcdef";
|
static CHAR Hex[] = "0123456789abcdef";
|
||||||
|
|
||||||
UCHAR PcBiosDiskCount = 0;
|
UCHAR PcBiosDiskCount = 0;
|
||||||
CHAR PcDiskIdentifier[32][20];
|
static CHAR PcDiskIdentifier[32][20];
|
||||||
|
|
||||||
PVOID DiskReadBuffer;
|
PVOID DiskReadBuffer;
|
||||||
SIZE_T DiskReadBufferSize;
|
SIZE_T DiskReadBufferSize;
|
||||||
|
|
||||||
|
|
||||||
static ARC_STATUS DiskClose(ULONG FileId)
|
/* FUNCTIONS *****************************************************************/
|
||||||
|
|
||||||
|
// static
|
||||||
|
ARC_STATUS
|
||||||
|
DiskClose(ULONG FileId)
|
||||||
{
|
{
|
||||||
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
||||||
|
|
||||||
|
@ -53,7 +59,9 @@ static ARC_STATUS DiskClose(ULONG FileId)
|
||||||
return ESUCCESS;
|
return ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARC_STATUS DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
|
// static
|
||||||
|
ARC_STATUS
|
||||||
|
DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information)
|
||||||
{
|
{
|
||||||
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
||||||
|
|
||||||
|
@ -64,7 +72,8 @@ static ARC_STATUS DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Informat
|
||||||
return ESUCCESS;
|
return ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
static ARC_STATUS
|
||||||
|
DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
||||||
{
|
{
|
||||||
DISKCONTEXT* Context;
|
DISKCONTEXT* Context;
|
||||||
UCHAR DriveNumber;
|
UCHAR DriveNumber;
|
||||||
|
@ -84,9 +93,12 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* This is either a floppy disk device (DrivePartition == 0) or
|
/*
|
||||||
* a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
|
* This is either a floppy disk device (DrivePartition == 0) or
|
||||||
* it doesn't matter which one because they both have 512 bytes per sector */
|
* a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF)
|
||||||
|
* but it doesn't matter which one because they both have 512 bytes
|
||||||
|
* per sector.
|
||||||
|
*/
|
||||||
SectorSize = 512;
|
SectorSize = 512;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,13 +106,21 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
||||||
{
|
{
|
||||||
if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
|
if (!DiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
|
||||||
return EINVAL;
|
return EINVAL;
|
||||||
|
|
||||||
SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
|
SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
|
||||||
SectorCount = PartitionTableEntry.PartitionSectorCount;
|
SectorCount = PartitionTableEntry.PartitionSectorCount;
|
||||||
}
|
}
|
||||||
|
#if 0 // FIXME: Investigate
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SectorCount = 0; /* FIXME */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
|
Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
|
||||||
if (!Context)
|
if (!Context)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
Context->DriveNumber = DriveNumber;
|
Context->DriveNumber = DriveNumber;
|
||||||
Context->SectorSize = SectorSize;
|
Context->SectorSize = SectorSize;
|
||||||
Context->SectorOffset = SectorOffset;
|
Context->SectorOffset = SectorOffset;
|
||||||
|
@ -111,7 +131,9 @@ static ARC_STATUS DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
||||||
return ESUCCESS;
|
return ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
// static
|
||||||
|
ARC_STATUS
|
||||||
|
DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
||||||
{
|
{
|
||||||
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
||||||
UCHAR* Ptr = (UCHAR*)Buffer;
|
UCHAR* Ptr = (UCHAR*)Buffer;
|
||||||
|
@ -123,7 +145,7 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
||||||
MaxSectors = DiskReadBufferSize / Context->SectorSize;
|
MaxSectors = DiskReadBufferSize / Context->SectorSize;
|
||||||
SectorOffset = Context->SectorNumber + Context->SectorOffset;
|
SectorOffset = Context->SectorNumber + Context->SectorOffset;
|
||||||
|
|
||||||
ret = 1;
|
ret = TRUE;
|
||||||
|
|
||||||
while (TotalSectors)
|
while (TotalSectors)
|
||||||
{
|
{
|
||||||
|
@ -131,11 +153,10 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
||||||
if (ReadSectors > MaxSectors)
|
if (ReadSectors > MaxSectors)
|
||||||
ReadSectors = MaxSectors;
|
ReadSectors = MaxSectors;
|
||||||
|
|
||||||
ret = MachDiskReadLogicalSectors(
|
ret = MachDiskReadLogicalSectors(Context->DriveNumber,
|
||||||
Context->DriveNumber,
|
SectorOffset,
|
||||||
SectorOffset,
|
ReadSectors,
|
||||||
ReadSectors,
|
DiskReadBuffer);
|
||||||
DiskReadBuffer);
|
|
||||||
if (!ret)
|
if (!ret)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -156,7 +177,9 @@ static ARC_STATUS DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count)
|
||||||
return (!ret) ? EIO : ESUCCESS;
|
return (!ret) ? EIO : ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ARC_STATUS DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
|
// static
|
||||||
|
ARC_STATUS
|
||||||
|
DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode)
|
||||||
{
|
{
|
||||||
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
DISKCONTEXT* Context = FsGetDeviceSpecific(FileId);
|
||||||
|
|
||||||
|
@ -169,7 +192,8 @@ static ARC_STATUS DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekM
|
||||||
return ESUCCESS;
|
return ESUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const DEVVTBL DiskVtbl = {
|
static const DEVVTBL DiskVtbl =
|
||||||
|
{
|
||||||
DiskClose,
|
DiskClose,
|
||||||
DiskGetFileInformation,
|
DiskGetFileInformation,
|
||||||
DiskOpen,
|
DiskOpen,
|
||||||
|
@ -177,6 +201,7 @@ static const DEVVTBL DiskVtbl = {
|
||||||
DiskSeek,
|
DiskSeek,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
PCHAR
|
PCHAR
|
||||||
GetHarddiskIdentifier(
|
GetHarddiskIdentifier(
|
||||||
UCHAR DriveNumber)
|
UCHAR DriveNumber)
|
||||||
|
@ -264,14 +289,13 @@ GetHarddiskInformation(
|
||||||
Identifier[15] = Hex[(Signature >> 4) & 0x0F];
|
Identifier[15] = Hex[(Signature >> 4) & 0x0F];
|
||||||
Identifier[16] = Hex[Signature & 0x0F];
|
Identifier[16] = Hex[Signature & 0x0F];
|
||||||
Identifier[17] = '-';
|
Identifier[17] = '-';
|
||||||
Identifier[18] = 'A';
|
Identifier[18] = 'A'; // FIXME: Not always 'A' ...
|
||||||
Identifier[19] = 0;
|
Identifier[19] = 0;
|
||||||
TRACE("Identifier: %s\n", Identifier);
|
TRACE("Identifier: %s\n", Identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
HwInitializeBiosDisks(VOID)
|
PcInitializeBootDevices(VOID)
|
||||||
{
|
{
|
||||||
UCHAR DiskCount, DriveNumber;
|
UCHAR DiskCount, DriveNumber;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
|
@ -314,9 +338,11 @@ HwInitializeBiosDisks(VOID)
|
||||||
|
|
||||||
DiskCount++;
|
DiskCount++;
|
||||||
DriveNumber++;
|
DriveNumber++;
|
||||||
memset(DiskReadBuffer, 0xcd, 512);
|
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
|
||||||
}
|
}
|
||||||
DiskReportError(TRUE);
|
DiskReportError(TRUE);
|
||||||
|
TRACE("BIOS reports %d harddisk%s\n",
|
||||||
|
(int)DiskCount, (DiskCount == 1) ? "" : "s");
|
||||||
|
|
||||||
/* Get the drive we're booting from */
|
/* Get the drive we're booting from */
|
||||||
MachDiskGetBootPath(BootPath, sizeof(BootPath));
|
MachDiskGetBootPath(BootPath, sizeof(BootPath));
|
||||||
|
@ -366,5 +392,5 @@ HwInitializeBiosDisks(VOID)
|
||||||
TRACE("BIOS reports %d harddisk%s\n",
|
TRACE("BIOS reports %d harddisk%s\n",
|
||||||
(int)DiskCount, (DiskCount == 1) ? "": "s");
|
(int)DiskCount, (DiskCount == 1) ? "": "s");
|
||||||
|
|
||||||
return DiskCount != 0;
|
return (DiskCount != 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>
|
#include <freeldr.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
|
#include <debug.h>
|
||||||
|
|
||||||
|
DBG_DEFAULT_CHANNEL(HWDETECT);
|
||||||
|
|
||||||
|
|
||||||
|
static CHAR Hex[] = "0123456789ABCDEF";
|
||||||
|
|
||||||
|
extern ULONG reactos_disk_count;
|
||||||
|
extern ARC_DISK_SIGNATURE_EX reactos_arc_disk_info[];
|
||||||
|
|
||||||
|
typedef struct tagDISKCONTEXT
|
||||||
|
{
|
||||||
|
UCHAR DriveNumber;
|
||||||
|
ULONG SectorSize;
|
||||||
|
ULONGLONG SectorOffset;
|
||||||
|
ULONGLONG SectorCount;
|
||||||
|
ULONGLONG SectorNumber;
|
||||||
|
} DISKCONTEXT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// NOTE: Similar to hardware.c!PcGetHarddiskConfigurationData(),
|
||||||
|
// but without extended geometry support.
|
||||||
|
static
|
||||||
|
PCM_PARTIAL_RESOURCE_LIST
|
||||||
|
XboxGetHarddiskConfigurationData(UCHAR DriveNumber, ULONG* pSize)
|
||||||
|
{
|
||||||
|
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
|
||||||
|
PCM_DISK_GEOMETRY_DEVICE_DATA DiskGeometry;
|
||||||
|
//EXTENDED_GEOMETRY ExtGeometry;
|
||||||
|
GEOMETRY Geometry;
|
||||||
|
ULONG Size;
|
||||||
|
|
||||||
|
//
|
||||||
|
// Initialize returned size
|
||||||
|
//
|
||||||
|
*pSize = 0;
|
||||||
|
|
||||||
|
/* Set 'Configuration Data' value */
|
||||||
|
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
|
||||||
|
sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
|
||||||
|
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
|
||||||
|
if (PartialResourceList == NULL)
|
||||||
|
{
|
||||||
|
ERR("Failed to allocate a full resource descriptor\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(PartialResourceList, 0, Size);
|
||||||
|
PartialResourceList->Version = 1;
|
||||||
|
PartialResourceList->Revision = 1;
|
||||||
|
PartialResourceList->Count = 1;
|
||||||
|
PartialResourceList->PartialDescriptors[0].Type =
|
||||||
|
CmResourceTypeDeviceSpecific;
|
||||||
|
// PartialResourceList->PartialDescriptors[0].ShareDisposition =
|
||||||
|
// PartialResourceList->PartialDescriptors[0].Flags =
|
||||||
|
PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
|
||||||
|
sizeof(CM_DISK_GEOMETRY_DEVICE_DATA);
|
||||||
|
|
||||||
|
/* Get pointer to geometry data */
|
||||||
|
DiskGeometry = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
|
||||||
|
|
||||||
|
/* Get the disk geometry */
|
||||||
|
//ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
|
||||||
|
|
||||||
|
if (MachDiskGetDriveGeometry(DriveNumber, &Geometry))
|
||||||
|
{
|
||||||
|
DiskGeometry->BytesPerSector = Geometry.BytesPerSector;
|
||||||
|
DiskGeometry->NumberOfCylinders = Geometry.Cylinders;
|
||||||
|
DiskGeometry->SectorsPerTrack = Geometry.Sectors;
|
||||||
|
DiskGeometry->NumberOfHeads = Geometry.Heads;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Reading disk geometry failed\n");
|
||||||
|
FrLdrHeapFree(PartialResourceList, TAG_HW_RESOURCE_LIST);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
TRACE("Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
|
||||||
|
DriveNumber,
|
||||||
|
DiskGeometry->NumberOfCylinders,
|
||||||
|
DiskGeometry->NumberOfHeads,
|
||||||
|
DiskGeometry->SectorsPerTrack,
|
||||||
|
DiskGeometry->BytesPerSector);
|
||||||
|
|
||||||
|
//
|
||||||
|
// Return configuration data
|
||||||
|
//
|
||||||
|
*pSize = Size;
|
||||||
|
return PartialResourceList;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define GetHarddiskConfigurationData XboxGetHarddiskConfigurationData
|
||||||
|
|
||||||
|
|
||||||
|
extern ARC_STATUS
|
||||||
|
DiskClose(ULONG FileId);
|
||||||
|
|
||||||
|
extern ARC_STATUS
|
||||||
|
DiskGetFileInformation(ULONG FileId, FILEINFORMATION* Information);
|
||||||
|
|
||||||
|
static
|
||||||
|
ARC_STATUS
|
||||||
|
DiskOpen(CHAR* Path, OPENMODE OpenMode, ULONG* FileId)
|
||||||
|
{
|
||||||
|
DISKCONTEXT* Context;
|
||||||
|
ULONG DrivePartition, SectorSize;
|
||||||
|
UCHAR DriveNumber;
|
||||||
|
ULONGLONG SectorOffset = 0;
|
||||||
|
ULONGLONG SectorCount = 0;
|
||||||
|
PARTITION_TABLE_ENTRY PartitionTableEntry;
|
||||||
|
CHAR FileName[1];
|
||||||
|
|
||||||
|
if (!DissectArcPath(Path, FileName, &DriveNumber, &DrivePartition))
|
||||||
|
return EINVAL;
|
||||||
|
|
||||||
|
if (DrivePartition == 0xff)
|
||||||
|
{
|
||||||
|
/* This is a CD-ROM device */
|
||||||
|
SectorSize = 2048;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* This is either a floppy disk device (DrivePartition == 0) or
|
||||||
|
* a hard disk device (DrivePartition != 0 && DrivePartition != 0xFF) but
|
||||||
|
* it doesn't matter which one because they both have 512 bytes per sector */
|
||||||
|
SectorSize = 512;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DrivePartition != 0xff && DrivePartition != 0)
|
||||||
|
{
|
||||||
|
if (!XboxDiskGetPartitionEntry(DriveNumber, DrivePartition, &PartitionTableEntry))
|
||||||
|
return EINVAL;
|
||||||
|
SectorOffset = PartitionTableEntry.SectorCountBeforePartition;
|
||||||
|
SectorCount = PartitionTableEntry.PartitionSectorCount;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
SectorCount = 0; /* FIXME */
|
||||||
|
}
|
||||||
|
|
||||||
|
Context = FrLdrTempAlloc(sizeof(DISKCONTEXT), TAG_HW_DISK_CONTEXT);
|
||||||
|
if (!Context)
|
||||||
|
return ENOMEM;
|
||||||
|
Context->DriveNumber = DriveNumber;
|
||||||
|
Context->SectorSize = SectorSize;
|
||||||
|
Context->SectorOffset = SectorOffset;
|
||||||
|
Context->SectorCount = SectorCount;
|
||||||
|
Context->SectorNumber = 0;
|
||||||
|
FsSetDeviceSpecific(*FileId, Context);
|
||||||
|
|
||||||
|
return ESUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
extern ARC_STATUS
|
||||||
|
DiskRead(ULONG FileId, VOID* Buffer, ULONG N, ULONG* Count);
|
||||||
|
|
||||||
|
extern ARC_STATUS
|
||||||
|
DiskSeek(ULONG FileId, LARGE_INTEGER* Position, SEEKMODE SeekMode);
|
||||||
|
|
||||||
|
static const DEVVTBL DiskVtbl =
|
||||||
|
{
|
||||||
|
DiskClose,
|
||||||
|
DiskGetFileInformation,
|
||||||
|
DiskOpen,
|
||||||
|
DiskRead,
|
||||||
|
DiskSeek,
|
||||||
|
};
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
GetHarddiskIdentifier(PCHAR Identifier,
|
||||||
|
UCHAR DriveNumber)
|
||||||
|
{
|
||||||
|
PMASTER_BOOT_RECORD Mbr;
|
||||||
|
PULONG Buffer;
|
||||||
|
ULONG i;
|
||||||
|
ULONG Checksum;
|
||||||
|
ULONG Signature;
|
||||||
|
CHAR ArcName[MAX_PATH];
|
||||||
|
PARTITION_TABLE_ENTRY PartitionTableEntry;
|
||||||
|
|
||||||
|
/* Read the MBR */
|
||||||
|
if (!MachDiskReadLogicalSectors(DriveNumber, 0ULL, 1, DiskReadBuffer))
|
||||||
|
{
|
||||||
|
ERR("Reading MBR failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Buffer = (ULONG*)DiskReadBuffer;
|
||||||
|
Mbr = (PMASTER_BOOT_RECORD)DiskReadBuffer;
|
||||||
|
|
||||||
|
Signature = Mbr->Signature;
|
||||||
|
TRACE("Signature: %x\n", Signature);
|
||||||
|
|
||||||
|
/* Calculate the MBR checksum */
|
||||||
|
Checksum = 0;
|
||||||
|
for (i = 0; i < 512 / sizeof(ULONG); i++)
|
||||||
|
{
|
||||||
|
Checksum += Buffer[i];
|
||||||
|
}
|
||||||
|
Checksum = ~Checksum + 1;
|
||||||
|
TRACE("Checksum: %x\n", Checksum);
|
||||||
|
|
||||||
|
/* Fill out the ARC disk block */
|
||||||
|
reactos_arc_disk_info[reactos_disk_count].DiskSignature.Signature = Signature;
|
||||||
|
reactos_arc_disk_info[reactos_disk_count].DiskSignature.CheckSum = Checksum;
|
||||||
|
sprintf(ArcName, "multi(0)disk(0)rdisk(%lu)", reactos_disk_count);
|
||||||
|
strcpy(reactos_arc_disk_info[reactos_disk_count].ArcName, ArcName);
|
||||||
|
reactos_arc_disk_info[reactos_disk_count].DiskSignature.ArcName =
|
||||||
|
reactos_arc_disk_info[reactos_disk_count].ArcName;
|
||||||
|
reactos_disk_count++;
|
||||||
|
|
||||||
|
sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(0)", DriveNumber - 0x80);
|
||||||
|
FsRegisterDevice(ArcName, &DiskVtbl);
|
||||||
|
|
||||||
|
/* Add partitions */
|
||||||
|
i = 1;
|
||||||
|
DiskReportError(FALSE);
|
||||||
|
while (XboxDiskGetPartitionEntry(DriveNumber, i, &PartitionTableEntry))
|
||||||
|
{
|
||||||
|
if (PartitionTableEntry.SystemIndicator != PARTITION_ENTRY_UNUSED)
|
||||||
|
{
|
||||||
|
sprintf(ArcName, "multi(0)disk(0)rdisk(%u)partition(%lu)", DriveNumber - 0x80, i);
|
||||||
|
FsRegisterDevice(ArcName, &DiskVtbl);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
DiskReportError(TRUE);
|
||||||
|
|
||||||
|
/* Convert checksum and signature to identifier string */
|
||||||
|
Identifier[0] = Hex[(Checksum >> 28) & 0x0F];
|
||||||
|
Identifier[1] = Hex[(Checksum >> 24) & 0x0F];
|
||||||
|
Identifier[2] = Hex[(Checksum >> 20) & 0x0F];
|
||||||
|
Identifier[3] = Hex[(Checksum >> 16) & 0x0F];
|
||||||
|
Identifier[4] = Hex[(Checksum >> 12) & 0x0F];
|
||||||
|
Identifier[5] = Hex[(Checksum >> 8) & 0x0F];
|
||||||
|
Identifier[6] = Hex[(Checksum >> 4) & 0x0F];
|
||||||
|
Identifier[7] = Hex[Checksum & 0x0F];
|
||||||
|
Identifier[8] = '-';
|
||||||
|
Identifier[9] = Hex[(Signature >> 28) & 0x0F];
|
||||||
|
Identifier[10] = Hex[(Signature >> 24) & 0x0F];
|
||||||
|
Identifier[11] = Hex[(Signature >> 20) & 0x0F];
|
||||||
|
Identifier[12] = Hex[(Signature >> 16) & 0x0F];
|
||||||
|
Identifier[13] = Hex[(Signature >> 12) & 0x0F];
|
||||||
|
Identifier[14] = Hex[(Signature >> 8) & 0x0F];
|
||||||
|
Identifier[15] = Hex[(Signature >> 4) & 0x0F];
|
||||||
|
Identifier[16] = Hex[Signature & 0x0F];
|
||||||
|
Identifier[17] = '-';
|
||||||
|
Identifier[18] = 'A';
|
||||||
|
Identifier[19] = 0;
|
||||||
|
TRACE("Identifier: %s\n", Identifier);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
DetectBiosDisks(PCONFIGURATION_COMPONENT_DATA SystemKey,
|
||||||
|
PCONFIGURATION_COMPONENT_DATA BusKey)
|
||||||
|
{
|
||||||
|
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
|
||||||
|
PCM_INT13_DRIVE_PARAMETER Int13Drives;
|
||||||
|
GEOMETRY Geometry;
|
||||||
|
PCONFIGURATION_COMPONENT_DATA DiskKey, ControllerKey;
|
||||||
|
UCHAR DiskCount;
|
||||||
|
ULONG i;
|
||||||
|
ULONG Size;
|
||||||
|
BOOLEAN Changed;
|
||||||
|
|
||||||
|
/* Count the number of visible drives */
|
||||||
|
DiskReportError(FALSE);
|
||||||
|
DiskCount = 0;
|
||||||
|
|
||||||
|
/* There are some really broken BIOSes out there. There are even BIOSes
|
||||||
|
* that happily report success when you ask them to read from non-existent
|
||||||
|
* harddisks. So, we set the buffer to known contents first, then try to
|
||||||
|
* read. If the BIOS reports success but the buffer contents haven't
|
||||||
|
* changed then we fail anyway */
|
||||||
|
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
|
||||||
|
while (MachDiskReadLogicalSectors(0x80 + DiskCount, 0ULL, 1, DiskReadBuffer))
|
||||||
|
{
|
||||||
|
Changed = FALSE;
|
||||||
|
for (i = 0; ! Changed && i < DiskReadBufferSize; i++)
|
||||||
|
{
|
||||||
|
Changed = ((PUCHAR)DiskReadBuffer)[i] != 0xcd;
|
||||||
|
}
|
||||||
|
if (! Changed)
|
||||||
|
{
|
||||||
|
TRACE("BIOS reports success for disk %d but data didn't change\n",
|
||||||
|
(int)DiskCount);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
DiskCount++;
|
||||||
|
memset(DiskReadBuffer, 0xcd, DiskReadBufferSize);
|
||||||
|
}
|
||||||
|
DiskReportError(TRUE);
|
||||||
|
TRACE("BIOS reports %d harddisk%s\n",
|
||||||
|
(int)DiskCount, (DiskCount == 1) ? "" : "s");
|
||||||
|
|
||||||
|
//DetectBiosFloppyController(BusKey);
|
||||||
|
|
||||||
|
/* Allocate resource descriptor */
|
||||||
|
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) +
|
||||||
|
sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
|
||||||
|
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
|
||||||
|
if (PartialResourceList == NULL)
|
||||||
|
{
|
||||||
|
ERR("Failed to allocate resource descriptor\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize resource descriptor */
|
||||||
|
memset(PartialResourceList, 0, Size);
|
||||||
|
PartialResourceList->Version = 1;
|
||||||
|
PartialResourceList->Revision = 1;
|
||||||
|
PartialResourceList->Count = 1;
|
||||||
|
PartialResourceList->PartialDescriptors[0].Type = CmResourceTypeDeviceSpecific;
|
||||||
|
PartialResourceList->PartialDescriptors[0].ShareDisposition = 0;
|
||||||
|
PartialResourceList->PartialDescriptors[0].Flags = 0;
|
||||||
|
PartialResourceList->PartialDescriptors[0].u.DeviceSpecificData.DataSize =
|
||||||
|
sizeof(CM_INT13_DRIVE_PARAMETER) * DiskCount;
|
||||||
|
|
||||||
|
/* Get harddisk Int13 geometry data */
|
||||||
|
Int13Drives = (PVOID)(((ULONG_PTR)PartialResourceList) + sizeof(CM_PARTIAL_RESOURCE_LIST));
|
||||||
|
for (i = 0; i < DiskCount; i++)
|
||||||
|
{
|
||||||
|
if (MachDiskGetDriveGeometry(0x80 + i, &Geometry))
|
||||||
|
{
|
||||||
|
Int13Drives[i].DriveSelect = 0x80 + i;
|
||||||
|
Int13Drives[i].MaxCylinders = Geometry.Cylinders - 1;
|
||||||
|
Int13Drives[i].SectorsPerTrack = (USHORT)Geometry.Sectors;
|
||||||
|
Int13Drives[i].MaxHeads = (USHORT)Geometry.Heads - 1;
|
||||||
|
Int13Drives[i].NumberDrives = DiskCount;
|
||||||
|
|
||||||
|
TRACE(
|
||||||
|
"Disk %x: %u Cylinders %u Heads %u Sectors %u Bytes\n",
|
||||||
|
0x80 + i,
|
||||||
|
Geometry.Cylinders - 1,
|
||||||
|
Geometry.Heads - 1,
|
||||||
|
Geometry.Sectors,
|
||||||
|
Geometry.BytesPerSector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FldrCreateComponentKey(BusKey,
|
||||||
|
ControllerClass,
|
||||||
|
DiskController,
|
||||||
|
Output | Input,
|
||||||
|
0,
|
||||||
|
0xFFFFFFFF,
|
||||||
|
NULL,
|
||||||
|
PartialResourceList,
|
||||||
|
Size,
|
||||||
|
&ControllerKey);
|
||||||
|
TRACE("Created key: DiskController\\0\n");
|
||||||
|
|
||||||
|
/* Create and fill subkey for each harddisk */
|
||||||
|
for (i = 0; i < DiskCount; i++)
|
||||||
|
{
|
||||||
|
CHAR Identifier[20];
|
||||||
|
|
||||||
|
/* Get disk values */
|
||||||
|
PartialResourceList = GetHarddiskConfigurationData(0x80 + i, &Size);
|
||||||
|
GetHarddiskIdentifier(Identifier, 0x80 + i);
|
||||||
|
|
||||||
|
/* Create disk key */
|
||||||
|
FldrCreateComponentKey(ControllerKey,
|
||||||
|
PeripheralClass,
|
||||||
|
DiskPeripheral,
|
||||||
|
Output | Input,
|
||||||
|
0,
|
||||||
|
0xFFFFFFFF,
|
||||||
|
Identifier,
|
||||||
|
PartialResourceList,
|
||||||
|
Size,
|
||||||
|
&DiskKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN
|
||||||
|
XboxInitializeBootDevices(VOID)
|
||||||
|
{
|
||||||
|
// Emulate old behavior
|
||||||
|
return XboxHwDetect() != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
VOID
|
||||||
|
DetectIsaBios(PCONFIGURATION_COMPONENT_DATA SystemKey, ULONG *BusNumber)
|
||||||
|
{
|
||||||
|
PCM_PARTIAL_RESOURCE_LIST PartialResourceList;
|
||||||
|
PCONFIGURATION_COMPONENT_DATA BusKey;
|
||||||
|
ULONG Size;
|
||||||
|
|
||||||
|
/* Set 'Configuration Data' value */
|
||||||
|
Size = sizeof(CM_PARTIAL_RESOURCE_LIST) -
|
||||||
|
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
|
||||||
|
PartialResourceList = FrLdrHeapAlloc(Size, TAG_HW_RESOURCE_LIST);
|
||||||
|
if (PartialResourceList == NULL)
|
||||||
|
{
|
||||||
|
TRACE("Failed to allocate resource descriptor\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize resource descriptor */
|
||||||
|
memset(PartialResourceList, 0, Size);
|
||||||
|
PartialResourceList->Version = 1;
|
||||||
|
PartialResourceList->Revision = 1;
|
||||||
|
PartialResourceList->Count = 0;
|
||||||
|
|
||||||
|
/* Create new bus key */
|
||||||
|
FldrCreateComponentKey(SystemKey,
|
||||||
|
AdapterClass,
|
||||||
|
MultiFunctionAdapter,
|
||||||
|
0x0,
|
||||||
|
0x0,
|
||||||
|
0xFFFFFFFF,
|
||||||
|
"ISA",
|
||||||
|
PartialResourceList,
|
||||||
|
Size,
|
||||||
|
&BusKey);
|
||||||
|
|
||||||
|
/* Increment bus number */
|
||||||
|
(*BusNumber)++;
|
||||||
|
|
||||||
|
/* Detect ISA/BIOS devices */
|
||||||
|
DetectBiosDisks(SystemKey, BusKey);
|
||||||
|
|
||||||
|
/* FIXME: Detect more ISA devices */
|
||||||
|
}
|
||||||
|
|
||||||
|
PCONFIGURATION_COMPONENT_DATA
|
||||||
|
XboxHwDetect(VOID)
|
||||||
|
{
|
||||||
|
PCONFIGURATION_COMPONENT_DATA SystemKey;
|
||||||
|
ULONG BusNumber = 0;
|
||||||
|
|
||||||
|
TRACE("DetectHardware()\n");
|
||||||
|
|
||||||
|
/* Create the 'System' key */
|
||||||
|
FldrCreateSystemKey(&SystemKey);
|
||||||
|
|
||||||
|
/* TODO: Build actual xbox's hardware configuration tree */
|
||||||
|
DetectIsaBios(SystemKey, &BusNumber);
|
||||||
|
|
||||||
|
TRACE("DetectHardware() Done\n");
|
||||||
|
return SystemKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
VOID XboxHwIdle(VOID)
|
||||||
|
{
|
||||||
|
/* UNIMPLEMENTED */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/******************************************************************************/
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
XboxMachInit(const char *CmdLine)
|
XboxMachInit(const char *CmdLine)
|
||||||
{
|
{
|
||||||
/* Set LEDs to red before anything is initialized */
|
/* Set LEDs to red before anything is initialized */
|
||||||
XboxSetLED("rrrr");
|
XboxSetLED("rrrr");
|
||||||
|
|
||||||
/* Initialize our stuff */
|
/* Initialize our stuff */
|
||||||
XboxMemInit();
|
XboxMemInit();
|
||||||
XboxVideoInit();
|
XboxVideoInit();
|
||||||
|
|
||||||
/* Setup vtbl */
|
/* Setup vtbl */
|
||||||
MachVtbl.ConsPutChar = XboxConsPutChar;
|
MachVtbl.ConsPutChar = XboxConsPutChar;
|
||||||
MachVtbl.ConsKbHit = XboxConsKbHit;
|
MachVtbl.ConsKbHit = XboxConsKbHit;
|
||||||
MachVtbl.ConsGetCh = XboxConsGetCh;
|
MachVtbl.ConsGetCh = XboxConsGetCh;
|
||||||
MachVtbl.VideoClearScreen = XboxVideoClearScreen;
|
MachVtbl.VideoClearScreen = XboxVideoClearScreen;
|
||||||
MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode;
|
MachVtbl.VideoSetDisplayMode = XboxVideoSetDisplayMode;
|
||||||
MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize;
|
MachVtbl.VideoGetDisplaySize = XboxVideoGetDisplaySize;
|
||||||
MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize;
|
MachVtbl.VideoGetBufferSize = XboxVideoGetBufferSize;
|
||||||
MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor;
|
MachVtbl.VideoHideShowTextCursor = XboxVideoHideShowTextCursor;
|
||||||
MachVtbl.VideoPutChar = XboxVideoPutChar;
|
MachVtbl.VideoPutChar = XboxVideoPutChar;
|
||||||
MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM;
|
MachVtbl.VideoCopyOffScreenBufferToVRAM = XboxVideoCopyOffScreenBufferToVRAM;
|
||||||
MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed;
|
MachVtbl.VideoIsPaletteFixed = XboxVideoIsPaletteFixed;
|
||||||
MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor;
|
MachVtbl.VideoSetPaletteColor = XboxVideoSetPaletteColor;
|
||||||
MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor;
|
MachVtbl.VideoGetPaletteColor = XboxVideoGetPaletteColor;
|
||||||
MachVtbl.VideoSync = XboxVideoSync;
|
MachVtbl.VideoSync = XboxVideoSync;
|
||||||
MachVtbl.Beep = PcBeep;
|
MachVtbl.Beep = PcBeep;
|
||||||
MachVtbl.PrepareForReactOS = XboxPrepareForReactOS;
|
MachVtbl.PrepareForReactOS = XboxPrepareForReactOS;
|
||||||
MachVtbl.GetMemoryMap = XboxMemGetMemoryMap;
|
MachVtbl.GetMemoryMap = XboxMemGetMemoryMap;
|
||||||
MachVtbl.DiskGetBootPath = DiskGetBootPath;
|
MachVtbl.DiskGetBootPath = DiskGetBootPath;
|
||||||
MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors;
|
MachVtbl.DiskReadLogicalSectors = XboxDiskReadLogicalSectors;
|
||||||
MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry;
|
MachVtbl.DiskGetDriveGeometry = XboxDiskGetDriveGeometry;
|
||||||
MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount;
|
MachVtbl.DiskGetCacheableBlockCount = XboxDiskGetCacheableBlockCount;
|
||||||
MachVtbl.GetTime = XboxGetTime;
|
MachVtbl.GetTime = XboxGetTime;
|
||||||
MachVtbl.InitializeBootDevices = XboxInitializeBootDevices;
|
MachVtbl.InitializeBootDevices = PcInitializeBootDevices;
|
||||||
MachVtbl.HwDetect = XboxHwDetect;
|
MachVtbl.HwDetect = XboxHwDetect;
|
||||||
MachVtbl.HwIdle = XboxHwIdle;
|
MachVtbl.HwIdle = XboxHwIdle;
|
||||||
|
|
||||||
/* Set LEDs to orange after init */
|
/* Set LEDs to orange after init */
|
||||||
XboxSetLED("oooo");
|
XboxSetLED("oooo");
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID
|
VOID
|
||||||
XboxPrepareForReactOS(IN BOOLEAN Setup)
|
XboxPrepareForReactOS(IN BOOLEAN Setup)
|
||||||
{
|
{
|
||||||
//
|
/* On XBOX, prepare video and turn off the floppy motor */
|
||||||
// On XBOX, prepare video and turn off the floppy motor
|
|
||||||
//
|
|
||||||
XboxVideoPrepareForReactOS(Setup);
|
XboxVideoPrepareForReactOS(Setup);
|
||||||
DiskStopFloppyMotor();
|
DiskStopFloppyMotor();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* EOF */
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <freeldr.h>
|
#include <freeldr.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
DBG_DEFAULT_CHANNEL(DISK);
|
DBG_DEFAULT_CHANNEL(DISK);
|
||||||
|
@ -25,41 +27,40 @@ DBG_DEFAULT_CHANNEL(DISK);
|
||||||
#include <pshpack2.h>
|
#include <pshpack2.h>
|
||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
UCHAR PacketSize; // 00h - Size of packet (10h or 18h)
|
UCHAR PacketSize; // 00h - Size of packet (10h or 18h)
|
||||||
UCHAR Reserved; // 01h - Reserved (0)
|
UCHAR Reserved; // 01h - Reserved (0)
|
||||||
USHORT LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD)
|
USHORT LBABlockCount; // 02h - Number of blocks to transfer (max 007Fh for Phoenix EDD)
|
||||||
USHORT TransferBufferOffset; // 04h - Transfer buffer offset (seg:off)
|
USHORT TransferBufferOffset; // 04h - Transfer buffer offset (seg:off)
|
||||||
USHORT TransferBufferSegment; // Transfer buffer segment (seg:off)
|
USHORT TransferBufferSegment; // Transfer buffer segment (seg:off)
|
||||||
ULONGLONG LBAStartBlock; // 08h - Starting absolute block number
|
ULONGLONG LBAStartBlock; // 08h - Starting absolute block number
|
||||||
//ULONGLONG TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer
|
// ULONGLONG TransferBuffer64; // 10h - (EDD-3.0, optional) 64-bit flat address of transfer buffer
|
||||||
// used if DWORD at 04h is FFFFh:FFFFh
|
// used if DWORD at 04h is FFFFh:FFFFh
|
||||||
// Commented since some earlier BIOSes refuse to work with
|
// Commented since some earlier BIOSes refuse to work with
|
||||||
// such extended structure
|
// such extended structure
|
||||||
} I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET;
|
} I386_DISK_ADDRESS_PACKET, *PI386_DISK_ADDRESS_PACKET;
|
||||||
#include <poppack.h>
|
#include <poppack.h>
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/* FUNCTIONS *****************************************************************/
|
||||||
// FUNCTIONS
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
static BOOLEAN PcDiskResetController(UCHAR DriveNumber)
|
BOOLEAN DiskResetController(UCHAR DriveNumber)
|
||||||
{
|
{
|
||||||
REGS RegsIn;
|
REGS RegsIn, RegsOut;
|
||||||
REGS RegsOut;
|
|
||||||
|
|
||||||
WARN("PcDiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
|
WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DriveNumber);
|
||||||
|
|
||||||
// BIOS Int 13h, function 0 - Reset disk system
|
/*
|
||||||
// AH = 00h
|
* BIOS Int 13h, function 0 - Reset disk system
|
||||||
// DL = drive (if bit 7 is set both hard disks and floppy disks reset)
|
* AH = 00h
|
||||||
// Return:
|
* DL = drive (if bit 7 is set both hard disks and floppy disks reset)
|
||||||
// AH = status
|
* Return:
|
||||||
// CF clear if successful
|
* AH = status
|
||||||
// CF set on error
|
* CF clear if successful
|
||||||
|
* CF set on error
|
||||||
|
*/
|
||||||
RegsIn.b.ah = 0x00;
|
RegsIn.b.ah = 0x00;
|
||||||
RegsIn.b.dl = DriveNumber;
|
RegsIn.b.dl = DriveNumber;
|
||||||
|
|
||||||
// Reset the disk controller
|
/* Reset the disk controller */
|
||||||
Int386(0x13, &RegsIn, &RegsOut);
|
Int386(0x13, &RegsIn, &RegsOut);
|
||||||
|
|
||||||
return INT386_SUCCESS(RegsOut);
|
return INT386_SUCCESS(RegsOut);
|
||||||
|
@ -67,23 +68,16 @@ static BOOLEAN PcDiskResetController(UCHAR DriveNumber)
|
||||||
|
|
||||||
static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||||
{
|
{
|
||||||
REGS RegsIn;
|
REGS RegsIn, RegsOut;
|
||||||
REGS RegsOut;
|
ULONG RetryCount;
|
||||||
ULONG RetryCount;
|
PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER);
|
||||||
PI386_DISK_ADDRESS_PACKET Packet = (PI386_DISK_ADDRESS_PACKET)(BIOSCALLBUFFER);
|
|
||||||
|
|
||||||
TRACE("PcDiskReadLogicalSectorsLBA() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer);
|
TRACE("PcDiskReadLogicalSectorsLBA() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer);
|
||||||
ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
|
ASSERT(((ULONG_PTR)Buffer) <= 0xFFFFF);
|
||||||
|
|
||||||
// BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
|
/* Setup disk address packet */
|
||||||
RegsIn.b.ah = 0x42; // Subfunction 42h
|
RtlZeroMemory(Packet, sizeof(*Packet));
|
||||||
RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk)
|
Packet->PacketSize = sizeof(*Packet);
|
||||||
RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
|
|
||||||
RegsIn.w.si = BIOSCALLBUFOFFSET;
|
|
||||||
|
|
||||||
// Setup disk address packet
|
|
||||||
RtlZeroMemory(Packet, sizeof(I386_DISK_ADDRESS_PACKET));
|
|
||||||
Packet->PacketSize = sizeof(I386_DISK_ADDRESS_PACKET);
|
|
||||||
Packet->Reserved = 0;
|
Packet->Reserved = 0;
|
||||||
Packet->LBABlockCount = (USHORT)SectorCount;
|
Packet->LBABlockCount = (USHORT)SectorCount;
|
||||||
ASSERT(Packet->LBABlockCount == SectorCount);
|
ASSERT(Packet->LBABlockCount == SectorCount);
|
||||||
|
@ -91,39 +85,45 @@ static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNu
|
||||||
Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4);
|
Packet->TransferBufferSegment = (USHORT)(((ULONG_PTR)Buffer) >> 4);
|
||||||
Packet->LBAStartBlock = SectorNumber;
|
Packet->LBAStartBlock = SectorNumber;
|
||||||
|
|
||||||
// BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
|
/*
|
||||||
// Return:
|
* BIOS int 0x13, function 42h - IBM/MS INT 13 Extensions - EXTENDED READ
|
||||||
// CF clear if successful
|
* Return:
|
||||||
// AH = 00h
|
* CF clear if successful
|
||||||
// CF set on error
|
* AH = 00h
|
||||||
// AH = error code
|
* CF set on error
|
||||||
// disk address packet's block count field set to the
|
* AH = error code
|
||||||
// number of blocks successfully transferred
|
* Disk address packet's block count field set to the
|
||||||
|
* number of blocks successfully transferred.
|
||||||
|
*/
|
||||||
|
RegsIn.b.ah = 0x42; // Subfunction 42h
|
||||||
|
RegsIn.b.dl = DriveNumber; // Drive number in DL (0 - floppy, 0x80 - harddisk)
|
||||||
|
RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> disk address packet
|
||||||
|
RegsIn.w.si = BIOSCALLBUFOFFSET;
|
||||||
|
|
||||||
// Retry 3 times
|
/* Retry 3 times */
|
||||||
for (RetryCount=0; RetryCount<3; RetryCount++)
|
for (RetryCount=0; RetryCount<3; RetryCount++)
|
||||||
{
|
{
|
||||||
Int386(0x13, &RegsIn, &RegsOut);
|
Int386(0x13, &RegsIn, &RegsOut);
|
||||||
|
|
||||||
// If it worked return TRUE
|
/* If it worked return TRUE */
|
||||||
if (INT386_SUCCESS(RegsOut))
|
if (INT386_SUCCESS(RegsOut))
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
// If it was a corrected ECC error then the data is still good
|
/* If it was a corrected ECC error then the data is still good */
|
||||||
else if (RegsOut.b.ah == 0x11)
|
else if (RegsOut.b.ah == 0x11)
|
||||||
{
|
{
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
// If it failed then do the next retry
|
/* If it failed then do the next retry */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PcDiskResetController(DriveNumber);
|
DiskResetController(DriveNumber);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we get here then the read failed
|
/* If we get here then the read failed */
|
||||||
ERR("Disk Read Failed in LBA mode: %x (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n", RegsOut.b.ah, DriveNumber, SectorNumber, SectorCount);
|
ERR("Disk Read Failed in LBA mode: %x (DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d)\n", RegsOut.b.ah, DriveNumber, SectorNumber, SectorCount);
|
||||||
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -131,20 +131,17 @@ static BOOLEAN PcDiskReadLogicalSectorsLBA(UCHAR DriveNumber, ULONGLONG SectorNu
|
||||||
|
|
||||||
static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||||
{
|
{
|
||||||
UCHAR PhysicalSector;
|
UCHAR PhysicalSector;
|
||||||
UCHAR PhysicalHead;
|
UCHAR PhysicalHead;
|
||||||
ULONG PhysicalTrack;
|
ULONG PhysicalTrack;
|
||||||
GEOMETRY DriveGeometry;
|
GEOMETRY DriveGeometry;
|
||||||
ULONG NumberOfSectorsToRead;
|
ULONG NumberOfSectorsToRead;
|
||||||
REGS RegsIn;
|
REGS RegsIn, RegsOut;
|
||||||
REGS RegsOut;
|
ULONG RetryCount;
|
||||||
ULONG RetryCount;
|
|
||||||
|
|
||||||
TRACE("PcDiskReadLogicalSectorsCHS()\n");
|
TRACE("PcDiskReadLogicalSectorsCHS()\n");
|
||||||
|
|
||||||
//
|
/* Get the drive geometry */
|
||||||
// Get the drive geometry
|
|
||||||
//
|
|
||||||
if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
|
if (!MachDiskGetDriveGeometry(DriveNumber, &DriveGeometry) ||
|
||||||
DriveGeometry.Sectors == 0 ||
|
DriveGeometry.Sectors == 0 ||
|
||||||
DriveGeometry.Heads == 0)
|
DriveGeometry.Heads == 0)
|
||||||
|
@ -154,18 +151,15 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
||||||
|
|
||||||
while (SectorCount)
|
while (SectorCount)
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
//
|
* Calculate the physical disk offsets.
|
||||||
// Calculate the physical disk offsets
|
* Note: DriveGeometry.Sectors < 64
|
||||||
// Note: DriveGeometry.Sectors < 64
|
*/
|
||||||
//
|
|
||||||
PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors);
|
PhysicalSector = 1 + (UCHAR)(SectorNumber % DriveGeometry.Sectors);
|
||||||
PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads);
|
PhysicalHead = (UCHAR)((SectorNumber / DriveGeometry.Sectors) % DriveGeometry.Heads);
|
||||||
PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads);
|
PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.Sectors) / DriveGeometry.Heads);
|
||||||
|
|
||||||
//
|
/* Calculate how many sectors we need to read this round */
|
||||||
// Calculate how many sectors we need to read this round
|
|
||||||
//
|
|
||||||
if (PhysicalSector > 1)
|
if (PhysicalSector > 1)
|
||||||
{
|
{
|
||||||
if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
|
if (SectorCount >= (DriveGeometry.Sectors - (PhysicalSector - 1)))
|
||||||
|
@ -181,9 +175,7 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
||||||
NumberOfSectorsToRead = SectorCount;
|
NumberOfSectorsToRead = SectorCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
/* Make sure the read is within the geometry boundaries */
|
||||||
// Make sure the read is within the geometry boundaries
|
|
||||||
//
|
|
||||||
if ((PhysicalHead >= DriveGeometry.Heads) ||
|
if ((PhysicalHead >= DriveGeometry.Heads) ||
|
||||||
(PhysicalTrack >= DriveGeometry.Cylinders) ||
|
(PhysicalTrack >= DriveGeometry.Cylinders) ||
|
||||||
((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
|
((NumberOfSectorsToRead + PhysicalSector) > (DriveGeometry.Sectors + 1)) ||
|
||||||
|
@ -193,22 +185,24 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// BIOS Int 13h, function 2 - Read Disk Sectors
|
/*
|
||||||
// AH = 02h
|
* BIOS Int 13h, function 2 - Read Disk Sectors
|
||||||
// AL = number of sectors to read (must be nonzero)
|
* AH = 02h
|
||||||
// CH = low eight bits of cylinder number
|
* AL = number of sectors to read (must be nonzero)
|
||||||
// CL = sector number 1-63 (bits 0-5)
|
* CH = low eight bits of cylinder number
|
||||||
// high two bits of cylinder (bits 6-7, hard disk only)
|
* CL = sector number 1-63 (bits 0-5)
|
||||||
// DH = head number
|
* high two bits of cylinder (bits 6-7, hard disk only)
|
||||||
// DL = drive number (bit 7 set for hard disk)
|
* DH = head number
|
||||||
// ES:BX -> data buffer
|
* DL = drive number (bit 7 set for hard disk)
|
||||||
// Return:
|
* ES:BX -> data buffer
|
||||||
// CF set on error
|
* Return:
|
||||||
// if AH = 11h (corrected ECC error), AL = burst length
|
* CF set on error
|
||||||
// CF clear if successful
|
* if AH = 11h (corrected ECC error), AL = burst length
|
||||||
// AH = status
|
* CF clear if successful
|
||||||
// AL = number of sectors transferred
|
* AH = status
|
||||||
// (only valid if CF set for some BIOSes)
|
* AL = number of sectors transferred
|
||||||
|
* (only valid if CF set for some BIOSes)
|
||||||
|
*/
|
||||||
RegsIn.b.ah = 0x02;
|
RegsIn.b.ah = 0x02;
|
||||||
RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
|
RegsIn.b.al = (UCHAR)NumberOfSectorsToRead;
|
||||||
RegsIn.b.ch = (PhysicalTrack & 0xFF);
|
RegsIn.b.ch = (PhysicalTrack & 0xFF);
|
||||||
|
@ -218,41 +212,37 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
||||||
RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
|
RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4);
|
||||||
RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;
|
RegsIn.w.bx = ((ULONG_PTR)Buffer) & 0x0F;
|
||||||
|
|
||||||
//
|
/* Perform the read. Retry 3 times. */
|
||||||
// Perform the read
|
|
||||||
// Retry 3 times
|
|
||||||
//
|
|
||||||
for (RetryCount=0; RetryCount<3; RetryCount++)
|
for (RetryCount=0; RetryCount<3; RetryCount++)
|
||||||
{
|
{
|
||||||
Int386(0x13, &RegsIn, &RegsOut);
|
Int386(0x13, &RegsIn, &RegsOut);
|
||||||
|
|
||||||
// If it worked break out
|
/* If it worked break out */
|
||||||
if (INT386_SUCCESS(RegsOut))
|
if (INT386_SUCCESS(RegsOut))
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// If it was a corrected ECC error then the data is still good
|
/* If it was a corrected ECC error then the data is still good */
|
||||||
else if (RegsOut.b.ah == 0x11)
|
else if (RegsOut.b.ah == 0x11)
|
||||||
{
|
{
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// If it failed the do the next retry
|
/* If it failed the do the next retry */
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PcDiskResetController(DriveNumber);
|
DiskResetController(DriveNumber);
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we retried 3 times then fail
|
/* If we retried 3 times then fail */
|
||||||
if (RetryCount >= 3)
|
if (RetryCount >= 3)
|
||||||
{
|
{
|
||||||
ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x\n", RegsOut.b.ah);
|
ERR("Disk Read Failed in CHS mode, after retrying 3 times: %x\n", RegsOut.b.ah);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// I have learned that not all bioses return
|
// I have learned that not all BIOSes return
|
||||||
// the sector read count in the AL register (at least mine doesn't)
|
// the sector read count in the AL register (at least mine doesn't)
|
||||||
// even if the sectors were read correctly. So instead
|
// even if the sectors were read correctly. So instead
|
||||||
// of checking the sector read count we will rely solely
|
// of checking the sector read count we will rely solely
|
||||||
|
@ -266,122 +256,287 @@ static BOOLEAN PcDiskReadLogicalSectorsCHS(UCHAR DriveNumber, ULONGLONG SectorNu
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber)
|
||||||
|
{
|
||||||
|
static UCHAR LastDriveNumber = 0xff;
|
||||||
|
static BOOLEAN LastSupported;
|
||||||
|
REGS RegsIn, RegsOut;
|
||||||
|
|
||||||
|
TRACE("DiskInt13ExtensionsSupported()\n");
|
||||||
|
|
||||||
|
if (DriveNumber == LastDriveNumber)
|
||||||
|
{
|
||||||
|
TRACE("Using cached value %s for drive 0x%x\n",
|
||||||
|
LastSupported ? "TRUE" : "FALSE", DriveNumber);
|
||||||
|
return LastSupported;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Some BIOSes report that extended disk access functions are not supported
|
||||||
|
* when booting from a CD (e.g. Phoenix BIOS v6.00PG and Insyde BIOS shipping
|
||||||
|
* with Intel Macs). Therefore we just return TRUE if we're booting from a CD -
|
||||||
|
* we can assume that all El Torito capable BIOSes support INT 13 extensions.
|
||||||
|
* We simply detect whether we're booting from CD by checking whether the drive
|
||||||
|
* number is >= 0x8A. It's 0x90 on the Insyde BIOS, and 0x9F on most other BIOSes.
|
||||||
|
*/
|
||||||
|
if (DriveNumber >= 0x8A)
|
||||||
|
{
|
||||||
|
LastSupported = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastDriveNumber = DriveNumber;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IBM/MS INT 13 Extensions - INSTALLATION CHECK
|
||||||
|
* AH = 41h
|
||||||
|
* BX = 55AAh
|
||||||
|
* DL = drive (80h-FFh)
|
||||||
|
* Return:
|
||||||
|
* CF set on error (extensions not supported)
|
||||||
|
* AH = 01h (invalid function)
|
||||||
|
* CF clear if successful
|
||||||
|
* BX = AA55h if installed
|
||||||
|
* AH = major version of extensions
|
||||||
|
* 01h = 1.x
|
||||||
|
* 20h = 2.0 / EDD-1.0
|
||||||
|
* 21h = 2.1 / EDD-1.1
|
||||||
|
* 30h = EDD-3.0
|
||||||
|
* AL = internal use
|
||||||
|
* CX = API subset support bitmap
|
||||||
|
* DH = extension version (v2.0+ ??? -- not present in 1.x)
|
||||||
|
*
|
||||||
|
* Bitfields for IBM/MS INT 13 Extensions API support bitmap
|
||||||
|
* Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported
|
||||||
|
* Bit 1, removable drive controller functions (AH=45h,46h,48h,49h,INT 15/AH=52h) supported
|
||||||
|
* Bit 2, enhanced disk drive (EDD) functions (AH=48h,AH=4Eh) supported
|
||||||
|
* extended drive parameter table is valid
|
||||||
|
* Bits 3-15 reserved
|
||||||
|
*/
|
||||||
|
RegsIn.b.ah = 0x41;
|
||||||
|
RegsIn.w.bx = 0x55AA;
|
||||||
|
RegsIn.b.dl = DriveNumber;
|
||||||
|
|
||||||
|
/* Reset the disk controller */
|
||||||
|
Int386(0x13, &RegsIn, &RegsOut);
|
||||||
|
|
||||||
|
if (!INT386_SUCCESS(RegsOut))
|
||||||
|
{
|
||||||
|
/* CF set on error (extensions not supported) */
|
||||||
|
LastSupported = FALSE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RegsOut.w.bx != 0xAA55)
|
||||||
|
{
|
||||||
|
/* BX = AA55h if installed */
|
||||||
|
LastSupported = FALSE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(RegsOut.w.cx & 0x0001))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* CX = API subset support bitmap.
|
||||||
|
* Bit 0, extended disk access functions (AH=42h-44h,47h,48h) supported.
|
||||||
|
*/
|
||||||
|
DbgPrint("Suspicious API subset support bitmap 0x%x on device 0x%lx\n",
|
||||||
|
RegsOut.w.cx, DriveNumber);
|
||||||
|
LastSupported = FALSE;
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
LastSupported = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||||
{
|
{
|
||||||
BOOLEAN ExtensionsSupported;
|
BOOLEAN ExtensionsSupported;
|
||||||
|
|
||||||
TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n", DriveNumber, SectorNumber, SectorCount, Buffer);
|
TRACE("PcDiskReadLogicalSectors() DriveNumber: 0x%x SectorNumber: %I64d SectorCount: %d Buffer: 0x%x\n",
|
||||||
|
DriveNumber, SectorNumber, SectorCount, Buffer);
|
||||||
|
|
||||||
//
|
/*
|
||||||
// Check to see if it is a fixed disk drive
|
* Check to see if it is a fixed disk drive.
|
||||||
// If so then check to see if Int13 extensions work
|
* If so then check to see if Int13 extensions work.
|
||||||
// If they do then use them, otherwise default back to BIOS calls
|
* If they do then use them, otherwise default back to BIOS calls.
|
||||||
//
|
*/
|
||||||
ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
|
ExtensionsSupported = DiskInt13ExtensionsSupported(DriveNumber);
|
||||||
|
|
||||||
if ((DriveNumber >= 0x80) && ExtensionsSupported)
|
if ((DriveNumber >= 0x80) && ExtensionsSupported)
|
||||||
{
|
{
|
||||||
TRACE("Using Int 13 Extensions for read. DiskInt13ExtensionsSupported(%d) = %s\n", DriveNumber, ExtensionsSupported ? "TRUE" : "FALSE");
|
TRACE("Using Int 13 Extensions for read. DiskInt13ExtensionsSupported(%d) = %s\n", DriveNumber, ExtensionsSupported ? "TRUE" : "FALSE");
|
||||||
|
|
||||||
//
|
/* LBA is easy, nothing to calculate. Just do the read. */
|
||||||
// LBA is easy, nothing to calculate
|
|
||||||
// Just do the read
|
|
||||||
//
|
|
||||||
return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
|
return PcDiskReadLogicalSectorsLBA(DriveNumber, SectorNumber, SectorCount, Buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// LBA is not supported default to the CHS calls
|
/* LBA is not supported default to the CHS calls */
|
||||||
return PcDiskReadLogicalSectorsCHS(DriveNumber, SectorNumber, SectorCount, Buffer);
|
return PcDiskReadLogicalSectorsCHS(DriveNumber, SectorNumber, SectorCount, Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VOID DiskStopFloppyMotor(VOID)
|
||||||
|
{
|
||||||
|
WRITE_PORT_UCHAR((PUCHAR)0x3F2, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize)
|
||||||
|
{
|
||||||
|
REGS RegsIn, RegsOut;
|
||||||
|
PUSHORT Ptr = (PUSHORT)(BIOSCALLBUFFER);
|
||||||
|
|
||||||
|
TRACE("DiskGetExtendedDriveParameters()\n");
|
||||||
|
|
||||||
|
if (!DiskInt13ExtensionsSupported(DriveNumber))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
/* Initialize transfer buffer */
|
||||||
|
*Ptr = BufferSize;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* BIOS Int 13h, function 48h - Get drive parameters
|
||||||
|
* AH = 48h
|
||||||
|
* DL = drive (bit 7 set for hard disk)
|
||||||
|
* DS:SI = result buffer
|
||||||
|
* Return:
|
||||||
|
* CF set on error
|
||||||
|
* AH = status (07h)
|
||||||
|
* CF clear if successful
|
||||||
|
* AH = 00h
|
||||||
|
* DS:SI -> result buffer
|
||||||
|
*/
|
||||||
|
RegsIn.b.ah = 0x48;
|
||||||
|
RegsIn.b.dl = DriveNumber;
|
||||||
|
RegsIn.x.ds = BIOSCALLBUFSEGMENT; // DS:SI -> result buffer
|
||||||
|
RegsIn.w.si = BIOSCALLBUFOFFSET;
|
||||||
|
|
||||||
|
/* Get drive parameters */
|
||||||
|
Int386(0x13, &RegsIn, &RegsOut);
|
||||||
|
if (!INT386_SUCCESS(RegsOut))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
memcpy(Buffer, Ptr, BufferSize);
|
||||||
|
|
||||||
|
#if DBG
|
||||||
|
TRACE("size of buffer: %x\n", Ptr[0]);
|
||||||
|
TRACE("information flags: %x\n", Ptr[1]);
|
||||||
|
TRACE("number of physical cylinders on drive: %u\n", *(PULONG)&Ptr[2]);
|
||||||
|
TRACE("number of physical heads on drive: %u\n", *(PULONG)&Ptr[4]);
|
||||||
|
TRACE("number of physical sectors per track: %u\n", *(PULONG)&Ptr[6]);
|
||||||
|
TRACE("total number of sectors on drive: %I64u\n", *(unsigned long long*)&Ptr[8]);
|
||||||
|
TRACE("bytes per sector: %u\n", Ptr[12]);
|
||||||
|
if (Ptr[0] >= 0x1e)
|
||||||
|
{
|
||||||
|
TRACE("EED configuration parameters: %x:%x\n", Ptr[13], Ptr[14]);
|
||||||
|
if (Ptr[13] != 0xffff && Ptr[14] != 0xffff)
|
||||||
|
{
|
||||||
|
PUCHAR SpecPtr = (PUCHAR)(ULONG_PTR)((Ptr[13] << 4) + Ptr[14]);
|
||||||
|
TRACE("SpecPtr: %x\n", SpecPtr);
|
||||||
|
TRACE("physical I/O port base address: %x\n", *(PUSHORT)&SpecPtr[0]);
|
||||||
|
TRACE("disk-drive control port address: %x\n", *(PUSHORT)&SpecPtr[2]);
|
||||||
|
TRACE("drive flags: %x\n", SpecPtr[4]);
|
||||||
|
TRACE("proprietary information: %x\n", SpecPtr[5]);
|
||||||
|
TRACE("IRQ for drive: %u\n", SpecPtr[6]);
|
||||||
|
TRACE("sector count for multi-sector transfers: %u\n", SpecPtr[7]);
|
||||||
|
TRACE("DMA control: %x\n", SpecPtr[8]);
|
||||||
|
TRACE("programmed I/O control: %x\n", SpecPtr[9]);
|
||||||
|
TRACE("drive options: %x\n", *(PUSHORT)&SpecPtr[10]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Ptr[0] >= 0x42)
|
||||||
|
{
|
||||||
|
TRACE("signature: %x\n", Ptr[15]);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
|
PcDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
|
||||||
{
|
{
|
||||||
EXTENDED_GEOMETRY ExtGeometry;
|
EXTENDED_GEOMETRY ExtGeometry;
|
||||||
REGS RegsIn;
|
REGS RegsIn, RegsOut;
|
||||||
REGS RegsOut;
|
ULONG Cylinders;
|
||||||
ULONG Cylinders;
|
|
||||||
|
|
||||||
TRACE("DiskGetDriveGeometry()\n");
|
TRACE("DiskGetDriveGeometry()\n");
|
||||||
|
|
||||||
/* Try to get the extended geometry first */
|
/* Try to get the extended geometry first */
|
||||||
ExtGeometry.Size = sizeof(EXTENDED_GEOMETRY);
|
ExtGeometry.Size = sizeof(ExtGeometry);
|
||||||
if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
|
if (DiskGetExtendedDriveParameters(DriveNumber, &ExtGeometry, ExtGeometry.Size))
|
||||||
{
|
|
||||||
Geometry->Cylinders = ExtGeometry.Cylinders;
|
|
||||||
Geometry->Heads = ExtGeometry.Heads;
|
|
||||||
Geometry->Sectors = ExtGeometry.SectorsPerTrack;
|
|
||||||
Geometry->BytesPerSector = ExtGeometry.BytesPerSector;
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* BIOS Int 13h, function 08h - Get drive parameters
|
|
||||||
* AH = 08h
|
|
||||||
* DL = drive (bit 7 set for hard disk)
|
|
||||||
* ES:DI = 0000h:0000h to guard against BIOS bugs
|
|
||||||
* Return:
|
|
||||||
* CF set on error
|
|
||||||
* AH = status (07h)
|
|
||||||
* CF clear if successful
|
|
||||||
* AH = 00h
|
|
||||||
* AL = 00h on at least some BIOSes
|
|
||||||
* BL = drive type (AT/PS2 floppies only)
|
|
||||||
* CH = low eight bits of maximum cylinder number
|
|
||||||
* CL = maximum sector number (bits 5-0)
|
|
||||||
* high two bits of maximum cylinder number (bits 7-6)
|
|
||||||
* DH = maximum head number
|
|
||||||
* DL = number of drives
|
|
||||||
* ES:DI -> drive parameter table (floppies only)
|
|
||||||
*/
|
|
||||||
RegsIn.b.ah = 0x08;
|
|
||||||
RegsIn.b.dl = DriveNumber;
|
|
||||||
RegsIn.w.es = 0x0000;
|
|
||||||
RegsIn.w.di = 0x0000;
|
|
||||||
|
|
||||||
/* Get drive parameters */
|
|
||||||
Int386(0x13, &RegsIn, &RegsOut);
|
|
||||||
|
|
||||||
if (! INT386_SUCCESS(RegsOut))
|
|
||||||
{
|
{
|
||||||
return FALSE;
|
Geometry->Cylinders = ExtGeometry.Cylinders;
|
||||||
|
Geometry->Heads = ExtGeometry.Heads;
|
||||||
|
Geometry->Sectors = ExtGeometry.SectorsPerTrack;
|
||||||
|
Geometry->BytesPerSector = ExtGeometry.BytesPerSector;
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cylinders = (RegsOut.b.cl & 0xC0) << 2;
|
/*
|
||||||
Cylinders += RegsOut.b.ch;
|
* BIOS Int 13h, function 08h - Get drive parameters
|
||||||
Cylinders++;
|
* AH = 08h
|
||||||
Geometry->Cylinders = Cylinders;
|
* DL = drive (bit 7 set for hard disk)
|
||||||
Geometry->Heads = RegsOut.b.dh + 1;
|
* ES:DI = 0000h:0000h to guard against BIOS bugs
|
||||||
Geometry->Sectors = RegsOut.b.cl & 0x3F;
|
* Return:
|
||||||
Geometry->BytesPerSector = 512; /* Just assume 512 bytes per sector */
|
* CF set on error
|
||||||
|
* AH = status (07h)
|
||||||
|
* CF clear if successful
|
||||||
|
* AH = 00h
|
||||||
|
* AL = 00h on at least some BIOSes
|
||||||
|
* BL = drive type (AT/PS2 floppies only)
|
||||||
|
* CH = low eight bits of maximum cylinder number
|
||||||
|
* CL = maximum sector number (bits 5-0)
|
||||||
|
* high two bits of maximum cylinder number (bits 7-6)
|
||||||
|
* DH = maximum head number
|
||||||
|
* DL = number of drives
|
||||||
|
* ES:DI -> drive parameter table (floppies only)
|
||||||
|
*/
|
||||||
|
RegsIn.b.ah = 0x08;
|
||||||
|
RegsIn.b.dl = DriveNumber;
|
||||||
|
RegsIn.w.es = 0x0000;
|
||||||
|
RegsIn.w.di = 0x0000;
|
||||||
|
|
||||||
return TRUE;
|
/* Get drive parameters */
|
||||||
|
Int386(0x13, &RegsIn, &RegsOut);
|
||||||
|
if (!INT386_SUCCESS(RegsOut))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
Cylinders = (RegsOut.b.cl & 0xC0) << 2;
|
||||||
|
Cylinders += RegsOut.b.ch;
|
||||||
|
Cylinders++;
|
||||||
|
Geometry->Cylinders = Cylinders;
|
||||||
|
Geometry->Heads = RegsOut.b.dh + 1;
|
||||||
|
Geometry->Sectors = RegsOut.b.cl & 0x3F;
|
||||||
|
Geometry->BytesPerSector = 512; /* Just assume 512 bytes per sector */
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
PcDiskGetCacheableBlockCount(UCHAR DriveNumber)
|
PcDiskGetCacheableBlockCount(UCHAR DriveNumber)
|
||||||
{
|
{
|
||||||
GEOMETRY Geometry;
|
GEOMETRY Geometry;
|
||||||
|
|
||||||
/* If LBA is supported then the block size will be 64 sectors (32k)
|
/* If LBA is supported then the block size will be 64 sectors (32k)
|
||||||
* If not then the block size is the size of one track */
|
* If not then the block size is the size of one track. */
|
||||||
if (DiskInt13ExtensionsSupported(DriveNumber))
|
if (DiskInt13ExtensionsSupported(DriveNumber))
|
||||||
{
|
{
|
||||||
return 64;
|
return 64;
|
||||||
}
|
}
|
||||||
/* Get the disk geometry
|
/* Get the disk geometry. If this fails then we will
|
||||||
* If this fails then we will just return 1 sector to be safe */
|
* just return 1 sector to be safe. */
|
||||||
else if (! PcDiskGetDriveGeometry(DriveNumber, &Geometry))
|
else if (! PcDiskGetDriveGeometry(DriveNumber, &Geometry))
|
||||||
{
|
{
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return Geometry.Sectors;
|
return Geometry.Sectors;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -36,22 +36,22 @@ DBG_DEFAULT_CHANNEL(DISK);
|
||||||
|
|
||||||
static struct
|
static struct
|
||||||
{
|
{
|
||||||
ULONG SectorCountBeforePartition;
|
ULONG SectorCountBeforePartition;
|
||||||
ULONG PartitionSectorCount;
|
ULONG PartitionSectorCount;
|
||||||
UCHAR SystemIndicator;
|
UCHAR SystemIndicator;
|
||||||
} XboxPartitions[] =
|
} XboxPartitions[] =
|
||||||
{
|
{
|
||||||
/* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */
|
/* This is in the \Device\Harddisk0\Partition.. order used by the Xbox kernel */
|
||||||
{ 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store, E: */
|
{ 0x0055F400, 0x0098f800, PARTITION_FAT32 }, /* Store , E: */
|
||||||
{ 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */
|
{ 0x00465400, 0x000FA000, PARTITION_FAT_16 }, /* System, C: */
|
||||||
{ 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */
|
{ 0x00000400, 0x00177000, PARTITION_FAT_16 }, /* Cache1, X: */
|
||||||
{ 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */
|
{ 0x00177400, 0x00177000, PARTITION_FAT_16 }, /* Cache2, Y: */
|
||||||
{ 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */
|
{ 0x002EE400, 0x00177000, PARTITION_FAT_16 } /* Cache3, Z: */
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IDE_SECTOR_BUF_SZ 512
|
#define IDE_SECTOR_BUF_SZ 512
|
||||||
#define IDE_MAX_POLL_RETRIES 100000
|
#define IDE_MAX_POLL_RETRIES 100000
|
||||||
#define IDE_MAX_BUSY_RETRIES 50000
|
#define IDE_MAX_BUSY_RETRIES 50000
|
||||||
|
|
||||||
/* Control Block offsets and masks */
|
/* Control Block offsets and masks */
|
||||||
#define IDE_REG_ALT_STATUS 0x0000
|
#define IDE_REG_ALT_STATUS 0x0000
|
||||||
|
@ -111,131 +111,131 @@ static struct
|
||||||
* Each macro takes an address of the command port block, and data
|
* Each macro takes an address of the command port block, and data
|
||||||
*/
|
*/
|
||||||
#define IDEReadError(Address) \
|
#define IDEReadError(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ERROR)))
|
||||||
#define IDEWritePrecomp(Address, Data) \
|
#define IDEWritePrecomp(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_PRECOMP), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_PRECOMP), (Data)))
|
||||||
#define IDEReadSectorCount(Address) \
|
#define IDEReadSectorCount(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT)))
|
||||||
#define IDEWriteSectorCount(Address, Data) \
|
#define IDEWriteSectorCount(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_CNT), (Data)))
|
||||||
#define IDEReadSectorNum(Address) \
|
#define IDEReadSectorNum(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM)))
|
||||||
#define IDEWriteSectorNum(Address, Data) \
|
#define IDEWriteSectorNum(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_SECTOR_NUM), (Data)))
|
||||||
#define IDEReadCylinderLow(Address) \
|
#define IDEReadCylinderLow(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW)))
|
||||||
#define IDEWriteCylinderLow(Address, Data) \
|
#define IDEWriteCylinderLow(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_LOW), (Data)))
|
||||||
#define IDEReadCylinderHigh(Address) \
|
#define IDEReadCylinderHigh(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH)))
|
||||||
#define IDEWriteCylinderHigh(Address, Data) \
|
#define IDEWriteCylinderHigh(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_CYL_HIGH), (Data)))
|
||||||
#define IDEReadDriveHead(Address) \
|
#define IDEReadDriveHead(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD)))
|
||||||
#define IDEWriteDriveHead(Address, Data) \
|
#define IDEWriteDriveHead(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DRV_HEAD), (Data)))
|
||||||
#define IDEReadStatus(Address) \
|
#define IDEReadStatus(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_STATUS)))
|
||||||
#define IDEWriteCommand(Address, Data) \
|
#define IDEWriteCommand(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_COMMAND), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_COMMAND), (Data)))
|
||||||
#define IDEReadDMACommand(Address) \
|
#define IDEReadDMACommand(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address))))
|
(READ_PORT_UCHAR((PUCHAR)((Address))))
|
||||||
#define IDEWriteDMACommand(Address, Data) \
|
#define IDEWriteDMACommand(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address)), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address)), (Data)))
|
||||||
#define IDEReadDMAStatus(Address) \
|
#define IDEReadDMAStatus(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + 2)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + 2)))
|
||||||
#define IDEWriteDMAStatus(Address, Data) \
|
#define IDEWriteDMAStatus(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + 2), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + 2), (Data)))
|
||||||
#define IDEWritePRDTable(Address, Data) \
|
#define IDEWritePRDTable(Address, Data) \
|
||||||
(WRITE_PORT_ULONG((PULONG)((Address) + 4), (Data)))
|
(WRITE_PORT_ULONG((PULONG)((Address) + 4), (Data)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data block read and write commands
|
* Data block read and write commands
|
||||||
*/
|
*/
|
||||||
#define IDEReadBlock(Address, Buffer, Count) \
|
#define IDEReadBlock(Address, Buffer, Count) \
|
||||||
(READ_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2))
|
(READ_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2))
|
||||||
#define IDEWriteBlock(Address, Buffer, Count) \
|
#define IDEWriteBlock(Address, Buffer, Count) \
|
||||||
(WRITE_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2))
|
(WRITE_PORT_BUFFER_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT), (PUSHORT)(Buffer), (Count) / 2))
|
||||||
|
|
||||||
#define IDEReadBlock32(Address, Buffer, Count) \
|
#define IDEReadBlock32(Address, Buffer, Count) \
|
||||||
(READ_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4))
|
(READ_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4))
|
||||||
#define IDEWriteBlock32(Address, Buffer, Count) \
|
#define IDEWriteBlock32(Address, Buffer, Count) \
|
||||||
(WRITE_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4))
|
(WRITE_PORT_BUFFER_ULONG((PULONG)((Address) + IDE_REG_DATA_PORT), (PULONG)(Buffer), (Count) / 4))
|
||||||
|
|
||||||
#define IDEReadWord(Address) \
|
#define IDEReadWord(Address) \
|
||||||
(READ_PORT_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT)))
|
(READ_PORT_USHORT((PUSHORT)((Address) + IDE_REG_DATA_PORT)))
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Access macros for control registers
|
* Access macros for control registers
|
||||||
* Each macro takes an address of the control port blank and data
|
* Each macro takes an address of the control port blank and data
|
||||||
*/
|
*/
|
||||||
#define IDEReadAltStatus(Address) \
|
#define IDEReadAltStatus(Address) \
|
||||||
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ALT_STATUS)))
|
(READ_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_ALT_STATUS)))
|
||||||
#define IDEWriteDriveControl(Address, Data) \
|
#define IDEWriteDriveControl(Address, Data) \
|
||||||
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data)))
|
(WRITE_PORT_UCHAR((PUCHAR)((Address) + IDE_REG_DEV_CNTRL), (Data)))
|
||||||
|
|
||||||
/* IDE_DRIVE_IDENTIFY */
|
/* IDE_DRIVE_IDENTIFY */
|
||||||
|
|
||||||
typedef struct _IDE_DRIVE_IDENTIFY
|
typedef struct _IDE_DRIVE_IDENTIFY
|
||||||
{
|
{
|
||||||
USHORT ConfigBits; /*00*/
|
USHORT ConfigBits; /*00*/
|
||||||
USHORT LogicalCyls; /*01*/
|
USHORT LogicalCyls; /*01*/
|
||||||
USHORT Reserved02; /*02*/
|
USHORT Reserved02; /*02*/
|
||||||
USHORT LogicalHeads; /*03*/
|
USHORT LogicalHeads; /*03*/
|
||||||
USHORT BytesPerTrack; /*04*/
|
USHORT BytesPerTrack; /*04*/
|
||||||
USHORT BytesPerSector; /*05*/
|
USHORT BytesPerSector; /*05*/
|
||||||
USHORT SectorsPerTrack; /*06*/
|
USHORT SectorsPerTrack; /*06*/
|
||||||
UCHAR InterSectorGap; /*07*/
|
UCHAR InterSectorGap; /*07*/
|
||||||
UCHAR InterSectorGapSize;
|
UCHAR InterSectorGapSize;
|
||||||
UCHAR Reserved08H; /*08*/
|
UCHAR Reserved08H; /*08*/
|
||||||
UCHAR BytesInPLO;
|
UCHAR BytesInPLO;
|
||||||
USHORT VendorUniqueCnt; /*09*/
|
USHORT VendorUniqueCnt; /*09*/
|
||||||
char SerialNumber[20]; /*10*/
|
UCHAR SerialNumber[20]; /*10*/
|
||||||
USHORT ControllerType; /*20*/
|
USHORT ControllerType; /*20*/
|
||||||
USHORT BufferSize; /*21*/
|
USHORT BufferSize; /*21*/
|
||||||
USHORT ECCByteCnt; /*22*/
|
USHORT ECCByteCnt; /*22*/
|
||||||
char FirmwareRev[8]; /*23*/
|
UCHAR FirmwareRev[8]; /*23*/
|
||||||
char ModelNumber[40]; /*27*/
|
UCHAR ModelNumber[40]; /*27*/
|
||||||
USHORT RWMultImplemented; /*47*/
|
USHORT RWMultImplemented; /*47*/
|
||||||
USHORT DWordIo; /*48*/
|
USHORT DWordIo; /*48*/
|
||||||
USHORT Capabilities; /*49*/
|
USHORT Capabilities; /*49*/
|
||||||
#define IDE_DRID_STBY_SUPPORTED 0x2000
|
#define IDE_DRID_STBY_SUPPORTED 0x2000
|
||||||
#define IDE_DRID_IORDY_SUPPORTED 0x0800
|
#define IDE_DRID_IORDY_SUPPORTED 0x0800
|
||||||
#define IDE_DRID_IORDY_DISABLE 0x0400
|
#define IDE_DRID_IORDY_DISABLE 0x0400
|
||||||
#define IDE_DRID_LBA_SUPPORTED 0x0200
|
#define IDE_DRID_LBA_SUPPORTED 0x0200
|
||||||
#define IDE_DRID_DMA_SUPPORTED 0x0100
|
#define IDE_DRID_DMA_SUPPORTED 0x0100
|
||||||
USHORT Reserved50; /*50*/
|
USHORT Reserved50; /*50*/
|
||||||
USHORT MinPIOTransTime; /*51*/
|
USHORT MinPIOTransTime; /*51*/
|
||||||
USHORT MinDMATransTime; /*52*/
|
USHORT MinDMATransTime; /*52*/
|
||||||
USHORT TMFieldsValid; /*53*/
|
USHORT TMFieldsValid; /*53*/
|
||||||
USHORT TMCylinders; /*54*/
|
USHORT TMCylinders; /*54*/
|
||||||
USHORT TMHeads; /*55*/
|
USHORT TMHeads; /*55*/
|
||||||
USHORT TMSectorsPerTrk; /*56*/
|
USHORT TMSectorsPerTrk; /*56*/
|
||||||
USHORT TMCapacityLo; /*57*/
|
USHORT TMCapacityLo; /*57*/
|
||||||
USHORT TMCapacityHi; /*58*/
|
USHORT TMCapacityHi; /*58*/
|
||||||
USHORT RWMultCurrent; /*59*/
|
USHORT RWMultCurrent; /*59*/
|
||||||
USHORT TMSectorCountLo; /*60*/
|
USHORT TMSectorCountLo; /*60*/
|
||||||
USHORT TMSectorCountHi; /*61*/
|
USHORT TMSectorCountHi; /*61*/
|
||||||
USHORT DmaModes; /*62*/
|
USHORT DmaModes; /*62*/
|
||||||
USHORT MultiDmaModes; /*63*/
|
USHORT MultiDmaModes; /*63*/
|
||||||
USHORT Reserved64[5]; /*64*/
|
USHORT Reserved64[5]; /*64*/
|
||||||
USHORT Reserved69[2]; /*69*/
|
USHORT Reserved69[2]; /*69*/
|
||||||
USHORT Reserved71[4]; /*71*/
|
USHORT Reserved71[4]; /*71*/
|
||||||
USHORT MaxQueueDepth; /*75*/
|
USHORT MaxQueueDepth; /*75*/
|
||||||
USHORT Reserved76[4]; /*76*/
|
USHORT Reserved76[4]; /*76*/
|
||||||
USHORT MajorRevision; /*80*/
|
USHORT MajorRevision; /*80*/
|
||||||
USHORT MinorRevision; /*81*/
|
USHORT MinorRevision; /*81*/
|
||||||
USHORT SupportedFeatures82; /*82*/
|
USHORT SupportedFeatures82; /*82*/
|
||||||
USHORT SupportedFeatures83; /*83*/
|
USHORT SupportedFeatures83; /*83*/
|
||||||
USHORT SupportedFeatures84; /*84*/
|
USHORT SupportedFeatures84; /*84*/
|
||||||
USHORT EnabledFeatures85; /*85*/
|
USHORT EnabledFeatures85; /*85*/
|
||||||
USHORT EnabledFeatures86; /*86*/
|
USHORT EnabledFeatures86; /*86*/
|
||||||
USHORT EnabledFeatures87; /*87*/
|
USHORT EnabledFeatures87; /*87*/
|
||||||
USHORT UltraDmaModes; /*88*/
|
USHORT UltraDmaModes; /*88*/
|
||||||
USHORT Reserved89[11]; /*89*/
|
USHORT Reserved89[11]; /*89*/
|
||||||
USHORT Max48BitAddress[4]; /*100*/
|
USHORT Max48BitAddress[4]; /*100*/
|
||||||
USHORT Reserved104[151]; /*104*/
|
USHORT Reserved104[151]; /*104*/
|
||||||
USHORT Checksum; /*255*/
|
USHORT Checksum; /*255*/
|
||||||
} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
|
} IDE_DRIVE_IDENTIFY, *PIDE_DRIVE_IDENTIFY;
|
||||||
|
|
||||||
/* XboxDiskPolledRead
|
/* XboxDiskPolledRead
|
||||||
|
@ -247,21 +247,20 @@ typedef struct _IDE_DRIVE_IDENTIFY
|
||||||
* PASSIVE_LEVEL
|
* PASSIVE_LEVEL
|
||||||
*
|
*
|
||||||
* ARGUMENTS:
|
* ARGUMENTS:
|
||||||
* ULONG CommandPort Address of command port for drive
|
* ULONG CommandPort Address of command port for drive
|
||||||
* ULONG ControlPort Address of control port for drive
|
* ULONG ControlPort Address of control port for drive
|
||||||
* UCHAR PreComp Value to write to precomp register
|
* UCHAR PreComp Value to write to precomp register
|
||||||
* UCHAR SectorCnt Value to write to sectorCnt register
|
* UCHAR SectorCnt Value to write to sectorCnt register
|
||||||
* UCHAR SectorNum Value to write to sectorNum register
|
* UCHAR SectorNum Value to write to sectorNum register
|
||||||
* UCHAR CylinderLow Value to write to CylinderLow register
|
* UCHAR CylinderLow Value to write to CylinderLow register
|
||||||
* UCHAR CylinderHigh Value to write to CylinderHigh register
|
* UCHAR CylinderHigh Value to write to CylinderHigh register
|
||||||
* UCHAR DrvHead Value to write to Drive/Head register
|
* UCHAR DrvHead Value to write to Drive/Head register
|
||||||
* UCHAR Command Value to write to Command register
|
* UCHAR Command Value to write to Command register
|
||||||
* PVOID Buffer Buffer for output data
|
* PVOID Buffer Buffer for output data
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
* BOOLEAN: TRUE success, FALSE error
|
* BOOLEAN: TRUE success, FALSE error
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static BOOLEAN
|
static BOOLEAN
|
||||||
XboxDiskPolledRead(ULONG CommandPort,
|
XboxDiskPolledRead(ULONG CommandPort,
|
||||||
ULONG ControlPort,
|
ULONG ControlPort,
|
||||||
|
@ -274,300 +273,296 @@ XboxDiskPolledRead(ULONG CommandPort,
|
||||||
UCHAR Command,
|
UCHAR Command,
|
||||||
PVOID Buffer)
|
PVOID Buffer)
|
||||||
{
|
{
|
||||||
ULONG SectorCount = 0;
|
ULONG SectorCount = 0;
|
||||||
ULONG RetryCount;
|
ULONG RetryCount;
|
||||||
BOOLEAN Junk = FALSE;
|
BOOLEAN Junk = FALSE;
|
||||||
UCHAR Status;
|
UCHAR Status;
|
||||||
|
|
||||||
/* Wait for BUSY to clear */
|
/* Wait for BUSY to clear */
|
||||||
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
|
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
|
||||||
{
|
{
|
||||||
Status = IDEReadStatus(CommandPort);
|
Status = IDEReadStatus(CommandPort);
|
||||||
if (!(Status & IDE_SR_BUSY))
|
if (!(Status & IDE_SR_BUSY))
|
||||||
|
break;
|
||||||
|
|
||||||
|
StallExecutionProcessor(10);
|
||||||
|
}
|
||||||
|
TRACE("status=0x%x\n", Status);
|
||||||
|
TRACE("waited %d usecs for busy to clear\n", RetryCount * 10);
|
||||||
|
if (RetryCount >= IDE_MAX_BUSY_RETRIES)
|
||||||
|
{
|
||||||
|
WARN("Drive is BUSY for too long\n");
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write Drive/Head to select drive */
|
||||||
|
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
|
||||||
|
StallExecutionProcessor(500);
|
||||||
|
|
||||||
|
/* Disable interrupts */
|
||||||
|
IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
|
||||||
|
StallExecutionProcessor(500);
|
||||||
|
|
||||||
|
/* Issue command to drive */
|
||||||
|
if (DrvHead & IDE_DH_LBA)
|
||||||
|
{
|
||||||
|
TRACE("READ:DRV=%d:LBA=1:BLK=%d:SC=0x%x:CM=0x%x\n",
|
||||||
|
DrvHead & IDE_DH_DRV1 ? 1 : 0,
|
||||||
|
((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
|
||||||
|
SectorCnt,
|
||||||
|
Command);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
TRACE("READ:DRV=%d:LBA=0:CH=0x%x:CL=0x%x:HD=0x%x:SN=0x%x:SC=0x%x:CM=0x%x\n",
|
||||||
|
DrvHead & IDE_DH_DRV1 ? 1 : 0,
|
||||||
|
CylinderHigh,
|
||||||
|
CylinderLow,
|
||||||
|
DrvHead & 0x0f,
|
||||||
|
SectorNum,
|
||||||
|
SectorCnt,
|
||||||
|
Command);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup command parameters */
|
||||||
|
IDEWritePrecomp(CommandPort, PreComp);
|
||||||
|
IDEWriteSectorCount(CommandPort, SectorCnt);
|
||||||
|
IDEWriteSectorNum(CommandPort, SectorNum);
|
||||||
|
IDEWriteCylinderHigh(CommandPort, CylinderHigh);
|
||||||
|
IDEWriteCylinderLow(CommandPort, CylinderLow);
|
||||||
|
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
|
||||||
|
|
||||||
|
/* Issue the command */
|
||||||
|
IDEWriteCommand(CommandPort, Command);
|
||||||
|
StallExecutionProcessor(50);
|
||||||
|
|
||||||
|
/* Wait for DRQ or error */
|
||||||
|
for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
|
||||||
|
{
|
||||||
|
Status = IDEReadStatus(CommandPort);
|
||||||
|
if (!(Status & IDE_SR_BUSY))
|
||||||
{
|
{
|
||||||
break;
|
if (Status & IDE_SR_ERR)
|
||||||
}
|
|
||||||
StallExecutionProcessor(10);
|
|
||||||
}
|
|
||||||
TRACE("status=0x%x\n", Status);
|
|
||||||
TRACE("waited %d usecs for busy to clear\n", RetryCount * 10);
|
|
||||||
if (RetryCount >= IDE_MAX_BUSY_RETRIES)
|
|
||||||
{
|
|
||||||
WARN("Drive is BUSY for too long\n");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Write Drive/Head to select drive */
|
|
||||||
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
|
|
||||||
StallExecutionProcessor(500);
|
|
||||||
|
|
||||||
/* Disable interrupts */
|
|
||||||
IDEWriteDriveControl(ControlPort, IDE_DC_nIEN);
|
|
||||||
StallExecutionProcessor(500);
|
|
||||||
|
|
||||||
/* Issue command to drive */
|
|
||||||
if (DrvHead & IDE_DH_LBA)
|
|
||||||
{
|
|
||||||
TRACE("READ:DRV=%d:LBA=1:BLK=%d:SC=0x%x:CM=0x%x\n",
|
|
||||||
DrvHead & IDE_DH_DRV1 ? 1 : 0,
|
|
||||||
((DrvHead & 0x0f) << 24) + (CylinderHigh << 16) + (CylinderLow << 8) + SectorNum,
|
|
||||||
SectorCnt,
|
|
||||||
Command);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
TRACE("READ:DRV=%d:LBA=0:CH=0x%x:CL=0x%x:HD=0x%x:SN=0x%x:SC=0x%x:CM=0x%x\n",
|
|
||||||
DrvHead & IDE_DH_DRV1 ? 1 : 0,
|
|
||||||
CylinderHigh,
|
|
||||||
CylinderLow,
|
|
||||||
DrvHead & 0x0f,
|
|
||||||
SectorNum,
|
|
||||||
SectorCnt,
|
|
||||||
Command);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Setup command parameters */
|
|
||||||
IDEWritePrecomp(CommandPort, PreComp);
|
|
||||||
IDEWriteSectorCount(CommandPort, SectorCnt);
|
|
||||||
IDEWriteSectorNum(CommandPort, SectorNum);
|
|
||||||
IDEWriteCylinderHigh(CommandPort, CylinderHigh);
|
|
||||||
IDEWriteCylinderLow(CommandPort, CylinderLow);
|
|
||||||
IDEWriteDriveHead(CommandPort, IDE_DH_FIXED | DrvHead);
|
|
||||||
|
|
||||||
/* Issue the command */
|
|
||||||
IDEWriteCommand(CommandPort, Command);
|
|
||||||
StallExecutionProcessor(50);
|
|
||||||
|
|
||||||
/* wait for DRQ or error */
|
|
||||||
for (RetryCount = 0; RetryCount < IDE_MAX_POLL_RETRIES; RetryCount++)
|
|
||||||
{
|
|
||||||
Status = IDEReadStatus(CommandPort);
|
|
||||||
if (!(Status & IDE_SR_BUSY))
|
|
||||||
{
|
|
||||||
if (Status & IDE_SR_ERR)
|
|
||||||
{
|
|
||||||
IDEWriteDriveControl(ControlPort, 0);
|
|
||||||
StallExecutionProcessor(50);
|
|
||||||
IDEReadStatus(CommandPort);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Status & IDE_SR_DRQ)
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
IDEWriteDriveControl(ControlPort, 0);
|
|
||||||
StallExecutionProcessor(50);
|
|
||||||
IDEReadStatus(CommandPort);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
StallExecutionProcessor(10);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* timed out */
|
|
||||||
if (RetryCount >= IDE_MAX_POLL_RETRIES)
|
|
||||||
{
|
|
||||||
IDEWriteDriveControl(ControlPort, 0);
|
|
||||||
StallExecutionProcessor(50);
|
|
||||||
IDEReadStatus(CommandPort);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (1)
|
|
||||||
{
|
|
||||||
/* Read data into buffer */
|
|
||||||
if (Junk == FALSE)
|
|
||||||
{
|
|
||||||
IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
|
|
||||||
Buffer = (PVOID)((ULONG_PTR)Buffer + IDE_SECTOR_BUF_SZ);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
|
|
||||||
IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
|
|
||||||
}
|
|
||||||
SectorCount++;
|
|
||||||
|
|
||||||
/* Check for error or more sectors to read */
|
|
||||||
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
|
|
||||||
{
|
|
||||||
Status = IDEReadStatus(CommandPort);
|
|
||||||
if (!(Status & IDE_SR_BUSY))
|
|
||||||
{
|
|
||||||
if (Status & IDE_SR_ERR)
|
|
||||||
{
|
|
||||||
IDEWriteDriveControl(ControlPort, 0);
|
|
||||||
StallExecutionProcessor(50);
|
|
||||||
IDEReadStatus(CommandPort);
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
if (Status & IDE_SR_DRQ)
|
|
||||||
{
|
|
||||||
if (SectorCount >= SectorCnt)
|
|
||||||
{
|
{
|
||||||
TRACE("Buffer size exceeded!\n");
|
IDEWriteDriveControl(ControlPort, 0);
|
||||||
Junk = TRUE;
|
StallExecutionProcessor(50);
|
||||||
|
IDEReadStatus(CommandPort);
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (SectorCount > SectorCnt)
|
|
||||||
{
|
|
||||||
TRACE("Read %lu sectors of junk!\n",
|
|
||||||
SectorCount - SectorCnt);
|
|
||||||
}
|
|
||||||
IDEWriteDriveControl(ControlPort, 0);
|
|
||||||
StallExecutionProcessor(50);
|
|
||||||
IDEReadStatus(CommandPort);
|
|
||||||
|
|
||||||
return TRUE;
|
if (Status & IDE_SR_DRQ)
|
||||||
}
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
IDEWriteDriveControl(ControlPort, 0);
|
||||||
|
StallExecutionProcessor(50);
|
||||||
|
IDEReadStatus(CommandPort);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
StallExecutionProcessor(10);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Timed out */
|
||||||
|
if (RetryCount >= IDE_MAX_POLL_RETRIES)
|
||||||
|
{
|
||||||
|
IDEWriteDriveControl(ControlPort, 0);
|
||||||
|
StallExecutionProcessor(50);
|
||||||
|
IDEReadStatus(CommandPort);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
/* Read data into buffer */
|
||||||
|
if (Junk == FALSE)
|
||||||
|
{
|
||||||
|
IDEReadBlock(CommandPort, Buffer, IDE_SECTOR_BUF_SZ);
|
||||||
|
Buffer = (PVOID)((ULONG_PTR)Buffer + IDE_SECTOR_BUF_SZ);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UCHAR JunkBuffer[IDE_SECTOR_BUF_SZ];
|
||||||
|
IDEReadBlock(CommandPort, JunkBuffer, IDE_SECTOR_BUF_SZ);
|
||||||
|
}
|
||||||
|
SectorCount++;
|
||||||
|
|
||||||
|
/* Check for error or more sectors to read */
|
||||||
|
for (RetryCount = 0; RetryCount < IDE_MAX_BUSY_RETRIES; RetryCount++)
|
||||||
|
{
|
||||||
|
Status = IDEReadStatus(CommandPort);
|
||||||
|
if (!(Status & IDE_SR_BUSY))
|
||||||
|
{
|
||||||
|
if (Status & IDE_SR_ERR)
|
||||||
|
{
|
||||||
|
IDEWriteDriveControl(ControlPort, 0);
|
||||||
|
StallExecutionProcessor(50);
|
||||||
|
IDEReadStatus(CommandPort);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
if (Status & IDE_SR_DRQ)
|
||||||
|
{
|
||||||
|
if (SectorCount >= SectorCnt)
|
||||||
|
{
|
||||||
|
TRACE("Buffer size exceeded!\n");
|
||||||
|
Junk = TRUE;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (SectorCount > SectorCnt)
|
||||||
|
{
|
||||||
|
TRACE("Read %lu sectors of junk!\n",
|
||||||
|
SectorCount - SectorCnt);
|
||||||
|
}
|
||||||
|
|
||||||
|
IDEWriteDriveControl(ControlPort, 0);
|
||||||
|
StallExecutionProcessor(50);
|
||||||
|
IDEReadStatus(CommandPort);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer)
|
||||||
{
|
{
|
||||||
ULONG StartSector;
|
ULONG StartSector;
|
||||||
UCHAR Count;
|
UCHAR Count;
|
||||||
|
|
||||||
if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f))
|
if (DriveNumber < 0x80 || 2 <= (DriveNumber & 0x0f))
|
||||||
{
|
{
|
||||||
/* Xbox has only 1 IDE controller and no floppy */
|
/* Xbox has only 1 IDE controller and no floppy */
|
||||||
WARN("Invalid drive number\n");
|
WARN("Invalid drive number\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (UINT64_C(0) != ((SectorNumber + SectorCount) & UINT64_C(0xfffffffff0000000)))
|
if (UINT64_C(0) != ((SectorNumber + SectorCount) & UINT64_C(0xfffffffff0000000)))
|
||||||
{
|
{
|
||||||
FIXME("48bit LBA required but not implemented\n");
|
FIXME("48bit LBA required but not implemented\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
StartSector = (ULONG) SectorNumber;
|
StartSector = (ULONG) SectorNumber;
|
||||||
while (0 < SectorCount)
|
while (0 < SectorCount)
|
||||||
{
|
{
|
||||||
Count = (SectorCount <= 255 ? (UCHAR)SectorCount : 255);
|
Count = (SectorCount <= 255 ? (UCHAR)SectorCount : 255);
|
||||||
if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
|
if (!XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
|
||||||
XBOX_IDE_CONTROL_PORT,
|
XBOX_IDE_CONTROL_PORT,
|
||||||
0, Count,
|
0, Count,
|
||||||
StartSector & 0xff,
|
StartSector & 0xff,
|
||||||
(StartSector >> 8) & 0xff,
|
(StartSector >> 8) & 0xff,
|
||||||
(StartSector >> 16) & 0xff,
|
(StartSector >> 16) & 0xff,
|
||||||
((StartSector >> 24) & 0x0f) | IDE_DH_LBA |
|
((StartSector >> 24) & 0x0f) | IDE_DH_LBA |
|
||||||
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
|
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
|
||||||
IDE_CMD_READ,
|
IDE_CMD_READ,
|
||||||
Buffer))
|
Buffer))
|
||||||
{
|
{
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
SectorCount -= Count;
|
SectorCount -= Count;
|
||||||
Buffer = (PVOID) ((PCHAR) Buffer + Count * IDE_SECTOR_BUF_SZ);
|
Buffer = (PVOID) ((PCHAR) Buffer + Count * IDE_SECTOR_BUF_SZ);
|
||||||
}
|
}
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
XboxDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
|
XboxDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry)
|
||||||
{
|
{
|
||||||
UCHAR SectorData[IDE_SECTOR_BUF_SZ];
|
UCHAR SectorData[IDE_SECTOR_BUF_SZ];
|
||||||
|
|
||||||
/* This is the Xbox, chances are that there is a Xbox-standard partitionless
|
/*
|
||||||
* disk in it so let's check that first */
|
* This is the Xbox, chances are that there is a Xbox-standard
|
||||||
|
* partitionless disk in it so let's check that first.
|
||||||
if (1 <= PartitionNumber && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) &&
|
*/
|
||||||
MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData))
|
if (1 <= PartitionNumber && PartitionNumber <= sizeof(XboxPartitions) / sizeof(XboxPartitions[0]) &&
|
||||||
|
MachDiskReadLogicalSectors(DriveNumber, XBOX_SIGNATURE_SECTOR, 1, SectorData))
|
||||||
{
|
{
|
||||||
if (*((PULONG) SectorData) == XBOX_SIGNATURE)
|
if (*((PULONG) SectorData) == XBOX_SIGNATURE)
|
||||||
{
|
{
|
||||||
memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY));
|
memset(PartitionTableEntry, 0, sizeof(PARTITION_TABLE_ENTRY));
|
||||||
PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator;
|
PartitionTableEntry->SystemIndicator = XboxPartitions[PartitionNumber - 1].SystemIndicator;
|
||||||
PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition;
|
PartitionTableEntry->SectorCountBeforePartition = XboxPartitions[PartitionNumber - 1].SectorCountBeforePartition;
|
||||||
PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount;
|
PartitionTableEntry->PartitionSectorCount = XboxPartitions[PartitionNumber - 1].PartitionSectorCount;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* No magic Xbox partitions. Maybe there's a MBR */
|
/* No magic Xbox partitions. Maybe there's a MBR */
|
||||||
return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry);
|
return DiskGetPartitionEntry(DriveNumber, PartitionNumber, PartitionTableEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOLEAN
|
BOOLEAN
|
||||||
XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
|
XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
|
||||||
{
|
{
|
||||||
IDE_DRIVE_IDENTIFY DrvParms;
|
IDE_DRIVE_IDENTIFY DrvParms;
|
||||||
ULONG i;
|
ULONG i;
|
||||||
BOOLEAN Atapi;
|
BOOLEAN Atapi;
|
||||||
|
|
||||||
Atapi = FALSE; /* FIXME */
|
Atapi = FALSE; /* FIXME */
|
||||||
/* Get the Drive Identify block from drive or die */
|
/* Get the Drive Identify block from drive or die */
|
||||||
if (! XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
|
if (!XboxDiskPolledRead(XBOX_IDE_COMMAND_PORT,
|
||||||
XBOX_IDE_CONTROL_PORT,
|
XBOX_IDE_CONTROL_PORT,
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
0,
|
0,
|
||||||
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
|
(0 == (DriveNumber & 0x0f) ? IDE_DH_DRV0 : IDE_DH_DRV1),
|
||||||
(Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
|
(Atapi ? IDE_CMD_IDENT_ATAPI_DRV : IDE_CMD_IDENT_ATA_DRV),
|
||||||
(PUCHAR) &DrvParms))
|
(PUCHAR) &DrvParms))
|
||||||
{
|
{
|
||||||
ERR("XboxDiskPolledRead() failed\n");
|
ERR("XboxDiskPolledRead() failed\n");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
Geometry->Cylinders = DrvParms.LogicalCyls;
|
Geometry->Cylinders = DrvParms.LogicalCyls;
|
||||||
Geometry->Heads = DrvParms.LogicalHeads;
|
Geometry->Heads = DrvParms.LogicalHeads;
|
||||||
Geometry->Sectors = DrvParms.SectorsPerTrack;
|
Geometry->Sectors = DrvParms.SectorsPerTrack;
|
||||||
|
|
||||||
if (! Atapi && 0 != (DrvParms.Capabilities & IDE_DRID_LBA_SUPPORTED))
|
if (! Atapi && 0 != (DrvParms.Capabilities & IDE_DRID_LBA_SUPPORTED))
|
||||||
{
|
{
|
||||||
/* LBA ATA drives always have a sector size of 512 */
|
/* LBA ATA drives always have a sector size of 512 */
|
||||||
Geometry->BytesPerSector = 512;
|
Geometry->BytesPerSector = 512;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACE("BytesPerSector %d\n", DrvParms.BytesPerSector);
|
TRACE("BytesPerSector %d\n", DrvParms.BytesPerSector);
|
||||||
if (DrvParms.BytesPerSector == 0)
|
if (DrvParms.BytesPerSector == 0)
|
||||||
{
|
{
|
||||||
Geometry->BytesPerSector = 512;
|
Geometry->BytesPerSector = 512;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
for (i = 1 << 15; i; i /= 2)
|
for (i = 1 << 15; i; i /= 2)
|
||||||
{
|
{
|
||||||
if (0 != (DrvParms.BytesPerSector & i))
|
if ((DrvParms.BytesPerSector & i) != 0)
|
||||||
{
|
{
|
||||||
Geometry->BytesPerSector = i;
|
Geometry->BytesPerSector = i;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TRACE("Cylinders %d\n", Geometry->Cylinders);
|
TRACE("Cylinders %d\n", Geometry->Cylinders);
|
||||||
TRACE("Heads %d\n", Geometry->Heads);
|
TRACE("Heads %d\n", Geometry->Heads);
|
||||||
TRACE("Sectors %d\n", Geometry->Sectors);
|
TRACE("Sectors %d\n", Geometry->Sectors);
|
||||||
TRACE("BytesPerSector %d\n", Geometry->BytesPerSector);
|
TRACE("BytesPerSector %d\n", Geometry->BytesPerSector);
|
||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
ULONG
|
ULONG
|
||||||
XboxDiskGetCacheableBlockCount(UCHAR DriveNumber)
|
XboxDiskGetCacheableBlockCount(UCHAR DriveNumber)
|
||||||
{
|
{
|
||||||
/* 64 seems a nice number, it is used by the machpc code for LBA devices */
|
/* 64 seems a nice number, it is used by the machpc code for LBA devices */
|
||||||
return 64;
|
return 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -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
|
#ifndef _M_ARM
|
||||||
#include <freeldr.h>
|
#include <freeldr.h>
|
||||||
|
|
||||||
|
#define NDEBUG
|
||||||
#include <debug.h>
|
#include <debug.h>
|
||||||
|
|
||||||
DBG_DEFAULT_CHANNEL(DISK);
|
DBG_DEFAULT_CHANNEL(DISK);
|
||||||
|
|
||||||
static BOOLEAN bReportError = TRUE;
|
static BOOLEAN bReportError = TRUE;
|
||||||
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
/* FUNCTIONS *****************************************************************/
|
||||||
// FUNCTIONS
|
|
||||||
/////////////////////////////////////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
VOID DiskReportError (BOOLEAN bError)
|
VOID DiskReportError(BOOLEAN bError)
|
||||||
{
|
{
|
||||||
bReportError = bError;
|
bReportError = bError;
|
||||||
}
|
}
|
||||||
|
|
||||||
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
|
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode)
|
||||||
{
|
{
|
||||||
CHAR ErrorCodeString[200];
|
CHAR ErrorCodeString[200];
|
||||||
|
|
||||||
if (bReportError == FALSE)
|
if (bReportError == FALSE)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sprintf(ErrorCodeString, "%s\n\nError Code: 0x%lx\nError: %s", ErrorString, ErrorCode, DiskGetErrorCodeString(ErrorCode));
|
sprintf(ErrorCodeString, "%s\n\nError Code: 0x%lx\nError: %s",
|
||||||
|
ErrorString, ErrorCode, DiskGetErrorCodeString(ErrorCode));
|
||||||
|
|
||||||
TRACE("%s\n", ErrorCodeString);
|
TRACE("%s\n", ErrorCodeString);
|
||||||
|
|
||||||
|
@ -83,21 +84,17 @@ PCSTR DiskGetErrorCodeString(ULONG ErrorCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is in arch/i386/i386disk.c
|
|
||||||
//BOOLEAN DiskReadLogicalSectors(ULONG DriveNumber, U64 SectorNumber, ULONG SectorCount, PVOID Buffer)
|
|
||||||
|
|
||||||
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber)
|
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber)
|
||||||
{
|
{
|
||||||
// Hard disks use drive numbers >= 0x80
|
/*
|
||||||
// So if the drive number indicates a hard disk
|
* Hard disks use drive numbers >= 0x80 . So if the drive number
|
||||||
// then return FALSE
|
* indicates a hard disk then return FALSE.
|
||||||
// 0x49 is our magic ramdisk drive, so return FALSE for that too
|
* 0x49 is our magic ramdisk drive, so return FALSE for that too.
|
||||||
|
*/
|
||||||
if ((DriveNumber >= 0x80) || (DriveNumber == 0x49))
|
if ((DriveNumber >= 0x80) || (DriveNumber == 0x49))
|
||||||
{
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
|
||||||
|
|
||||||
// Drive is a floppy diskette so return TRUE
|
/* The drive is a floppy diskette so return TRUE */
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -191,10 +188,4 @@ DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size)
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// This function is in arch/i386/i386disk.c
|
|
||||||
//VOID DiskStopFloppyMotor(VOID)
|
|
||||||
|
|
||||||
// This function is in arch/i386/i386disk.c
|
|
||||||
//ULONG DiskGetCacheableBlockCount(UCHAR DriveNumber)
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -49,6 +49,9 @@ VOID PcPrepareForReactOS(IN BOOLEAN Setup);
|
||||||
|
|
||||||
PFREELDR_MEMORY_DESCRIPTOR PcMemGetMemoryMap(ULONG *MemoryMapSize);
|
PFREELDR_MEMORY_DESCRIPTOR PcMemGetMemoryMap(ULONG *MemoryMapSize);
|
||||||
|
|
||||||
|
BOOLEAN DiskResetController(UCHAR DriveNumber);
|
||||||
|
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize);
|
||||||
|
|
||||||
BOOLEAN PcDiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size);
|
BOOLEAN PcDiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size);
|
||||||
BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer);
|
BOOLEAN PcDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer);
|
||||||
BOOLEAN PcDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
BOOLEAN PcDiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
||||||
|
|
|
@ -23,10 +23,10 @@
|
||||||
|
|
||||||
typedef struct _GEOMETRY
|
typedef struct _GEOMETRY
|
||||||
{
|
{
|
||||||
ULONG Cylinders; // Number of cylinders on the disk
|
ULONG Cylinders; // Number of cylinders on the disk
|
||||||
ULONG Heads; // Number of heads on the disk
|
ULONG Heads; // Number of heads on the disk
|
||||||
ULONG Sectors; // Number of sectors per track
|
ULONG Sectors; // Number of sectors per track
|
||||||
ULONG BytesPerSector; // Number of bytes per sector
|
ULONG BytesPerSector; // Number of bytes per sector
|
||||||
|
|
||||||
} GEOMETRY, *PGEOMETRY;
|
} GEOMETRY, *PGEOMETRY;
|
||||||
|
|
||||||
|
@ -36,14 +36,15 @@ typedef struct _GEOMETRY
|
||||||
#include <pshpack1.h>
|
#include <pshpack1.h>
|
||||||
typedef struct _EXTENDED_GEOMETRY
|
typedef struct _EXTENDED_GEOMETRY
|
||||||
{
|
{
|
||||||
USHORT Size;
|
USHORT Size;
|
||||||
USHORT Flags;
|
USHORT Flags;
|
||||||
ULONG Cylinders;
|
ULONG Cylinders;
|
||||||
ULONG Heads;
|
ULONG Heads;
|
||||||
ULONG SectorsPerTrack;
|
ULONG SectorsPerTrack;
|
||||||
ULONGLONG Sectors;
|
ULONGLONG Sectors;
|
||||||
USHORT BytesPerSector;
|
USHORT BytesPerSector;
|
||||||
ULONG PDPTE;
|
ULONG PDPTE;
|
||||||
|
|
||||||
} EXTENDED_GEOMETRY, *PEXTENDED_GEOMETRY;
|
} EXTENDED_GEOMETRY, *PEXTENDED_GEOMETRY;
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -51,16 +52,17 @@ typedef struct _EXTENDED_GEOMETRY
|
||||||
//
|
//
|
||||||
typedef struct _PARTITION_TABLE_ENTRY
|
typedef struct _PARTITION_TABLE_ENTRY
|
||||||
{
|
{
|
||||||
UCHAR BootIndicator; // 0x00 - non-bootable partition, 0x80 - bootable partition (one partition only)
|
UCHAR BootIndicator; // 0x00 - non-bootable partition,
|
||||||
UCHAR StartHead; // Beginning head number
|
// 0x80 - bootable partition (one partition only)
|
||||||
UCHAR StartSector; // Beginning sector (2 high bits of cylinder #)
|
UCHAR StartHead; // Beginning head number
|
||||||
UCHAR StartCylinder; // Beginning cylinder# (low order bits of cylinder #)
|
UCHAR StartSector; // Beginning sector (2 high bits of cylinder #)
|
||||||
UCHAR SystemIndicator; // System indicator
|
UCHAR StartCylinder; // Beginning cylinder# (low order bits of cylinder #)
|
||||||
UCHAR EndHead; // Ending head number
|
UCHAR SystemIndicator; // System indicator
|
||||||
UCHAR EndSector; // Ending sector (2 high bits of cylinder #)
|
UCHAR EndHead; // Ending head number
|
||||||
UCHAR EndCylinder; // Ending cylinder# (low order bits of cylinder #)
|
UCHAR EndSector; // Ending sector (2 high bits of cylinder #)
|
||||||
ULONG SectorCountBeforePartition; // Number of sectors preceding the partition
|
UCHAR EndCylinder; // Ending cylinder# (low order bits of cylinder #)
|
||||||
ULONG PartitionSectorCount; // Number of sectors in the partition
|
ULONG SectorCountBeforePartition; // Number of sectors preceding the partition
|
||||||
|
ULONG PartitionSectorCount; // Number of sectors in the partition
|
||||||
|
|
||||||
} PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY;
|
} PARTITION_TABLE_ENTRY, *PPARTITION_TABLE_ENTRY;
|
||||||
|
|
||||||
|
@ -69,11 +71,11 @@ typedef struct _PARTITION_TABLE_ENTRY
|
||||||
//
|
//
|
||||||
typedef struct _MASTER_BOOT_RECORD
|
typedef struct _MASTER_BOOT_RECORD
|
||||||
{
|
{
|
||||||
UCHAR MasterBootRecordCodeAndData[0x1b8]; /* 0x000 */
|
UCHAR MasterBootRecordCodeAndData[0x1b8]; /* 0x000 */
|
||||||
ULONG Signature; /* 0x1B8 */
|
ULONG Signature; /* 0x1B8 */
|
||||||
USHORT Reserved; /* 0x1BC */
|
USHORT Reserved; /* 0x1BC */
|
||||||
PARTITION_TABLE_ENTRY PartitionTable[4]; /* 0x1BE */
|
PARTITION_TABLE_ENTRY PartitionTable[4]; /* 0x1BE */
|
||||||
USHORT MasterBootRecordMagic; /* 0x1FE */
|
USHORT MasterBootRecordMagic; /* 0x1FE */
|
||||||
|
|
||||||
} MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD;
|
} MASTER_BOOT_RECORD, *PMASTER_BOOT_RECORD;
|
||||||
#include <poppack.h>
|
#include <poppack.h>
|
||||||
|
@ -107,16 +109,11 @@ typedef struct _MASTER_BOOT_RECORD
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
//
|
//
|
||||||
// i386 BIOS Disk Functions (i386disk.c)
|
// PC x86/64 BIOS Disk Functions (pcdisk.c)
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
#if defined(__i386__) || defined(_M_AMD64)
|
#if defined(__i386__) || defined(_M_AMD64)
|
||||||
|
VOID DiskStopFloppyMotor(VOID);
|
||||||
BOOLEAN DiskResetController(UCHAR DriveNumber);
|
|
||||||
BOOLEAN DiskInt13ExtensionsSupported(UCHAR DriveNumber);
|
|
||||||
//VOID DiskStopFloppyMotor(VOID);
|
|
||||||
BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHORT BufferSize);
|
|
||||||
|
|
||||||
#endif // defined __i386__ || defined(_M_AMD64)
|
#endif // defined __i386__ || defined(_M_AMD64)
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -124,12 +121,10 @@ BOOLEAN DiskGetExtendedDriveParameters(UCHAR DriveNumber, PVOID Buffer, USHOR
|
||||||
// FreeLoader Disk Functions
|
// FreeLoader Disk Functions
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
VOID DiskReportError (BOOLEAN bError);
|
VOID DiskReportError (BOOLEAN bError);
|
||||||
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode);
|
VOID DiskError(PCSTR ErrorString, ULONG ErrorCode);
|
||||||
PCSTR DiskGetErrorCodeString(ULONG ErrorCode);
|
PCSTR DiskGetErrorCodeString(ULONG ErrorCode);
|
||||||
BOOLEAN DiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); // Implemented in i386disk.c
|
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
|
||||||
BOOLEAN DiskIsDriveRemovable(UCHAR DriveNumber);
|
|
||||||
VOID DiskStopFloppyMotor(VOID); // Implemented in i386disk.c
|
|
||||||
extern UCHAR FrldrBootDrive;
|
extern UCHAR FrldrBootDrive;
|
||||||
extern ULONG FrldrBootPartition;
|
extern ULONG FrldrBootPartition;
|
||||||
extern PVOID DiskReadBuffer;
|
extern PVOID DiskReadBuffer;
|
||||||
|
@ -143,10 +138,13 @@ BOOLEAN DiskGetBootPath(OUT PCHAR BootPath, IN ULONG Size);
|
||||||
// Fixed Disk Partition Management Functions
|
// Fixed Disk Partition Management Functions
|
||||||
//
|
//
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, ULONG *ActivePartition);
|
BOOLEAN DiskGetActivePartitionEntry(UCHAR DriveNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry, ULONG *ActivePartition);
|
||||||
BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
BOOLEAN DiskGetPartitionEntry(UCHAR DriveNumber, ULONG PartitionNumber, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
||||||
BOOLEAN DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
BOOLEAN DiskGetFirstPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
||||||
BOOLEAN DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
BOOLEAN DiskGetFirstExtendedPartitionEntry(PMASTER_BOOT_RECORD MasterBootRecord, PPARTITION_TABLE_ENTRY PartitionTableEntry);
|
||||||
BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord);
|
BOOLEAN DiskReadBootRecord(UCHAR DriveNumber, ULONGLONG LogicalSectorNumber, PMASTER_BOOT_RECORD BootRecord);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* SCSI support (disk/scsiport.c)
|
||||||
|
*/
|
||||||
ULONG LoadBootDeviceDriver(VOID);
|
ULONG LoadBootDeviceDriver(VOID);
|
||||||
|
|
Loading…
Reference in a new issue