ReactOS 0.4.16-dev-2206-gc56950d
hwide.c
Go to the documentation of this file.
1/*
2 * PROJECT: FreeLoader
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: ATA/ATAPI programmed I/O driver.
5 * COPYRIGHT: Copyright 2019-2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/* INCLUDES *******************************************************************/
9
10#include <freeldr.h>
11
12/* DDK */
13#include <ata.h>
14#include <scsi.h>
15
16#include <hwide.h>
17#include "hwidep.h"
18
19#include <debug.h>
21
22/* GLOBALS ********************************************************************/
23
26{
27#if defined(SARCH_PC98)
28 0x640
29#elif defined(SARCH_XBOX)
30 0x1F0
31#else
32 0x1F0, 0x170, 0x1E8, 0x168
33#endif
34};
35#define CHANNEL_MAX_CHANNELS RTL_NUMBER_OF(AtapChannelBaseArray)
36
38
39/* PRIVATE FUNCTIONS **********************************************************/
40
41static
42VOID
44 _In_ PIDE_REGISTERS Registers,
46{
47#if defined(SARCH_PC98)
48 /* Select the primary (0) or secondary (1) IDE channel */
49 ATA_WRITE(0x432, DeviceNumber >> 1);
50#endif
51
52 ATA_WRITE(Registers->Device, (DEV_SLAVE(DeviceNumber) << 4) | IDE_DRIVE_SELECT);
54}
55
56static
59 _In_ PIDE_REGISTERS Registers,
63{
64 UCHAR IdeStatus;
65 ULONG i;
66
67 ASSERT(Timeout != 0);
68
69 for (i = 0; i < Timeout; ++i)
70 {
71 IdeStatus = ATA_READ(Registers->Status);
72 if ((IdeStatus & Mask) == Value)
73 break;
74
75 if (IdeStatus == 0xFF)
76 break;
77
79 }
80
81 return IdeStatus;
82}
83
84static
85VOID
87 _In_ PHW_DEVICE_UNIT DeviceUnit,
89{
90#if defined(ATA_SUPPORT_32_BIT_IO)
91 ATA_WRITE_BLOCK_32(DeviceUnit->Registers.Data,
92 Request->Cdb,
93 DeviceUnit->CdbSize / sizeof(USHORT));
94#else
95 ATA_WRITE_BLOCK_16(DeviceUnit->Registers.Data,
96 Request->Cdb,
97 DeviceUnit->CdbSize);
98#endif
99}
100
101static
102VOID
104 _In_ PHW_DEVICE_UNIT DeviceUnit,
106{
107 ByteCount = min(ByteCount, DeviceUnit->BytesToTransfer);
108
109#if defined(ATA_SUPPORT_32_BIT_IO)
110 if (!(ByteCount & (sizeof(ULONG) - 1)))
111 {
112 ATA_READ_BLOCK_32(DeviceUnit->Registers.Data,
113 (PULONG)DeviceUnit->DataBuffer,
114 ByteCount / sizeof(ULONG));
115 }
116 else
117#endif
118 {
119 ATA_READ_BLOCK_16(DeviceUnit->Registers.Data,
120 (PUSHORT)DeviceUnit->DataBuffer,
121 ByteCount / sizeof(USHORT));
122 }
123
124 DeviceUnit->DataBuffer += ByteCount;
125 DeviceUnit->BytesToTransfer -= ByteCount;
126}
127
128static
131 _In_ PIDE_REGISTERS Registers,
133{
134 ULONG i;
135
136 for (i = 0; i < ATA_TIME_RESET_SELECT; ++i)
137 {
138 /* Select the device again */
139 AtapSelectDevice(Registers, DeviceNumber);
140
141 /* Check whether the selection was successful */
142 ATA_WRITE(Registers->ByteCountLow, 0xAA);
143 ATA_WRITE(Registers->ByteCountLow, 0x55);
144 ATA_WRITE(Registers->ByteCountLow, 0xAA);
145 if (ATA_READ(Registers->ByteCountLow) == 0xAA)
146 return TRUE;
147
149 }
150
151 return FALSE;
152}
153
154static
155VOID
157 _In_ PIDE_REGISTERS Registers)
158{
159 ATA_WRITE(Registers->Control, IDE_DC_RESET_CONTROLLER | IDE_DC_ALWAYS);
163}
164
165static
166VOID
168 _In_ PIDE_REGISTERS Registers)
169{
170 UCHAR IdeStatus;
171 ULONG i;
172
173 /* Try to clear the DRQ indication */
174 for (i = 0; i < 0x10000 / sizeof(USHORT); ++i)
175 {
176 IdeStatus = ATA_READ(Registers->Status);
177 if (!(IdeStatus & IDE_STATUS_DRQ))
178 break;
179
180 READ_PORT_USHORT((PUSHORT)(ULONG_PTR)Registers->Data);
181 }
182}
183
184static
187 _In_ PHW_DEVICE_UNIT DeviceUnit)
188{
189 PIDE_REGISTERS Registers = &DeviceUnit->Registers;
190 UCHAR IdeStatus;
191
192 ERR("Reset device at %X:%u\n", Registers->Data, DeviceUnit->DeviceNumber);
193
194 AtapDrainDeviceBuffer(Registers);
195
196 /* Perform a software reset */
197 AtapSoftwareReset(Registers);
198
199 /* The reset will cause the master device to be selected */
200 if (DEV_SLAVE(DeviceUnit->DeviceNumber))
201 {
202 if (!AtapWaitForRegisterAccess(Registers, DeviceUnit->DeviceNumber))
203 return FALSE;
204 }
205
206 /* Now wait for busy to clear */
207 IdeStatus = AtapWait(Registers, ATA_TIME_BUSY_RESET, IDE_STATUS_BUSY, 0);
208 if (IdeStatus & IDE_STATUS_BUSY)
209 return FALSE;
210
211 return TRUE;
212}
213
214static
215UCHAR
217 _In_ PHW_DEVICE_UNIT DeviceUnit,
219 _In_ UCHAR IdeStatus)
220{
221 UCHAR InterruptReason;
222
223 InterruptReason = ATA_READ(DeviceUnit->Registers.InterruptReason);
224 InterruptReason &= ATAPI_INT_REASON_MASK;
225 InterruptReason |= IdeStatus & IDE_STATUS_DRQ;
226
227 /*
228 * The NEC CDR-C251 drive is not fully ATAPI-compliant
229 * and clears BSY before raising the DRQ bit and updating the interrupt reason register.
230 * As a workaround, we will wait a bit more in the case the valid IR is not quite there yet.
231 */
232 if ((InterruptReason == ATAPI_INT_REASON_COD) || (InterruptReason == ATAPI_INT_REASON_IO))
233 {
234 IdeStatus = AtapWait(&DeviceUnit->Registers,
238
239 InterruptReason = ATA_READ(DeviceUnit->Registers.InterruptReason);
240 InterruptReason &= ATAPI_INT_REASON_MASK;
241 InterruptReason |= IdeStatus & IDE_STATUS_DRQ;
242 }
243
244 switch (InterruptReason)
245 {
247 {
248 if (!(Request->Flags & REQUEST_FLAG_AWAIT_CDB))
249 return ATA_STATUS_RESET;
250
251 Request->Flags &= ~REQUEST_FLAG_AWAIT_CDB;
252
253 AtapSendCdb(DeviceUnit, Request);
254 return ATA_STATUS_PENDING;
255 }
256
258 {
260
261 if (!Request->DataBuffer || (Request->Flags & REQUEST_FLAG_AWAIT_CDB))
262 return ATA_STATUS_RESET;
263
264 ByteCount = ATA_READ(DeviceUnit->Registers.ByteCountLow);
265 ByteCount |= ATA_READ(DeviceUnit->Registers.ByteCountHigh) << 8;
266
267 AtapPioDataIn(DeviceUnit, ByteCount);
268 return ATA_STATUS_PENDING;
269 }
270
272 {
273 /* The NEC CDR-260 drive always clears CoD and IO on command completion */
274 if (!(DeviceUnit->P.Flags & ATA_DEVICE_IS_NEC_CDR260))
275 return ATA_STATUS_RESET;
276
278 }
280 {
281 if (IdeStatus & (IDE_STATUS_ERROR | IDE_STATUS_DEVICE_FAULT))
282 return ATA_STATUS_ERROR;
283
284 break;
285 }
286
287 default:
288 return ATA_STATUS_RESET;
289 }
290
291 return ATA_STATUS_SUCCESS;
292}
293
294static
295UCHAR
297 _In_ PHW_DEVICE_UNIT DeviceUnit,
299 _In_ UCHAR IdeStatus)
300{
301 /* Check for errors */
302 if (IdeStatus & (IDE_STATUS_ERROR | IDE_STATUS_DEVICE_FAULT))
303 {
304 if (IdeStatus & IDE_STATUS_DRQ)
305 return ATA_STATUS_RESET;
306 else
307 return ATA_STATUS_ERROR;
308 }
309
310 /* Read command */
311 if (Request->DataBuffer)
312 {
313 /*
314 * The NEC CDR-C251 drive clears BSY before raising the DRQ bit
315 * while processing the ATAPI identify command.
316 * Give the device a chance to assert that bit.
317 */
318 if (!(IdeStatus & IDE_STATUS_DRQ))
319 {
320 IdeStatus = AtapWait(&DeviceUnit->Registers,
324 if (!(IdeStatus & IDE_STATUS_DRQ))
325 return ATA_STATUS_RESET;
326 }
327
328 /* Read the next data block */
329 AtapPioDataIn(DeviceUnit, DeviceUnit->DrqByteCount);
330
331 if (DeviceUnit->BytesToTransfer != 0)
332 return ATA_STATUS_PENDING;
333
334 /* All data has been transferred, wait for DRQ to clear */
335 IdeStatus = AtapWait(&DeviceUnit->Registers,
338 0);
339 if (IdeStatus & (IDE_STATUS_BUSY | IDE_STATUS_DRQ))
340 return ATA_STATUS_RESET;
341
342 if (IdeStatus & (IDE_STATUS_ERROR | IDE_STATUS_DEVICE_FAULT))
343 return ATA_STATUS_ERROR;
344 }
345
346 /* Status phase or non-data ATA command */
347 return ATA_STATUS_SUCCESS;
348}
349
350static
351UCHAR
353 _In_ PHW_DEVICE_UNIT DeviceUnit,
355 _In_ UCHAR IdeStatus)
356{
357 UCHAR AtaStatus;
358
359 if (!(Request->Flags & REQUEST_FLAG_PACKET_COMMAND))
360 return AtapProcessAtaRequest(DeviceUnit, Request, IdeStatus);
361
362 AtaStatus = AtapProcessAtapiRequest(DeviceUnit, Request, IdeStatus);
363
364 /*
365 * In polled mode (interrupts disabled), the NEC CDR-260 drive behaves quite differently
366 * that other devices. This drive does not raise BSY immediately
367 * in response to a CDB or buffer write. The status and interrupt reason registers
368 * remain invalid and unchanged for the time of media access.
369 * As a workaround, we will wait for the phase change.
370 */
371 if ((DeviceUnit->P.Flags & ATA_DEVICE_IS_NEC_CDR260) && (AtaStatus == ATA_STATUS_PENDING))
372 {
373 UCHAR OldInterruptReason, NewInterruptReason;
374 ULONG i;
375
376 OldInterruptReason = ATA_READ(DeviceUnit->Registers.InterruptReason);
377
378 /* Set a long timeout on purpose */
379 for (i = ATA_TIME_BUSY_POLL; i > 0; i--)
380 {
381 NewInterruptReason = ATA_READ(DeviceUnit->Registers.InterruptReason);
382 if (NewInterruptReason != OldInterruptReason)
383 break;
384
386 }
387 if (i == 0)
388 {
389 AtaStatus = ATA_STATUS_RESET;
390 }
391 }
392
393 return AtaStatus;
394}
395
396static
397VOID
399 _In_ PHW_DEVICE_UNIT DeviceUnit,
401{
403
405
406 /*
407 * If a larger transfer is attempted, the 16-bit ByteCount register might overflow.
408 * In this case we round down the length to the closest multiple of 2.
409 */
410 ByteCount = min(Request->DataTransferLength, 0xFFFE);
411
412 /* Prepare to transfer a device command */
413 ATA_WRITE(DeviceUnit->Registers.ByteCountLow, (UCHAR)(ByteCount >> 0));
414 ATA_WRITE(DeviceUnit->Registers.ByteCountHigh, (UCHAR)(ByteCount >> 8));
415 ATA_WRITE(DeviceUnit->Registers.Features, IDE_FEATURE_PIO);
416 ATA_WRITE(DeviceUnit->Registers.Command, IDE_COMMAND_ATAPI_PACKET);
417}
418
419static
420VOID
422 _In_ PHW_DEVICE_UNIT DeviceUnit,
424{
425 PATA_TASKFILE TaskFile = &Request->TaskFile;
426 ULONG i, BlockCount;
427
428 /* Store the extra information in the second byte of FIFO for 48-bit commands */
429 i = (Request->Flags & REQUEST_FLAG_LBA48) ? 2 : 1;
430
431 while (i--)
432 {
433 ATA_WRITE(DeviceUnit->Registers.Features, TaskFile->Data[i].Feature);
434 ATA_WRITE(DeviceUnit->Registers.SectorCount, TaskFile->Data[i].SectorCount);
435 ATA_WRITE(DeviceUnit->Registers.LbaLow, TaskFile->Data[i].LowLba);
436 ATA_WRITE(DeviceUnit->Registers.LbaMid, TaskFile->Data[i].MidLba);
437 ATA_WRITE(DeviceUnit->Registers.LbaHigh, TaskFile->Data[i].HighLba);
438 }
440 {
441 ATA_WRITE(DeviceUnit->Registers.Device, TaskFile->DriveSelect);
442 }
443 ATA_WRITE(DeviceUnit->Registers.Command, TaskFile->Command);
444
445 /* Set the byte count per DRQ data block */
447 BlockCount = DeviceUnit->MultiSectorTransfer;
448 else
449 BlockCount = 1;
450 DeviceUnit->DrqByteCount = BlockCount * DeviceUnit->P.SectorSize;
451}
452
453static
454UCHAR
456 _In_ PHW_DEVICE_UNIT DeviceUnit,
458{
459 UCHAR IdeStatus, AtaStatus;
460
461 DeviceUnit->BytesToTransfer = Request->DataTransferLength;
462 DeviceUnit->DataBuffer = Request->DataBuffer;
463
464 /* Select the device */
465 AtapSelectDevice(&DeviceUnit->Registers, DeviceUnit->DeviceNumber);
466 IdeStatus = AtapWait(&DeviceUnit->Registers, ATA_TIME_BUSY_SELECT, IDE_STATUS_BUSY, 0);
467 if (IdeStatus & IDE_STATUS_BUSY)
468 return ATA_STATUS_RETRY;
469
470 /* Always disable interrupts, otherwise it may lead to problems in underlying BIOS firmware */
471 ATA_WRITE(DeviceUnit->Registers.Control, IDE_DC_DISABLE_INTERRUPTS | IDE_DC_ALWAYS);
472
474 AtapIssuePacketCommand(DeviceUnit, Request);
475 else
476 AtapLoadTaskFile(DeviceUnit, Request);
477
478 while (TRUE)
479 {
480 ATA_IO_WAIT();
481
482 IdeStatus = AtapWait(&DeviceUnit->Registers, ATA_TIME_BUSY_POLL, IDE_STATUS_BUSY, 0);
483 if (IdeStatus & IDE_STATUS_BUSY)
484 return ATA_STATUS_RESET;
485
486 AtaStatus = AtapProcessRequest(DeviceUnit, Request, IdeStatus);
487 if (AtaStatus != ATA_STATUS_PENDING)
488 break;
489 }
490
491 return AtaStatus;
492}
493
494static
495VOID
498 _Out_ PSENSE_DATA SenseData)
499{
501 Request->DataBuffer = SenseData;
502 Request->DataTransferLength = sizeof(*SenseData);
504 Request->Cdb[4] = (UCHAR)Request->DataTransferLength;
505}
506
507static
510 _In_ PHW_DEVICE_UNIT DeviceUnit)
511{
513 SENSE_DATA SenseData;
514
516 if (AtapSendCommand(DeviceUnit, &Request) != ATA_STATUS_SUCCESS)
517 return FALSE;
518
519 ERR("SK %02X, ASC %02X, ASCQ %02X\n",
520 SenseData.SenseKey,
521 SenseData.AdditionalSenseCode,
523
524 return TRUE;
525}
526
527static
530 _In_ PHW_DEVICE_UNIT DeviceUnit,
532{
533 ULONG RetryCount;
534
535 for (RetryCount = 0; RetryCount < 3; ++RetryCount)
536 {
537 UCHAR AtaStatus;
538
539 AtaStatus = AtapSendCommand(DeviceUnit, Request);
540
541 if ((AtaStatus != ATA_STATUS_SUCCESS) &&
543 {
544 ERR("ATA%s command %02X failed %u %02X:%02X at %X:%u\n",
545 (Request->Flags & REQUEST_FLAG_PACKET_COMMAND) ? "PI" : "",
547 Request->Cdb[0] : Request->TaskFile.Command,
548 AtaStatus,
549 ATA_READ(DeviceUnit->Registers.Status),
550 ATA_READ(DeviceUnit->Registers.Error),
551 DeviceUnit->Registers.Data,
552 DeviceUnit->DeviceNumber);
553 }
554
555 switch (AtaStatus)
556 {
558 return TRUE;
559
560 case ATA_STATUS_RETRY:
561 break;
562
563 case ATA_STATUS_RESET:
564 {
566 {
567 /*
568 * Some controllers indicate status 0x00
569 * when the selected device does not exist,
570 * no point in going further.
571 */
572 if (ATA_READ(DeviceUnit->Registers.Status) == 0)
573 return FALSE;
574 }
575
576 if (!AtapPerformSoftwareReset(DeviceUnit))
577 return FALSE;
578
579 break;
580 }
581
582 default:
583 {
585 {
586 if (!AtapAtapiHandleError(DeviceUnit))
587 return FALSE;
588 }
589
590 /* Only retry failed read commands */
591 if (!(Request->Flags & REQUEST_FLAG_READ_COMMAND))
592 return FALSE;
593
594 break;
595 }
596 }
597 }
598
599 return FALSE;
600}
601
602static
603UCHAR
606{
607 static const UCHAR AtapReadCommandMap[2][2] =
608 {
609 /* Read Read EXT */
610 { IDE_COMMAND_READ, IDE_COMMAND_READ_EXT }, // PIO single
612 };
613
614 return AtapReadCommandMap[(Request->Flags & REQUEST_FLAG_READ_WRITE_MULTIPLE) ? 1 : 0]
615 [(Request->Flags & REQUEST_FLAG_LBA48) ? 1 : 0];
616}
617
618static
619VOID
621 _In_ PHW_DEVICE_UNIT DeviceUnit,
623 _In_ ULONG64 Lba,
625{
626 PATA_TASKFILE TaskFile = &Request->TaskFile;
627 UCHAR DriveSelect;
628
630
631 if (DeviceUnit->MultiSectorTransfer != 0)
632 {
634 }
635
636 if (DeviceUnit->P.Flags & ATA_DEVICE_LBA)
637 {
638 DriveSelect = IDE_LBA_MODE;
639
640 TaskFile->Data[0].SectorCount = (UCHAR)SectorCount;
641 TaskFile->Data[0].LowLba = (UCHAR)Lba; // LBA bits 0-7
642 TaskFile->Data[0].MidLba = (UCHAR)(Lba >> 8); // LBA bits 8-15
643 TaskFile->Data[0].HighLba = (UCHAR)(Lba >> 16); // LBA bits 16-23
644
645 if ((DeviceUnit->P.Flags & ATA_DEVICE_LBA48) && (AtaCommandUseLba48(Lba, SectorCount)))
646 {
648
649 /* 48-bit command */
650 TaskFile->Data[1].SectorCount = (UCHAR)(SectorCount >> 8);
651 TaskFile->Data[1].LowLba = (UCHAR)(Lba >> 24); // LBA bits 24-31
652 TaskFile->Data[1].MidLba = (UCHAR)(Lba >> 32); // LBA bits 32-39
653 TaskFile->Data[1].HighLba = (UCHAR)(Lba >> 40); // LBA bits 40-47
654
655 Request->Flags |= REQUEST_FLAG_LBA48;
656 }
657 else
658 {
660
661 /* 28-bit command */
662 DriveSelect |= ((Lba >> 24) & 0x0F); // LBA bits 24-27
663 }
664 }
665 else
666 {
667 ULONG ChsTemp, Cylinder, Head, Sector;
668
669 ChsTemp = (ULONG)Lba / DeviceUnit->P.SectorsPerTrack;
670
671 /* Legacy CHS translation */
672 Cylinder = ChsTemp / DeviceUnit->P.Heads;
673 Head = ChsTemp % DeviceUnit->P.Heads;
674 Sector = ((ULONG)Lba % DeviceUnit->P.SectorsPerTrack) + 1;
675
676 ASSERT(Cylinder <= 65535 && Head <= 15 && Sector <= 255);
677
678 TaskFile->Data[0].SectorCount = (UCHAR)SectorCount;
679 TaskFile->Data[0].LowLba = (UCHAR)Sector;
680 TaskFile->Data[0].MidLba = (UCHAR)Cylinder;
681 TaskFile->Data[0].HighLba = (UCHAR)(Cylinder >> 8);
682
683 DriveSelect = Head;
684 }
685 TaskFile->DriveSelect = DeviceUnit->DeviceSelect | DriveSelect;
687}
688
689static
690VOID
693 _In_ ULONG64 Lba,
695{
697
698 RtlZeroMemory(Request->Cdb, sizeof(Request->Cdb));
699
700 if (Lba > MAXULONG)
701 {
702 /* READ (16) */
703 Request->Cdb[0] = SCSIOP_READ16;
704 Request->Cdb[2] = (UCHAR)(Lba >> 56);
705 Request->Cdb[3] = (UCHAR)(Lba >> 48);
706 Request->Cdb[4] = (UCHAR)(Lba >> 40);
707 Request->Cdb[5] = (UCHAR)(Lba >> 32);
708 Request->Cdb[6] = (UCHAR)(Lba >> 24);
709 Request->Cdb[7] = (UCHAR)(Lba >> 16);
710 Request->Cdb[8] = (UCHAR)(Lba >> 8);
711 Request->Cdb[9] = (UCHAR)(Lba >> 0);
712 Request->Cdb[10] = (UCHAR)(SectorCount >> 24);
713 Request->Cdb[11] = (UCHAR)(SectorCount >> 16);
714 Request->Cdb[12] = (UCHAR)(SectorCount >> 8);
715 Request->Cdb[13] = (UCHAR)(SectorCount >> 0);
716 }
717 else
718 {
719 /* READ (10) */
720 Request->Cdb[0] = SCSIOP_READ;
721 Request->Cdb[2] = (UCHAR)(Lba >> 24);
722 Request->Cdb[3] = (UCHAR)(Lba >> 16);
723 Request->Cdb[4] = (UCHAR)(Lba >> 8);
724 Request->Cdb[5] = (UCHAR)(Lba >> 0);
725 Request->Cdb[7] = (UCHAR)(SectorCount >> 8);
726 Request->Cdb[8] = (UCHAR)(SectorCount >> 0);
727 }
728}
729
730static
733 _In_ PHW_DEVICE_UNIT DeviceUnit)
734{
735 PIDE_REGISTERS Registers = &DeviceUnit->Registers;
736 UCHAR IdeStatus;
737
738 AtapSelectDevice(Registers, DeviceUnit->DeviceNumber);
739
740 IdeStatus = ATA_READ(Registers->Status);
741 if (IdeStatus == 0xFF || IdeStatus == 0x7F)
742 return FALSE;
743
744 ATA_WRITE(Registers->ByteCountLow, 0x55);
745 ATA_WRITE(Registers->ByteCountLow, 0xAA);
746 ATA_WRITE(Registers->ByteCountLow, 0x55);
747 if (ATA_READ(Registers->ByteCountLow) != 0x55)
748 return FALSE;
749 ATA_WRITE(Registers->ByteCountHigh, 0xAA);
750 ATA_WRITE(Registers->ByteCountHigh, 0x55);
751 ATA_WRITE(Registers->ByteCountHigh, 0xAA);
752 if (ATA_READ(Registers->ByteCountHigh) != 0xAA)
753 return FALSE;
754
755 IdeStatus = AtapWait(&DeviceUnit->Registers, ATA_TIME_BUSY_ENUM, IDE_STATUS_BUSY, 0);
756 if (IdeStatus & (IDE_STATUS_BUSY | IDE_STATUS_DRQ))
757 {
758 ERR("Device %X:%u is busy %02x\n", Registers->Data, DeviceUnit->DeviceNumber, IdeStatus);
759
760 /* Bring the device into a known state */
761 if (!AtapPerformSoftwareReset(DeviceUnit))
762 return FALSE;
763 }
764
765 return TRUE;
766}
767
768static
771 _In_ PHW_DEVICE_UNIT DeviceUnit,
773{
775 PIDENTIFY_DEVICE_DATA Id = &DeviceUnit->IdentifyDeviceData;
776
777 /* Send the identify command */
779 Request.DataBuffer = Id;
780 Request.DataTransferLength = sizeof(*Id);
781 Request.TaskFile.Command = Command;
782
783 return AtapIssueCommand(DeviceUnit, &Request);
784}
785
786static
789 _In_ PHW_DEVICE_UNIT DeviceUnit)
790{
791 if (!AtapIsDevicePresent(DeviceUnit))
792 return DEV_NONE;
793
794 /*
795 * We don't check the device signature here,
796 * because the NEC CDR-260 drive reports an ATA signature.
797 */
798
799 /* Check for ATA */
801 return DEV_ATA;
802
803 /* Check for ATAPI */
805 return DEV_ATAPI;
806
807 return DEV_NONE;
808}
809
810static
813 _In_ PHW_DEVICE_UNIT DeviceUnit,
814 _Out_ PREAD_CAPACITY16_DATA CapacityData)
815{
817
818 /* Send the SCSI READ CAPACITY(16) command */
820 Request.DataBuffer = CapacityData;
821 Request.DataTransferLength = sizeof(*CapacityData);
824 Request.Cdb[13] = sizeof(*CapacityData);
825
826 return AtapIssueCommand(DeviceUnit, &Request);
827}
828
829static
832 _In_ PHW_DEVICE_UNIT DeviceUnit,
833 _Out_ PREAD_CAPACITY_DATA CapacityData)
834{
836
837 /* Send the SCSI READ CAPACITY(10) command */
839 Request.DataBuffer = CapacityData;
840 Request.DataTransferLength = sizeof(*CapacityData);
842
843 return AtapIssueCommand(DeviceUnit, &Request);
844}
845
846static
847VOID
849 _In_ PHW_DEVICE_UNIT DeviceUnit,
850 _Out_ PULONG64 TotalSectors,
852{
853 union
854 {
855 READ_CAPACITY_DATA Cmd10;
857 } CapacityData;
858 ULONG LastLba;
859
860 *TotalSectors = 0;
861 *SectorSize = 0;
862
863 if (!AtapAtapiReadCapacity10(DeviceUnit, &CapacityData.Cmd10))
864 return;
865
866 LastLba = RtlUlongByteSwap(CapacityData.Cmd10.LogicalBlockAddress);
867 if (LastLba == MAXULONG)
868 {
869 if (!AtapAtapiReadCapacity16(DeviceUnit, &CapacityData.Cmd16))
870 return;
871
872 *TotalSectors = RtlUlonglongByteSwap(CapacityData.Cmd16.LogicalBlockAddress.QuadPart) + 1;
873 *SectorSize = RtlUlongByteSwap(CapacityData.Cmd16.BytesPerBlock);
874 }
875 else
876 {
877 *TotalSectors = LastLba + 1;
878 *SectorSize = RtlUlongByteSwap(CapacityData.Cmd10.BytesPerBlock);
879 }
880
881 /*
882 * If device reports a non-zero block length, reset to defaults
883 * (we use a READ command instead of READ CD).
884 */
885 if (*SectorSize != 0)
886 *SectorSize = 2048;
887}
888
889static
892 _In_ PHW_DEVICE_UNIT DeviceUnit)
893{
895
896 /* Send the SCSI TEST UNIT READY command */
899
900 return AtapIssueCommand(DeviceUnit, &Request);
901}
902
903static
906 _In_ PHW_DEVICE_UNIT DeviceUnit,
907 _Out_ PSENSE_DATA SenseData)
908{
910
912 return AtapIssueCommand(DeviceUnit, &Request);
913}
914
915static
918 _In_ PHW_DEVICE_UNIT DeviceUnit)
919{
922
923 /* Send the SCSI READ TOC command */
925 Request.DataBuffer = DummyData;
926 Request.DataTransferLength = sizeof(DummyData);
927 Request.Cdb[0] = SCSIOP_READ_TOC;
928 Request.Cdb[7] = (MAXIMUM_CDROM_SIZE >> 8) & 0xFF;
929 Request.Cdb[8] = MAXIMUM_CDROM_SIZE & 0xFF;
930 Request.Cdb[9] = READ_TOC_FORMAT_SESSION << 6;
931
932 return AtapIssueCommand(DeviceUnit, &Request);
933}
934
935static
938 _In_ PHW_DEVICE_UNIT DeviceUnit)
939{
940 SENSE_DATA SenseData;
941
942 if (!AtapAtapiTestUnitReady(DeviceUnit))
943 return FALSE;
944
945 if (!AtapAtapiRequestSense(DeviceUnit, &SenseData))
946 return FALSE;
947
948 if (SenseData.SenseKey == SCSI_SENSE_NOT_READY)
949 {
951 return FALSE;
952
954 {
955 switch (SenseData.AdditionalSenseCodeQualifier)
956 {
958 /* Wait until the CD is spun up */
960 return FALSE;
961
963 /* The drive needs to be spun up */
964 AtapAtapiReadToc(DeviceUnit);
965 return FALSE;
966
967 default:
968 return FALSE;
969 }
970 }
971 }
972
973 return TRUE;
974}
975
976static
977VOID
979 _In_ PHW_DEVICE_UNIT DeviceUnit)
980{
981 SENSE_DATA SenseData;
982 ULONG i;
983
984 for (i = 0; i < 5; ++i)
985 {
986 if (!AtapAtapiRequestSense(DeviceUnit, &SenseData))
987 continue;
988
989 if ((SenseData.SenseKey != SCSI_SENSE_UNIT_ATTENTION) &&
991 {
992 break;
993 }
994 }
995}
996
997static
1000 _In_ PHW_DEVICE_UNIT DeviceUnit)
1001{
1002 PIDENTIFY_PACKET_DATA IdentifyPacketData = &DeviceUnit->IdentifyPacketData;
1003 ULONG i;
1004
1005 DeviceUnit->CdbSize = AtaDevCdbSizeInWords(IdentifyPacketData);
1006
1007 /* Clear the ATAPI 'Bus reset' indication */
1008 AtapAtapiClearUnitAttention(DeviceUnit);
1009
1010 /* Make the device ready */
1011 for (i = 4; i > 0; i--)
1012 {
1013 if (AtapAtapiReadyCheck(DeviceUnit))
1014 break;
1015 }
1016 if (i == 0)
1017 {
1018 ERR("Device not ready\n");
1019 return FALSE;
1020 }
1021
1022 /* Detect a medium's capacity */
1023 AtapAtapiDetectCapacity(DeviceUnit,
1024 &DeviceUnit->P.TotalSectors,
1025 &DeviceUnit->P.SectorSize);
1026 if (DeviceUnit->P.SectorSize == 0 || DeviceUnit->P.TotalSectors == 0)
1027 {
1028 TRACE("No media found\n");
1029 return FALSE;
1030 }
1031
1032 DeviceUnit->P.Cylinders = MAXULONG;
1033 DeviceUnit->P.Heads = MAXULONG;
1034 DeviceUnit->P.SectorsPerTrack = MAXULONG;
1035
1036 DeviceUnit->MaximumTransferLength = 0xFFFF;
1037
1038 return TRUE;
1039}
1040
1041static
1042VOID
1044 _In_ PHW_DEVICE_UNIT DeviceUnit)
1045{
1047
1048#if !defined(ATA_ENABLE_MULTIPLE_MODE)
1049 /* Inherit multiple mode from the state the BIOS firmware left the device in during boot */
1050 DeviceUnit->MultiSectorTransfer = AtaDevCurrentSectorsPerDrq(&DeviceUnit->IdentifyDeviceData);
1051 if (DeviceUnit->MultiSectorTransfer != 0)
1052 return;
1053#endif
1054
1055 /* Use the maximum possible value */
1056 DeviceUnit->MultiSectorTransfer = AtaDevMaximumSectorsPerDrq(&DeviceUnit->IdentifyDeviceData);
1057 if (DeviceUnit->MultiSectorTransfer == 0)
1058 return;
1059
1060 Request.TaskFile.Command = IDE_COMMAND_SET_MULTIPLE;
1061 Request.TaskFile.Data[0].SectorCount = DeviceUnit->MultiSectorTransfer;
1062 if (!AtapIssueCommand(DeviceUnit, &Request))
1063 {
1064 DeviceUnit->MultiSectorTransfer = 0;
1065 }
1066}
1067
1068static
1069BOOLEAN
1071 _In_ PHW_DEVICE_UNIT DeviceUnit)
1072{
1073 PIDENTIFY_DEVICE_DATA IdentifyData = &DeviceUnit->IdentifyDeviceData;
1074 ULONG64 TotalSectors;
1075 USHORT Cylinders, Heads, SectorsPerTrack;
1076
1077 DeviceUnit->MaximumTransferLength = 0xFF;
1078
1079 if (AtaDevIsCurrentGeometryValid(IdentifyData))
1080 AtaDevCurrentChsTranslation(IdentifyData, &Cylinders, &Heads, &SectorsPerTrack);
1081 else
1082 AtaDevDefaultChsTranslation(IdentifyData, &Cylinders, &Heads, &SectorsPerTrack);
1083
1084 /* Using LBA addressing mode */
1085 if (AtaDevHasLbaTranslation(IdentifyData))
1086 {
1087 DeviceUnit->P.Flags |= ATA_DEVICE_LBA;
1088
1089 if (AtaDevHas48BitAddressFeature(IdentifyData))
1090 {
1091 /* Using LBA48 addressing mode */
1092 TotalSectors = AtaDevUserAddressableSectors48Bit(IdentifyData);
1093 ASSERT(TotalSectors <= ATA_MAX_LBA_48);
1094
1095 DeviceUnit->P.Flags |= ATA_DEVICE_LBA48;
1096 DeviceUnit->MaximumTransferLength = 0x10000;
1097 }
1098 else
1099 {
1100 /* Using LBA28 addressing mode */
1101 TotalSectors = AtaDevUserAddressableSectors28Bit(IdentifyData);
1102 ASSERT(TotalSectors <= ATA_MAX_LBA_28);
1103 }
1104 }
1105 else
1106 {
1107 /* Using CHS addressing mode */
1108 TotalSectors = (ULONG64)Cylinders * Heads * SectorsPerTrack;
1109 }
1110
1111 if (TotalSectors == 0)
1112 {
1113 ERR("Unknown geometry\n");
1114 return FALSE;
1115 }
1116
1117 DeviceUnit->P.TotalSectors = TotalSectors;
1118 DeviceUnit->P.Cylinders = Cylinders;
1119 DeviceUnit->P.Heads = Heads;
1120 DeviceUnit->P.SectorsPerTrack = SectorsPerTrack;
1121 DeviceUnit->P.SectorSize = AtaDevBytesPerLogicalSector(IdentifyData);
1122 ASSERT(DeviceUnit->P.SectorSize >= 512);
1123 DeviceUnit->P.SectorSize = max(DeviceUnit->P.SectorSize, 512);
1124
1125 AtapAtaSetMultipleMode(DeviceUnit);
1126
1127 TRACE("Multiple sector setting %u\n", DeviceUnit->MultiSectorTransfer);
1128
1129 return TRUE;
1130}
1131
1132static
1133BOOLEAN
1135 _In_ PHW_DEVICE_UNIT DeviceUnit,
1136 _In_ ATA_DEVICE_CLASS DeviceClass)
1137{
1138 PIDENTIFY_DEVICE_DATA Id = &DeviceUnit->IdentifyDeviceData;
1139 ULONG i;
1140
1141 /* Verify the checksum */
1143 {
1144 ERR("Identify data CRC error\n");
1145 return FALSE;
1146 }
1147
1148 if (DeviceClass == DEV_ATAPI)
1149 {
1150 DeviceUnit->P.Flags |= ATA_DEVICE_ATAPI | ATA_DEVICE_LBA;
1151
1152 /* The returned string is not byteswapped */
1153 if (Id->ModelNumber[0] == 'N' &&
1154 Id->ModelNumber[1] == 'E' &&
1155 Id->ModelNumber[2] == 'C' &&
1156 Id->ModelNumber[3] == ' ')
1157 {
1158 DeviceUnit->P.Flags |= ATA_DEVICE_IS_NEC_CDR260;
1159 }
1160 }
1161
1162 /* Swap byte order of the ASCII data */
1163 for (i = 0; i < sizeof(Id->SerialNumber) / 2; ++i)
1164 ((PUSHORT)Id->SerialNumber)[i] = RtlUshortByteSwap(((PUSHORT)Id->SerialNumber)[i]);
1165
1166 for (i = 0; i < sizeof(Id->FirmwareRevision) / 2; ++i)
1167 ((PUSHORT)Id->FirmwareRevision)[i] = RtlUshortByteSwap(((PUSHORT)Id->FirmwareRevision)[i]);
1168
1169 for (i = 0; i < sizeof(Id->ModelNumber) / 2; ++i)
1170 ((PUSHORT)Id->ModelNumber)[i] = RtlUshortByteSwap(((PUSHORT)Id->ModelNumber)[i]);
1171
1172 TRACE("MN '%.*s'\n", sizeof(Id->ModelNumber), Id->ModelNumber);
1173 TRACE("FR '%.*s'\n", sizeof(Id->FirmwareRevision), Id->FirmwareRevision);
1174 TRACE("S/N '%.*s'\n", sizeof(Id->SerialNumber), Id->SerialNumber);
1175
1176 return TRUE;
1177}
1178
1179static
1180BOOLEAN
1182 _In_ PHW_DEVICE_UNIT DeviceUnit,
1183 _In_ ATA_DEVICE_CLASS DeviceClass)
1184{
1185 if (!AtapAnalyzeIdentifyData(DeviceUnit, DeviceClass))
1186 return FALSE;
1187
1188 if (DeviceClass == DEV_ATAPI)
1189 return AtapAtapiInitDevice(DeviceUnit);
1190 else
1191 return AtapAtaInitDevice(DeviceUnit);
1192}
1193
1194static
1195BOOLEAN
1197 _In_ ULONG ChannelNumber,
1198 _Out_ PIDE_REGISTERS Registers)
1199{
1200 const IDE_REG IoBase = AtapChannelBaseArray[ChannelNumber];
1201 ULONG Spare;
1202
1203#if defined(SARCH_PC98)
1204 if (ATA_READ(0x432) == 0xFF)
1205 return FALSE;
1206#endif
1207
1208#if defined(SARCH_PC98)
1209 Spare = 2;
1210 Registers->Control = 0x74C;
1211#else
1212 Spare = 1;
1213 Registers->Control = IoBase + 0x206;
1214#endif
1215 Registers->Data = IoBase + 0 * Spare;
1216 Registers->Error = IoBase + 1 * Spare;
1217 Registers->SectorCount = IoBase + 2 * Spare;
1218 Registers->LbaLow = IoBase + 3 * Spare;
1219 Registers->LbaMid = IoBase + 4 * Spare;
1220 Registers->LbaHigh = IoBase + 5 * Spare;
1221 Registers->Device = IoBase + 6 * Spare;
1222 Registers->Status = IoBase + 7 * Spare;
1223
1224 return TRUE;
1225}
1226
1227/* PUBLIC FUNCTIONS ***********************************************************/
1228
1229BOOLEAN
1231 _In_ PDEVICE_UNIT DeviceUnit,
1232 _In_ ULONG64 SectorNumber,
1234 _Out_writes_bytes_all_(SectorCount * DeviceUnit->SectorSize) PVOID Buffer)
1235{
1236 PHW_DEVICE_UNIT Unit = (PHW_DEVICE_UNIT)DeviceUnit;
1238
1239 ASSERT(Unit);
1240 ASSERT((SectorNumber + SectorCount) <= Unit->P.TotalSectors);
1241 ASSERT(SectorCount != 0);
1242
1243 while (SectorCount > 0)
1244 {
1245 ULONG BlockCount;
1246
1247 BlockCount = min(SectorCount, Unit->MaximumTransferLength);
1248
1249 Request.DataBuffer = Buffer;
1250 Request.DataTransferLength = BlockCount * Unit->P.SectorSize;
1251
1252 if (Unit->P.Flags & ATA_DEVICE_ATAPI)
1253 AtapBuildReadPacketCommand(&Request, SectorNumber, BlockCount);
1254 else
1255 AtapBuildReadTaskFile(Unit, &Request, SectorNumber, BlockCount);
1256
1258 return FALSE;
1259
1260 SectorNumber += BlockCount;
1261 SectorCount -= BlockCount;
1262
1263 Buffer = (PVOID)((ULONG_PTR)Buffer + Unit->P.SectorSize);
1264 }
1265
1266 return TRUE;
1267}
1268
1271 _In_ UCHAR UnitNumber)
1272{
1273 if (UnitNumber < RTL_NUMBER_OF(AtapUnits))
1274 return (PDEVICE_UNIT)AtapUnits[UnitNumber];
1275
1276 return NULL;
1277}
1278
1279BOOLEAN
1281 _Out_ PUCHAR DetectedCount)
1282{
1283 ULONG ChannelNumber;
1284
1285 *DetectedCount = 0;
1286
1287 /* Enumerate IDE channels */
1288 for (ChannelNumber = 0; ChannelNumber < CHANNEL_MAX_CHANNELS; ++ChannelNumber)
1289 {
1291 IDE_REGISTERS Registers;
1292
1293 if (!AtapIdentifyChannel(ChannelNumber, &Registers))
1294 continue;
1295
1296 /* Check for devices attached to the bus */
1298 {
1299 PHW_DEVICE_UNIT DeviceUnit;
1300 ATA_DEVICE_CLASS DeviceClass;
1301
1302 /* Allocate a new device unit structure */
1303 DeviceUnit = FrLdrTempAlloc(sizeof(*DeviceUnit), TAG_ATA_DEVICE);
1304 if (!DeviceUnit)
1305 {
1306 ERR("Failed to allocate device unit!\n");
1307 continue;
1308 }
1309 RtlZeroMemory(DeviceUnit, sizeof(*DeviceUnit));
1310
1311 /* Perform a minimal initialization */
1312 RtlCopyMemory(&DeviceUnit->Registers, &Registers, sizeof(Registers));
1313 DeviceUnit->DeviceNumber = DeviceNumber;
1314 DeviceUnit->P.SectorSize = 512;
1315 DeviceUnit->DeviceSelect = (DEV_SLAVE(DeviceNumber) << 4) | IDE_DRIVE_SELECT;
1316
1317 /* Let's see what kind of device this is */
1318 DeviceClass = AtapIdentifyDevice(DeviceUnit);
1319 if (DeviceClass == DEV_NONE)
1320 goto NextDevice;
1321
1322 TRACE("Found %lu device at %X:%u\n", DeviceClass, Registers.Data, DeviceNumber);
1323
1324 if (!AtapInitDevice(DeviceUnit, DeviceClass))
1325 goto NextDevice;
1326
1327 TRACE("Total sectors %I64u of size %lu, CHS %lu:%lu:%lu, %lx\n",
1328 DeviceUnit->P.TotalSectors,
1329 DeviceUnit->P.SectorSize,
1330 DeviceUnit->P.Cylinders,
1331 DeviceUnit->P.Heads,
1332 DeviceUnit->P.SectorsPerTrack,
1333 DeviceUnit->P.Flags);
1334
1335 AtapUnits[(*DetectedCount)++] = DeviceUnit;
1336 continue;
1337
1338NextDevice:
1339 FrLdrTempFree(DeviceUnit, TAG_ATA_DEVICE);
1340 }
1341 }
1342
1343 return (*DetectedCount > 0);
1344}
DWORD Id
unsigned char BOOLEAN
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
#define IDE_LBA_MODE
Definition: ata.h:613
#define IDE_COMMAND_READ_MULTIPLE_EXT
Definition: ata.h:648
#define IDE_STATUS_DEVICE_FAULT
Definition: ata.h:624
#define IDE_COMMAND_READ_EXT
Definition: ata.h:645
#define IDE_STATUS_BUSY
Definition: atapi.h:132
#define IDE_STATUS_ERROR
Definition: atapi.h:125
#define IDE_COMMAND_ATAPI_IDENTIFY
Definition: atapi.h:110
#define IDE_DC_RESET_CONTROLLER
Definition: atapi.h:146
#define IDE_COMMAND_IDENTIFY
Definition: atapi.h:118
#define IDE_STATUS_DRQ
Definition: atapi.h:128
#define IDE_COMMAND_READ_MULTIPLE
Definition: atapi.h:111
#define IDE_COMMAND_ATAPI_PACKET
Definition: atapi.h:109
#define IDE_COMMAND_SET_MULTIPLE
Definition: atapi.h:113
#define IDE_COMMAND_READ
Definition: atapi.h:104
#define IDE_DC_DISABLE_INTERRUPTS
Definition: atapi.h:145
#define ERR(fmt,...)
Definition: precomp.h:57
#define DBG_DEFAULT_CHANNEL(ch)
Definition: debug.h:106
VOID FrLdrTempFree(PVOID Allocation, ULONG Tag)
Definition: heap.c:553
PVOID FrLdrTempAlloc(_In_ SIZE_T Size, _In_ ULONG Tag)
Definition: heap.c:545
#define SCSI_ADSENSE_LUN_NOT_READY
Definition: cdrw_hw.h:1218
#define SCSIOP_REQUEST_SENSE
Definition: cdrw_hw.h:870
#define SCSIOP_TEST_UNIT_READY
Definition: cdrw_hw.h:866
#define SCSIOP_READ_TOC
Definition: cdrw_hw.h:927
#define SCSIOP_READ_CAPACITY
Definition: cdrw_hw.h:904
#define SCSI_SENSEQ_BECOMING_READY
Definition: cdrw_hw.h:1313
#define SCSI_SENSE_UNIT_ATTENTION
Definition: cdrw_hw.h:1193
#define SCSI_ADSENSE_NO_MEDIA_IN_DEVICE
Definition: cdrw_hw.h:1221
#define SCSI_SENSEQ_INIT_COMMAND_REQUIRED
Definition: cdrw_hw.h:1314
#define SCSIOP_READ
Definition: cdrw_hw.h:905
#define SCSI_SENSE_NOT_READY
Definition: cdrw_hw.h:1189
#define SCSI_ADSENSE_BUS_RESET
Definition: cdrw_hw.h:1289
Definition: bufpool.h:45
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1230
ULONG DummyData
Definition: cmdata.c:18
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define RtlUlongByteSwap(_x)
Definition: compat.h:815
#define SCSIOP_READ16
Definition: scsi.h:914
unsigned int Mask
Definition: fpcontrol.c:82
Unit
Definition: gdiplusenums.h:26
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
Definition: glfuncs.h:248
USHORT NTAPI READ_PORT_USHORT(IN PUSHORT Port)
Definition: portio.c:63
static PHW_DEVICE_UNIT AtapUnits[CHANNEL_MAX_CHANNELS *CHANNEL_MAX_DEVICES]
Definition: hwide.c:37
static VOID AtapPioDataIn(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ ULONG ByteCount)
Definition: hwide.c:103
static BOOLEAN AtapAtapiReadyCheck(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:937
static BOOLEAN AtapAtapiHandleError(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:509
static BOOLEAN AtapIsDevicePresent(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:732
static VOID AtapLoadTaskFile(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request)
Definition: hwide.c:421
static UCHAR AtapProcessAtapiRequest(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request, _In_ UCHAR IdeStatus)
Definition: hwide.c:216
static BOOLEAN AtapWaitForRegisterAccess(_In_ PIDE_REGISTERS Registers, _In_range_(0, 3) UCHAR DeviceNumber)
Definition: hwide.c:130
PDEVICE_UNIT AtaGetDevice(_In_ UCHAR UnitNumber)
Definition: hwide.c:1270
static BOOLEAN AtapAtapiReadToc(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:917
#define CHANNEL_MAX_CHANNELS
Definition: hwide.c:35
static VOID AtapSelectDevice(_In_ PIDE_REGISTERS Registers, _In_range_(0, 3) UCHAR DeviceNumber)
Definition: hwide.c:43
static VOID AtapSoftwareReset(_In_ PIDE_REGISTERS Registers)
Definition: hwide.c:156
static VOID AtapAtapiDetectCapacity(_In_ PHW_DEVICE_UNIT DeviceUnit, _Out_ PULONG64 TotalSectors, _Out_ PULONG SectorSize)
Definition: hwide.c:848
static BOOLEAN AtapAtapiReadCapacity10(_In_ PHW_DEVICE_UNIT DeviceUnit, _Out_ PREAD_CAPACITY_DATA CapacityData)
Definition: hwide.c:831
static BOOLEAN AtapAtapiRequestSense(_In_ PHW_DEVICE_UNIT DeviceUnit, _Out_ PSENSE_DATA SenseData)
Definition: hwide.c:905
static UCHAR AtapSendCommand(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request)
Definition: hwide.c:455
static BOOLEAN AtapIdentifyChannel(_In_ ULONG ChannelNumber, _Out_ PIDE_REGISTERS Registers)
Definition: hwide.c:1196
static VOID AtapBuildReadPacketCommand(_In_ PATA_DEVICE_REQUEST Request, _In_ ULONG64 Lba, _In_ ULONG SectorCount)
Definition: hwide.c:691
static VOID AtapBuildReadTaskFile(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request, _In_ ULONG64 Lba, _In_ ULONG SectorCount)
Definition: hwide.c:620
static UCHAR AtapProcessAtaRequest(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request, _In_ UCHAR IdeStatus)
Definition: hwide.c:296
static BOOLEAN AtapAtaInitDevice(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:1070
static BOOLEAN AtapReadIdentifyData(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ UCHAR Command)
Definition: hwide.c:770
static BOOLEAN AtapIssueCommand(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request)
Definition: hwide.c:529
static UCHAR AtapWait(_In_ PIDE_REGISTERS Registers, _In_range_(>, 0) ULONG Timeout, _In_ UCHAR Mask, _In_ UCHAR Value)
Definition: hwide.c:58
static VOID AtapDrainDeviceBuffer(_In_ PIDE_REGISTERS Registers)
Definition: hwide.c:167
static VOID AtapSendCdb(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request)
Definition: hwide.c:86
static VOID AtapAtaSetMultipleMode(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:1043
static BOOLEAN AtapAtapiReadCapacity16(_In_ PHW_DEVICE_UNIT DeviceUnit, _Out_ PREAD_CAPACITY16_DATA CapacityData)
Definition: hwide.c:812
static BOOLEAN AtapAnalyzeIdentifyData(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ ATA_DEVICE_CLASS DeviceClass)
Definition: hwide.c:1134
static UCHAR AtapProcessRequest(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request, _In_ UCHAR IdeStatus)
Definition: hwide.c:352
static VOID AtapAtapiClearUnitAttention(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:978
static UCHAR AtapGetReadCommand(_In_ PATA_DEVICE_REQUEST Request)
Definition: hwide.c:604
static BOOLEAN AtapAtapiInitDevice(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:999
static VOID AtapAtapiBuildRequestSense(_In_ PATA_DEVICE_REQUEST Request, _Out_ PSENSE_DATA SenseData)
Definition: hwide.c:496
static BOOLEAN AtapAtapiTestUnitReady(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:891
static const IDE_REG AtapChannelBaseArray[]
Definition: hwide.c:25
BOOLEAN AtaInit(_Out_ PUCHAR DetectedCount)
Definition: hwide.c:1280
static VOID AtapIssuePacketCommand(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ PATA_DEVICE_REQUEST Request)
Definition: hwide.c:398
static BOOLEAN AtapInitDevice(_In_ PHW_DEVICE_UNIT DeviceUnit, _In_ ATA_DEVICE_CLASS DeviceClass)
Definition: hwide.c:1181
BOOLEAN AtaReadLogicalSectors(_In_ PDEVICE_UNIT DeviceUnit, _In_ ULONG64 SectorNumber, _In_ ULONG SectorCount, _Out_writes_bytes_all_(SectorCount *DeviceUnit->SectorSize) PVOID Buffer)
Definition: hwide.c:1230
static ATA_DEVICE_CLASS AtapIdentifyDevice(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:788
static BOOLEAN AtapPerformSoftwareReset(_In_ PHW_DEVICE_UNIT DeviceUnit)
Definition: hwide.c:186
#define ATA_DEVICE_LBA
Definition: hwide.h:31
#define ATA_DEVICE_IS_NEC_CDR260
Definition: hwide.h:33
#define ATA_DEVICE_ATAPI
Definition: hwide.h:30
#define ATA_DEVICE_LBA48
Definition: hwide.h:32
#define ATA_STATUS_ERROR
Definition: hwidep.h:14
#define REQUEST_FLAG_AWAIT_CDB
Definition: hwidep.h:171
FORCEINLINE VOID AtaDevDefaultChsTranslation(_In_ PIDENTIFY_DEVICE_DATA IdentifyData, _Out_ PUSHORT Cylinders, _Out_ PUSHORT Heads, _Out_ PUSHORT SectorsPerTrack)
Definition: hwidep.h:290
#define ATA_IO_WAIT()
Definition: hwidep.h:39
FORCEINLINE ULONG AtaDevBytesPerLogicalSector(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:362
#define ATAPI_INT_REASON_STATUS_NEC
Definition: hwidep.h:62
#define REQUEST_FLAG_LBA48
Definition: hwidep.h:167
#define MAXIMUM_CDROM_SIZE
Definition: hwidep.h:67
enum _ATA_DEVICE_CLASS ATA_DEVICE_CLASS
struct _HW_DEVICE_UNIT * PHW_DEVICE_UNIT
#define ATA_WRITE_BLOCK_16(Port, Buffer, Count)
Definition: hwidep.h:83
FORCEINLINE BOOLEAN AtaDevIsIdentifyDataValid(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:201
#define ATA_MAX_LBA_48
Definition: hwidep.h:50
FORCEINLINE UCHAR AtaDevCurrentSectorsPerDrq(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:326
FORCEINLINE BOOLEAN AtaCommandUseLba48(_In_ ULONG64 SectorNumber, _In_ ULONG SectorCount)
Definition: hwidep.h:386
#define ATA_TIME_DRQ_ASSERT
150 us
Definition: hwidep.h:78
#define ATAPI_INT_REASON_IO
Definition: hwidep.h:59
#define ATAPI_INT_REASON_COD
Definition: hwidep.h:58
FORCEINLINE BOOLEAN AtaDevHas48BitAddressFeature(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:262
#define ATA_TIME_BUSY_RESET
10 s
Definition: hwidep.h:72
@ DEV_ATA
Definition: hwidep.h:100
@ DEV_ATAPI
Definition: hwidep.h:101
@ DEV_NONE
Definition: hwidep.h:102
FORCEINLINE ULONG64 AtaDevUserAddressableSectors48Bit(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:253
#define ATA_TIME_BUSY_POLL
5 s
Definition: hwidep.h:70
#define REQUEST_FLAG_READ_COMMAND
Definition: hwidep.h:172
#define REQUEST_FLAG_IDENTIFY_COMMAND
Definition: hwidep.h:173
#define ATA_TIME_BUSY_ENUM
1 ms
Definition: hwidep.h:71
FORCEINLINE BOOLEAN AtaDevHasLbaTranslation(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:235
#define ATAPI_INT_REASON_STATUS
Definition: hwidep.h:63
#define REQUEST_FLAG_READ_WRITE_MULTIPLE
Definition: hwidep.h:168
#define ATAPI_INT_REASON_MASK
Definition: hwidep.h:60
#define ATA_STATUS_RESET
Definition: hwidep.h:15
FORCEINLINE ULONG AtaDevUserAddressableSectors28Bit(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:244
FORCEINLINE UCHAR AtaDevMaximumSectorsPerDrq(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:346
#define ATA_MAX_LBA_28
Definition: hwidep.h:49
#define REQUEST_FLAG_PACKET_COMMAND
Definition: hwidep.h:169
#define CHANNEL_MAX_DEVICES
Definition: hwidep.h:24
#define ATA_TIME_DRQ_CLEAR
10 ms
Definition: hwidep.h:74
ULONG_PTR IDE_REG
Definition: hwidep.h:46
#define IDE_FEATURE_PIO
Definition: hwidep.h:52
#define ATA_WRITE(Port, Value)
Definition: hwidep.h:80
#define ATAPI_INT_REASON_AWAIT_CDB
Definition: hwidep.h:64
#define ATA_READ_BLOCK_16(Port, Buffer, Count)
Definition: hwidep.h:92
#define IDE_DC_ALWAYS
Definition: hwidep.h:54
#define ATA_TIME_RESET_SELECT
2 s
Definition: hwidep.h:73
#define DEV_SLAVE(DeviceNumber)
Definition: hwidep.h:25
#define ATA_READ_BLOCK_32(Port, Buffer, Count)
Definition: hwidep.h:95
#define ATAPI_INT_REASON_DATA_IN
Definition: hwidep.h:65
#define ATA_TIME_BUSY_SELECT
20 ms
Definition: hwidep.h:69
FORCEINLINE BOOLEAN AtaDevIsCurrentGeometryValid(_In_ PIDENTIFY_DEVICE_DATA IdentifyData)
Definition: hwidep.h:277
#define REQUEST_FLAG_SET_DEVICE_REGISTER
Definition: hwidep.h:170
FORCEINLINE VOID AtaDevCurrentChsTranslation(_In_ PIDENTIFY_DEVICE_DATA IdentifyData, _Out_ PUSHORT Cylinders, _Out_ PUSHORT Heads, _Out_ PUSHORT SectorsPerTrack)
Definition: hwidep.h:308
#define ATA_STATUS_PENDING
Definition: hwidep.h:13
#define ATA_STATUS_SUCCESS
Definition: hwidep.h:12
#define ATA_STATUS_RETRY
Definition: hwidep.h:16
#define ATA_WRITE_BLOCK_32(Port, Buffer, Count)
Definition: hwidep.h:86
#define TAG_ATA_DEVICE
Definition: hwidep.h:10
#define ATA_READ(Port)
Definition: hwidep.h:89
FORCEINLINE UCHAR AtaDevCdbSizeInWords(_In_ PIDENTIFY_PACKET_DATA IdentifyPacketData)
Definition: hwidep.h:226
#define IDE_DRIVE_SELECT
Definition: hwidep.h:56
#define ASSERT(a)
Definition: mode.c:44
unsigned __int64 * PULONG64
Definition: imports.h:198
unsigned __int64 ULONG64
Definition: imports.h:198
#define min(a, b)
Definition: monoChain.cc:55
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _Out_writes_bytes_all_(s)
Definition: no_sal2.h:194
#define _In_range_(l, h)
Definition: no_sal2.h:368
ULONG SectorCount
Definition: part_xbox.c:31
VOID StallExecutionProcessor(ULONG Microseconds)
Definition: pchw.c:60
unsigned short USHORT
Definition: pedump.c:61
static ULONG Timeout
Definition: ping.c:61
#define __fallthrough
Definition: sal_old.h:314
#define SERVICE_ACTION_READ_CAPACITY16
Definition: scsi.h:474
#define READ_TOC_FORMAT_SESSION
Definition: scsi.h:178
#define SCSIOP_SERVICE_ACTION_IN16
Definition: scsi.h:368
#define TRACE(s)
Definition: solgame.cpp:4
Definition: shell.h:41
UCHAR Command
Definition: hwidep.h:147
UCHAR DriveSelect
Definition: hwidep.h:146
struct _ATA_TASKFILE::@186 Data[2]
Data structure for the ATA device.
Definition: hwide.h:12
ULONG Cylinders
Definition: hwide.h:14
ULONG SectorSize
Definition: hwide.h:23
ULONG SectorsPerTrack
Definition: hwide.h:20
ULONG64 TotalSectors
Definition: hwide.h:26
ULONG Flags
Definition: hwide.h:29
ULONG Heads
Definition: hwide.h:17
UCHAR DeviceNumber
Definition: hwidep.h:188
DEVICE_UNIT P
Definition: hwidep.h:181
UCHAR DeviceSelect
Definition: hwidep.h:189
IDE_REGISTERS Registers
Definition: hwidep.h:183
IDE_REG Data
Definition: hwidep.h:107
IDE_REG Status
Definition: hwidep.h:135
IDE_REG ByteCountHigh
Definition: hwidep.h:128
IDE_REG ByteCountLow
Definition: hwidep.h:122
UCHAR AdditionalSenseCode
Definition: cdrw_hw.h:1175
UCHAR AdditionalSenseCodeQualifier
Definition: cdrw_hw.h:1176
UCHAR SenseKey
Definition: cdrw_hw.h:1167
#define max(a, b)
Definition: svc.c:63
#define MAXULONG
Definition: typedefs.h:251
uint32_t * PULONG
Definition: typedefs.h:59
void * PVOID
Definition: typedefs.h:50
uint16_t * PUSHORT
Definition: typedefs.h:56
#define RtlCopyMemory(Destination, Source, Length)
Definition: typedefs.h:263
#define RtlZeroMemory(Destination, Length)
Definition: typedefs.h:262
uint32_t ULONG_PTR
Definition: typedefs.h:65
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
_In_ WDFREQUEST Request
Definition: wdfdevice.h:547
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_In_ ULONG SectorSize
Definition: halfuncs.h:291
_In_ ULONG _In_ ULONG SectorsPerTrack
Definition: iofuncs.h:2071
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _In_ LARGE_INTEGER ByteCount
Definition: iotypes.h:1099
#define RtlUlonglongByteSwap(_x)
Definition: rtlfuncs.h:3216
#define RtlUshortByteSwap(_x)
Definition: rtlfuncs.h:3214
unsigned char UCHAR
Definition: xmlstorage.h:181