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
AtaInit(OUT PUCHAR DetectedCount)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
AtaFree(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
AtaGetDevice(IN UCHAR UnitNumber)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
AtaAtapiReadLogicalSectorsLBA(IN OUT PDEVICE_UNIT DeviceUnit,IN ULONGLONG SectorNumber,IN ULONG SectorCount,OUT PVOID Buffer)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
AtaReadLogicalSectorsLBA(IN PDEVICE_UNIT DeviceUnit,IN ULONGLONG SectorNumber,IN ULONG SectorCount,OUT PVOID Buffer)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
AtaSendAtapiPacket(IN UCHAR Channel,IN PUCHAR AtapiPacket,IN UCHAR PacketSize,IN USHORT ByteCount)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
AtapiReadLogicalSectorLBA(IN PDEVICE_UNIT DeviceUnit,IN ULONGLONG SectorNumber,OUT PVOID Buffer)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
AtapiCapacityDetect(IN PDEVICE_UNIT DeviceUnit,OUT PULONGLONG TotalSectors,OUT PULONG SectorSize)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
AtapiRequestSense(IN PDEVICE_UNIT DeviceUnit,OUT PSENSE_DATA SenseData)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
AtapiPrintSenseData(IN PDEVICE_UNIT DeviceUnit)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
AtapiReadyCheck(IN OUT PDEVICE_UNIT DeviceUnit)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
WaitForFlags(IN UCHAR Channel,IN UCHAR Flags,IN UCHAR ExpectedValue,IN ULONG Timeout)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
WaitForFlagsOr(IN UCHAR Channel,IN UCHAR FirstValue,IN UCHAR SecondValue,IN ULONG Timeout)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
WaitForBusy(IN UCHAR Channel,IN ULONG Timeout)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
AtaHardReset(IN UCHAR Channel)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
SelectDevice(IN UCHAR Channel,IN UCHAR DeviceNumber)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
IdentifyDevice(IN UCHAR Channel,IN UCHAR DeviceNumber,OUT PDEVICE_UNIT * DeviceUnit)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