22#define TAG_ATA_DEVICE 'DatA'
23#define ATAPI_PACKET_SIZE(IdentifyData) (IdentifyData.AtapiCmdSize ? 16 : 12)
24#define ATA_STATUS_TIMEOUT 31e5
26#define AtaWritePort(Channel, Port, Data) \
27 WRITE_PORT_UCHAR(UlongToPtr(BaseArray[(Channel)] + (Port)), (Data))
29#define AtaReadPort(Channel, Port) \
30 READ_PORT_UCHAR(UlongToPtr(BaseArray[(Channel)] + (Port)))
32#define AtaWriteBuffer(Channel, Buffer, Count) \
33 WRITE_PORT_BUFFER_USHORT(UlongToPtr(BaseArray[(Channel)] + IDX_IO1_o_Data), \
34 (PUSHORT)(Buffer), (Count)/sizeof(USHORT))
36#define AtaReadBuffer(Channel, Buffer, Count) \
37 READ_PORT_BUFFER_USHORT(UlongToPtr(BaseArray[(Channel)] + IDX_IO1_i_Data), \
38 (PUSHORT)(Buffer), (Count)/sizeof(USHORT))
43#if defined(SARCH_XBOX)
45#elif defined(SARCH_PC98)
48 0x1F0, 0x170, 0x1E8, 0x168
52#define MAX_CHANNELS RTL_NUMBER_OF(BaseArray)
144 TRACE(
"AtaInit()\n");
157 Units[(*DetectedCount)++] = DeviceUnit;
162 return (*DetectedCount > 0);
181 return Units[UnitNumber];
204 for (RetryCount = 0; RetryCount < 4; ++RetryCount)
212 ERR(
"AtaAtapiReadLogicalSectorsLBA(): Device not ready.\n");
216 if (SectorNumber +
SectorCount > DeviceUnit->TotalSectors + 1)
218 ERR(
"AtaAtapiReadLogicalSectorsLBA(): Attempt to read more than there is to read.\n");
237 for (RetryCount = 0; RetryCount < 3; ++RetryCount)
264 ULONG RemainingBlockCount;
282 ChsTemp = DeviceUnit->IdentifyData.SectorsPerTrack * DeviceUnit->IdentifyData.NumberOfHeads;
285 Cylinder = SectorNumber / ChsTemp;
286 Head = (SectorNumber % ChsTemp) / DeviceUnit->IdentifyData.SectorsPerTrack;
287 Sector = (SectorNumber % DeviceUnit->IdentifyData.SectorsPerTrack) + 1;
295 Lba = (Sector & 0xFF) | ((Cylinder & 0xFFFFF) << 8) | ((Head & 0x0F) << 24);
303 SelectDevice(DeviceUnit->Channel, DeviceUnit->DeviceNumber);
306 ERR(
"AtaReadLogicalSectorsLBA() failed. Device is busy.\n");
339 ((Lba >> 24) & 0x0F) |
349 for (RemainingBlockCount = BlockCount; RemainingBlockCount > 0; --RemainingBlockCount)
355 ERR(
"AtaReadLogicalSectorsLBA() failed. Status: 0x%02x, Error: 0x%02x\n",
367 SectorNumber += BlockCount;
404 ERR(
"AtaSendAtapiPacket(0x%x) failed. A device error occurred Status: 0x%02x, Error: 0x%02x\n",
413 TRACE(
"AtaSendAtapiPacket(0x%x) failed. An execution error occurred Status: 0x%02x, Error: 0x%02x\n",
428 UCHAR AtapiPacket[16];
433 SelectDevice(DeviceUnit->Channel, DeviceUnit->DeviceNumber);
436 ERR(
"AtapiReadLogicalSectorLBA() failed. Device is busy!\n");
447 AtapiPacket[2] = (SectorNumber >> 24) & 0xFF;
448 AtapiPacket[3] = (SectorNumber >> 16) & 0xFF;
449 AtapiPacket[4] = (SectorNumber >> 8) & 0xFF;
450 AtapiPacket[5] = SectorNumber & 0xFF;
455 DeviceUnit->SectorSize);
458 ERR(
"AtapiReadLogicalSectorLBA() failed. A read error occurred.\n");
479 UCHAR AtapiPacket[16];
480 UCHAR AtapiCapacity[8];
489 *TotalSectors = (AtapiCapacity[0] << 24) | (AtapiCapacity[1] << 16) |
490 (AtapiCapacity[2] << 8) | AtapiCapacity[3];
492 *
SectorSize = (AtapiCapacity[4] << 24) | (AtapiCapacity[5] << 16) |
493 (AtapiCapacity[6] << 8) | AtapiCapacity[7];
514 UCHAR AtapiPacket[16];
532 ERR(
"Cannot read the sense data.\n");
545 ERR(
"SK 0x%x, ASC 0x%x, ASCQ 0x%x\n",
556 UCHAR AtapiPacket[16];
562 SelectDevice(DeviceUnit->Channel, DeviceUnit->DeviceNumber);
578 TRACE(
"SK 0x%x, ASC 0x%x, ASCQ 0x%x\n",
615 DeviceUnit->Flags &= ~ATA_DEVICE_NOT_READY;
628 DeviceUnit->Flags &= ~ATA_DEVICE_NOT_READY;
637 if (DeviceUnit->SectorSize == 0)
638 DeviceUnit->SectorSize = 2048;
639 if (DeviceUnit->TotalSectors == 0)
640 DeviceUnit->TotalSectors = 0xFFFFFFFF;
642 DeviceUnit->Flags &= ~ATA_DEVICE_NO_MEDIA;
696 else if ((
Status & FirstValue) || (
Status & SecondValue))
724 TRACE(
"AtaHardReset(Controller %d)\n", Channel);
737#if defined(SARCH_PC98)
755 UCHAR SignatureLow, SignatureHigh, SignatureCount, SignatureNumber;
764 TRACE(
"IdentifyDevice() Channel = %x, Device = %x, BaseIoAddress = 0x%x\n",
789 TRACE(
"IdentifyDevice(): SL = 0x%x, SH = 0x%x, SC = 0x%x, SN = 0x%x\n",
790 SignatureLow, SignatureHigh, SignatureCount, SignatureNumber);
791 if (SignatureLow == 0x00 && SignatureHigh == 0x00 &&
792 SignatureCount == 0x01 && SignatureNumber == 0x01)
818 ERR(
"IdentifyDevice(): Identify command failed.\n");
835 TRACE(
"S/N %.*s\n",
sizeof(
Id.SerialNumber),
Id.SerialNumber);
836 TRACE(
"FR %.*s\n",
sizeof(
Id.FirmwareRevision),
Id.FirmwareRevision);
837 TRACE(
"MN %.*s\n",
sizeof(
Id.ModelNumber),
Id.ModelNumber);
841 if (*DeviceUnit ==
NULL)
843 ERR(
"Failed to allocate device unit!\n");
848 (*DeviceUnit)->Channel = Channel;
850 (*DeviceUnit)->IdentifyData =
Id;
855 for (
i = 0;
i < 10; ++
i)
866 TRACE(
"No media found.\n");
872 if (
Id.SupportLba || (
Id.MajorRevision &&
Id.UserAddressableSectors))
874 if (
Id.FeaturesSupport.Address48)
876 TRACE(
"Using LBA48 addressing mode.\n");
878 TotalSectors =
Id.UserAddressableSectors48;
882 TRACE(
"Using LBA28 addressing mode.\n");
884 TotalSectors =
Id.UserAddressableSectors;
892 TRACE(
"Using CHS addressing mode.\n");
895 if (
Id.UnformattedBytesPerSector == 0)
901 for (
i = 1 << 15;
i > 0;
i >>= 1)
903 if ((
Id.UnformattedBytesPerSector &
i) != 0)
910 TotalSectors =
Id.NumberOfCylinders *
Id.NumberOfHeads *
Id.SectorsPerTrack;
913 TRACE(
"Sector size %d ; Total sectors %I64d\n",
SectorSize, TotalSectors);
915 (*DeviceUnit)->Flags =
Flags;
917 (*DeviceUnit)->TotalSectors = TotalSectors;
920 (*DeviceUnit)->Cylinders = 0xFFFFFFFF;
921 (*DeviceUnit)->Heads = 0xFFFFFFFF;
922 (*DeviceUnit)->Sectors = 0xFFFFFFFF;
926 (*DeviceUnit)->Cylinders =
Id.NumberOfCylinders;
927 (*DeviceUnit)->Heads =
Id.NumberOfHeads;
928 (*DeviceUnit)->Sectors =
Id.SectorsPerTrack;
935 TRACE(
"IdentifyDevice() done.\n");
939 TRACE(
"IdentifyDevice() done. No device present at %d:%d\n", Channel,
DeviceNumber);
#define IDE_COMMAND_READ_EXT
#define IDE_COMMAND_ATAPI_IDENTIFY
#define IDE_COMMAND_IDENTIFY
#define IDE_COMMAND_ATAPI_PACKET
#define DbgDumpBuffer(mask, buf, len)
#define DBG_DEFAULT_CHANNEL(ch)
FORCEINLINE PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
FORCEINLINE VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
#define SCSI_ADSENSE_LUN_NOT_READY
#define SCSIOP_REQUEST_SENSE
#define SCSIOP_TEST_UNIT_READY
#define SCSIOP_READ_CAPACITY
#define SCSI_SENSEQ_BECOMING_READY
#define SENSE_BUFFER_SIZE
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED
#define SCSI_SENSE_NOT_READY
_In_ PCHAR _In_ ULONG DeviceNumber
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
PDEVICE_UNIT AtaGetDevice(IN UCHAR UnitNumber)
#define ATA_STATUS_TIMEOUT
static BOOLEAN WaitForFlags(IN UCHAR Channel, IN UCHAR Flags, IN UCHAR ExpectedValue, IN ULONG Timeout)
#define AtaWritePort(Channel, Port, Data)
#define AtaReadBuffer(Channel, Buffer, Count)
static BOOLEAN IdentifyDevice(IN UCHAR Channel, IN UCHAR DeviceNumber, OUT PDEVICE_UNIT *DeviceUnit)
static BOOLEAN AtapiReadyCheck(IN OUT PDEVICE_UNIT DeviceUnit)
static VOID AtapiCapacityDetect(IN PDEVICE_UNIT DeviceUnit, OUT PULONGLONG TotalSectors, OUT PULONG SectorSize)
static BOOLEAN WaitForBusy(IN UCHAR Channel, IN ULONG Timeout)
static VOID AtaHardReset(IN UCHAR Channel)
static BOOLEAN AtapiReadLogicalSectorLBA(IN PDEVICE_UNIT DeviceUnit, IN ULONGLONG SectorNumber, OUT PVOID Buffer)
static const ULONG BaseArray[]
static VOID SelectDevice(IN UCHAR Channel, IN UCHAR DeviceNumber)
static BOOLEAN AtapiRequestSense(IN PDEVICE_UNIT DeviceUnit, OUT PSENSE_DATA SenseData)
BOOLEAN AtaAtapiReadLogicalSectorsLBA(IN OUT PDEVICE_UNIT DeviceUnit, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
static BOOLEAN AtaSendAtapiPacket(IN UCHAR Channel, IN PUCHAR AtapiPacket, IN UCHAR PacketSize, IN USHORT ByteCount)
#define ATAPI_PACKET_SIZE(IdentifyData)
BOOLEAN AtaInit(OUT PUCHAR DetectedCount)
#define AtaReadPort(Channel, Port)
#define AtaWriteBuffer(Channel, Buffer, Count)
static BOOLEAN WaitForFlagsOr(IN UCHAR Channel, IN UCHAR FirstValue, IN UCHAR SecondValue, IN ULONG Timeout)
static BOOLEAN AtaReadLogicalSectorsLBA(IN PDEVICE_UNIT DeviceUnit, IN ULONGLONG SectorNumber, IN ULONG SectorCount, OUT PVOID Buffer)
static VOID AtapiPrintSenseData(IN PDEVICE_UNIT DeviceUnit)
static PDEVICE_UNIT Units[MAX_CHANNELS *MAX_DEVICES]
#define IDX_IO1_o_BlockNumber
#define IDX_ATAPI_IO1_o_Command
#define IDX_IO1_o_CylinderHigh
#define IDX_ATAPI_IO1_o_ByteCountHigh
#define MAXIMUM_CDROM_SIZE
#define IDENTIFY_DATA_SIZE
#define IDX_IO1_i_BlockNumber
#define ATA_DEVICE_NOT_READY
#define IDX_ATAPI_IO1_i_ByteCountHigh
#define IDE_DRIVE_SELECT_1
#define IDX_IO1_o_Feature
#define IDE_DC_RESET_CONTROLLER
#define IDX_IO1_i_CylinderLow
#define IDX_ATAPI_IO1_o_ByteCountLow
#define IDX_IO1_i_BlockCount
#define IDX_ATAPI_IO1_i_Status
#define IDX_ATAPI_IO1_i_ByteCountLow
#define IDX_IO1_i_CylinderHigh
#define IDE_DRIVE_SELECT_2
#define IDX_IO1_o_DriveSelect
#define IDX_IO1_o_Command
#define ATA_DEVICE_NO_MEDIA
#define IDX_ATAPI_IO1_o_Feature
#define IDE_DC_DISABLE_INTERRUPTS
#define IDE_DC_REENABLE_CONTROLLER
#define IDX_IO2_o_Control
#define IDX_IO1_o_BlockCount
#define IDX_IO1_o_CylinderLow
#define IDX_ATAPI_IO1_i_Error
_In_ NDIS_STATUS _In_ ULONG _In_ USHORT _In_opt_ PVOID _In_ ULONG DataSize
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
#define WRITE_PORT_UCHAR(p, d)
VOID StallExecutionProcessor(ULONG Microseconds)
#define READ_TOC_FORMAT_SESSION
UCHAR AdditionalSenseCode
UCHAR AdditionalSenseCodeQualifier
#define RtlZeroMemory(Destination, Length)
_Must_inspect_result_ _In_ ULONG Flags
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
#define RtlUshortByteSwap(_x)