[FREELDR] Refactor and optimize the IDE driver (#7728)

[DDK] Update IDENTIFY data and other ATA definitions.
Based on the MinGW header.

[FREELDR] Refactor and optimize the IDE driver.
Fix long-standing bugs, which have a negative impact on the boot stability.

- Make the driver more ATA specification compliant.
- Improve the speed of device detection.
- Remove inconsistent delays.
- Support modern hard drives with sector size greater than 512 bytes.
- Add basic error recovery.
- Move private definitions to a separate private header.
- Remove the useless AtaFree API method.
This commit is contained in:
Dmitry Borisov 2025-03-19 02:56:25 +06:00 committed by GitHub
parent ddf55b3772
commit 787f81f3f5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 2119 additions and 1214 deletions

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,387 @@
/*
* PROJECT: FreeLoader
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: Private header for ATA/ATAPI programmed I/O driver.
* COPYRIGHT: Copyright 2019-2025 Dmitry Borisov (di.sean@protonmail.com)
*/
#pragma once
#define TAG_ATA_DEVICE 'dATA'
#define ATA_STATUS_SUCCESS 0
#define ATA_STATUS_PENDING 1
#define ATA_STATUS_ERROR 2
#define ATA_STATUS_RESET 3
#define ATA_STATUS_RETRY 4
#if defined(SARCH_PC98)
/* Master/Slave devices for Bank 0 and Bank 1 */
#define CHANNEL_MAX_DEVICES 4
#define DEV_SLAVE(DeviceNumber) ((DeviceNumber) & 1)
#else
/* Master/Slave devices */
#define CHANNEL_MAX_DEVICES 2
#define DEV_SLAVE(DeviceNumber) (DeviceNumber)
#endif
#if defined(SARCH_XBOX)
/* It's safe to enable the multiple mode */
#define ATA_ENABLE_MULTIPLE_MODE
#endif
/* Delay of 400ns */
#if defined(SARCH_PC98)
#define ATA_IO_WAIT() WRITE_PORT_UCHAR((PUCHAR)0x5F, 0)
#else
#define ATA_IO_WAIT() StallExecutionProcessor(1)
#endif
#if defined(_M_IX86) || defined(_M_AMD64)
/* x86 I/O address space spans from 0 to 0xFFFF */
typedef USHORT IDE_REG;
#else
typedef ULONG_PTR IDE_REG;
#endif
#define ATA_MAX_LBA_28 0x0FFFFFFFULL
#define ATA_MAX_LBA_48 (1ULL << 48)
#define IDE_FEATURE_PIO 0x00
#define IDE_DC_ALWAYS 0x08
#define IDE_DRIVE_SELECT 0xA0
#define ATAPI_INT_REASON_COD 0x01
#define ATAPI_INT_REASON_IO 0x02
#define ATAPI_INT_REASON_MASK (ATAPI_INT_REASON_IO | ATAPI_INT_REASON_COD)
#define ATAPI_INT_REASON_STATUS_NEC 0x00
#define ATAPI_INT_REASON_STATUS (ATAPI_INT_REASON_IO | ATAPI_INT_REASON_COD)
#define ATAPI_INT_REASON_AWAIT_CDB (IDE_STATUS_DRQ | ATAPI_INT_REASON_COD)
#define ATAPI_INT_REASON_DATA_IN (ATAPI_INT_REASON_IO | IDE_STATUS_DRQ)
#define MAXIMUM_CDROM_SIZE 804 // == sizeof(CDROM_TOC)
#define ATA_TIME_BUSY_SELECT 2000 ///< 20 ms
#define ATA_TIME_BUSY_POLL 500000 ///< 5 s
#define ATA_TIME_BUSY_ENUM 100 ///< 1 ms
#define ATA_TIME_BUSY_RESET 1000000 ///< 10 s
#define ATA_TIME_RESET_SELECT 200000 ///< 2 s
#define ATA_TIME_DRQ_CLEAR 100 ///< 200 us
#define ATA_TIME_PHASE_CHANGE 100 ///< 1 ms
#define ATA_WRITE(Port, Value) \
WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)(Port), (Value))
#define ATA_WRITE_BLOCK_16(Port, Buffer, Count) \
WRITE_PORT_BUFFER_USHORT((PUSHORT)(ULONG_PTR)(Port), (PUSHORT)(Buffer), (Count))
#define ATA_WRITE_BLOCK_32(Port, Buffer, Count) \
WRITE_PORT_BUFFER_ULONG((PULONG)(ULONG_PTR)(Port), (PULONG)(Buffer), (Count))
#define ATA_READ(Port) \
READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)(Port))
#define ATA_READ_BLOCK_16(Port, Buffer, Count) \
READ_PORT_BUFFER_USHORT((PUSHORT)(ULONG_PTR)(Port), (PUSHORT)(Buffer), (Count))
#define ATA_READ_BLOCK_32(Port, Buffer, Count) \
READ_PORT_BUFFER_ULONG((PULONG)(ULONG_PTR)(Port), (PULONG)(Buffer), (Count))
typedef enum _ATA_DEVICE_CLASS
{
DEV_ATA,
DEV_ATAPI,
DEV_NONE,
} ATA_DEVICE_CLASS, *PATA_DEVICE_CLASS;
typedef struct _IDE_REGISTERS
{
IDE_REG Data;
union
{
IDE_REG Features;
IDE_REG Error;
};
union
{
IDE_REG SectorCount;
IDE_REG InterruptReason;
};
IDE_REG LbaLow; ///< LBA bits 0-7, 24-31
union
{
IDE_REG LbaMid; ///< LBA bits 8-15, 32-39
IDE_REG ByteCountLow;
IDE_REG SignatureLow;
};
union
{
IDE_REG LbaHigh; ///< LBA bits 16-23, 40-47
IDE_REG ByteCountHigh;
IDE_REG SignatureHigh;
};
IDE_REG Device;
union
{
IDE_REG Command;
IDE_REG Status;
};
union
{
IDE_REG Control;
IDE_REG AlternateStatus;
};
} IDE_REGISTERS, *PIDE_REGISTERS;
typedef struct _ATA_TASKFILE
{
UCHAR DriveSelect;
UCHAR Command;
struct
{
UCHAR Feature;
UCHAR SectorCount;
UCHAR LowLba;
UCHAR MidLba;
UCHAR HighLba;
} Data[2]; // 0 - low part, 1 - high part
} ATA_TASKFILE, *PATA_TASKFILE;
typedef struct _ATA_DEVICE_REQUEST
{
union
{
UCHAR Cdb[16];
ATA_TASKFILE TaskFile;
};
PVOID DataBuffer;
ULONG Flags;
#define REQUEST_FLAG_LBA48 0x00000001
#define REQUEST_FLAG_READ_WRITE_MULTIPLE 0x00000002
#define REQUEST_FLAG_PACKET_COMMAND 0x00000004
#define REQUEST_FLAG_SET_DEVICE_REGISTER 0x00000008
#define REQUEST_FLAG_AWAIT_CDB 0x00000010
#define REQUEST_FLAG_READ_COMMAND 0x00000020
#define REQUEST_FLAG_IDENTIFY_COMMAND 0x00000040
ULONG DataTransferLength;
} ATA_DEVICE_REQUEST, *PATA_DEVICE_REQUEST;
typedef struct _HW_DEVICE_UNIT
{
/* Public data, must be the first member */
DEVICE_UNIT P;
IDE_REGISTERS Registers;
ULONG BytesToTransfer;
PUCHAR DataBuffer;
ULONG DrqByteCount;
ULONG MaximumTransferLength;
UCHAR DeviceNumber;
UCHAR DeviceSelect;
UCHAR CdbSize;
UCHAR MultiSectorTransfer;
union
{
IDENTIFY_DEVICE_DATA IdentifyDeviceData;
IDENTIFY_PACKET_DATA IdentifyPacketData;
};
} HW_DEVICE_UNIT, *PHW_DEVICE_UNIT;
FORCEINLINE
BOOLEAN
AtaDevIsIdentifyDataValid(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
ULONG i;
UCHAR Crc;
/* Bits 0:8 of word 255 */
if (IdentifyData->Signature != 0xA5)
{
/* The integrity word is missing, assume the data provided by the device is valid */
return TRUE;
}
/* Verify the checksum */
Crc = 0;
for (i = 0; i < sizeof(*IdentifyData); ++i)
{
Crc += ((PUCHAR)IdentifyData)[i];
}
return (Crc == 0);
}
FORCEINLINE
UCHAR
AtaDevCdbSizeInWords(
_In_ PIDENTIFY_PACKET_DATA IdentifyPacketData)
{
/* Bits 0:2 of word 0 */
return (IdentifyPacketData->GeneralConfiguration.PacketType != 0) ? 8 : 6;
}
FORCEINLINE
BOOLEAN
AtaDevHasLbaTranslation(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
/* Bit 9 of word 49 */
return IdentifyData->Capabilities.LbaSupported;
}
FORCEINLINE
ULONG
AtaDevUserAddressableSectors28Bit(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
/* Words 60-61 */
return IdentifyData->UserAddressableSectors;
}
FORCEINLINE
ULONG64
AtaDevUserAddressableSectors48Bit(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
/* Words 100-103 */
return ((ULONG64)IdentifyData->Max48BitLBA[1] << 32) | IdentifyData->Max48BitLBA[0];
}
FORCEINLINE
BOOLEAN
AtaDevHas48BitAddressFeature(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
/* Word 83: 15 = 0, 14 = 1 */
if (IdentifyData->CommandSetSupport.WordValid83 == 1)
{
/* Bit 10 of word 83 */
return IdentifyData->CommandSetSupport.BigLba;
}
return FALSE;
}
FORCEINLINE
BOOLEAN
AtaDevIsCurrentGeometryValid(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
return ((IdentifyData->TranslationFieldsValid & 1) &&
(IdentifyData->NumberOfCurrentCylinders != 0) &&
(IdentifyData->NumberOfCurrentCylinders <= 63) &&
(IdentifyData->NumberOfCurrentHeads != 0) &&
(IdentifyData->NumberOfCurrentHeads <= 16) &&
(IdentifyData->CurrentSectorsPerTrack != 0));
}
FORCEINLINE
VOID
AtaDevDefaultChsTranslation(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData,
_Out_ PUSHORT Cylinders,
_Out_ PUSHORT Heads,
_Out_ PUSHORT SectorsPerTrack)
{
/* Word 1 */
*Cylinders = IdentifyData->NumCylinders;
/* Word 3 */
*Heads = IdentifyData->NumHeads;
/* Word 6 */
*SectorsPerTrack = IdentifyData->NumSectorsPerTrack;
}
FORCEINLINE
VOID
AtaDevCurrentChsTranslation(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData,
_Out_ PUSHORT Cylinders,
_Out_ PUSHORT Heads,
_Out_ PUSHORT SectorsPerTrack)
{
/* Word 54 */
*Cylinders = IdentifyData->NumberOfCurrentCylinders;
/* Word 55 */
*Heads = IdentifyData->NumberOfCurrentHeads;
/* Word 55 */
*SectorsPerTrack = IdentifyData->CurrentSectorsPerTrack;
}
FORCEINLINE
UCHAR
AtaDevCurrentSectorsPerDrq(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
UCHAR MultiSectorCurrent;
/* Bit 8 of word 59 */
if (!(IdentifyData->MultiSectorSettingValid))
return 0;
/* The word 59 should be a power of 2 */
MultiSectorCurrent = IdentifyData->CurrentMultiSectorSetting;
if ((MultiSectorCurrent > 0) && ((MultiSectorCurrent & (MultiSectorCurrent - 1)) == 0))
return MultiSectorCurrent;
return 0;
}
FORCEINLINE
UCHAR
AtaDevMaximumSectorsPerDrq(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
UCHAR MultiSectorMax;
/* The word 47 should be a power of 2 */
MultiSectorMax = IdentifyData->MaximumBlockTransfer;
if ((MultiSectorMax > 0) && ((MultiSectorMax & (MultiSectorMax - 1)) == 0))
return MultiSectorMax;
return 0;
}
FORCEINLINE
ULONG
AtaDevBytesPerLogicalSector(
_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
{
ULONG WordCount;
/* Word 106: 15 = 0, 14 = 1, 12 = 1 */
if (IdentifyData->PhysicalLogicalSectorSize.Reserved1 == 1 &&
IdentifyData->PhysicalLogicalSectorSize.LogicalSectorLongerThan256Words)
{
/* Words 116-117 */
WordCount = IdentifyData->WordsPerLogicalSector[0];
WordCount |= (ULONG)IdentifyData->WordsPerLogicalSector[1] << 16;
}
else
{
/* 256 words = 512 bytes */
WordCount = 256;
}
return WordCount * sizeof(USHORT);
}
FORCEINLINE
BOOLEAN
AtaCommandUseLba48(
_In_ ULONG64 SectorNumber,
_In_ ULONG SectorCount)
{
/* Use the 48-bit command when reasonable */
return (((SectorNumber + SectorCount) >= ATA_MAX_LBA_28) || (SectorCount > 0x100));
}

View file

@ -34,7 +34,6 @@ Pc98HwIdle(VOID)
VOID
Pc98PrepareForReactOS(VOID)
{
Pc98DiskPrepareForReactOS();
Pc98VideoPrepareForReactOS();
DiskStopFloppyMotor();
DebugDisableScreenPort();

View file

@ -132,11 +132,6 @@ BOOLEAN DiskResetController(IN PPC98_DISK_DRIVE DiskDrive)
return INT386_SUCCESS(Regs);
}
VOID Pc98DiskPrepareForReactOS(VOID)
{
AtaFree();
}
PPC98_DISK_DRIVE
Pc98DiskDriveNumberToDrive(IN UCHAR DriveNumber)
{
@ -187,7 +182,7 @@ Pc98DiskReadLogicalSectorsLBA(
if (DiskDrive->Type & DRIVE_IDE && DiskDrive->Type & DRIVE_CDROM)
{
return AtaAtapiReadLogicalSectorsLBA(AtaGetDevice(DiskDrive->IdeUnitNumber), SectorNumber, SectorCount, Buffer);
return AtaReadLogicalSectors(AtaGetDevice(DiskDrive->IdeUnitNumber), SectorNumber, SectorCount, Buffer);
}
else
{
@ -503,7 +498,7 @@ InitIdeDrive(
{
DiskDrive->Geometry.Cylinders = DeviceUnit->Cylinders;
DiskDrive->Geometry.Heads = DeviceUnit->Heads;
DiskDrive->Geometry.SectorsPerTrack = DeviceUnit->Sectors;
DiskDrive->Geometry.SectorsPerTrack = DeviceUnit->SectorsPerTrack;
DiskDrive->Geometry.BytesPerSector = DeviceUnit->SectorSize;
DiskDrive->Geometry.Sectors = DeviceUnit->TotalSectors;

View file

@ -374,7 +374,6 @@ XboxPrepareForReactOS(VOID)
{
/* On Xbox, prepare video and disk support */
XboxVideoPrepareForReactOS();
XboxDiskInit(FALSE);
DiskStopFloppyMotor();
/* Turn off debug messages to screen */

View file

@ -3,7 +3,7 @@
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* PURPOSE: Xbox specific disk access routines
* COPYRIGHT: Copyright 2004 van Geldorp (gvg@reactos.com)
* Copyright 2019 Dmitry Borisov (di.sean@protonmail.com)
* Copyright 2019-2025 Dmitry Borisov (di.sean@protonmail.com)
*/
/* INCLUDES *******************************************************************/
@ -22,15 +22,18 @@ static BOOLEAN AtaInitialized = FALSE;
/* FUNCTIONS ******************************************************************/
static
VOID
XboxDiskInit(BOOLEAN Init)
XboxDiskInit(VOID)
{
UCHAR DetectedCount;
UCHAR UnitNumber;
PDEVICE_UNIT DeviceUnit = NULL;
if (Init & !AtaInitialized)
{
ASSERT(!AtaInitialized);
AtaInitialized = TRUE;
/* Find first HDD and CD */
AtaInit(&DetectedCount);
for (UnitNumber = 0; UnitNumber <= DetectedCount; UnitNumber++)
@ -50,12 +53,6 @@ XboxDiskInit(BOOLEAN Init)
}
}
}
AtaInitialized = TRUE;
}
else
{
AtaFree();
}
}
static inline
@ -67,7 +64,7 @@ XboxDiskDriveNumberToDeviceUnit(UCHAR DriveNumber)
return NULL;
if (!AtaInitialized)
XboxDiskInit(TRUE);
XboxDiskInit();
/* HDD */
if ((DriveNumber == 0x80) && HardDrive)
@ -96,7 +93,7 @@ XboxDiskReadLogicalSectors(
if (!DeviceUnit)
return FALSE;
return AtaAtapiReadLogicalSectorsLBA(DeviceUnit, SectorNumber, SectorCount, Buffer);
return AtaReadLogicalSectors(DeviceUnit, SectorNumber, SectorCount, Buffer);
}
BOOLEAN
@ -112,7 +109,7 @@ XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY Geometry)
Geometry->Cylinders = DeviceUnit->Cylinders;
Geometry->Heads = DeviceUnit->Heads;
Geometry->SectorsPerTrack = DeviceUnit->Sectors;
Geometry->SectorsPerTrack = DeviceUnit->SectorsPerTrack;
Geometry->BytesPerSector = DeviceUnit->SectorSize;
Geometry->Sectors = DeviceUnit->TotalSectors;
@ -135,7 +132,7 @@ XboxDiskGetCacheableBlockCount(UCHAR DriveNumber)
if (DeviceUnit->Flags & ATA_DEVICE_LBA)
return 64;
else
return DeviceUnit->Sectors;
return DeviceUnit->SectorsPerTrack;
}
/* EOF */

View file

@ -151,7 +151,6 @@ UCHAR Pc98GetFloppyCount(VOID);
PPC98_DISK_DRIVE Pc98DiskDriveNumberToDrive(IN UCHAR DriveNumber);
ULONG Pc98GetBootSectorLoadAddress(IN UCHAR DriveNumber);
VOID Pc98DiskPrepareForReactOS(VOID);
/* hwdisk.c */
BOOLEAN PcInitializeBootDevices(VOID);

View file

@ -51,7 +51,6 @@ VOID XboxPrepareForReactOS(VOID);
VOID XboxMemInit(VOID);
PFREELDR_MEMORY_DESCRIPTOR XboxMemGetMemoryMap(ULONG *MemoryMapSize);
VOID XboxDiskInit(BOOLEAN Init);
BOOLEAN XboxDiskReadLogicalSectors(UCHAR DriveNumber, ULONGLONG SectorNumber, ULONG SectorCount, PVOID Buffer);
BOOLEAN XboxDiskGetDriveGeometry(UCHAR DriveNumber, PGEOMETRY DriveGeometry);
ULONG XboxDiskGetCacheableBlockCount(UCHAR DriveNumber);

View file

@ -1,331 +1,52 @@
/*
* PROJECT: FreeLoader
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
* LICENSE: MIT (https://spdx.org/licenses/MIT)
* PURPOSE: ATA/ATAPI programmed I/O driver header file.
* COPYRIGHT: Copyright 2019-2020 Dmitry Borisov (di.sean@protonmail.com)
* COPYRIGHT: Copyright 2019-2025 Dmitry Borisov (di.sean@protonmail.com)
*/
/* GLOBALS ********************************************************************/
/* Some definitions were taken from UniATA driver by Alter */
/*
* IDE registers offsets
*/
#if defined(SARCH_PC98)
#define IDX_IO1_i_Data 0x00
#define IDX_IO1_i_Error 0x02
#define IDX_IO1_i_BlockCount 0x04
#define IDX_IO1_i_BlockNumber 0x06
#define IDX_IO1_i_CylinderLow 0x08
#define IDX_IO1_i_CylinderHigh 0x0A
#define IDX_IO1_i_DriveSelect 0x0C
#define IDX_IO1_i_Status 0x0E
#define IDX_IO2_i_AltStatus 0x10C
#define IDX_IO2_i_DriveAddress 0x10E
#define IDE_IO_i_Bank 0x432
#define IDX_IO1_o_Data 0x00
#define IDX_IO1_o_Feature 0x02
#define IDX_IO1_o_BlockCount 0x04
#define IDX_IO1_o_BlockNumber 0x06
#define IDX_IO1_o_CylinderLow 0x08
#define IDX_IO1_o_CylinderHigh 0x0A
#define IDX_IO1_o_DriveSelect 0x0C
#define IDX_IO1_o_Command 0x0E
#define IDX_IO2_o_Control 0x10C
#define IDE_IO_o_BankSelect 0x432
#else /* SARCH_PC98 */
#define IDX_IO1_i_Data 0x00
#define IDX_IO1_i_Error 0x01
#define IDX_IO1_i_BlockCount 0x02
#define IDX_IO1_i_BlockNumber 0x03
#define IDX_IO1_i_CylinderLow 0x04
#define IDX_IO1_i_CylinderHigh 0x05
#define IDX_IO1_i_DriveSelect 0x06
#define IDX_IO1_i_Status 0x07
#define IDX_IO2_i_AltStatus 0x206
#define IDX_IO2_i_DriveAddress 0x207
#define IDX_IO1_o_Data 0x00
#define IDX_IO1_o_Feature 0x01
#define IDX_IO1_o_BlockCount 0x02
#define IDX_IO1_o_BlockNumber 0x03
#define IDX_IO1_o_CylinderLow 0x04
#define IDX_IO1_o_CylinderHigh 0x05
#define IDX_IO1_o_DriveSelect 0x06
#define IDX_IO1_o_Command 0x07
#define IDX_IO2_o_Control 0x206
#endif
/*
* ATAPI registers offsets
*/
#if defined(SARCH_PC98)
#define IDX_ATAPI_IO1_i_Data 0x00
#define IDX_ATAPI_IO1_i_Error 0x02
#define IDX_ATAPI_IO1_i_InterruptReason 0x04
#define IDX_ATAPI_IO1_i_Unused1 0x06
#define IDX_ATAPI_IO1_i_ByteCountLow 0x08
#define IDX_ATAPI_IO1_i_ByteCountHigh 0x0A
#define IDX_ATAPI_IO1_i_DriveSelect 0x0C
#define IDX_ATAPI_IO1_i_Status 0x0E
#define IDX_ATAPI_IO1_o_Data 0x00
#define IDX_ATAPI_IO1_o_Feature 0x02
#define IDX_ATAPI_IO1_o_Unused0 0x04
#define IDX_ATAPI_IO1_o_Unused1 0x06
#define IDX_ATAPI_IO1_o_ByteCountLow 0x08
#define IDX_ATAPI_IO1_o_ByteCountHigh 0x0A
#define IDX_ATAPI_IO1_o_DriveSelect 0x0C
#define IDX_ATAPI_IO1_o_Command 0x0E
#else /* SARCH_PC98 */
#define IDX_ATAPI_IO1_i_Data 0x00
#define IDX_ATAPI_IO1_i_Error 0x01
#define IDX_ATAPI_IO1_i_InterruptReason 0x02
#define IDX_ATAPI_IO1_i_Unused1 0x03
#define IDX_ATAPI_IO1_i_ByteCountLow 0x04
#define IDX_ATAPI_IO1_i_ByteCountHigh 0x05
#define IDX_ATAPI_IO1_i_DriveSelect 0x06
#define IDX_ATAPI_IO1_i_Status 0x07
#define IDX_ATAPI_IO1_o_Data 0x00
#define IDX_ATAPI_IO1_o_Feature 0x01
#define IDX_ATAPI_IO1_o_Unused0 0x02
#define IDX_ATAPI_IO1_o_Unused1 0x03
#define IDX_ATAPI_IO1_o_ByteCountLow 0x04
#define IDX_ATAPI_IO1_o_ByteCountHigh 0x05
#define IDX_ATAPI_IO1_o_DriveSelect 0x06
#define IDX_ATAPI_IO1_o_Command 0x07
#endif
/*
* IDE status definitions
*/
#define IDE_STATUS_SUCCESS 0x00
#define IDE_STATUS_ERROR 0x01
#define IDE_STATUS_INDEX 0x02
#define IDE_STATUS_CORRECTED_ERROR 0x04
#define IDE_STATUS_DRQ 0x08
#define IDE_STATUS_DSC 0x10
#define IDE_STATUS_DMA 0x20 /* DMA ready */
#define IDE_STATUS_DWF 0x20 /* drive write fault */
#define IDE_STATUS_DRDY 0x40
#define IDE_STATUS_IDLE 0x50
#define IDE_STATUS_BUSY 0x80
#define IDE_STATUS_WRONG 0xff
#define IDE_STATUS_MASK 0xff
/*
* IDE drive select/head definitions
*/
#define IDE_DRIVE_SELECT 0xA0
#define IDE_DRIVE_1 0x00
#define IDE_DRIVE_2 0x10
#define IDE_DRIVE_SELECT_1 (IDE_DRIVE_SELECT | IDE_DRIVE_1)
#define IDE_DRIVE_SELECT_2 (IDE_DRIVE_SELECT | IDE_DRIVE_2)
#define IDE_DRIVE_MASK (IDE_DRIVE_SELECT_1 | IDE_DRIVE_SELECT_2)
#define IDE_USE_LBA 0x40
/*
* IDE drive control definitions
*/
#define IDE_DC_DISABLE_INTERRUPTS 0x02
#define IDE_DC_RESET_CONTROLLER 0x04
#define IDE_DC_A_4BIT 0x80
#define IDE_DC_USE_HOB 0x80 // use high-order byte(s)
#define IDE_DC_REENABLE_CONTROLLER 0x00
/*
* IDE error definitions
*/
#define IDE_ERROR_ICRC 0x80
#define IDE_ERROR_BAD_BLOCK 0x80
#define IDE_ERROR_DATA_ERROR 0x40
#define IDE_ERROR_MEDIA_CHANGE 0x20
#define IDE_ERROR_ID_NOT_FOUND 0x10
#define IDE_ERROR_MEDIA_CHANGE_REQ 0x08
#define IDE_ERROR_COMMAND_ABORTED 0x04
#define IDE_ERROR_END_OF_MEDIA 0x02
#define IDE_ERROR_NO_MEDIA 0x02
#define IDE_ERROR_ILLEGAL_LENGTH 0x01
/*
* Values for TransferMode
*/
#define ATA_PIO 0x00
/*
* IDENTIFY data
*/
#include <pshpack1.h>
typedef struct _IDENTIFY_DATA
{
UCHAR AtapiCmdSize:2; // 00 00 General configuration
UCHAR Unused1:3;
UCHAR DrqType:2;
UCHAR Removable:1;
UCHAR DeviceType:5;
UCHAR Unused2:1;
UCHAR CmdProtocol:2;
USHORT NumberOfCylinders; // 02 1
USHORT Reserved1; // 04 2
USHORT NumberOfHeads; // 06 3
USHORT UnformattedBytesPerTrack; // 08 4
USHORT UnformattedBytesPerSector; // 0A 5
USHORT SectorsPerTrack; // 0C 6
USHORT VendorUnique1[3]; // 0E 7-9
USHORT SerialNumber[10]; // 14 10-19
USHORT BufferType; // 28 20
USHORT BufferSectorSize; // 2A 21
USHORT NumberOfEccBytes; // 2C 22
USHORT FirmwareRevision[4]; // 2E 23-26
USHORT ModelNumber[20]; // 36 27-46
UCHAR ReadWriteMultipleSupport; // 5E 47
UCHAR VendorUnique2; // 5F
USHORT DoubleWordIo; // 60 48
USHORT Reserved62_0:8; // 62 49 Capabilities
USHORT SupportDma:1;
USHORT SupportLba:1;
USHORT DisableIordy:1;
USHORT SupportIordy:1;
USHORT SoftReset:1;
USHORT StandbyOverlap:1;
USHORT SupportQTag:1;
USHORT SupportIDma:1;
USHORT Reserved2; // 64 50
UCHAR VendorUnique3; // 66 51
UCHAR PioCycleTimingMode; // 67
UCHAR VendorUnique4; // 68 52
UCHAR DmaCycleTimingMode; // 69
USHORT TranslationFieldsValid:1; // 6A 53
USHORT Reserved3:15;
USHORT NumberOfCurrentCylinders; // 6C 54
USHORT NumberOfCurrentHeads; // 6E 55
USHORT CurrentSectorsPerTrack; // 70 56
ULONG CurrentSectorCapacity; // 72 57-58
USHORT CurrentMultiSectorSetting; // 59
ULONG UserAddressableSectors; // 60-61
USHORT SingleWordDMASupport:8; // 62
USHORT SingleWordDMAActive:8;
USHORT MultiWordDMASupport:8; // 63
USHORT MultiWordDMAActive:8;
USHORT AdvancedPIOModes:8; // 64
USHORT Reserved4:8;
USHORT MinimumMWXferCycleTime; // 65
USHORT RecommendedMWXferCycleTime; // 66
USHORT MinimumPIOCycleTime; // 67
USHORT MinimumPIOCycleTimeIORDY; // 68
USHORT Reserved5[2]; // 69-70
USHORT ReleaseTimeOverlapped; // 71
USHORT ReleaseTimeServiceCommand; // 72
USHORT Reserved73_74[2]; // 73-74
USHORT QueueLength:5; // 75
USHORT Reserved75_6:11;
USHORT SataCapabilities; // 76
USHORT Reserved77; // 77
USHORT SataSupport; // 78
USHORT SataEnable; // 79
USHORT MajorRevision; // 80
USHORT MinorRevision; // 81
struct {
USHORT Smart:1; // 82
USHORT Security:1;
USHORT Removable:1;
USHORT PowerMngt:1;
USHORT Packet:1;
USHORT WriteCache:1;
USHORT LookAhead:1;
USHORT ReleaseDRQ:1;
USHORT ServiceDRQ:1;
USHORT Reset:1;
USHORT Protected:1;
USHORT Reserved_82_11:1;
USHORT WriteBuffer:1;
USHORT ReadBuffer:1;
USHORT Nop:1;
USHORT Reserved_82_15:1;
USHORT Microcode:1; // 83/86
USHORT Queued:1;
USHORT CFA:1;
USHORT APM:1;
USHORT Notify:1;
USHORT Standby:1;
USHORT Spinup:1;
USHORT Reserver_83_7:1;
USHORT MaxSecurity:1;
USHORT AutoAcoustic:1;
USHORT Address48:1;
USHORT ConfigOverlay:1;
USHORT FlushCache:1;
USHORT FlushCache48:1;
USHORT SupportOne:1;
USHORT SupportZero:1;
USHORT SmartErrorLog:1; // 84/87
USHORT SmartSelfTest:1;
USHORT MediaSerialNo:1;
USHORT MediaCardPass:1;
USHORT Streaming:1;
USHORT Logging:1;
USHORT Reserver_84_6:8;
USHORT ExtendedOne:1;
USHORT ExtendedZero:1;
} FeaturesSupport, FeaturesEnabled;
USHORT Reserved6[13]; // 88-99
ULONGLONG UserAddressableSectors48; // 100-103
USHORT Reserved7[151]; // 104-255
} IDENTIFY_DATA, *PIDENTIFY_DATA;
#include <poppack.h>
#define IDENTIFY_DATA_SIZE sizeof(IDENTIFY_DATA)
#define ATAPI_MAGIC_LSB 0x14
#define ATAPI_MAGIC_MSB 0xEB
#define MAXIMUM_CDROM_SIZE 804
#pragma once
/** @brief Data structure for the ATA device. */
typedef struct _DEVICE_UNIT
{
UCHAR Channel;
UCHAR DeviceNumber;
/** Number of cylinders on the device */
ULONG Cylinders;
/** Number of heads on the device */
ULONG Heads;
ULONG Sectors;
/** Number of sectors per track */
ULONG SectorsPerTrack;
/** Number of bytes per sector */
ULONG SectorSize;
ULONGLONG TotalSectors; /* This number starts from 0 */
USHORT Flags;
IDENTIFY_DATA IdentifyData;
/** Total number of device sectors/LBA blocks */
ULONG64 TotalSectors;
/** Device-specific flags */
ULONG Flags;
#define ATA_DEVICE_ATAPI 0x00000001
#define ATA_DEVICE_LBA 0x00000002
#define ATA_DEVICE_LBA48 0x00000004
#define ATA_DEVICE_IS_NEC_CDR260 0x00000008
#define ATA_DEVICE_FLAG_IO32 0x00000010
} DEVICE_UNIT, *PDEVICE_UNIT;
#define ATA_DEVICE_ATAPI (1 << 0)
#define ATA_DEVICE_NO_MEDIA (1 << 1)
#define ATA_DEVICE_NOT_READY (1 << 2)
#define ATA_DEVICE_LBA48 (1 << 3)
#define ATA_DEVICE_LBA (1 << 4)
#define ATA_DEVICE_CHS (1 << 5)
/* PROTOTYPES ****************************************************************/
/* FUNCTIONS ******************************************************************/
BOOLEAN
AtaInit(
OUT PUCHAR DetectedCount
);
VOID
AtaFree();
_Out_ PUCHAR DetectedCount);
PDEVICE_UNIT
AtaGetDevice(
IN UCHAR UnitNumber
);
_In_ UCHAR UnitNumber);
BOOLEAN
AtaAtapiReadLogicalSectorsLBA(
IN OUT PDEVICE_UNIT DeviceUnit,
IN ULONGLONG SectorNumber,
IN ULONG SectorCount,
OUT PVOID Buffer
);
AtaReadLogicalSectors(
_In_ PDEVICE_UNIT DeviceUnit,
_In_ ULONG64 SectorNumber,
_In_ ULONG SectorCount,
_Out_writes_bytes_all_(SectorCount * DeviceUnit->SectorSize) PVOID Buffer);

View file

@ -14,7 +14,7 @@ typedef struct _IDENTIFY_DEVICE_DATA {
USHORT DeviceType :1;
} GeneralConfiguration;
USHORT NumCylinders;
USHORT ReservedWord2;
USHORT SpecificConfiguration;
USHORT NumHeads;
USHORT Retired1[2];
USHORT NumSectorsPerTrack;
@ -26,9 +26,13 @@ typedef struct _IDENTIFY_DEVICE_DATA {
UCHAR ModelNumber[40];
UCHAR MaximumBlockTransfer;
UCHAR VendorUnique2;
USHORT ReservedWord48;
struct {
UCHAR ReservedByte49;
USHORT FeatureSupported :1;
USHORT Reserved :15;
} TrustedComputing;
struct {
UCHAR CurrentLongPhysicalSectorAlignment :2;
UCHAR ReservedByte49 :6;
UCHAR DmaSupported :1;
UCHAR LbaSupported :1;
UCHAR IordyDisable :1;
@ -40,14 +44,19 @@ typedef struct _IDENTIFY_DEVICE_DATA {
} Capabilities;
USHORT ObsoleteWords51[2];
USHORT TranslationFieldsValid :3;
USHORT Reserved3 :13;
USHORT Reserved3 :5;
USHORT FreeFallControlSensitivity :8;
USHORT NumberOfCurrentCylinders;
USHORT NumberOfCurrentHeads;
USHORT CurrentSectorsPerTrack;
ULONG CurrentSectorCapacity;
UCHAR CurrentMultiSectorSetting;
UCHAR MultiSectorSettingValid :1;
UCHAR ReservedByte59 :7;
UCHAR ReservedByte59 :3;
UCHAR SanitizeFeatureSupported :1;
UCHAR CryptoScrambleExtCommandSupported :1;
UCHAR OverwriteExtCommandSupported :1;
UCHAR BlockEraseExtCommandSupported :1;
ULONG UserAddressableSectors;
USHORT ObsoleteWord62;
USHORT MultiWordDMASupport :8;
@ -58,10 +67,74 @@ typedef struct _IDENTIFY_DEVICE_DATA {
USHORT RecommendedMWXferCycleTime;
USHORT MinimumPIOCycleTime;
USHORT MinimumPIOCycleTimeIORDY;
USHORT ReservedWords69[6];
struct {
USHORT ZonedCapabilities :2;
USHORT NonVolatileWriteCache :1;
USHORT ExtendedUserAddressableSectorsSupported :1;
USHORT DeviceEncryptsAllUserData :1;
USHORT ReadZeroAfterTrimSupported :1;
USHORT Optional28BitCommandsSupported :1;
USHORT IEEE1667 :1;
USHORT DownloadMicrocodeDmaSupported :1;
USHORT SetMaxSetPasswordUnlockDmaSupported :1;
USHORT WriteBufferDmaSupported :1;
USHORT ReadBufferDmaSupported :1;
USHORT DeviceConfigIdentifySetDmaSupported :1;
USHORT LPSAERCSupported :1;
USHORT DeterministicReadAfterTrimSupported :1;
USHORT CFastSpecSupported :1;
} AdditionalSupported;
USHORT ReservedWords70[5];
USHORT QueueDepth :5;
USHORT ReservedWord75 :11;
USHORT ReservedWords76[4];
struct {
USHORT Reserved0 :1;
USHORT SataGen1 :1;
USHORT SataGen2 :1;
USHORT SataGen3 :1;
USHORT Reserved1 :4;
USHORT NCQ :1;
USHORT HIPM :1;
USHORT PhyEvents :1;
USHORT NcqUnload :1;
USHORT NcqPriority :1;
USHORT HostAutoPS :1;
USHORT DeviceAutoPS :1;
USHORT ReadLogDMA :1;
USHORT Reserved2 :1;
USHORT CurrentSpeed :3;
USHORT NcqStreaming :1;
USHORT NcqQueueMgmt :1;
USHORT NcqReceiveSend :1;
USHORT DEVSLPtoReducedPwrState :1;
USHORT Reserved3 :8;
} SerialAtaCapabilities;
struct {
USHORT Reserved0 :1;
USHORT NonZeroOffsets :1;
USHORT DmaSetupAutoActivate :1;
USHORT DIPM :1;
USHORT InOrderData :1;
USHORT HardwareFeatureControl :1;
USHORT SoftwareSettingsPreservation :1;
USHORT NCQAutosense :1;
USHORT DEVSLP :1;
USHORT HybridInformation :1;
USHORT Reserved1 :6;
} SerialAtaFeaturesSupported;
struct {
USHORT Reserved0 :1;
USHORT NonZeroOffsets :1;
USHORT DmaSetupAutoActivate :1;
USHORT DIPM :1;
USHORT InOrderData :1;
USHORT HardwareFeatureControl :1;
USHORT SoftwareSettingsPreservation :1;
USHORT DeviceAutoPS :1;
USHORT DEVSLP :1;
USHORT HybridInformation :1;
USHORT Reserved1 :6;
} SerialAtaFeaturesEnabled;
USHORT MajorRevision;
USHORT MinorRevision;
struct {
@ -95,7 +168,7 @@ typedef struct _IDENTIFY_DEVICE_DATA {
USHORT DeviceConfigOverlay :1;
USHORT FlushCache :1;
USHORT FlushCacheExt :1;
USHORT Resrved3 :2;
USHORT WordValid83 :2;
USHORT SmartErrorLog :1;
USHORT SmartSelfTest :1;
USHORT MediaSerialNumber :1;
@ -109,7 +182,7 @@ typedef struct _IDENTIFY_DEVICE_DATA {
USHORT URGWriteStream :1;
USHORT ReservedForTechReport :2;
USHORT IdleWithUnloadFeature :1;
USHORT Reserved4 :2;
USHORT WordValid :2;
} CommandSetSupport;
struct {
USHORT SmartCommands :1;
@ -142,7 +215,8 @@ typedef struct _IDENTIFY_DEVICE_DATA {
USHORT DeviceConfigOverlay :1;
USHORT FlushCache :1;
USHORT FlushCacheExt :1;
USHORT Resrved3 :2;
USHORT Resrved3 :1;
USHORT Words119_120Valid :1;
USHORT SmartErrorLog :1;
USHORT SmartSelfTest :1;
USHORT MediaSerialNumber :1;
@ -160,14 +234,27 @@ typedef struct _IDENTIFY_DEVICE_DATA {
} CommandSetActive;
USHORT UltraDMASupport :8;
USHORT UltraDMAActive :8;
USHORT ReservedWord89[4];
struct {
USHORT TimeRequired :15;
USHORT ExtendedTimeReported :1;
} NormalSecurityEraseUnit;
struct {
USHORT TimeRequired :15;
USHORT ExtendedTimeReported :1;
} EnhancedSecurityEraseUnit;
USHORT CurrentAPMLevel :8;
USHORT ReservedWord91 :8;
USHORT MasterPasswordID;
USHORT HardwareResetResult;
USHORT CurrentAcousticValue :8;
USHORT RecommendedAcousticValue :8;
USHORT ReservedWord95[5];
USHORT StreamMinRequestSize;
USHORT StreamingTransferTimeDMA;
USHORT StreamingAccessLatencyDMAPIO;
ULONG StreamingPerfGranularity;
ULONG Max48BitLBA[2];
USHORT StreamingTransferTime;
USHORT ReservedWord105;
USHORT DsmCap;
struct {
USHORT LogicalSectorsPerPhysicalSector :4;
USHORT Reserved0 :8;
@ -182,19 +269,31 @@ typedef struct _IDENTIFY_DEVICE_DATA {
USHORT WordsPerLogicalSector[2];
struct {
USHORT ReservedForDrqTechnicalReport :1;
USHORT WriteReadVerifySupported :1;
USHORT Reserved01 :11;
USHORT Reserved1 :2;
USHORT WriteReadVerify :1;
USHORT WriteUncorrectableExt :1;
USHORT ReadWriteLogDmaExt :1;
USHORT DownloadMicrocodeMode3 :1;
USHORT FreefallControl :1;
USHORT SenseDataReporting :1;
USHORT ExtendedPowerConditions :1;
USHORT Reserved0 :6;
USHORT WordValid :2;
} CommandSetSupportExt;
struct {
USHORT ReservedForDrqTechnicalReport :1;
USHORT WriteReadVerifyEnabled :1;
USHORT Reserved01 :11;
USHORT WriteReadVerify :1;
USHORT WriteUncorrectableExt :1;
USHORT ReadWriteLogDmaExt :1;
USHORT DownloadMicrocodeMode3 :1;
USHORT FreefallControl :1;
USHORT SenseDataReporting :1;
USHORT ExtendedPowerConditions :1;
USHORT Reserved0 :6;
USHORT Reserved1 :2;
} CommandSetActiveExt;
USHORT ReservedForExpandedSupportandActive[6];
USHORT MsnSupport :2;
USHORT ReservedWord1274 :14;
USHORT ReservedWord127 :14;
struct {
USHORT SecuritySupported :1;
USHORT SecurityEnabled :1;
@ -208,20 +307,32 @@ typedef struct _IDENTIFY_DEVICE_DATA {
} SecurityStatus;
USHORT ReservedWord129[31];
struct {
USHORT MaximumCurrentInMA2 :12;
USHORT MaximumCurrentInMA :12;
USHORT CfaPowerMode1Disabled :1;
USHORT CfaPowerMode1Required :1;
USHORT Reserved0 :1;
USHORT Word160Supported :1;
} CfaPowerModel;
USHORT ReservedForCfaWord161[8];
} CfaPowerMode1;
USHORT ReservedForCfaWord161[7];
USHORT NominalFormFactor :4;
USHORT ReservedWord168 :12;
struct {
USHORT SupportsTrim :1;
USHORT Reserved0 :15;
} DataSetManagementFeature;
USHORT ReservedForCfaWord170[6];
USHORT AdditionalProductID[4];
USHORT ReservedForCfaWord174[2];
USHORT CurrentMediaSerialNumber[30];
USHORT ReservedWord206;
struct {
USHORT Supported :1;
USHORT Reserved0 :1;
USHORT WriteSameSuported :1;
USHORT ErrorRecoveryControlSupported :1;
USHORT FeatureControlSuported :1;
USHORT DataTablesSuported :1;
USHORT Reserved1 :6;
USHORT VendorSpecific :4;
} SCTCommandTransport;
USHORT ReservedWord207[2];
struct {
USHORT AlignmentOfLogicalWithinPhysical :14;
@ -246,22 +357,296 @@ typedef struct _IDENTIFY_DEVICE_DATA {
UCHAR NVCacheEstimatedTimeToSpinUpInSeconds;
UCHAR Reserved;
} NVCacheOptions;
USHORT ReservedWord220[35];
USHORT WriteReadVerifySectorCountMode :8;
USHORT ReservedWord220 :8;
USHORT ReservedWord221;
struct {
USHORT MajorVersion :12;
USHORT TransportType :4;
} TransportMajorVersion;
USHORT TransportMinorVersion;
USHORT ReservedWord224[6];
ULONG ExtendedNumberOfUserAddressableSectors[2];
USHORT MinBlocksPerDownloadMicrocodeMode03;
USHORT MaxBlocksPerDownloadMicrocodeMode03;
USHORT ReservedWord236[19];
USHORT Signature :8;
USHORT CheckSum :8;
} IDENTIFY_DEVICE_DATA, *PIDENTIFY_DEVICE_DATA;
typedef struct _IDENTIFY_PACKET_DATA {
struct {
USHORT PacketType :2;
USHORT IncompleteResponse :1;
USHORT Reserved1 :2;
USHORT DrqDelay :2;
USHORT RemovableMedia :1;
USHORT CommandPacketType :5;
USHORT Reserved2 :1;
USHORT DeviceType :2;
} GeneralConfiguration;
USHORT ResevedWord1;
USHORT UniqueConfiguration;
USHORT ReservedWords3[7];
UCHAR SerialNumber[20];
USHORT ReservedWords20[3];
UCHAR FirmwareRevision[8];
UCHAR ModelNumber[40];
USHORT ReservedWords47[2];
struct {
USHORT VendorSpecific :8;
USHORT DmaSupported :1;
USHORT LbaSupported :1;
USHORT IordyDisabled :1;
USHORT IordySupported :1;
USHORT Obsolete :1;
USHORT OverlapSupported :1;
USHORT QueuedCommandsSupported :1;
USHORT InterleavedDmaSupported :1;
USHORT DeviceSpecificStandbyTimerValueMin :1;
USHORT Obsolete1 :1;
USHORT ReservedWord50 :12;
USHORT WordValid :2;
} Capabilities;
USHORT ObsoleteWords51[2];
USHORT TranslationFieldsValid :3;
USHORT Reserved3 :13;
USHORT ReservedWords54[8];
struct {
USHORT UDMA0Supported :1;
USHORT UDMA1Supported :1;
USHORT UDMA2Supported :1;
USHORT UDMA3Supported :1;
USHORT UDMA4Supported :1;
USHORT UDMA5Supported :1;
USHORT UDMA6Supported :1;
USHORT MDMA0Supported :1;
USHORT MDMA1Supported :1;
USHORT MDMA2Supported :1;
USHORT DMASupported :1;
USHORT ReservedWord62 :4;
USHORT DMADIRBitRequired :1;
} DMADIR;
USHORT MultiWordDMASupport :8;
USHORT MultiWordDMAActive :8;
USHORT AdvancedPIOModes :8;
USHORT ReservedByte64 :8;
USHORT MinimumMWXferCycleTime;
USHORT RecommendedMWXferCycleTime;
USHORT MinimumPIOCycleTime;
USHORT MinimumPIOCycleTimeIORDY;
USHORT ReservedWords69[2];
USHORT BusReleaseDelay;
USHORT ServiceCommandDelay;
USHORT ReservedWords73[2];
USHORT QueueDepth :5;
USHORT ReservedWord75 :11;
struct {
USHORT Reserved0 :1;
USHORT SataGen1 :1;
USHORT SataGen2 :1;
USHORT SataGen3 :1;
USHORT Reserved1 :5;
USHORT HIPM :1;
USHORT PhyEvents :1;
USHORT Reserved3 :2;
USHORT HostAutoPS :1;
USHORT DeviceAutoPS :1;
USHORT Reserved4 :1;
USHORT Reserved5 :1;
USHORT CurrentSpeed :3;
USHORT SlimlineDeviceAttention :1;
USHORT HostEnvironmentDetect :1;
USHORT Reserved :10;
} SerialAtaCapabilities;
struct {
USHORT Reserved0 :1;
USHORT Reserved1 :2;
USHORT DIPM :1;
USHORT Reserved2 :1;
USHORT AsynchronousNotification :1;
USHORT SoftwareSettingsPreservation :1;
USHORT Reserved3 :9;
} SerialAtaFeaturesSupported;
struct {
USHORT Reserved0 :1;
USHORT Reserved1 :2;
USHORT DIPM :1;
USHORT Reserved2 :1;
USHORT AsynchronousNotification :1;
USHORT SoftwareSettingsPreservation :1;
USHORT DeviceAutoPS :1;
USHORT Reserved3 :8;
} SerialAtaFeaturesEnabled;
USHORT MajorRevision;
USHORT MinorRevision;
struct {
USHORT SmartCommands :1;
USHORT SecurityMode :1;
USHORT RemovableMedia :1;
USHORT PowerManagement :1;
USHORT PacketCommands :1;
USHORT WriteCache :1;
USHORT LookAhead :1;
USHORT ReleaseInterrupt :1;
USHORT ServiceInterrupt :1;
USHORT DeviceReset :1;
USHORT HostProtectedArea :1;
USHORT Obsolete1 :1;
USHORT WriteBuffer :1;
USHORT ReadBuffer :1;
USHORT Nop :1;
USHORT Obsolete2 :1;
USHORT DownloadMicrocode :1;
USHORT Reserved1 :2;
USHORT AdvancedPm :1;
USHORT Msn :1;
USHORT PowerUpInStandby :1;
USHORT ManualPowerUp :1;
USHORT Reserved2 :1;
USHORT SetMax :1;
USHORT Reserved3 :3;
USHORT FlushCache :1;
USHORT Reserved4 :1;
USHORT WordValid :2;
} CommandSetSupport;
struct {
USHORT Reserved0 :5;
USHORT GpLogging :1;
USHORT Reserved1 :2;
USHORT WWN64Bit :1;
USHORT Reserved2 :5;
USHORT WordValid :2;
} CommandSetSupportExt;
struct {
USHORT SmartCommands :1;
USHORT SecurityMode :1;
USHORT RemovableMedia :1;
USHORT PowerManagement :1;
USHORT PacketCommands :1;
USHORT WriteCache :1;
USHORT LookAhead :1;
USHORT ReleaseInterrupt :1;
USHORT ServiceInterrupt :1;
USHORT DeviceReset :1;
USHORT HostProtectedArea :1;
USHORT Obsolete1 :1;
USHORT WriteBuffer :1;
USHORT ReadBuffer :1;
USHORT Nop :1;
USHORT Obsolete2 :1;
USHORT DownloadMicrocode :1;
USHORT Reserved1 :2;
USHORT AdvancedPm :1;
USHORT Msn :1;
USHORT PowerUpInStandby :1;
USHORT ManualPowerUp :1;
USHORT Reserved2 :1;
USHORT SetMax :1;
USHORT Reserved3 :3;
USHORT FlushCache :1;
USHORT Reserved :3;
} CommandSetActive;
struct {
USHORT Reserved0 :5;
USHORT GpLogging :1;
USHORT Reserved1 :2;
USHORT WWN64Bit :1;
USHORT Reserved2 :5;
USHORT WordValid :2;
} CommandSetActiveExt;
USHORT UltraDMASupport :8;
USHORT UltraDMAActive :8;
USHORT TimeRequiredForNormalEraseModeSecurityEraseUnit;
USHORT TimeRequiredForEnhancedEraseModeSecurityEraseUnit;
USHORT CurrentAPMLevel;
USHORT MasterPasswordID;
USHORT HardwareResetResult;
USHORT ReservedWords94[14];
USHORT WorldWideName[4];
USHORT ReservedWords112[13];
USHORT AtapiZeroByteCount;
USHORT ReservedWord126;
USHORT MsnSupport :2;
USHORT ReservedWord127 :14;
USHORT SecurityStatus;
USHORT VendorSpecific[31];
USHORT ReservedWord160[16];
USHORT ReservedWord176[46];
struct {
USHORT MajorVersion :12;
USHORT TransportType :4;
} TransportMajorVersion;
USHORT TransportMinorVersion;
USHORT ReservedWord224[31];
USHORT Signature :8;
USHORT CheckSum :8;
} IDENTIFY_PACKET_DATA, *PIDENTIFY_PACKET_DATA;
typedef struct _GP_LOG_NCQ_COMMAND_ERROR {
UCHAR NcqTag : 5;
UCHAR Reserved0 : 1;
UCHAR UNL : 1;
UCHAR NonQueuedCmd : 1;
UCHAR Reserved1;
UCHAR Status;
UCHAR Error;
UCHAR LBA7_0;
UCHAR LBA15_8;
UCHAR LBA23_16;
UCHAR Device;
UCHAR LBA31_24;
UCHAR LBA39_32;
UCHAR LBA47_40;
UCHAR Reserved2;
UCHAR Count7_0;
UCHAR Count15_8;
UCHAR SenseKey;
UCHAR ASC;
UCHAR ASCQ;
UCHAR Reserved3[239];
UCHAR Vendor[255];
UCHAR Checksum;
} GP_LOG_NCQ_COMMAND_ERROR, *PGP_LOG_NCQ_COMMAND_ERROR;
#include <poppack.h>
#define IDE_LBA_MODE (1 << 6)
#define IDE_DC_DISABLE_INTERRUPTS 0x02
#define IDE_DC_RESET_CONTROLLER 0x04
#define IDE_DC_REENABLE_CONTROLLER 0x00
#define IDE_STATUS_ERROR 0x01
#define IDE_STATUS_INDEX 0x02
#define IDE_STATUS_CORRECTED_ERROR 0x04
#define IDE_STATUS_DRQ 0x08
#define IDE_STATUS_DSC 0x10
#define IDE_STATUS_DEVICE_FAULT 0x20
#define IDE_STATUS_DRDY 0x40
#define IDE_STATUS_IDLE 0x50
#define IDE_STATUS_BUSY 0x80
#define IDE_ERROR_ILLEGAL_LENGTH 0x01
#define IDE_ERROR_ADDRESS_NOT_FOUND IDE_ERROR_ILLEGAL_LENGTH
#define IDE_ERROR_END_OF_MEDIA 0x02
#define IDE_ERROR_COMMAND_ABORTED 0x04
#define IDE_ERROR_MEDIA_CHANGE_REQ 0x08
#define IDE_ERROR_ID_NOT_FOUND 0x10
#define IDE_ERROR_MEDIA_CHANGE 0x20
#define IDE_ERROR_DATA_ERROR 0x40
#define IDE_ERROR_BAD_BLOCK 0x80
#define IDE_ERROR_CRC_ERROR IDE_ERROR_BAD_BLOCK
#define IDE_COMMAND_NOP 0x00
#define IDE_COMMAND_DATA_SET_MANAGEMENT 0x06
#define IDE_COMMAND_ATAPI_RESET 0x08
#define IDE_COMMAND_GET_PHYSICAL_ELEMENT_STATUS 0x12
#define IDE_COMMAND_READ 0x20
#define IDE_COMMAND_READ_EXT 0x24
#define IDE_COMMAND_READ_DMA_EXT 0x25
#define IDE_COMMAND_READ_DMA_QUEUED_EXT 0x26
#define IDE_COMMAND_READ_MULTIPLE_EXT 0x29
#define IDE_COMMAND_READ_LOG_EXT 0x2F
#define IDE_COMMAND_WRITE 0x30
#define IDE_COMMAND_WRITE_EXT 0x34
#define IDE_COMMAND_WRITE_DMA_EXT 0x35
@ -269,13 +654,33 @@ typedef struct _IDENTIFY_DEVICE_DATA {
#define IDE_COMMAND_WRITE_MULTIPLE_EXT 0x39
#define IDE_COMMAND_WRITE_DMA_FUA_EXT 0x3D
#define IDE_COMMAND_WRITE_DMA_QUEUED_FUA_EXT 0x3E
#define IDE_COMMAND_WRITE_LOG_EXT 0x3F
#define IDE_COMMAND_VERIFY 0x40
#define IDE_COMMAND_VERIFY_EXT 0x42
#define IDE_COMMAND_ZAC_MANAGEMENT_IN 0x4A
#define IDE_COMMAND_WRITE_LOG_DMA_EXT 0x57
#define IDE_COMMAND_TRUSTED_NON_DATA 0x5B
#define IDE_COMMAND_TRUSTED_RECEIVE 0x5C
#define IDE_COMMAND_TRUSTED_RECEIVE_DMA 0x5D
#define IDE_COMMAND_TRUSTED_SEND 0x5E
#define IDE_COMMAND_TRUSTED_SEND_DMA 0x5F
#define IDE_COMMAND_READ_FPDMA_QUEUED 0x60
#define IDE_COMMAND_WRITE_FPDMA_QUEUED 0x61
#define IDE_COMMAND_NCQ_NON_DATA 0x63
#define IDE_COMMAND_SEND_FPDMA_QUEUED 0x64
#define IDE_COMMAND_RECEIVE_FPDMA_QUEUED 0x65
#define IDE_COMMAND_SET_DATE_AND_TIME 0x77
#define IDE_COMMAND_REMOVE_ELEMENT_AND_TRUNCATE 0x7C
#define IDE_COMMAND_EXECUTE_DEVICE_DIAGNOSTIC 0x90
#define IDE_COMMAND_SET_DRIVE_PARAMETERS 0x91
#define IDE_COMMAND_DOWNLOAD_MICROCODE 0x92
#define IDE_COMMAND_DOWNLOAD_MICROCODE_DMA 0x93
#define IDE_COMMAND_ZAC_MANAGEMENT_OUT 0x9F
#define IDE_COMMAND_ATAPI_PACKET 0xA0
#define IDE_COMMAND_ATAPI_IDENTIFY 0xA1
#define IDE_COMMAND_SMART 0xB0
#define IDE_COMMAND_READ_LOG_DMA_EXT 0xB1
#define IDE_COMMAND_SANITIZE_DEVICE 0xB4
#define IDE_COMMAND_READ_MULTIPLE 0xC4
#define IDE_COMMAND_WRITE_MULTIPLE 0xC5
#define IDE_COMMAND_SET_MULTIPLE 0xC6
@ -295,7 +700,24 @@ typedef struct _IDENTIFY_DEVICE_DATA {
#define IDE_COMMAND_IDENTIFY 0xEC
#define IDE_COMMAND_MEDIA_EJECT 0xED
#define IDE_COMMAND_SET_FEATURE 0xEF
#define IDE_COMMAND_SECURITY_SET_PASSWORD 0xF1
#define IDE_COMMAND_SECURITY_UNLOCK 0xF2
#define IDE_COMMAND_SECURITY_ERASE_PREPARE 0xF3
#define IDE_COMMAND_SECURITY_ERASE_UNIT 0xF4
#define IDE_COMMAND_SECURITY_FREEZE_LOCK 0xF5
#define IDE_COMMAND_SECURITY_DISABLE_PASSWORD 0xF6
#define IDE_COMMAND_NOT_VALID 0xFF
#define IDE_FEATURE_ENABLE_WRITE_CACHE 0x2
#define IDE_FEATURE_SET_TRANSFER_MODE 0x3
#define IDE_FEATURE_ENABLE_PUIS 0x6
#define IDE_FEATURE_PUIS_SPIN_UP 0x7
#define IDE_FEATURE_ENABLE_SATA_FEATURE 0x10
#define IDE_FEATURE_DISABLE_MSN 0x31
#define IDE_FEATURE_DISABLE_REVERT_TO_POWER_ON 0x66
#define IDE_FEATURE_DISABLE_WRITE_CACHE 0x82
#define IDE_FEATURE_DISABLE_PUIS 0x86
#define IDE_FEATURE_DISABLE_SATA_FEATURE 0x90
#define IDE_FEATURE_ENABLE_MSN 0x95
#endif