1 /*
2  * PROJECT:     FreeLoader
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)
6  */
7 
8 /* INCLUDES *******************************************************************/
9 
10 #include <freeldr.h>
11 #include <hwide.h>
12 
13 /* DDK */
14 #include <ata.h>
15 #include <scsi.h>
16 
17 #include <debug.h>
18 DBG_DEFAULT_CHANNEL(DISK);
19 
20 /* GLOBALS ********************************************************************/
21 
22 #define TAG_ATA_DEVICE 'DatA'
23 #define ATAPI_PACKET_SIZE(IdentifyData) (IdentifyData.AtapiCmdSize ? 16 : 12)
24 #define ATA_STATUS_TIMEOUT 31e5
25 
26 #define AtaWritePort(Channel, Port, Data) \
27     WRITE_PORT_UCHAR(UlongToPtr(BaseArray[(Channel)] + (Port)), (Data))
28 
29 #define AtaReadPort(Channel, Port) \
30     READ_PORT_UCHAR(UlongToPtr(BaseArray[(Channel)] + (Port)))
31 
32 #define AtaWriteBuffer(Channel, Buffer, Count) \
33     WRITE_PORT_BUFFER_USHORT(UlongToPtr(BaseArray[(Channel)] + IDX_IO1_o_Data), \
34                              (PUSHORT)(Buffer), (Count)/sizeof(USHORT))
35 
36 #define AtaReadBuffer(Channel, Buffer, Count) \
37     READ_PORT_BUFFER_USHORT(UlongToPtr(BaseArray[(Channel)] + IDX_IO1_i_Data), \
38                             (PUSHORT)(Buffer), (Count)/sizeof(USHORT))
39 
40 /* IDE/ATA Channels base - Primary, Secondary, Tertiary, Quaternary */
41 static const ULONG BaseArray[] =
42 {
43 #if defined(SARCH_XBOX)
44     0x1F0
45 #elif defined(SARCH_PC98)
46     0x640, 0x640
47 #else
48     0x1F0, 0x170, 0x1E8, 0x168
49 #endif
50 };
51 
52 #define MAX_CHANNELS RTL_NUMBER_OF(BaseArray)
53 #define MAX_DEVICES  2 /* Master/Slave */
54 
55 static PDEVICE_UNIT Units[MAX_CHANNELS * MAX_DEVICES];
56 
57 /* PRIVATE PROTOTYPES *********************************************************/
58 
59 static
60 BOOLEAN
61 WaitForFlags(
62     IN UCHAR Channel,
63     IN UCHAR Flags,
64     IN UCHAR ExpectedValue,
65     IN ULONG Timeout
66 );
67 
68 static
69 BOOLEAN
70 WaitForFlagsOr(
71     IN UCHAR Channel,
72     IN UCHAR FirstValue,
73     IN UCHAR SecondValue,
74     IN ULONG Timeout
75 );
76 
77 static
78 BOOLEAN
79 WaitForBusy(
80     IN UCHAR Channel,
81     IN ULONG Timeout
82 );
83 
84 static
85 VOID
86 SelectDevice(
87     IN UCHAR Channel,
88     IN UCHAR DeviceNumber
89 );
90 
91 static
92 BOOLEAN
93 IdentifyDevice(
94     IN UCHAR Channel,
95     IN UCHAR DeviceNumber,
96     OUT PDEVICE_UNIT *DeviceUnit
97 );
98 
99 static
100 BOOLEAN
101 AtapiRequestSense(
102     IN PDEVICE_UNIT DeviceUnit,
103     OUT PSENSE_DATA SenseData
104 );
105 
106 static
107 VOID
108 AtapiPrintSenseData(
109     IN PDEVICE_UNIT DeviceUnit
110 );
111 
112 static
113 BOOLEAN
114 AtapiReadyCheck(
115     IN OUT PDEVICE_UNIT DeviceUnit
116 );
117 
118 static
119 BOOLEAN
120 AtapiReadLogicalSectorLBA(
121     IN PDEVICE_UNIT DeviceUnit,
122     IN ULONGLONG SectorNumber,
123     OUT PVOID Buffer
124 );
125 
126 static
127 BOOLEAN
128 AtaReadLogicalSectorsLBA(
129     IN PDEVICE_UNIT DeviceUnit,
130     IN ULONGLONG SectorNumber,
131     IN ULONG SectorCount,
132     OUT PVOID Buffer
133 );
134 
135 /* FUNCTIONS ******************************************************************/
136 
137 /* Don't call this before running the system timer calibration and MM initialization */
138 BOOLEAN
139 AtaInit(OUT PUCHAR DetectedCount)
140 {
141     UCHAR Channel, DeviceNumber;
142     PDEVICE_UNIT DeviceUnit = NULL;
143 
144     TRACE("AtaInit()\n");
145 
146     *DetectedCount = 0;
147 
148     RtlZeroMemory(&Units, sizeof(Units));
149 
150     /* Detect and enumerate ATA/ATAPI devices */
151     for (Channel = 0; Channel < MAX_CHANNELS; ++Channel)
152     {
153         for (DeviceNumber = 0; DeviceNumber < MAX_DEVICES; ++DeviceNumber)
154         {
155             if (IdentifyDevice(Channel, DeviceNumber, &DeviceUnit))
156             {
157                 Units[(*DetectedCount)++] = DeviceUnit;
158             }
159         }
160     }
161 
162     return (*DetectedCount > 0);
163 }
164 
165 VOID
166 AtaFree(VOID)
167 {
168     UCHAR i;
169 
170     for (i = 0; i < RTL_NUMBER_OF(Units); ++i)
171     {
172         if (Units[i])
173             FrLdrTempFree(Units[i], TAG_ATA_DEVICE);
174     }
175 }
176 
177 PDEVICE_UNIT
178 AtaGetDevice(IN UCHAR UnitNumber)
179 {
180     if (UnitNumber < RTL_NUMBER_OF(Units))
181         return Units[UnitNumber];
182     else
183         return NULL;
184 }
185 
186 BOOLEAN
187 AtaAtapiReadLogicalSectorsLBA(
188     IN OUT PDEVICE_UNIT DeviceUnit,
189     IN ULONGLONG SectorNumber,
190     IN ULONG SectorCount,
191     OUT PVOID Buffer)
192 {
193     UCHAR RetryCount;
194     BOOLEAN Success;
195 
196     if (DeviceUnit == NULL || SectorCount == 0)
197         return FALSE;
198 
199     if (DeviceUnit->Flags & ATA_DEVICE_ATAPI)
200     {
201         if ((DeviceUnit->Flags & ATA_DEVICE_NO_MEDIA) || (DeviceUnit->Flags & ATA_DEVICE_NOT_READY))
202         {
203             /* Retry 4 times */
204             for (RetryCount = 0; RetryCount < 4; ++RetryCount)
205             {
206                 /* Make the device ready */
207                 if (AtapiReadyCheck(DeviceUnit))
208                     break;
209             }
210             if (RetryCount >= 4)
211             {
212                 ERR("AtaAtapiReadLogicalSectorsLBA(): Device not ready.\n");
213                 return FALSE;
214             }
215         }
216         if (SectorNumber + SectorCount > DeviceUnit->TotalSectors + 1)
217         {
218             ERR("AtaAtapiReadLogicalSectorsLBA(): Attempt to read more than there is to read.\n");
219             return FALSE;
220         }
221 
222         while (SectorCount > 0)
223         {
224             /* Read a single sector */
225             Success = AtapiReadLogicalSectorLBA(DeviceUnit, SectorNumber, Buffer);
226             if (!Success)
227                 return FALSE;
228 
229             --SectorCount;
230             ++SectorNumber;
231             Buffer = (PVOID)((ULONG_PTR)Buffer + DeviceUnit->SectorSize);
232         }
233     }
234     else
235     {
236         /* Retry 3 times */
237         for (RetryCount = 0; RetryCount < 3; ++RetryCount)
238         {
239             /* Read a multiple sectors */
240             Success = AtaReadLogicalSectorsLBA(DeviceUnit, SectorNumber, SectorCount, Buffer);
241             if (Success)
242                 return TRUE;
243         }
244         return FALSE;
245     }
246 
247     return TRUE;
248 }
249 
250 static
251 BOOLEAN
252 AtaReadLogicalSectorsLBA(
253     IN PDEVICE_UNIT DeviceUnit,
254     IN ULONGLONG SectorNumber,
255     IN ULONG SectorCount,
256     OUT PVOID Buffer)
257 {
258     UCHAR Command;
259     ULONG ChsTemp;
260     USHORT Cylinder;
261     UCHAR Head;
262     UCHAR Sector;
263     ULONG BlockCount;
264     ULONG RemainingBlockCount;
265     ULONGLONG Lba;
266     BOOLEAN UseLBA48;
267 
268     UseLBA48 = (DeviceUnit->Flags & ATA_DEVICE_LBA48) &&
269                 (((SectorNumber + SectorCount) >= UINT64_C(0x0FFFFF80)) || SectorCount > 256);
270 
271     while (SectorCount > 0)
272     {
273         /* Prevent sector count overflow, divide it into maximum possible chunks and loop each one */
274         if (UseLBA48)
275             BlockCount = min(SectorCount, USHRT_MAX);
276         else
277             BlockCount = min(SectorCount, UCHAR_MAX);
278 
279         /* Convert LBA into a format CHS if needed */
280         if (DeviceUnit->Flags & ATA_DEVICE_CHS)
281         {
282             ChsTemp = DeviceUnit->IdentifyData.SectorsPerTrack * DeviceUnit->IdentifyData.NumberOfHeads;
283             if (ChsTemp)
284             {
285                 Cylinder = SectorNumber / ChsTemp;
286                 Head = (SectorNumber % ChsTemp) / DeviceUnit->IdentifyData.SectorsPerTrack;
287                 Sector = (SectorNumber % DeviceUnit->IdentifyData.SectorsPerTrack) + 1;
288             }
289             else
290             {
291                 Cylinder = 0;
292                 Head = 0;
293                 Sector = 1;
294             }
295             Lba = (Sector & 0xFF) | ((Cylinder & 0xFFFFF) << 8) | ((Head & 0x0F) << 24);
296         }
297         else
298         {
299             Lba = SectorNumber;
300         }
301 
302         /* Select the drive */
303         SelectDevice(DeviceUnit->Channel, DeviceUnit->DeviceNumber);
304         if (!WaitForBusy(DeviceUnit->Channel, ATA_STATUS_TIMEOUT))
305         {
306             ERR("AtaReadLogicalSectorsLBA() failed. Device is busy.\n");
307             return FALSE;
308         }
309 
310         /* Disable interrupts */
311         AtaWritePort(DeviceUnit->Channel, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS);
312         StallExecutionProcessor(1);
313 
314         if (UseLBA48)
315         {
316             /* FIFO */
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;
330         }
331         else
332         {
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;
343         }
344 
345         /* Send read command */
346         AtaWritePort(DeviceUnit->Channel, IDX_IO1_o_Command, Command);
347         StallExecutionProcessor(5);
348 
349         for (RemainingBlockCount = BlockCount; RemainingBlockCount > 0; --RemainingBlockCount)
350         {
351             /* Wait for ready to transfer data block */
352             if (!WaitForFlags(DeviceUnit->Channel, IDE_STATUS_DRQ,
353                               IDE_STATUS_DRQ, ATA_STATUS_TIMEOUT))
354             {
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));
358                 return FALSE;
359             }
360 
361             /* Transfer the data block */
362             AtaReadBuffer(DeviceUnit->Channel, Buffer, DeviceUnit->SectorSize);
363 
364             Buffer = (PVOID)((ULONG_PTR)Buffer + DeviceUnit->SectorSize);
365         }
366 
367         SectorNumber += BlockCount;
368         SectorCount -= BlockCount;
369     }
370 
371     return TRUE;
372 }
373 
374 static
375 BOOLEAN
376 AtaSendAtapiPacket(
377     IN UCHAR Channel,
378     IN PUCHAR AtapiPacket,
379     IN UCHAR PacketSize,
380     IN USHORT ByteCount)
381 {
382     /*
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.
385      */
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);
391 
392     /* PIO mode */
393     AtaWritePort(Channel, IDX_ATAPI_IO1_o_Feature, ATA_PIO);
394 
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);
398 
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))
403     {
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));
406         return FALSE;
407     }
408 
409     /* Command packet transfer */
410     AtaWriteBuffer(Channel, AtapiPacket, PacketSize);
411     if (!WaitForFlags(Channel, ExpectedFlagsMask, ExpectedFlags, ATA_STATUS_TIMEOUT))
412     {
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));
415         return FALSE;
416     }
417 
418     return TRUE;
419 }
420 
421 static
422 BOOLEAN
423 AtapiReadLogicalSectorLBA(
424     IN PDEVICE_UNIT DeviceUnit,
425     IN ULONGLONG SectorNumber,
426     OUT PVOID Buffer)
427 {
428     UCHAR AtapiPacket[16];
429     USHORT DataSize;
430     BOOLEAN Success;
431 
432     /* Select the drive */
433     SelectDevice(DeviceUnit->Channel, DeviceUnit->DeviceNumber);
434     if (!WaitForBusy(DeviceUnit->Channel, ATA_STATUS_TIMEOUT))
435     {
436         ERR("AtapiReadLogicalSectorLBA() failed. Device is busy!\n");
437         return FALSE;
438     }
439 
440     /* Disable interrupts */
441     AtaWritePort(DeviceUnit->Channel, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS);
442     StallExecutionProcessor(1);
443 
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;
451     AtapiPacket[8] = 1;
452     Success = AtaSendAtapiPacket(DeviceUnit->Channel,
453                                  AtapiPacket,
454                                  ATAPI_PACKET_SIZE(DeviceUnit->IdentifyData),
455                                  DeviceUnit->SectorSize);
456     if (!Success)
457     {
458         ERR("AtapiReadLogicalSectorLBA() failed. A read error occurred.\n");
459         AtapiPrintSenseData(DeviceUnit);
460         return FALSE;
461     }
462 
463     DataSize = (AtaReadPort(DeviceUnit->Channel, IDX_ATAPI_IO1_i_ByteCountHigh) << 8) |
464                 AtaReadPort(DeviceUnit->Channel, IDX_ATAPI_IO1_i_ByteCountLow);
465 
466     /* Transfer the data block */
467     AtaReadBuffer(DeviceUnit->Channel, Buffer, DataSize);
468 
469     return TRUE;
470 }
471 
472 static
473 VOID
474 AtapiCapacityDetect(
475     IN PDEVICE_UNIT DeviceUnit,
476     OUT PULONGLONG TotalSectors,
477     OUT PULONG SectorSize)
478 {
479     UCHAR AtapiPacket[16];
480     UCHAR AtapiCapacity[8];
481 
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))
486     {
487         AtaReadBuffer(DeviceUnit->Channel, &AtapiCapacity, 8);
488 
489         *TotalSectors = (AtapiCapacity[0] << 24) | (AtapiCapacity[1] << 16) |
490                         (AtapiCapacity[2] << 8) | AtapiCapacity[3];
491 
492         *SectorSize = (AtapiCapacity[4] << 24) | (AtapiCapacity[5] << 16) |
493                       (AtapiCapacity[6] << 8) | AtapiCapacity[7];
494 
495         /* If device reports a non-zero block length, reset to defaults (we use READ command instead of READ CD) */
496         if (*SectorSize != 0)
497             *SectorSize = 2048;
498     }
499     else
500     {
501         *TotalSectors = 0;
502         *SectorSize = 0;
503 
504         AtapiPrintSenseData(DeviceUnit);
505     }
506 }
507 
508 static
509 BOOLEAN
510 AtapiRequestSense(
511     IN PDEVICE_UNIT DeviceUnit,
512     OUT PSENSE_DATA SenseData)
513 {
514     UCHAR AtapiPacket[16];
515     BOOLEAN Success;
516 
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,
522                                  AtapiPacket,
523                                  ATAPI_PACKET_SIZE(DeviceUnit->IdentifyData),
524                                  SENSE_BUFFER_SIZE);
525     if (Success)
526     {
527         AtaReadBuffer(DeviceUnit->Channel, SenseData, SENSE_BUFFER_SIZE);
528         return TRUE;
529     }
530     else
531     {
532         ERR("Cannot read the sense data.\n");
533         return FALSE;
534     }
535 }
536 
537 static
538 VOID
539 AtapiPrintSenseData(IN PDEVICE_UNIT DeviceUnit)
540 {
541     SENSE_DATA SenseData;
542 
543     if (AtapiRequestSense(DeviceUnit, &SenseData))
544     {
545         ERR("SK 0x%x, ASC 0x%x, ASCQ 0x%x\n",
546             SenseData.SenseKey,
547             SenseData.AdditionalSenseCode,
548             SenseData.AdditionalSenseCodeQualifier);
549     }
550 }
551 
552 static
553 BOOLEAN
554 AtapiReadyCheck(IN OUT PDEVICE_UNIT DeviceUnit)
555 {
556     UCHAR AtapiPacket[16];
557     UCHAR DummyData[MAXIMUM_CDROM_SIZE];
558     SENSE_DATA SenseData;
559     BOOLEAN Success;
560 
561     /* Select the drive */
562     SelectDevice(DeviceUnit->Channel, DeviceUnit->DeviceNumber);
563     if (!WaitForBusy(DeviceUnit->Channel, ATA_STATUS_TIMEOUT))
564         return FALSE;
565 
566     /* Send the SCSI TEST UNIT READY command */
567     RtlZeroMemory(&AtapiPacket, sizeof(AtapiPacket));
568     AtapiPacket[0] = SCSIOP_TEST_UNIT_READY;
569     AtaSendAtapiPacket(DeviceUnit->Channel,
570                        AtapiPacket,
571                        ATAPI_PACKET_SIZE(DeviceUnit->IdentifyData),
572                        0);
573 
574     if (!AtapiRequestSense(DeviceUnit, &SenseData))
575         return FALSE;
576 
577     AtaReadBuffer(DeviceUnit->Channel, &SenseData, SENSE_BUFFER_SIZE);
578     TRACE("SK 0x%x, ASC 0x%x, ASCQ 0x%x\n",
579           SenseData.SenseKey,
580           SenseData.AdditionalSenseCode,
581           SenseData.AdditionalSenseCodeQualifier);
582 
583     if (SenseData.SenseKey == SCSI_SENSE_NOT_READY)
584     {
585         if (SenseData.AdditionalSenseCode == SCSI_ADSENSE_LUN_NOT_READY)
586         {
587             switch (SenseData.AdditionalSenseCodeQualifier)
588             {
589                 case SCSI_SENSEQ_BECOMING_READY:
590                     /* Wait until the CD is spun up */
591                     StallExecutionProcessor(4e6);
592                     return FALSE;
593 
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,
602                                                  AtapiPacket,
603                                                  ATAPI_PACKET_SIZE(DeviceUnit->IdentifyData),
604                                                  MAXIMUM_CDROM_SIZE);
605                     if (!Success)
606                     {
607                         AtapiPrintSenseData(DeviceUnit);
608                         return FALSE;
609                     }
610 
611                     AtaReadBuffer(DeviceUnit->Channel, &DummyData, MAXIMUM_CDROM_SIZE);
612                     /* fall through */
613 
614                 default:
615                     DeviceUnit->Flags &= ~ATA_DEVICE_NOT_READY;
616                     return FALSE;
617 
618             }
619         }
620         else if (SenseData.AdditionalSenseCode == SCSI_ADSENSE_NO_MEDIA_IN_DEVICE)
621         {
622             DeviceUnit->Flags |= ATA_DEVICE_NO_MEDIA;
623             return FALSE;
624         }
625     }
626     else
627     {
628         DeviceUnit->Flags &= ~ATA_DEVICE_NOT_READY;
629     }
630 
631     if (DeviceUnit->Flags & ATA_DEVICE_NO_MEDIA)
632     {
633         /* Detect a medium's capacity */
634         AtapiCapacityDetect(DeviceUnit, &DeviceUnit->TotalSectors, &DeviceUnit->SectorSize);
635 
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;
641 
642         DeviceUnit->Flags &= ~ATA_DEVICE_NO_MEDIA;
643     }
644 
645     return TRUE;
646 }
647 
648 static
649 BOOLEAN
650 WaitForFlags(
651     IN UCHAR Channel,
652     IN UCHAR Flags,
653     IN UCHAR ExpectedValue,
654     IN ULONG Timeout)
655 {
656     UCHAR Status;
657 
658     ASSERT(Timeout != 0);
659 
660     WaitForBusy(Channel, ATA_STATUS_TIMEOUT);
661 
662     while (Timeout--)
663     {
664         StallExecutionProcessor(10);
665 
666         Status = AtaReadPort(Channel, IDX_IO1_i_Status);
667         if (Status & IDE_STATUS_ERROR)
668             return FALSE;
669         else if ((Status & Flags) == ExpectedValue)
670             return TRUE;
671     }
672     return FALSE;
673 }
674 
675 static
676 BOOLEAN
677 WaitForFlagsOr(
678     IN UCHAR Channel,
679     IN UCHAR FirstValue,
680     IN UCHAR SecondValue,
681     IN ULONG Timeout)
682 {
683     UCHAR Status;
684 
685     ASSERT(Timeout != 0);
686 
687     WaitForBusy(Channel, ATA_STATUS_TIMEOUT);
688 
689     while (Timeout--)
690     {
691         StallExecutionProcessor(10);
692 
693         Status = AtaReadPort(Channel, IDX_IO1_i_Status);
694         if (Status & IDE_STATUS_ERROR)
695             return FALSE;
696         else if ((Status & FirstValue) || (Status & SecondValue))
697             return TRUE;
698     }
699     return FALSE;
700 }
701 
702 static
703 BOOLEAN
704 WaitForBusy(
705     IN UCHAR Channel,
706     IN ULONG Timeout)
707 {
708     ASSERT(Timeout != 0);
709 
710     while (Timeout--)
711     {
712         StallExecutionProcessor(10);
713 
714         if ((AtaReadPort(Channel, IDX_IO1_i_Status) & IDE_STATUS_BUSY) == 0)
715             return TRUE;
716     }
717     return FALSE;
718 }
719 
720 static
721 VOID
722 AtaHardReset(IN UCHAR Channel)
723 {
724     TRACE("AtaHardReset(Controller %d)\n", Channel);
725 
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);
731 }
732 
733 static
734 VOID
735 SelectDevice(IN UCHAR Channel, IN UCHAR DeviceNumber)
736 {
737 #if defined(SARCH_PC98)
738     /* Select IDE Channel */
739     WRITE_PORT_UCHAR((PUCHAR)IDE_IO_o_BankSelect, Channel);
740     StallExecutionProcessor(5);
741 #endif
742 
743     AtaWritePort(Channel, IDX_IO1_o_DriveSelect,
744                  DeviceNumber ? IDE_DRIVE_SELECT_2 : IDE_DRIVE_SELECT_1);
745     StallExecutionProcessor(5);
746 }
747 
748 static
749 BOOLEAN
750 IdentifyDevice(
751     IN UCHAR Channel,
752     IN UCHAR DeviceNumber,
753     OUT PDEVICE_UNIT *DeviceUnit)
754 {
755     UCHAR SignatureLow, SignatureHigh, SignatureCount, SignatureNumber;
756     UCHAR Command;
757     IDENTIFY_DATA Id;
758     SENSE_DATA SenseData;
759     ULONG i;
760     ULONG SectorSize;
761     ULONGLONG TotalSectors;
762     USHORT Flags = 0;
763 
764     TRACE("IdentifyDevice() Channel = %x, Device = %x, BaseIoAddress = 0x%x\n",
765           Channel, DeviceNumber, BaseArray[Channel]);
766 
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)
774         goto Failure;
775 
776     /* Reset the controller */
777     AtaHardReset(Channel);
778 
779     /* Select the drive */
780     SelectDevice(Channel, DeviceNumber);
781     if (!WaitForBusy(Channel, ATA_STATUS_TIMEOUT))
782         goto Failure;
783 
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)
793     {
794         TRACE("IdentifyDevice(): Found PATA device at %d:%d\n", Channel, DeviceNumber);
795         Command = IDE_COMMAND_IDENTIFY;
796     }
797     else if (SignatureLow == ATAPI_MAGIC_LSB &&
798              SignatureHigh == ATAPI_MAGIC_MSB)
799     {
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;
803     }
804     else
805     {
806         goto Failure;
807     }
808 
809     /* Disable interrupts */
810     AtaWritePort(Channel, IDX_IO2_o_Control, IDE_DC_DISABLE_INTERRUPTS);
811     StallExecutionProcessor(5);
812 
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))
817     {
818         ERR("IdentifyDevice(): Identify command failed.\n");
819         goto Failure;
820     }
821 
822     /* Receive parameter information from the device */
823     AtaReadBuffer(Channel, &Id, IDENTIFY_DATA_SIZE);
824 
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]);
828 
829     for (i = 0; i < RTL_NUMBER_OF(Id.FirmwareRevision); ++i)
830         Id.FirmwareRevision[i] = RtlUshortByteSwap(Id.FirmwareRevision[i]);
831 
832     for (i = 0; i < RTL_NUMBER_OF(Id.ModelNumber); ++i)
833         Id.ModelNumber[i] = RtlUshortByteSwap(Id.ModelNumber[i]);
834 
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);
838 
839     /* Allocate a new device unit structure */
840     *DeviceUnit = FrLdrTempAlloc(sizeof(DEVICE_UNIT), TAG_ATA_DEVICE);
841     if (*DeviceUnit == NULL)
842     {
843         ERR("Failed to allocate device unit!\n");
844         return FALSE;
845     }
846 
847     RtlZeroMemory(*DeviceUnit, sizeof(DEVICE_UNIT));
848     (*DeviceUnit)->Channel = Channel;
849     (*DeviceUnit)->DeviceNumber = DeviceNumber;
850     (*DeviceUnit)->IdentifyData = Id;
851 
852     if (Flags & ATA_DEVICE_ATAPI)
853     {
854         /* Clear the ATAPI 'Bus reset' indication */
855         for (i = 0; i < 10; ++i)
856         {
857             AtapiRequestSense(*DeviceUnit, &SenseData);
858             StallExecutionProcessor(10);
859         }
860 
861         /* Detect a medium's capacity */
862         AtapiCapacityDetect(*DeviceUnit, &TotalSectors, &SectorSize);
863         if (SectorSize == 0 || TotalSectors == 0)
864         {
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;
868         }
869     }
870     else
871     {
872         if (Id.SupportLba || (Id.MajorRevision && Id.UserAddressableSectors))
873         {
874             if (Id.FeaturesSupport.Address48)
875             {
876                 TRACE("Using LBA48 addressing mode.\n");
877                 Flags |= ATA_DEVICE_LBA48 | ATA_DEVICE_LBA;
878                 TotalSectors = Id.UserAddressableSectors48;
879             }
880             else
881             {
882                 TRACE("Using LBA28 addressing mode.\n");
883                 Flags |= ATA_DEVICE_LBA;
884                 TotalSectors = Id.UserAddressableSectors;
885             }
886 
887             /* LBA ATA drives always have a sector size of 512 */
888             SectorSize = 512;
889         }
890         else
891         {
892             TRACE("Using CHS addressing mode.\n");
893             Flags |= ATA_DEVICE_CHS;
894 
895             if (Id.UnformattedBytesPerSector == 0)
896             {
897                 SectorSize = 512;
898             }
899             else
900             {
901                 for (i = 1 << 15; i > 0; i >>= 1)
902                 {
903                     if ((Id.UnformattedBytesPerSector & i) != 0)
904                     {
905                         SectorSize = i;
906                         break;
907                     }
908                 }
909             }
910             TotalSectors = Id.NumberOfCylinders * Id.NumberOfHeads * Id.SectorsPerTrack;
911         }
912     }
913     TRACE("Sector size %d ; Total sectors %I64d\n", SectorSize, TotalSectors);
914 
915     (*DeviceUnit)->Flags = Flags;
916     (*DeviceUnit)->SectorSize = SectorSize;
917     (*DeviceUnit)->TotalSectors = TotalSectors;
918     if (Flags & ATA_DEVICE_ATAPI)
919     {
920         (*DeviceUnit)->Cylinders = 0xFFFFFFFF;
921         (*DeviceUnit)->Heads = 0xFFFFFFFF;
922         (*DeviceUnit)->Sectors = 0xFFFFFFFF;
923     }
924     else
925     {
926         (*DeviceUnit)->Cylinders = Id.NumberOfCylinders;
927         (*DeviceUnit)->Heads = Id.NumberOfHeads;
928         (*DeviceUnit)->Sectors = Id.SectorsPerTrack;
929     }
930 
931 #if DBG
932     DbgDumpBuffer(DPRINT_DISK, &Id, IDENTIFY_DATA_SIZE);
933 #endif
934 
935     TRACE("IdentifyDevice() done.\n");
936     return TRUE;
937 
938 Failure:
939     TRACE("IdentifyDevice() done. No device present at %d:%d\n", Channel, DeviceNumber);
940     return FALSE;
941 }
942