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