3 * LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later)
4 * PURPOSE: ATA/ATAPI programmed I/O driver.
5 * COPYRIGHT: Copyright 2019-2020 Dmitry Borisov (di.sean@protonmail.com)
8 /* INCLUDES *******************************************************************/
18 DBG_DEFAULT_CHANNEL(DISK
);
20 /* GLOBALS ********************************************************************/
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))
40 /* IDE/ATA Channels base - Primary, Secondary, Tertiary, Quaternary */
41 static const ULONG BaseArray
[] =
43 #if defined(SARCH_XBOX)
45 #elif defined(SARCH_PC98)
48 0x1F0, 0x170, 0x1E8, 0x168
52 #define MAX_CHANNELS RTL_NUMBER_OF(BaseArray)
53 #define MAX_DEVICES 2 /* Master/Slave */
55 static PDEVICE_UNIT Units
[MAX_CHANNELS
* MAX_DEVICES
];
57 /* PRIVATE PROTOTYPES *********************************************************/
64 IN UCHAR ExpectedValue
,
95 IN UCHAR DeviceNumber
,
96 OUT PDEVICE_UNIT
*DeviceUnit
102 IN PDEVICE_UNIT DeviceUnit
,
103 OUT PSENSE_DATA SenseData
109 IN PDEVICE_UNIT DeviceUnit
115 IN OUT PDEVICE_UNIT DeviceUnit
120 AtapiReadLogicalSectorLBA(
121 IN PDEVICE_UNIT DeviceUnit
,
122 IN ULONGLONG SectorNumber
,
128 AtaReadLogicalSectorsLBA(
129 IN PDEVICE_UNIT DeviceUnit
,
130 IN ULONGLONG SectorNumber
,
131 IN ULONG SectorCount
,
135 /* FUNCTIONS ******************************************************************/
137 /* Don't call this before running the system timer calibration and MM initialization */
139 AtaInit(OUT PUCHAR DetectedCount
)
141 UCHAR Channel
, DeviceNumber
;
142 PDEVICE_UNIT DeviceUnit
= NULL
;
144 TRACE("AtaInit()\n");
148 RtlZeroMemory(&Units
, sizeof(Units
));
150 /* Detect and enumerate ATA/ATAPI devices */
151 for (Channel
= 0; Channel
< MAX_CHANNELS
; ++Channel
)
153 for (DeviceNumber
= 0; DeviceNumber
< MAX_DEVICES
; ++DeviceNumber
)
155 if (IdentifyDevice(Channel
, DeviceNumber
, &DeviceUnit
))
157 Units
[(*DetectedCount
)++] = DeviceUnit
;
162 return (*DetectedCount
> 0);
170 for (i
= 0; i
< RTL_NUMBER_OF(Units
); ++i
)
173 FrLdrTempFree(Units
[i
], TAG_ATA_DEVICE
);
178 AtaGetDevice(IN UCHAR UnitNumber
)
180 if (UnitNumber
< RTL_NUMBER_OF(Units
))
181 return Units
[UnitNumber
];
187 AtaAtapiReadLogicalSectorsLBA(
188 IN OUT PDEVICE_UNIT DeviceUnit
,
189 IN ULONGLONG SectorNumber
,
190 IN ULONG SectorCount
,
196 if (DeviceUnit
== NULL
|| SectorCount
== 0)
199 if (DeviceUnit
->Flags
& ATA_DEVICE_ATAPI
)
201 if ((DeviceUnit
->Flags
& ATA_DEVICE_NO_MEDIA
) || (DeviceUnit
->Flags
& ATA_DEVICE_NOT_READY
))
204 for (RetryCount
= 0; RetryCount
< 4; ++RetryCount
)
206 /* Make the device ready */
207 if (AtapiReadyCheck(DeviceUnit
))
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");
222 while (SectorCount
> 0)
224 /* Read a single sector */
225 Success
= AtapiReadLogicalSectorLBA(DeviceUnit
, SectorNumber
, Buffer
);
231 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ DeviceUnit
->SectorSize
);
237 for (RetryCount
= 0; RetryCount
< 3; ++RetryCount
)
239 /* Read a multiple sectors */
240 Success
= AtaReadLogicalSectorsLBA(DeviceUnit
, SectorNumber
, SectorCount
, Buffer
);
252 AtaReadLogicalSectorsLBA(
253 IN PDEVICE_UNIT DeviceUnit
,
254 IN ULONGLONG SectorNumber
,
255 IN ULONG SectorCount
,
264 ULONG RemainingBlockCount
;
268 UseLBA48
= (DeviceUnit
->Flags
& ATA_DEVICE_LBA48
) &&
269 (((SectorNumber
+ SectorCount
) >= UINT64_C(0x0FFFFF80)) || SectorCount
> 256);
271 while (SectorCount
> 0)
273 /* Prevent sector count overflow, divide it into maximum possible chunks and loop each one */
275 BlockCount
= min(SectorCount
, USHRT_MAX
);
277 BlockCount
= min(SectorCount
, UCHAR_MAX
);
279 /* Convert LBA into a format CHS if needed */
280 if (DeviceUnit
->Flags
& ATA_DEVICE_CHS
)
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);
302 /* Select the drive */
303 SelectDevice(DeviceUnit
->Channel
, DeviceUnit
->DeviceNumber
);
304 if (!WaitForBusy(DeviceUnit
->Channel
, ATA_STATUS_TIMEOUT
))
306 ERR("AtaReadLogicalSectorsLBA() failed. Device is busy.\n");
310 /* Disable interrupts */
311 AtaWritePort(DeviceUnit
->Channel
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
);
312 StallExecutionProcessor(1);
317 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_Feature
, 0);
318 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_Feature
, ATA_PIO
);
319 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_BlockCount
, (BlockCount
>> 8) & 0xFF);
320 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_BlockCount
, BlockCount
& 0xFF);
321 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_BlockNumber
, (Lba
>> 24) & 0xFF);
322 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_BlockNumber
, Lba
& 0xFF);
323 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_CylinderLow
, (Lba
>> 32) & 0xFF);
324 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_CylinderLow
, (Lba
>> 8) & 0xFF);
325 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_CylinderHigh
, (Lba
>> 40) & 0xFF);
326 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_CylinderHigh
, (Lba
>> 16) & 0xFF);
327 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_DriveSelect
,
328 IDE_USE_LBA
| (DeviceUnit
->DeviceNumber
? IDE_DRIVE_2
: IDE_DRIVE_1
));
329 Command
= IDE_COMMAND_READ_EXT
;
333 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_Feature
, ATA_PIO
);
334 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_BlockCount
, BlockCount
& 0xFF);
335 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_BlockNumber
, Lba
& 0xFF);
336 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_CylinderLow
, (Lba
>> 8) & 0xFF);
337 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_CylinderHigh
, (Lba
>> 16) & 0xFF);
338 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_DriveSelect
,
339 ((Lba
>> 24) & 0x0F) |
340 (DeviceUnit
->Flags
& ATA_DEVICE_CHS
? 0x00 : IDE_USE_LBA
) |
341 (DeviceUnit
->DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
));
342 Command
= IDE_COMMAND_READ
;
345 /* Send read command */
346 AtaWritePort(DeviceUnit
->Channel
, IDX_IO1_o_Command
, Command
);
347 StallExecutionProcessor(5);
349 for (RemainingBlockCount
= BlockCount
; RemainingBlockCount
> 0; --RemainingBlockCount
)
351 /* Wait for ready to transfer data block */
352 if (!WaitForFlags(DeviceUnit
->Channel
, IDE_STATUS_DRQ
,
353 IDE_STATUS_DRQ
, ATA_STATUS_TIMEOUT
))
355 ERR("AtaReadLogicalSectorsLBA() failed. Status: 0x%02x, Error: 0x%02x\n",
356 AtaReadPort(DeviceUnit
->Channel
, IDX_IO1_i_Status
),
357 AtaReadPort(DeviceUnit
->Channel
, IDX_IO1_i_Error
));
361 /* Transfer the data block */
362 AtaReadBuffer(DeviceUnit
->Channel
, Buffer
, DeviceUnit
->SectorSize
);
364 Buffer
= (PVOID
)((ULONG_PTR
)Buffer
+ DeviceUnit
->SectorSize
);
367 SectorNumber
+= BlockCount
;
368 SectorCount
-= BlockCount
;
378 IN PUCHAR AtapiPacket
,
383 * REQUEST SENSE is used by driver to clear the ATAPI 'Bus reset' indication.
384 * TEST UNIT READY doesn't require space for returned data.
386 UCHAR ExpectedFlagsMask
= (AtapiPacket
[0] == SCSIOP_REQUEST_SENSE
) ?
387 IDE_STATUS_DRDY
: (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
);
388 UCHAR ExpectedFlags
= ((AtapiPacket
[0] == SCSIOP_TEST_UNIT_READY
) ||
389 (AtapiPacket
[0] == SCSIOP_REQUEST_SENSE
)) ?
390 IDE_STATUS_DRDY
: (IDE_STATUS_DRQ
| IDE_STATUS_DRDY
);
393 AtaWritePort(Channel
, IDX_ATAPI_IO1_o_Feature
, ATA_PIO
);
395 /* Maximum byte count that is to be transferred */
396 AtaWritePort(Channel
, IDX_ATAPI_IO1_o_ByteCountLow
, ByteCount
& 0xFF);
397 AtaWritePort(Channel
, IDX_ATAPI_IO1_o_ByteCountHigh
, (ByteCount
>> 8) & 0xFF);
399 /* Prepare to transfer a device command via a command packet */
400 AtaWritePort(Channel
, IDX_ATAPI_IO1_o_Command
, IDE_COMMAND_ATAPI_PACKET
);
401 StallExecutionProcessor(50);
402 if (!WaitForFlagsOr(Channel
, IDE_STATUS_DRQ
, IDE_STATUS_DRDY
, ATA_STATUS_TIMEOUT
))
404 ERR("AtaSendAtapiPacket(0x%x) failed. A device error occurred Status: 0x%02x, Error: 0x%02x\n",
405 AtapiPacket
[0], AtaReadPort(Channel
, IDX_ATAPI_IO1_i_Status
), AtaReadPort(Channel
, IDX_ATAPI_IO1_i_Error
));
409 /* Command packet transfer */
410 AtaWriteBuffer(Channel
, AtapiPacket
, PacketSize
);
411 if (!WaitForFlags(Channel
, ExpectedFlagsMask
, ExpectedFlags
, ATA_STATUS_TIMEOUT
))
413 TRACE("AtaSendAtapiPacket(0x%x) failed. An execution error occurred Status: 0x%02x, Error: 0x%02x\n",
414 AtapiPacket
[0], AtaReadPort(Channel
, IDX_ATAPI_IO1_i_Status
), AtaReadPort(Channel
, IDX_ATAPI_IO1_i_Error
));
423 AtapiReadLogicalSectorLBA(
424 IN PDEVICE_UNIT DeviceUnit
,
425 IN ULONGLONG SectorNumber
,
428 UCHAR AtapiPacket
[16];
432 /* Select the drive */
433 SelectDevice(DeviceUnit
->Channel
, DeviceUnit
->DeviceNumber
);
434 if (!WaitForBusy(DeviceUnit
->Channel
, ATA_STATUS_TIMEOUT
))
436 ERR("AtapiReadLogicalSectorLBA() failed. Device is busy!\n");
440 /* Disable interrupts */
441 AtaWritePort(DeviceUnit
->Channel
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
);
442 StallExecutionProcessor(1);
444 /* Send the SCSI READ command */
445 RtlZeroMemory(&AtapiPacket
, sizeof(AtapiPacket
));
446 AtapiPacket
[0] = SCSIOP_READ
;
447 AtapiPacket
[2] = (SectorNumber
>> 24) & 0xFF;
448 AtapiPacket
[3] = (SectorNumber
>> 16) & 0xFF;
449 AtapiPacket
[4] = (SectorNumber
>> 8) & 0xFF;
450 AtapiPacket
[5] = SectorNumber
& 0xFF;
452 Success
= AtaSendAtapiPacket(DeviceUnit
->Channel
,
454 ATAPI_PACKET_SIZE(DeviceUnit
->IdentifyData
),
455 DeviceUnit
->SectorSize
);
458 ERR("AtapiReadLogicalSectorLBA() failed. A read error occurred.\n");
459 AtapiPrintSenseData(DeviceUnit
);
463 DataSize
= (AtaReadPort(DeviceUnit
->Channel
, IDX_ATAPI_IO1_i_ByteCountHigh
) << 8) |
464 AtaReadPort(DeviceUnit
->Channel
, IDX_ATAPI_IO1_i_ByteCountLow
);
466 /* Transfer the data block */
467 AtaReadBuffer(DeviceUnit
->Channel
, Buffer
, DataSize
);
475 IN PDEVICE_UNIT DeviceUnit
,
476 OUT PULONGLONG TotalSectors
,
477 OUT PULONG SectorSize
)
479 UCHAR AtapiPacket
[16];
480 UCHAR AtapiCapacity
[8];
482 /* Send the SCSI READ CAPACITY(10) command */
483 RtlZeroMemory(&AtapiPacket
, sizeof(AtapiPacket
));
484 AtapiPacket
[0] = SCSIOP_READ_CAPACITY
;
485 if (AtaSendAtapiPacket(DeviceUnit
->Channel
, AtapiPacket
, ATAPI_PACKET_SIZE(DeviceUnit
->IdentifyData
), 8))
487 AtaReadBuffer(DeviceUnit
->Channel
, &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];
495 /* If device reports a non-zero block length, reset to defaults (we use READ command instead of READ CD) */
496 if (*SectorSize
!= 0)
504 AtapiPrintSenseData(DeviceUnit
);
511 IN PDEVICE_UNIT DeviceUnit
,
512 OUT PSENSE_DATA SenseData
)
514 UCHAR AtapiPacket
[16];
517 RtlZeroMemory(&AtapiPacket
, sizeof(AtapiPacket
));
518 RtlZeroMemory(SenseData
, sizeof(SENSE_DATA
));
519 AtapiPacket
[0] = SCSIOP_REQUEST_SENSE
;
520 AtapiPacket
[4] = SENSE_BUFFER_SIZE
;
521 Success
= AtaSendAtapiPacket(DeviceUnit
->Channel
,
523 ATAPI_PACKET_SIZE(DeviceUnit
->IdentifyData
),
527 AtaReadBuffer(DeviceUnit
->Channel
, SenseData
, SENSE_BUFFER_SIZE
);
532 ERR("Cannot read the sense data.\n");
539 AtapiPrintSenseData(IN PDEVICE_UNIT DeviceUnit
)
541 SENSE_DATA SenseData
;
543 if (AtapiRequestSense(DeviceUnit
, &SenseData
))
545 ERR("SK 0x%x, ASC 0x%x, ASCQ 0x%x\n",
547 SenseData
.AdditionalSenseCode
,
548 SenseData
.AdditionalSenseCodeQualifier
);
554 AtapiReadyCheck(IN OUT PDEVICE_UNIT DeviceUnit
)
556 UCHAR AtapiPacket
[16];
557 UCHAR DummyData
[MAXIMUM_CDROM_SIZE
];
558 SENSE_DATA SenseData
;
561 /* Select the drive */
562 SelectDevice(DeviceUnit
->Channel
, DeviceUnit
->DeviceNumber
);
563 if (!WaitForBusy(DeviceUnit
->Channel
, ATA_STATUS_TIMEOUT
))
566 /* Send the SCSI TEST UNIT READY command */
567 RtlZeroMemory(&AtapiPacket
, sizeof(AtapiPacket
));
568 AtapiPacket
[0] = SCSIOP_TEST_UNIT_READY
;
569 AtaSendAtapiPacket(DeviceUnit
->Channel
,
571 ATAPI_PACKET_SIZE(DeviceUnit
->IdentifyData
),
574 if (!AtapiRequestSense(DeviceUnit
, &SenseData
))
577 AtaReadBuffer(DeviceUnit
->Channel
, &SenseData
, SENSE_BUFFER_SIZE
);
578 TRACE("SK 0x%x, ASC 0x%x, ASCQ 0x%x\n",
580 SenseData
.AdditionalSenseCode
,
581 SenseData
.AdditionalSenseCodeQualifier
);
583 if (SenseData
.SenseKey
== SCSI_SENSE_NOT_READY
)
585 if (SenseData
.AdditionalSenseCode
== SCSI_ADSENSE_LUN_NOT_READY
)
587 switch (SenseData
.AdditionalSenseCodeQualifier
)
589 case SCSI_SENSEQ_BECOMING_READY
:
590 /* Wait until the CD is spun up */
591 StallExecutionProcessor(4e6
);
594 case SCSI_SENSEQ_INIT_COMMAND_REQUIRED
:
595 /* The drive needs to be spun up, send the SCSI READ TOC command */
596 RtlZeroMemory(&AtapiPacket
, sizeof(AtapiPacket
));
597 AtapiPacket
[0] = SCSIOP_READ_TOC
;
598 AtapiPacket
[7] = (MAXIMUM_CDROM_SIZE
<< 8) & 0xFF;
599 AtapiPacket
[8] = MAXIMUM_CDROM_SIZE
& 0xFF;
600 AtapiPacket
[9] = READ_TOC_FORMAT_SESSION
<< 6;
601 Success
= AtaSendAtapiPacket(DeviceUnit
->Channel
,
603 ATAPI_PACKET_SIZE(DeviceUnit
->IdentifyData
),
607 AtapiPrintSenseData(DeviceUnit
);
611 AtaReadBuffer(DeviceUnit
->Channel
, &DummyData
, MAXIMUM_CDROM_SIZE
);
615 DeviceUnit
->Flags
&= ~ATA_DEVICE_NOT_READY
;
620 else if (SenseData
.AdditionalSenseCode
== SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
)
622 DeviceUnit
->Flags
|= ATA_DEVICE_NO_MEDIA
;
628 DeviceUnit
->Flags
&= ~ATA_DEVICE_NOT_READY
;
631 if (DeviceUnit
->Flags
& ATA_DEVICE_NO_MEDIA
)
633 /* Detect a medium's capacity */
634 AtapiCapacityDetect(DeviceUnit
, &DeviceUnit
->TotalSectors
, &DeviceUnit
->SectorSize
);
636 /* If nothing was returned, reset to defaults */
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
;
653 IN UCHAR ExpectedValue
,
658 ASSERT(Timeout
!= 0);
660 WaitForBusy(Channel
, ATA_STATUS_TIMEOUT
);
664 StallExecutionProcessor(10);
666 Status
= AtaReadPort(Channel
, IDX_IO1_i_Status
);
667 if (Status
& IDE_STATUS_ERROR
)
669 else if ((Status
& Flags
) == ExpectedValue
)
680 IN UCHAR SecondValue
,
685 ASSERT(Timeout
!= 0);
687 WaitForBusy(Channel
, ATA_STATUS_TIMEOUT
);
691 StallExecutionProcessor(10);
693 Status
= AtaReadPort(Channel
, IDX_IO1_i_Status
);
694 if (Status
& IDE_STATUS_ERROR
)
696 else if ((Status
& FirstValue
) || (Status
& SecondValue
))
708 ASSERT(Timeout
!= 0);
712 StallExecutionProcessor(10);
714 if ((AtaReadPort(Channel
, IDX_IO1_i_Status
) & IDE_STATUS_BUSY
) == 0)
722 AtaHardReset(IN UCHAR Channel
)
724 TRACE("AtaHardReset(Controller %d)\n", Channel
);
726 AtaWritePort(Channel
, IDX_IO2_o_Control
, IDE_DC_RESET_CONTROLLER
);
727 StallExecutionProcessor(100000);
728 AtaWritePort(Channel
, IDX_IO2_o_Control
, IDE_DC_REENABLE_CONTROLLER
);
729 StallExecutionProcessor(5);
730 WaitForBusy(Channel
, ATA_STATUS_TIMEOUT
);
735 SelectDevice(IN UCHAR Channel
, IN UCHAR DeviceNumber
)
737 #if defined(SARCH_PC98)
738 /* Select IDE Channel */
739 WRITE_PORT_UCHAR((PUCHAR
)IDE_IO_o_BankSelect
, Channel
);
740 StallExecutionProcessor(5);
743 AtaWritePort(Channel
, IDX_IO1_o_DriveSelect
,
744 DeviceNumber
? IDE_DRIVE_SELECT_2
: IDE_DRIVE_SELECT_1
);
745 StallExecutionProcessor(5);
752 IN UCHAR DeviceNumber
,
753 OUT PDEVICE_UNIT
*DeviceUnit
)
755 UCHAR SignatureLow
, SignatureHigh
, SignatureCount
, SignatureNumber
;
758 SENSE_DATA SenseData
;
761 ULONGLONG TotalSectors
;
764 TRACE("IdentifyDevice() Channel = %x, Device = %x, BaseIoAddress = 0x%x\n",
765 Channel
, DeviceNumber
, BaseArray
[Channel
]);
767 /* Look at controller */
768 SelectDevice(Channel
, DeviceNumber
);
769 StallExecutionProcessor(5);
770 AtaWritePort(Channel
, IDX_IO1_o_BlockNumber
, 0x55);
771 AtaWritePort(Channel
, IDX_IO1_o_BlockNumber
, 0x55);
772 StallExecutionProcessor(5);
773 if (AtaReadPort(Channel
, IDX_IO1_i_BlockNumber
) != 0x55)
776 /* Reset the controller */
777 AtaHardReset(Channel
);
779 /* Select the drive */
780 SelectDevice(Channel
, DeviceNumber
);
781 if (!WaitForBusy(Channel
, ATA_STATUS_TIMEOUT
))
784 /* Signature check */
785 SignatureLow
= AtaReadPort(Channel
, IDX_IO1_i_CylinderLow
);
786 SignatureHigh
= AtaReadPort(Channel
, IDX_IO1_i_CylinderHigh
);
787 SignatureCount
= AtaReadPort(Channel
, IDX_IO1_i_BlockCount
);
788 SignatureNumber
= AtaReadPort(Channel
, IDX_IO1_i_BlockNumber
);
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)
794 TRACE("IdentifyDevice(): Found PATA device at %d:%d\n", Channel
, DeviceNumber
);
795 Command
= IDE_COMMAND_IDENTIFY
;
797 else if (SignatureLow
== ATAPI_MAGIC_LSB
&&
798 SignatureHigh
== ATAPI_MAGIC_MSB
)
800 TRACE("IdentifyDevice(): Found ATAPI device at %d:%d\n", Channel
, DeviceNumber
);
801 Flags
|= ATA_DEVICE_ATAPI
| ATA_DEVICE_LBA
| ATA_DEVICE_NOT_READY
;
802 Command
= IDE_COMMAND_ATAPI_IDENTIFY
;
809 /* Disable interrupts */
810 AtaWritePort(Channel
, IDX_IO2_o_Control
, IDE_DC_DISABLE_INTERRUPTS
);
811 StallExecutionProcessor(5);
813 /* Send the identify command */
814 AtaWritePort(Channel
, IDX_IO1_o_Command
, Command
);
815 StallExecutionProcessor(50);
816 if (!WaitForFlags(Channel
, IDE_STATUS_DRQ
, IDE_STATUS_DRQ
, ATA_STATUS_TIMEOUT
))
818 ERR("IdentifyDevice(): Identify command failed.\n");
822 /* Receive parameter information from the device */
823 AtaReadBuffer(Channel
, &Id
, IDENTIFY_DATA_SIZE
);
825 /* Swap byte order of the ASCII data */
826 for (i
= 0; i
< RTL_NUMBER_OF(Id
.SerialNumber
); ++i
)
827 Id
.SerialNumber
[i
] = RtlUshortByteSwap(Id
.SerialNumber
[i
]);
829 for (i
= 0; i
< RTL_NUMBER_OF(Id
.FirmwareRevision
); ++i
)
830 Id
.FirmwareRevision
[i
] = RtlUshortByteSwap(Id
.FirmwareRevision
[i
]);
832 for (i
= 0; i
< RTL_NUMBER_OF(Id
.ModelNumber
); ++i
)
833 Id
.ModelNumber
[i
] = RtlUshortByteSwap(Id
.ModelNumber
[i
]);
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
);
839 /* Allocate a new device unit structure */
840 *DeviceUnit
= FrLdrTempAlloc(sizeof(DEVICE_UNIT
), TAG_ATA_DEVICE
);
841 if (*DeviceUnit
== NULL
)
843 ERR("Failed to allocate device unit!\n");
847 RtlZeroMemory(*DeviceUnit
, sizeof(DEVICE_UNIT
));
848 (*DeviceUnit
)->Channel
= Channel
;
849 (*DeviceUnit
)->DeviceNumber
= DeviceNumber
;
850 (*DeviceUnit
)->IdentifyData
= Id
;
852 if (Flags
& ATA_DEVICE_ATAPI
)
854 /* Clear the ATAPI 'Bus reset' indication */
855 for (i
= 0; i
< 10; ++i
)
857 AtapiRequestSense(*DeviceUnit
, &SenseData
);
858 StallExecutionProcessor(10);
861 /* Detect a medium's capacity */
862 AtapiCapacityDetect(*DeviceUnit
, &TotalSectors
, &SectorSize
);
863 if (SectorSize
== 0 || TotalSectors
== 0)
865 /* It's ok and can be used to show alert like "Please insert the CD" */
866 TRACE("No media found.\n");
867 Flags
|= ATA_DEVICE_NO_MEDIA
;
872 if (Id
.SupportLba
|| (Id
.MajorRevision
&& Id
.UserAddressableSectors
))
874 if (Id
.FeaturesSupport
.Address48
)
876 TRACE("Using LBA48 addressing mode.\n");
877 Flags
|= ATA_DEVICE_LBA48
| ATA_DEVICE_LBA
;
878 TotalSectors
= Id
.UserAddressableSectors48
;
882 TRACE("Using LBA28 addressing mode.\n");
883 Flags
|= ATA_DEVICE_LBA
;
884 TotalSectors
= Id
.UserAddressableSectors
;
887 /* LBA ATA drives always have a sector size of 512 */
892 TRACE("Using CHS addressing mode.\n");
893 Flags
|= ATA_DEVICE_CHS
;
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
;
916 (*DeviceUnit
)->SectorSize
= SectorSize
;
917 (*DeviceUnit
)->TotalSectors
= TotalSectors
;
918 if (Flags
& ATA_DEVICE_ATAPI
)
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
;
932 DbgDumpBuffer(DPRINT_DISK
, &Id
, IDENTIFY_DATA_SIZE
);
935 TRACE("IdentifyDevice() done.\n");
939 TRACE("IdentifyDevice() done. No device present at %d:%d\n", Channel
, DeviceNumber
);