diff --git a/boot/freeldr/freeldr/arch/i386/pc98/machpc98.c b/boot/freeldr/freeldr/arch/i386/pc98/machpc98.c index 7fd9e292b55..3c07238e02b 100644 --- a/boot/freeldr/freeldr/arch/i386/pc98/machpc98.c +++ b/boot/freeldr/freeldr/arch/i386/pc98/machpc98.c @@ -40,7 +40,8 @@ Pc98PrepareForReactOS(VOID) } ULONG -Pc98GetBootSectorLoadAddress(IN UCHAR DriveNumber) +Pc98GetBootSectorLoadAddress( + _In_ UCHAR DriveNumber) { PPC98_DISK_DRIVE DiskDrive; @@ -57,7 +58,7 @@ Pc98GetBootSectorLoadAddress(IN UCHAR DriveNumber) /* 1.44 MB floppy */ return 0x1FE00; } - else if (DiskDrive->Type & DRIVE_FDD) + else if (DiskDrive->Type == DRIVE_TYPE_FDD) { return 0x1FC00; } diff --git a/boot/freeldr/freeldr/arch/i386/pc98/pc98disk.c b/boot/freeldr/freeldr/arch/i386/pc98/pc98disk.c index 97ed591c6f3..56dd9ed0d4a 100644 --- a/boot/freeldr/freeldr/arch/i386/pc98/pc98disk.c +++ b/boot/freeldr/freeldr/arch/i386/pc98/pc98disk.c @@ -19,14 +19,15 @@ DBG_DEFAULT_CHANNEL(DISK); #define MAX_DRIVES 0x100 /* Cache of all possible PC disk drives */ -PC98_DISK_DRIVE Pc98DiskDrive[MAX_DRIVES]; +static PC98_DISK_DRIVE Pc98DiskDrive[MAX_DRIVES]; /* DISK IO ERROR SUPPORT ******************************************************/ static LONG lReportError = 0; /* >= 0: display errors; < 0: hide errors */ LONG -DiskReportError(BOOLEAN bShowError) +DiskReportError( + _In_ BOOLEAN bShowError) { /* Set the reference count */ if (bShowError) @@ -36,8 +37,10 @@ DiskReportError(BOOLEAN bShowError) return lReportError; } -static PCSTR -DiskGetErrorCodeString(ULONG ErrorCode) +static +PCSTR +DiskGetErrorCodeString( + _In_ ULONG ErrorCode) { switch (ErrorCode & 0xF0) { @@ -70,16 +73,23 @@ DiskGetErrorCodeString(ULONG ErrorCode) } } -static VOID -DiskError(PCSTR ErrorString, ULONG ErrorCode) +static +VOID +DiskError( + _In_ PCSTR ErrorString, + _In_ ULONG ErrorCode) { CHAR ErrorCodeString[200]; if (lReportError < 0) return; - RtlStringCbPrintfA(ErrorCodeString, sizeof(ErrorCodeString), "%s\n\nError Code: 0x%lx\nError: %s", - ErrorString, ErrorCode, DiskGetErrorCodeString(ErrorCode)); + RtlStringCbPrintfA(ErrorCodeString, + sizeof(ErrorCodeString), + "%s\n\nError Code: 0x%lx\nError: %s", + ErrorString, + ErrorCode, + DiskGetErrorCodeString(ErrorCode)); ERR("%s\n", ErrorCodeString); @@ -88,11 +98,14 @@ DiskError(PCSTR ErrorString, ULONG ErrorCode) /* FUNCTIONS ******************************************************************/ -BOOLEAN DiskResetController(IN PPC98_DISK_DRIVE DiskDrive) +static +BOOLEAN +DiskResetController( + _In_ PPC98_DISK_DRIVE DiskDrive) { REGS Regs; - if (DiskDrive->Type & DRIVE_FDD) + if (DiskDrive->Type == DRIVE_TYPE_FDD) { /* Int 1Bh AH=07h * DISK BIOS - Recalibrate @@ -106,7 +119,7 @@ BOOLEAN DiskResetController(IN PPC98_DISK_DRIVE DiskDrive) */ Regs.b.ah = 0x07; } - else if (DiskDrive->Type != (DRIVE_IDE | DRIVE_CDROM)) + else if (DiskDrive->Type == DRIVE_TYPE_HDD) { /* Int 1Bh AH=03h * DISK BIOS - Initialize @@ -125,7 +138,8 @@ BOOLEAN DiskResetController(IN PPC98_DISK_DRIVE DiskDrive) return FALSE; } - WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", DiskDrive->DaUa); + WARN("DiskResetController(0x%x) DISK OPERATION FAILED -- RESETTING CONTROLLER\n", + DiskDrive->DaUa); Regs.b.al = DiskDrive->DaUa; Int386(0x1B, &Regs, &Regs); @@ -133,17 +147,18 @@ BOOLEAN DiskResetController(IN PPC98_DISK_DRIVE DiskDrive) } PPC98_DISK_DRIVE -Pc98DiskDriveNumberToDrive(IN UCHAR DriveNumber) +Pc98DiskDriveNumberToDrive( + _In_ UCHAR DriveNumber) { PPC98_DISK_DRIVE DiskDrive; - ASSERT((0 <= DriveNumber) && (DriveNumber < RTL_NUMBER_OF(Pc98DiskDrive))); + ASSERT(DriveNumber < RTL_NUMBER_OF(Pc98DiskDrive)); /* Retrieve a slot */ DiskDrive = &Pc98DiskDrive[DriveNumber]; /* The pre-initialization of the BIOS disks was already done in Pc98InitializeBootDevices() */ - if (DiskDrive->Initialized) + if (DiskDrive->Flags & DRIVE_FLAGS_INITIALIZED) return DiskDrive; else return NULL; @@ -159,17 +174,18 @@ DiskGetConfigType( if (!DiskDrive) return -1; // MaximumType; - if (DiskDrive->Type & DRIVE_CDROM || DiskDrive->Type & DRIVE_MO) + if (DiskDrive->Type == DRIVE_TYPE_CDROM) return CdromController; - else if (DiskDrive->Type & DRIVE_FDD) + else if (DiskDrive->Type == DRIVE_TYPE_FDD) return FloppyDiskPeripheral; else return DiskPeripheral; } -static inline +static UCHAR -BytesPerSectorToSectorLengthCode(IN ULONG BytesPerSector) +BytesPerSectorToSectorLengthCode( + _In_ ULONG BytesPerSector) { switch (BytesPerSector) { @@ -188,58 +204,52 @@ BytesPerSectorToSectorLengthCode(IN ULONG BytesPerSector) } } -static BOOLEAN +static +BOOLEAN Pc98DiskReadLogicalSectorsLBA( - IN PPC98_DISK_DRIVE DiskDrive, - IN ULONGLONG SectorNumber, - IN ULONG SectorCount, - OUT PVOID Buffer) + _In_ PPC98_DISK_DRIVE DiskDrive, + _In_ ULONG64 SectorNumber, + _In_ ULONG SectorCount, + _Out_writes_bytes_all_(SectorCount * DiskDrive->Geometry.BytesPerSector) PVOID Buffer) { REGS RegsIn, RegsOut; ULONG RetryCount; - if (DiskDrive->Type & DRIVE_IDE && DiskDrive->Type & DRIVE_CDROM) + /* Int 1Bh AH=06h + * DISK BIOS - Read data + * + * Call with: + * AL - drive number + * BX - bytes to read + * CX - cylinder number + * DH - head number + * DL - sector number + * ES:BP -> buffer to read data into + * + * Return: + * CF - set on error, clear if successful + * AH - status + */ + RegsIn.b.al = DiskDrive->DaUa; + RegsIn.b.ah = 0x06; + RegsIn.w.bx = DiskDrive->Geometry.BytesPerSector * SectorCount; + RegsIn.w.cx = SectorNumber & 0xFFFF; + RegsIn.w.dx = (SectorNumber >> 16) & 0xFFFF; + RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4); + RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F; + + /* Retry 3 times */ + for (RetryCount = 0; RetryCount < 3; ++RetryCount) { - return AtaReadLogicalSectors(AtaGetDevice(DiskDrive->IdeUnitNumber), SectorNumber, SectorCount, Buffer); - } - else - { - /* Int 1Bh AH=06h - * DISK BIOS - Read data - * - * Call with: - * AL - drive number - * BX - bytes to read - * CX - cylinder number - * DH - head number - * DL - sector number - * ES:BP -> buffer to read data into - * - * Return: - * CF - set on error, clear if successful - * AH - status - */ - RegsIn.b.al = DiskDrive->DaUa; - RegsIn.b.ah = 0x06; - RegsIn.w.bx = DiskDrive->Geometry.BytesPerSector * SectorCount; - RegsIn.w.cx = SectorNumber & 0xFFFF; - RegsIn.w.dx = (SectorNumber >> 16) & 0xFFFF; - RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4); - RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F; + Int386(0x1B, &RegsIn, &RegsOut); - /* Retry 3 times */ - for (RetryCount = 0; RetryCount < 3; ++RetryCount) - { - Int386(0x1B, &RegsIn, &RegsOut); + /* If it worked, or if it was a corrected ECC error + * and the data is still good, return success */ + if (INT386_SUCCESS(RegsOut) || (RegsOut.b.ah == 0x08)) + return TRUE; - /* If it worked, or if it was a corrected ECC error - * and the data is still good, return success */ - if (INT386_SUCCESS(RegsOut) || (RegsOut.b.ah == 0x08)) - return TRUE; - - /* It failed, do the next retry */ - DiskResetController(DiskDrive); - } + /* It failed, do the next retry */ + DiskResetController(DiskDrive); } /* If we get here then the read failed */ @@ -251,12 +261,13 @@ Pc98DiskReadLogicalSectorsLBA( return FALSE; } -static BOOLEAN +static +BOOLEAN Pc98DiskReadLogicalSectorsCHS( - IN PPC98_DISK_DRIVE DiskDrive, - IN ULONGLONG SectorNumber, - IN ULONG SectorCount, - OUT PVOID Buffer) + _In_ PPC98_DISK_DRIVE DiskDrive, + _In_ ULONG64 SectorNumber, + _In_ ULONG SectorCount, + _Out_writes_bytes_all_(SectorCount * DiskDrive->Geometry.BytesPerSector) PVOID Buffer) { UCHAR PhysicalSector; UCHAR PhysicalHead; @@ -279,7 +290,7 @@ Pc98DiskReadLogicalSectorsCHS( PhysicalTrack = (ULONG)((SectorNumber / DriveGeometry.SectorsPerTrack) / DriveGeometry.Heads); /* Floppy sectors value always start at 1 */ - if (DiskDrive->Type & DRIVE_FDD) + if (DiskDrive->Type == DRIVE_TYPE_FDD) ++PhysicalSector; /* Calculate how many sectors we need to read this round */ @@ -303,7 +314,7 @@ Pc98DiskReadLogicalSectorsCHS( return FALSE; } - if (DiskDrive->Type & DRIVE_FDD) + if (DiskDrive->Type == DRIVE_TYPE_FDD) { /* Int 1Bh AH=x6h * DISK BIOS - Read data @@ -321,15 +332,10 @@ Pc98DiskReadLogicalSectorsCHS( * CF - set on error, clear if successful * AH - status */ - RegsIn.b.al = DiskDrive->DaUa; RegsIn.b.ah = 0x56; /* With SEEK, and use double-density format (MFM) */ RegsIn.w.bx = DriveGeometry.BytesPerSector * (UCHAR)NumberOfSectorsToRead; RegsIn.b.cl = PhysicalTrack & 0xFFFF; RegsIn.b.ch = BytesPerSectorToSectorLengthCode(DriveGeometry.BytesPerSector); - RegsIn.b.dl = PhysicalSector; - RegsIn.b.dh = PhysicalHead; - RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4); - RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F; } else { @@ -348,15 +354,15 @@ Pc98DiskReadLogicalSectorsCHS( * CF - set on error, clear if successful * AH - status */ - RegsIn.b.al = DiskDrive->DaUa; RegsIn.b.ah = 0x06; RegsIn.w.bx = DriveGeometry.BytesPerSector * (UCHAR)NumberOfSectorsToRead; RegsIn.w.cx = PhysicalTrack & 0xFFFF; - RegsIn.b.dl = PhysicalSector; - RegsIn.b.dh = PhysicalHead; - RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4); - RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F; } + RegsIn.b.al = DiskDrive->DaUa; + RegsIn.b.dl = PhysicalSector; + RegsIn.b.dh = PhysicalHead; + RegsIn.w.es = (USHORT)(((ULONG_PTR)Buffer) >> 4); + RegsIn.w.bp = ((ULONG_PTR)Buffer) & 0x0F; /* Perform the read. Retry 3 times. */ for (RetryCount = 0; RetryCount < 3; ++RetryCount) @@ -390,16 +396,16 @@ Pc98DiskReadLogicalSectorsCHS( return TRUE; } -static BOOLEAN +static +BOOLEAN InitScsiDrive( - IN UCHAR DaUa, - IN OUT PPC98_DISK_DRIVE DiskDrive) + _Out_ PPC98_DISK_DRIVE DiskDrive, + _In_ UCHAR DaUa) { REGS RegsIn, RegsOut; UCHAR UnitAddress = DaUa & 0x0F; USHORT DiskEquipment = *(PUCHAR)MEM_DISK_EQUIPS; ULONG ScsiParameters = *(PULONG)(MEM_SCSI_TABLE + UnitAddress * sizeof(ULONG)); - UCHAR DeviceType; /* Hard drives */ if (DiskEquipment & (1 << UnitAddress)) @@ -422,22 +428,17 @@ InitScsiDrive( RegsIn.b.ah = 0x84; Int386(0x1B, &RegsIn, &RegsOut); if (!INT386_SUCCESS(RegsOut) || RegsOut.w.cx == 0) - { - DiskDrive->Initialized = FALSE; return FALSE; - } DiskDrive->Geometry.Cylinders = RegsOut.w.cx; DiskDrive->Geometry.Heads = RegsOut.b.dh; DiskDrive->Geometry.SectorsPerTrack = RegsOut.b.dl; DiskDrive->Geometry.BytesPerSector = RegsOut.w.bx; - DiskDrive->LBASupported = FALSE; - DiskDrive->IsRemovable = FALSE; } /* Other devices */ - else if (ScsiParameters) + else if (ScsiParameters != 0) { - DeviceType = ScsiParameters & 0x1F; + UCHAR DeviceType = ScsiParameters & 0x1F; switch (DeviceType) { case 0x05: @@ -446,9 +447,9 @@ InitScsiDrive( DiskDrive->Geometry.Heads = 0xFFFF; DiskDrive->Geometry.SectorsPerTrack = 0xFFFF; DiskDrive->Geometry.BytesPerSector = 2048; - DiskDrive->Type = DRIVE_CDROM; - DiskDrive->LBASupported = TRUE; - DiskDrive->IsRemovable = TRUE; + + DiskDrive->Type = DRIVE_TYPE_CDROM; + DiskDrive->Flags = DRIVE_FLAGS_LBA | DRIVE_FLAGS_REMOVABLE; break; case 0x07: @@ -457,30 +458,27 @@ InitScsiDrive( DiskDrive->Geometry.Heads = 8; DiskDrive->Geometry.SectorsPerTrack = 32; DiskDrive->Geometry.BytesPerSector = 512; - DiskDrive->Type = DRIVE_MO; - DiskDrive->LBASupported = TRUE; - DiskDrive->IsRemovable = TRUE; + + DiskDrive->Type = DRIVE_TYPE_CDROM; + DiskDrive->Flags = DRIVE_FLAGS_LBA | DRIVE_FLAGS_REMOVABLE; break; default: - DiskDrive->Initialized = FALSE; return FALSE; } } else { - DiskDrive->Initialized = FALSE; return FALSE; } + DiskDrive->Flags |= DRIVE_FLAGS_INITIALIZED; + DiskDrive->DaUa = DaUa; + DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders * DiskDrive->Geometry.Heads * DiskDrive->Geometry.SectorsPerTrack; - DiskDrive->DaUa = DaUa; - DiskDrive->Type |= DRIVE_SCSI; - DiskDrive->Initialized = TRUE; - TRACE("InitScsiDrive(0x%x) returned:\n" "Cylinders : 0x%x\n" "Heads : 0x%x\n" @@ -497,130 +495,15 @@ InitScsiDrive( return TRUE; } -static BOOLEAN -InitIdeDrive( - IN UCHAR UnitNumber, - IN OUT PPC98_DISK_DRIVE DiskDrive) -{ - PDEVICE_UNIT DeviceUnit = AtaGetDevice(UnitNumber); - - /* We work directly only with ATAPI drives because BIOS has ATA support */ - if (DeviceUnit && DeviceUnit->Flags & ATA_DEVICE_ATAPI) - { - DiskDrive->Geometry.Cylinders = DeviceUnit->Cylinders; - DiskDrive->Geometry.Heads = DeviceUnit->Heads; - DiskDrive->Geometry.SectorsPerTrack = DeviceUnit->SectorsPerTrack; - DiskDrive->Geometry.BytesPerSector = DeviceUnit->SectorSize; - DiskDrive->Geometry.Sectors = DeviceUnit->TotalSectors; - - DiskDrive->DaUa = 0xFF; - DiskDrive->IdeUnitNumber = UnitNumber; - DiskDrive->Type = DRIVE_IDE | DRIVE_CDROM; - DiskDrive->LBASupported = TRUE; - DiskDrive->IsRemovable = TRUE; - DiskDrive->Initialized = TRUE; - - TRACE("InitIdeDrive(0x%x) returned:\n" - "Cylinders : 0x%x\n" - "Heads : 0x%x\n" - "Sects/Track: 0x%x\n" - "Total Sects: 0x%llx\n" - "Bytes/Sect : 0x%x\n", - UnitNumber, - DiskDrive->Geometry.Cylinders, - DiskDrive->Geometry.Heads, - DiskDrive->Geometry.SectorsPerTrack, - DiskDrive->Geometry.Sectors, - DiskDrive->Geometry.BytesPerSector); - - return TRUE; - } - - DiskDrive->Initialized = FALSE; - return FALSE; -} - -static BOOLEAN -InitHardDrive( - IN UCHAR DaUa, - IN OUT PPC98_DISK_DRIVE DiskDrive) -{ - REGS RegsIn, RegsOut; - - /* Int 1Bh AH=8Eh - * DISK BIOS - Set half-height operation mode - * - * Call with: - * AL - drive number - */ - RegsIn.b.al = DaUa; - RegsIn.b.ah = 0x8E; - Int386(0x1B, &RegsIn, &RegsOut); - - /* Int 1Bh AH=84h - * DISK BIOS - Sense - * - * Call with: - * AL - drive number - * - * Return: - * BX - bytes per sector - * CX - cylinders number - * DH - heads number - * DL - sectors number - * CF - set on error, clear if successful - * AH - status - */ - RegsIn.b.al = DaUa; - RegsIn.b.ah = 0x84; - Int386(0x1B, &RegsIn, &RegsOut); - if (!INT386_SUCCESS(RegsOut) || RegsOut.w.cx == 0) - { - DiskDrive->Initialized = FALSE; - return FALSE; - } - - DiskDrive->Geometry.Cylinders = RegsOut.w.cx; - DiskDrive->Geometry.Heads = RegsOut.b.dh; - DiskDrive->Geometry.SectorsPerTrack = RegsOut.b.dl; - DiskDrive->Geometry.BytesPerSector = RegsOut.w.bx; - - DiskDrive->Geometry.Sectors = (ULONGLONG)DiskDrive->Geometry.Cylinders * - DiskDrive->Geometry.Heads * - DiskDrive->Geometry.SectorsPerTrack; - - DiskDrive->DaUa = DaUa; - DiskDrive->Type = DRIVE_IDE; - DiskDrive->LBASupported = FALSE; - DiskDrive->IsRemovable = FALSE; - DiskDrive->Initialized = TRUE; - - TRACE("InitHardDrive(0x%x) returned:\n" - "Cylinders : 0x%x\n" - "Heads : 0x%x\n" - "Sects/Track: 0x%x\n" - "Total Sects: 0x%llx\n" - "Bytes/Sect : 0x%x\n", - DaUa, - DiskDrive->Geometry.Cylinders, - DiskDrive->Geometry.Heads, - DiskDrive->Geometry.SectorsPerTrack, - DiskDrive->Geometry.Sectors, - DiskDrive->Geometry.BytesPerSector); - - return TRUE; -} - -static BOOLEAN +static +BOOLEAN InitFloppyDrive( - IN UCHAR DaUa, - IN OUT PPC98_DISK_DRIVE DiskDrive) + _Out_ PPC98_DISK_DRIVE DiskDrive, + _In_ UCHAR DaUa) { REGS RegsIn, RegsOut; - USHORT BytesPerSector; - UCHAR DeviceAddress = DaUa & 0xF0; - - /* There's no way to obtain floppy disk geometry in BIOS */ + ULONG BytesPerSector; + UCHAR DeviceAddress; /* Int 1Bh AH=4Ah * DISK BIOS - Read ID @@ -640,11 +523,10 @@ InitFloppyDrive( RegsIn.b.al = DaUa; Int386(0x1B, &RegsIn, &RegsOut); if (!INT386_SUCCESS(RegsOut)) - { - DiskDrive->Initialized = FALSE; return FALSE; - } + /* There is no way to obtain floppy disk geometry in BIOS */ + DeviceAddress = DaUa & 0xF0; BytesPerSector = 128 << RegsOut.b.ch; switch (BytesPerSector) { @@ -697,7 +579,6 @@ InitFloppyDrive( break; default: - DiskDrive->Initialized = FALSE; return FALSE; } @@ -707,10 +588,8 @@ InitFloppyDrive( DiskDrive->Geometry.SectorsPerTrack; DiskDrive->DaUa = DaUa; - DiskDrive->Type = DRIVE_FDD; - DiskDrive->LBASupported = FALSE; - DiskDrive->IsRemovable = TRUE; - DiskDrive->Initialized = TRUE; + DiskDrive->Type = DRIVE_TYPE_FDD; + DiskDrive->Flags = DRIVE_FLAGS_REMOVABLE | DRIVE_FLAGS_INITIALIZED; TRACE("InitFloppyDrive(0x%x) returned:\n" "Cylinders : 0x%x\n" @@ -728,119 +607,142 @@ InitFloppyDrive( return TRUE; } -/* We emulate PC BIOS drive numbers here */ +static +BOOLEAN +InitIdeDrive( + _Out_ PPC98_DISK_DRIVE DiskDrive, + _In_ UCHAR AtaUnitNumber) +{ + PDEVICE_UNIT DeviceUnit = AtaGetDevice(AtaUnitNumber); + + if (!DeviceUnit) + return FALSE; + + DiskDrive->Geometry.Cylinders = DeviceUnit->Cylinders; + DiskDrive->Geometry.Heads = DeviceUnit->Heads; + DiskDrive->Geometry.SectorsPerTrack = DeviceUnit->SectorsPerTrack; + DiskDrive->Geometry.BytesPerSector = DeviceUnit->SectorSize; + DiskDrive->Geometry.Sectors = DeviceUnit->TotalSectors; + + DiskDrive->DaUa = 0xFF; // Invalid + DiskDrive->AtaUnitNumber = AtaUnitNumber; + DiskDrive->Flags = DRIVE_FLAGS_IDE | DRIVE_FLAGS_INITIALIZED; + + if (DeviceUnit->Flags & ATA_DEVICE_LBA) + DiskDrive->Flags |= DRIVE_FLAGS_LBA; + + if (DeviceUnit->Flags & ATA_DEVICE_ATAPI) + { + DiskDrive->Type = DRIVE_TYPE_CDROM; + DiskDrive->Flags |= DRIVE_FLAGS_REMOVABLE; + } + else + { + DiskDrive->Type = DRIVE_TYPE_HDD; + } + + TRACE("InitIdeDrive(0x%x) returned:\n" + "Cylinders : 0x%x\n" + "Heads : 0x%x\n" + "Sects/Track: 0x%x\n" + "Total Sects: 0x%llx\n" + "Bytes/Sect : 0x%x\n", + AtaUnitNumber, + DiskDrive->Geometry.Cylinders, + DiskDrive->Geometry.Heads, + DiskDrive->Geometry.SectorsPerTrack, + DiskDrive->Geometry.Sectors, + DiskDrive->Geometry.BytesPerSector); + return TRUE; +} + BOOLEAN Pc98InitializeBootDevices(VOID) { - PPC98_DISK_DRIVE DiskDrive; - UCHAR FakeFloppyDriveNumber = 0x30; - UCHAR FakeHardDriveDriveNumber = 0x80; - UCHAR FakeCdRomDriveNumber = 0xE0; USHORT DiskEquipment = *(PUSHORT)MEM_DISK_EQUIP & ~(*(PUCHAR)MEM_RDISK_EQUIP); - UCHAR IdeDetectedCount; - UCHAR i; + PPC98_DISK_DRIVE DiskDrive; + UCHAR BiosFloppyDriveNumber, BiosHardDriveDriveNumber, IdeDetectedCount; + ULONG i; TRACE("Pc98InitializeBootDevices()\n"); RtlZeroMemory(&Pc98DiskDrive, sizeof(Pc98DiskDrive)); /* - * Map DA/UA to drive number, i.e. + * We emulate the standard PC BIOS drive numbers here. Map DA/UA to a drive number, i.e. * 0x90 -> 0x30 * 0x80 -> 0x80 * 0xA0 -> 0x81, etc. */ + BiosFloppyDriveNumber = 0x30; + BiosHardDriveDriveNumber = 0x80; /* Map floppies */ - for (i = 0; i < 4; i++) { - DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber]; + DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber]; if (FIRSTBYTE(DiskEquipment) & (1 << i)) { - if (InitFloppyDrive(0x30 + i, DiskDrive) || InitFloppyDrive(0xB0 + i, DiskDrive) || - InitFloppyDrive(0x90 + i, DiskDrive) || InitFloppyDrive(0x10 + i, DiskDrive)) - ++FakeFloppyDriveNumber; + if (InitFloppyDrive(DiskDrive, 0x30 + i) || InitFloppyDrive(DiskDrive, 0xB0 + i) || + InitFloppyDrive(DiskDrive, 0x90 + i) || InitFloppyDrive(DiskDrive, 0x10 + i)) + ++BiosFloppyDriveNumber; } } - for (i = 0; i < 4; i++) { - DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber]; + DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber]; if (FIRSTBYTE(DiskEquipment) & (16 << i)) { - if (InitFloppyDrive(0x50 + i, DiskDrive)) - ++FakeFloppyDriveNumber; + if (InitFloppyDrive(DiskDrive, 0x50 + i)) + ++BiosFloppyDriveNumber; } } - for (i = 0; i < 4; i++) { - DiskDrive = &Pc98DiskDrive[FakeFloppyDriveNumber]; + DiskDrive = &Pc98DiskDrive[BiosFloppyDriveNumber]; if (SECONDBYTE(DiskEquipment) & (16 << i)) { - if (InitFloppyDrive(0x70 + i, DiskDrive) || InitFloppyDrive(0xF0 + i, DiskDrive)) - ++FakeFloppyDriveNumber; + if (InitFloppyDrive(DiskDrive, 0x70 + i) || InitFloppyDrive(DiskDrive, 0xF0 + i)) + ++BiosFloppyDriveNumber; } } - /* Map IDE/SASI drives */ - - for (i = 0; i < 4; i++) - { - DiskDrive = &Pc98DiskDrive[FakeHardDriveDriveNumber]; - if (InitHardDrive(0x80 + i, DiskDrive) || InitHardDrive(0x00 + i, DiskDrive)) - ++FakeHardDriveDriveNumber; - } - + /* + * Map IDE drives. We provide our own IDE boot support because of IDE BIOS + * that cannot boot from a CD-ROM and has LBA limitations. + */ AtaInit(&IdeDetectedCount); for (i = 0; i <= IdeDetectedCount; i++) { - DiskDrive = &Pc98DiskDrive[FakeCdRomDriveNumber]; - if (InitIdeDrive(i, DiskDrive)) - ++FakeCdRomDriveNumber; + DiskDrive = &Pc98DiskDrive[BiosHardDriveDriveNumber]; + if (InitIdeDrive(DiskDrive, i)) + ++BiosHardDriveDriveNumber; } /* Map SCSI drives */ - for (i = 0; i < 7; i++) { - DiskDrive = &Pc98DiskDrive[FakeHardDriveDriveNumber]; - if (InitScsiDrive(0xA0 + i, DiskDrive) || InitScsiDrive(0x20 + i, DiskDrive)) - { - if (DiskDrive->Type & DRIVE_CDROM || DiskDrive->Type & DRIVE_MO) - { - /* Move to CD-ROM area */ - Pc98DiskDrive[FakeCdRomDriveNumber] = *DiskDrive; - RtlZeroMemory(DiskDrive, sizeof(PC98_DISK_DRIVE)); - ++FakeCdRomDriveNumber; - } - else - { - ++FakeHardDriveDriveNumber; - } - } + DiskDrive = &Pc98DiskDrive[BiosHardDriveDriveNumber]; + if (InitScsiDrive(DiskDrive, 0xA0 + i) || InitScsiDrive(DiskDrive, 0x20 + i)) + ++BiosHardDriveDriveNumber; } -#if 1 // Ugly HACK: Force ISO boot // FIXME: Fill ARC disk blocks completely // to allow usage of CD-ROM root path (See floppy_pc98.ini). - FrldrBootDrive = 0xE0; - FrldrBootPartition = 0xFF; -#else - /* Reassign boot drive */ - for (i = 0; i < MAX_DRIVES - 1; i++) + for (i = 0x80; i < RTL_NUMBER_OF(Pc98DiskDrive); i++) { DiskDrive = &Pc98DiskDrive[i]; - if (DiskDrive->Initialized && DiskDrive->DaUa == FrldrBootDrive) + + if ((DiskDrive->Flags & DRIVE_FLAGS_INITIALIZED) && + (DiskDrive->Flags & DRIVE_FLAGS_IDE) && + (DiskDrive->Type == DRIVE_TYPE_CDROM)) { - TRACE("Boot drive: old 0x%x, new 0x%x\n", FrldrBootDrive, i); FrldrBootDrive = i; + FrldrBootPartition = 0xFF; break; } } -#endif /* Call PC version */ return PcInitializeBootDevices(); @@ -848,10 +750,10 @@ Pc98InitializeBootDevices(VOID) BOOLEAN Pc98DiskReadLogicalSectors( - IN UCHAR DriveNumber, - IN ULONGLONG SectorNumber, - IN ULONG SectorCount, - OUT PVOID Buffer) + _In_ UCHAR DriveNumber, + _In_ ULONGLONG SectorNumber, + _In_ ULONG SectorCount, + _Out_ PVOID Buffer) { PPC98_DISK_DRIVE DiskDrive; @@ -865,7 +767,14 @@ Pc98DiskReadLogicalSectors( if (!DiskDrive) return FALSE; - if (DiskDrive->LBASupported) + if (DiskDrive->Flags & DRIVE_FLAGS_IDE) + { + return AtaReadLogicalSectors(AtaGetDevice(DiskDrive->AtaUnitNumber), + SectorNumber, + SectorCount, + Buffer); + } + else if (DiskDrive->Flags & DRIVE_FLAGS_LBA) { /* LBA is easy, nothing to calculate. Just do the read. */ TRACE("--> Using LBA\n"); @@ -880,7 +789,9 @@ Pc98DiskReadLogicalSectors( } BOOLEAN -Pc98DiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry) +Pc98DiskGetDriveGeometry( + _In_ UCHAR DriveNumber, + _Out_ PGEOMETRY Geometry) { PPC98_DISK_DRIVE DiskDrive; @@ -896,7 +807,8 @@ Pc98DiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry) } ULONG -Pc98DiskGetCacheableBlockCount(UCHAR DriveNumber) +Pc98DiskGetCacheableBlockCount( + _In_ UCHAR DriveNumber) { PPC98_DISK_DRIVE DiskDrive; @@ -908,7 +820,7 @@ Pc98DiskGetCacheableBlockCount(UCHAR DriveNumber) * If LBA is supported then the block size will be 64 sectors (32k). * If not then the block size is the size of one track. */ - if (DiskDrive->LBASupported) + if (DiskDrive->Flags & DRIVE_FLAGS_LBA) return 64; else return DiskDrive->Geometry.SectorsPerTrack; diff --git a/boot/freeldr/freeldr/include/arch/i386/machpc98.h b/boot/freeldr/freeldr/include/arch/i386/machpc98.h index 010ae8d6032..2e06669acc4 100644 --- a/boot/freeldr/freeldr/include/arch/i386/machpc98.h +++ b/boot/freeldr/freeldr/include/arch/i386/machpc98.h @@ -105,36 +105,24 @@ typedef struct _PC98_DISK_DRIVE /* Disk geometry */ GEOMETRY Geometry; - /* BIOS drive number */ + /* PC-98 BIOS drive number */ UCHAR DaUa; /* IDE driver drive number */ - UCHAR IdeUnitNumber; + UCHAR AtaUnitNumber; - /* Drive type flags */ + /* Drive type */ UCHAR Type; -#define DRIVE_SASI 0x00 -#define DRIVE_IDE 0x01 -#define DRIVE_SCSI 0x02 -#define DRIVE_CDROM 0x04 -#define DRIVE_FDD 0x08 -#define DRIVE_MO 0x10 -#define DRIVE_RAM 0x20 +#define DRIVE_TYPE_HDD 0 +#define DRIVE_TYPE_CDROM 1 +#define DRIVE_TYPE_FDD 2 - /* TRUE when LBA access are supported */ - BOOLEAN LBASupported; - - /* - * 'IsRemovable' flag: TRUE when the drive is removable (e.g. floppy, CD-ROM...). - * In that case some of the cached information might need to be refreshed regularly. - */ - BOOLEAN IsRemovable; - - /* - * 'Initialized' flag: if TRUE then the drive has been initialized; - * if FALSE then the disk isn't detected by BIOS/FreeLoader. - */ - BOOLEAN Initialized; + /* Drive flags */ + UCHAR Flags; +#define DRIVE_FLAGS_IDE 0x01 // IDE drive, accessed by the IDE driver +#define DRIVE_FLAGS_LBA 0x02 // LBA access supported +#define DRIVE_FLAGS_REMOVABLE 0x04 // The drive is removable (e.g. floppy, CD-ROM...) +#define DRIVE_FLAGS_INITIALIZED 0x80 // The drive has been initialized } PC98_DISK_DRIVE, *PPC98_DISK_DRIVE; /* Platform-specific boot drive and partition numbers */ @@ -145,16 +133,36 @@ CONFIGURATION_TYPE DiskGetConfigType( _In_ UCHAR DriveNumber); -LONG DiskReportError(BOOLEAN bShowError); -BOOLEAN DiskResetController(IN PPC98_DISK_DRIVE DiskDrive); +LONG +DiskReportError( + _In_ BOOLEAN bShowError); -BOOLEAN Pc98DiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer); -BOOLEAN Pc98DiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY DriveGeometry); -ULONG Pc98DiskGetCacheableBlockCount(UCHAR DriveNumber); -UCHAR Pc98GetFloppyCount(VOID); -PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive(IN UCHAR DriveNumber); +BOOLEAN +Pc98DiskReadLogicalSectors( + _In_ UCHAR DriveNumber, + _In_ ULONGLONG SectorNumber, + _In_ ULONG SectorCount, + _Out_ PVOID Buffer); -ULONG Pc98GetBootSectorLoadAddress(IN UCHAR DriveNumber); +BOOLEAN +Pc98DiskGetDriveGeometry( + _In_ UCHAR DriveNumber, + _Out_ PGEOMETRY DriveGeometry); + +ULONG +Pc98DiskGetCacheableBlockCount( + _In_ UCHAR DriveNumber); + +UCHAR +Pc98GetFloppyCount(VOID); + +PPC98_DISK_DRIVE +Pc98DiskDriveNumberToDrive( + _In_ UCHAR DriveNumber); + +ULONG +Pc98GetBootSectorLoadAddress( + _In_ UCHAR DriveNumber); /* hwdisk.c */ BOOLEAN PcInitializeBootDevices(VOID);