ReactOS 0.4.16-dev-2633-g8dc9e50
legide.c
Go to the documentation of this file.
1/*
2 * PROJECT: Legacy PATA Bus Enumerator Driver
3 * LICENSE: MIT (https://spdx.org/licenses/MIT)
4 * PURPOSE: Main file
5 * COPYRIGHT: Copyright 2026 Dmitry Borisov <di.sean@protonmail.com>
6 */
7
8/*
9 * This driver detects non-PnP PATA controllers in the system.
10 * The legacy PATA device detection should be done after PCI bus enumeration,
11 * therefore this logic is implemented in a separate kernel-mode driver.
12 */
13
14/* INCLUDES *******************************************************************/
15
16#include <ntddk.h>
17#include <ide.h>
18#include <ata.h>
19#include <scsi.h>
21
22#define NDEBUG
23#include <debug.h>
24
25/* GLOBALS ********************************************************************/
26
27#define ATAPORT_TAG 'PedI'
28
29#define IDE_DRIVE_SELECT 0xA0
30
31#define ATA_READ(Port) READ_PORT_UCHAR((Port))
32#define ATA_WRITE(Port, Value) WRITE_PORT_UCHAR((Port), (Value))
33#define ATA_IO_WAIT() KeStallExecutionProcessor(1)
34
35#define ATA_TIME_BUSY_SELECT 3000 // 30 ms
36#define ATA_TIME_BUSY_IDENTIFY 500000 // 5 s
37#define ATA_TIME_DRQ_CLEAR 1000 // 10 ms
38#define ATA_TIME_RESET_SELECT 200000 // 2 s
39#define ATA_TIME_BUSY_RESET 1000000 // 10 s
40
41typedef struct _ATA_LEGACY_CHANNEL
42{
46
47CODE_SEG("INIT")
48DRIVER_INITIALIZE DriverEntry;
49
50/* FUNCTIONS ******************************************************************/
51
52static
53CODE_SEG("INIT")
56 _In_ PIDE_REGISTERS Registers,
60{
61 UCHAR IdeStatus;
62 ULONG i;
63
64 for (i = 0; i < Timeout; ++i)
65 {
66 IdeStatus = ATA_READ(Registers->Status);
67 if ((IdeStatus & Mask) == Value)
68 break;
69
70 if (IdeStatus == 0xFF)
71 break;
72
74 }
75
76 return IdeStatus;
77}
78
79static
80CODE_SEG("INIT")
81VOID
83 _In_ PIDE_REGISTERS Registers)
84{
85 USHORT Buffer[256];
86
88}
89
90static
91CODE_SEG("INIT")
94 _In_ PIDE_REGISTERS Registers,
97{
98 UCHAR IdeStatus;
99
100 /* Select the device */
101 ATA_WRITE(Registers->Device, ((DeviceNumber << 4) | IDE_DRIVE_SELECT));
102 ATA_IO_WAIT();
103 IdeStatus = AtaWait(Registers, ATA_TIME_BUSY_SELECT, IDE_STATUS_BUSY, 0);
104 if (IdeStatus & IDE_STATUS_BUSY)
105 {
106 DPRINT("Timeout, status 0x%02x\n", IdeStatus);
107 return FALSE;
108 }
109
110 ATA_WRITE(Registers->Features, 0);
111 ATA_WRITE(Registers->SectorCount, 0);
112 ATA_WRITE(Registers->LbaLow, 0);
113 ATA_WRITE(Registers->LbaMid, 0);
114 ATA_WRITE(Registers->LbaHigh, 0);
115 ATA_WRITE(Registers->Command, Command);
116
117 /* Need to wait for a valid status */
118 ATA_IO_WAIT();
119
120 /* Now wait for busy to clear */
121 IdeStatus = AtaWait(Registers, ATA_TIME_BUSY_IDENTIFY, IDE_STATUS_BUSY, 0);
122 if (IdeStatus & IDE_STATUS_BUSY)
123 {
124 DPRINT("Timeout, status 0x%02x\n", IdeStatus);
125 return FALSE;
126 }
127 if (IdeStatus & ((IDE_STATUS_ERROR | IDE_STATUS_DEVICE_FAULT)))
128 {
129 DPRINT("Command 0x%02x aborted, status 0x%02x, error 0x%02x\n",
130 Command,
131 IdeStatus,
132 ATA_READ(Registers->Error));
133 return FALSE;
134 }
135 if (!(IdeStatus & IDE_STATUS_DRQ))
136 {
137 DPRINT1("DRQ not set, status 0x%02x\n", IdeStatus);
138 return FALSE;
139 }
140
141 /* Complete the data transfer */
143
144 /* All data has been transferred, wait for DRQ to clear */
145 IdeStatus = AtaWait(Registers,
148 0);
149 if (IdeStatus & (IDE_STATUS_BUSY | IDE_STATUS_DRQ))
150 {
151 DPRINT1("DRQ not cleared, status 0x%02x\n", IdeStatus);
152 return FALSE;
153 }
154
155 return TRUE;
156}
157
158static
159CODE_SEG("INIT")
162 _In_ PIDE_REGISTERS Registers,
164{
165 UCHAR IdeStatus;
166 ULONG i;
167
168 /* Perform a software reset */
169 ATA_WRITE(Registers->Control, IDE_DC_RESET_CONTROLLER);
171 ATA_WRITE(Registers->Control, IDE_DC_DISABLE_INTERRUPTS);
173
174 /* The reset will cause the master device to be selected */
175 if ((DeviceNumber & 1) != 0)
176 {
177 for (i = ATA_TIME_RESET_SELECT; i > 0; i--)
178 {
179 /* Select the device again */
180 ATA_WRITE(Registers->Device, ((DeviceNumber << 4) | IDE_DRIVE_SELECT));
181 ATA_IO_WAIT();
182
183 /* Check whether the selection was successful */
184 ATA_WRITE(Registers->ByteCountLow, 0xAA);
185 ATA_WRITE(Registers->ByteCountLow, 0x55);
186 ATA_WRITE(Registers->ByteCountLow, 0xAA);
187 if (ATA_READ(Registers->ByteCountLow) == 0xAA)
188 break;
189
191 }
192 if (i == 0)
193 {
194 DPRINT("Selection timeout\n");
195 return FALSE;
196 }
197 }
198
199 /* Now wait for busy to clear */
200 IdeStatus = AtaWait(Registers, ATA_TIME_BUSY_RESET, IDE_STATUS_BUSY, 0);
201 if (IdeStatus & IDE_STATUS_BUSY)
202 {
203 DPRINT1("Timeout, status 0x%02x\n", IdeStatus);
204 return FALSE;
205 }
206
207 return FALSE;
208}
209
210static
211CODE_SEG("INIT")
214 _In_ PIDE_REGISTERS Registers,
216{
217 UCHAR IdeStatus, SignatureLow, SignatureHigh;
218
219 /* Select the device */
220 ATA_WRITE(Registers->Device, ((DeviceNumber << 4) | IDE_DRIVE_SELECT));
221 ATA_IO_WAIT();
222
223 /* Do a quick check first */
224 IdeStatus = ATA_READ(Registers->Status);
225 if (IdeStatus == 0xFF || IdeStatus == 0x7F)
226 return FALSE;
227
228 /* Look at controller */
229 ATA_WRITE(Registers->ByteCountLow, 0x55);
230 ATA_WRITE(Registers->ByteCountLow, 0xAA);
231 ATA_WRITE(Registers->ByteCountLow, 0x55);
232 if (ATA_READ(Registers->ByteCountLow) != 0x55)
233 return FALSE;
234 ATA_WRITE(Registers->ByteCountHigh, 0xAA);
235 ATA_WRITE(Registers->ByteCountHigh, 0x55);
236 ATA_WRITE(Registers->ByteCountHigh, 0xAA);
237 if (ATA_READ(Registers->ByteCountHigh) != 0xAA)
238 return FALSE;
239
240 /* Wait for busy to clear */
241 IdeStatus = AtaWait(Registers, ATA_TIME_BUSY_SELECT, IDE_STATUS_BUSY, 0);
242 if (IdeStatus & IDE_STATUS_BUSY)
243 {
244 DPRINT1("Device is busy, attempting to recover %02x\n", IdeStatus);
245
247 {
248 DPRINT1("Failed to reset device %02x\n", ATA_READ(Registers->Status));
249 return FALSE;
250 }
251 }
252
253 /* Check for ATA */
255 return TRUE;
256
257 SignatureLow = ATA_READ(Registers->SignatureLow);
258 SignatureHigh = ATA_READ(Registers->SignatureHigh);
259
260 DPRINT("SL = 0x%02x, SH = 0x%02x\n", SignatureLow, SignatureHigh);
261
262 /* Check for ATAPI */
263 if (SignatureLow == 0x14 && SignatureHigh == 0xEB)
264 return TRUE;
265
266 /*
267 * ATAPI devices abort the IDENTIFY command and return an ATAPI signature
268 * in the task file registers. However the NEC CDR-260 drive doesn't return
269 * the correct signature, but instead shows up with zeroes.
270 * This drive also reports an ATA signature after device reset.
271 * To overcome this behavior, we try the ATAPI IDENTIFY command.
272 * It should be successfully completed or failed (aborted or time-out).
273 */
275}
276
277static
278CODE_SEG("INIT")
281 _In_ PIDE_REGISTERS Registers)
282{
283 ULONG i;
284
285 /* Check for the PC-98 on-board IDE interface */
286 if (IsNEC_98)
287 return (ATA_READ((PUCHAR)0x432) != 0xFF);
288
289 /*
290 * The only reliable way to detect the legacy IDE channel
291 * is to check for devices attached to the bus.
292 */
293 for (i = 0; i < MAX_IDE_DEVICE; ++i)
294 {
295 if (AtaLegacyFindAtaDevice(Registers, i))
296 {
297 DPRINT("Found IDE device\n");
298 return TRUE;
299 }
300 }
301
302 return FALSE;
303}
304
305static
306CODE_SEG("INIT")
307VOID
310 _In_ ULONG IoBase,
312{
314 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
316 Descriptor->u.Port.Start.u.LowPart = IoBase;
317 Descriptor->u.Port.Length = Length;
318}
319
320static
321CODE_SEG("INIT")
322VOID
326{
328 Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
330 Descriptor->u.Interrupt.Level = Level;
331 Descriptor->u.Interrupt.Vector = Level;
332 Descriptor->u.Interrupt.Affinity = (KAFFINITY)-1;
333}
334
335static
336CODE_SEG("INIT")
339 _In_ PATA_LEGACY_CHANNEL LegacyChannel,
341{
344 ULONG i;
345
346 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
347
348 if (IsNEC_98)
349 {
350 if (ConfigInfo->AtDiskPrimaryAddressClaimed || ConfigInfo->AtDiskSecondaryAddressClaimed)
351 return FALSE;
352
353#define CHANNEL_PC98_RESOURCE_COUNT 12
354 /*
355 * Make a resource list for the internal IDE interface:
356 *
357 * [ShareDisposition 1, Flags 11] IO: Start 0:640, Len 1
358 * [ShareDisposition 1, Flags 11] IO: Start 0:74C, Len 1
359 * [ShareDisposition 1, Flags 1] INT: Lev 9 Vec 9 Aff FFFFFFFF
360 * [ShareDisposition 1, Flags 11] IO: Start 0:642, Len 1
361 * [ShareDisposition 1, Flags 11] IO: Start 0:644, Len 1
362 * [ShareDisposition 1, Flags 11] IO: Start 0:646, Len 1
363 * [ShareDisposition 1, Flags 11] IO: Start 0:648, Len 1
364 * [ShareDisposition 1, Flags 11] IO: Start 0:64A, Len 1
365 * [ShareDisposition 1, Flags 11] IO: Start 0:64C, Len 1
366 * [ShareDisposition 1, Flags 11] IO: Start 0:64E, Len 1
367 * [ShareDisposition 1, Flags 11] IO: Start 0:432, Len 2
368 * [ShareDisposition 1, Flags 11] IO: Start 0:435, Len 1
369 */
373 for (i = 0; i < 7; ++i)
374 {
375 AtaLegacyMakePortResource(Descriptor++, 0x642 + i * 2, 1);
376 }
379 }
380 else
381 {
382 if (LegacyChannel->IoBase == 0x1F0 && ConfigInfo->AtDiskPrimaryAddressClaimed)
383 return FALSE;
384
385 if (LegacyChannel->IoBase == 0x170 && ConfigInfo->AtDiskSecondaryAddressClaimed)
386 return FALSE;
387
388#define CHANNEL_PCAT_RESOURCE_COUNT 3
389 /*
390 * For example, the following resource list is created for the primary IDE channel:
391 *
392 * [ShareDisposition 1, Flags 11] IO: Start 0:1F0, Len 8
393 * [ShareDisposition 1, Flags 11] IO: Start 0:3F6, Len 1
394 * [ShareDisposition 1, Flags 1] INT: Lev A Vec A Aff FFFFFFFF
395 */
396 AtaLegacyMakePortResource(Descriptor++, LegacyChannel->IoBase, 8);
397 AtaLegacyMakePortResource(Descriptor++, LegacyChannel->IoBase + 0x206, 1);
398 AtaLegacyMakeInterruptResource(Descriptor++, LegacyChannel->Irq);
399 }
400
401 return TRUE;
402}
403
404static
405CODE_SEG("INIT")
406VOID
409 _In_ PUCHAR CommandPortBase,
410 _In_ PUCHAR ControlPortBase)
411{
413 KIRQL Irql;
414
415 Descriptor = &ResourceList->List[0].PartialResourceList.PartialDescriptors[0];
416
417 /* Move on to the interrupt descriptor */
418 if (IsNEC_98)
419 {
420 Descriptor += 2;
421 }
422 else
423 {
424 Descriptor->u.Port.Start.QuadPart = (ULONG_PTR)CommandPortBase;
425 ++Descriptor;
426
427 Descriptor->u.Port.Start.QuadPart = (ULONG_PTR)ControlPortBase;
428 ++Descriptor;
429 }
431
432 Descriptor->u.Interrupt.Vector = HalGetInterruptVector(Isa,
433 0,
434 Descriptor->u.Interrupt.Level,
435 Descriptor->u.Interrupt.Vector,
436 &Irql,
437 &Descriptor->u.Interrupt.Affinity);
438 Descriptor->u.Interrupt.Level = Irql;
439}
440
441static
442CODE_SEG("INIT")
443PVOID
447 _Out_ PBOOLEAN IsAddressMmio)
448{
452
454 AddressSpace = 1; // I/O space
456 if (!Success)
457 return NULL;
458
459 /* I/O space */
460 if (AddressSpace != 0)
461 {
462 *IsAddressMmio = FALSE;
464 }
465 else
466 {
467 *IsAddressMmio = TRUE;
469 }
470}
471
472static
473CODE_SEG("INIT")
478 _In_ ULONG ResourceListSize)
479{
481 BOOLEAN ConflictDetected;
482
485 ResourceListSize,
486 NULL,
487 NULL,
488 0,
489 &ConflictDetected);
490 /* HACK: We really need to fix a number of resource bugs in the kernel */
491 if (IsNEC_98)
492 return TRUE;
493
494 if (!NT_SUCCESS(Status) || ConflictDetected)
495 return FALSE;
496
497 return TRUE;
498}
499
500static
501CODE_SEG("INIT")
502VOID
505{
506 BOOLEAN Dummy;
507
509}
510
511static
512CODE_SEG("INIT")
516 _In_ PPCIIDEX_LEGACY_CONTROLLER_INTERFACE ControllerInferface,
517 _In_ PATA_LEGACY_CHANNEL LegacyChannel,
519 _In_ ULONG ResourceListSize)
520{
521 BOOLEAN IsAddressMmio[2];
523 PVOID ControllerContext;
524 IDE_REGISTERS Registers;
526 ULONG Spare;
527
528 DPRINT("IDE Channel IO %lx, Irq %lu\n", LegacyChannel->IoBase, LegacyChannel->Irq);
529
530 if (!AtaLegacyChannelBuildResources(LegacyChannel, ResourceList))
531 {
532 DPRINT("Failed to build the resource list\n");
533 return FALSE;
534 }
535
537 {
538 DPRINT("Failed to claim resources\n");
539 return FALSE;
540 }
541
543 IsAddressMmio[0] = FALSE;
544 IsAddressMmio[1] = FALSE;
545
546 if (IsNEC_98)
547 {
548 /* No translation required for the C-Bus I/O space */
549 Registers.Data = (PVOID)0x640;
550 Registers.Control = (PVOID)0x74C;
551
552 Spare = 2;
553 }
554 else
555 {
556 Registers.Data = AtaLegacyTranslateBusAddress(LegacyChannel->IoBase,
557 8,
558 &IsAddressMmio[0]);
559 if (!Registers.Data)
560 {
561 DPRINT("Failed to map command port\n");
562
564 goto ReleaseResources;
565 }
566
567 Registers.Control = AtaLegacyTranslateBusAddress(LegacyChannel->IoBase + 0x206,
568 1,
569 &IsAddressMmio[1]);
570 if (!Registers.Control)
571 {
572 DPRINT("Failed to map control port\n");
573
575 goto ReleaseResources;
576 }
577
578 Spare = 1;
579 }
580 Registers.Error = (PVOID)((ULONG_PTR)Registers.Data + 1 * Spare);
581 Registers.SectorCount = (PVOID)((ULONG_PTR)Registers.Data + 2 * Spare);
582 Registers.LbaLow = (PVOID)((ULONG_PTR)Registers.Data + 3 * Spare);
583 Registers.LbaMid = (PVOID)((ULONG_PTR)Registers.Data + 4 * Spare);
584 Registers.LbaHigh = (PVOID)((ULONG_PTR)Registers.Data + 5 * Spare);
585 Registers.Device = (PVOID)((ULONG_PTR)Registers.Data + 6 * Spare);
586 Registers.Status = (PVOID)((ULONG_PTR)Registers.Data + 7 * Spare);
587
588 if (!AtaLegacyChannelPresent(&Registers))
589 {
590 DPRINT("No IDE devices found\n");
592 }
593
594ReleaseResources:
596
597 if (!NT_SUCCESS(Status))
598 goto Cleanup;
599
603 (ULONG)-1,
604 (ULONG)-1,
606 NULL,
607 0,
609 if (!NT_SUCCESS(Status))
610 {
611 DPRINT("IoReportDetectedDevice() failed with status 0x%lx\n", Status);
612 goto Cleanup;
613 }
614
615 if (ControllerInferface->Version != PCIIDEX_INTERFACE_VERSION)
616 {
617 /* ReactOS-specific: Retrieve the interface for legacy device detection */
619 NULL,
620 (PVOID)ControllerInferface,
622 if (!NT_SUCCESS(Status))
623 {
624 DPRINT1("Failed to register the legacy channel 0x%lx, status 0x%lx\n",
625 LegacyChannel->IoBase, Status);
626 goto Cleanup;
627 }
628
629 if (ControllerInferface->Version != PCIIDEX_INTERFACE_VERSION)
630 {
631 DPRINT1("Unknown interface version 0x%lx\n", ControllerInferface->Version);
633 goto Cleanup;
634 }
635 }
636
637 Status = ControllerInferface->AddDevice(DriverObject, PhysicalDeviceObject, &ControllerContext);
638 if (!NT_SUCCESS(Status))
639 {
640 DPRINT1("Failed to add the legacy channel 0x%lx, status 0x%lx\n",
641 LegacyChannel->IoBase, Status);
642 goto Cleanup;
643 }
644
646
647 Status = ControllerInferface->StartDevice(ControllerContext, ResourceList);
648 if (!NT_SUCCESS(Status))
649 {
650 DPRINT1("Failed to start the legacy channel 0x%lx, status 0x%lx\n",
651 LegacyChannel->IoBase, Status);
652
653 ControllerInferface->RemoveDevice(ControllerContext);
654 }
655
656Cleanup:
657 if (IsAddressMmio[0] && Registers.Data)
658 {
659 MmUnmapIoSpace(Registers.Data, 8);
660 }
661
662 if (IsAddressMmio[1] && Registers.Control)
663 {
664 MmUnmapIoSpace(Registers.Control, 1);
665 }
666
667 return NT_SUCCESS(Status);
668}
669
670static
671CODE_SEG("INIT")
677{
679
680 PAGED_CODE();
681
683 KeyName,
685 RootKey,
686 NULL);
687 return ZwOpenKey(KeyHandle, KEY_ALL_ACCESS, &ObjectAttributes);
688}
689
690static
691CODE_SEG("INIT")
695{
697 ULONG KeyValue;
698 BOOLEAN PerformDetection;
699 HANDLE SoftKeyHandle, ParamsKeyHandle;
701 UNICODE_STRING ParametersKeyName = RTL_CONSTANT_STRING(L"Parameters");
702 static const WCHAR MapperKeyPath[] =
703 L"\\Registry\\Machine\\System\\CurrentControlSet\\Control\\Pnp";
704
705 PAGED_CODE();
706
707 /*
708 * Read the firmware mapper key. If the firmware mapper is disabled,
709 * it is the responsibility of PnP drivers (ACPI, PCI, and others)
710 * to detect and enumerate IDE channels.
711 */
712 KeyValue = 0;
715 QueryTable[0].Name = L"DisableFirmwareMapper";
716 QueryTable[0].EntryContext = &KeyValue;
718 if (NT_SUCCESS(Status) && (KeyValue != 0))
719 {
720 DPRINT("Skipping legacy detection on a PnP system\n");
721 return FALSE;
722 }
723
724 /* Open the driver's software key */
725 Status = AtaOpenRegistryKey(&SoftKeyHandle, NULL, RegistryPath);
726 if (!NT_SUCCESS(Status))
727 {
728 DPRINT1("Failed to open the '%wZ' key, status 0x%lx\n", RegistryPath, Status);
729 return FALSE;
730 }
731
732 /* Open the 'Parameters' key */
733 Status = AtaOpenRegistryKey(&ParamsKeyHandle, SoftKeyHandle, &ParametersKeyName);
734 if (!NT_SUCCESS(Status))
735 {
736 DPRINT1("Failed to open the 'Parameters' key, status 0x%lx\n", Status);
737
738 ZwClose(SoftKeyHandle);
739 return FALSE;
740 }
741
742 /* Check whether it is the first time we detect IDE channels */
743 KeyValue = 0;
746 QueryTable[0].Name = L"LegacyDetection";
747 QueryTable[0].EntryContext = &KeyValue;
749 (PWSTR)ParamsKeyHandle,
751 NULL,
752 NULL);
753 PerformDetection = (KeyValue != 0);
754
755 /* Do not detect devices again on subsequent boots after driver installation */
756 if (PerformDetection)
757 {
758 KeyValue = 0;
760 (PWSTR)ParamsKeyHandle,
761 L"LegacyDetection",
762 REG_DWORD,
763 &KeyValue,
764 sizeof(KeyValue));
765 }
766
767 ZwClose(ParamsKeyHandle);
768 ZwClose(SoftKeyHandle);
769
770 return PerformDetection;
771}
772
773CODE_SEG("INIT")
775NTAPI
779{
780 PCIIDEX_LEGACY_CONTROLLER_INTERFACE ControllerInferface = { 0 };
781 ATA_LEGACY_CHANNEL LegacyChannel[4 + 1] = { 0 };
783 ULONG i, ListSize, ResourceCount;
785
787 return STATUS_CANCELLED;
788
789 if (IsNEC_98)
790 {
791 /* Internal IDE interface */
792 LegacyChannel[0].IoBase = 0x640;
793 LegacyChannel[0].Irq = 9;
794
796 }
797 else
798 {
799 /* Primary IDE channel */
800 LegacyChannel[0].IoBase = 0x1F0;
801 LegacyChannel[0].Irq = 14;
802
803 /* Secondary IDE channel */
804 LegacyChannel[1].IoBase = 0x170;
805 LegacyChannel[1].Irq = 15;
806
807 /* Tertiary IDE channel */
808 LegacyChannel[2].IoBase = 0x1E8;
809 LegacyChannel[2].Irq = 11;
810
811 /* Quaternary IDE channel */
812 LegacyChannel[3].IoBase = 0x168;
813 LegacyChannel[3].Irq = 10;
814
816 }
817
818 ListSize = FIELD_OFFSET(CM_RESOURCE_LIST, List[0].PartialResourceList.PartialDescriptors) +
820
822 if (!ResourceList)
823 {
824 DPRINT1("Failed to allocate the resource list\n");
826 }
827 ResourceList->Count = 1;
828 ResourceList->List[0].InterfaceType = Isa;
829 ResourceList->List[0].BusNumber = 0;
830 ResourceList->List[0].PartialResourceList.Version = 1;
831 ResourceList->List[0].PartialResourceList.Revision = 1;
832 ResourceList->List[0].PartialResourceList.Count = ResourceCount;
833
835
836 for (i = 0; LegacyChannel[i].IoBase != 0; ++i)
837 {
839 &ControllerInferface,
840 &LegacyChannel[i],
842 ListSize))
843 {
845 }
846 }
847
849 return Status;
850}
#define PAGED_CODE()
#define CODE_SEG(...)
#define RTL_NUMBER_OF(x)
Definition: RtlRegistry.c:12
unsigned char BOOLEAN
Definition: actypes.h:127
#define IDE_STATUS_DEVICE_FAULT
Definition: ata.h:624
#define PCIIDEX_INTERFACE_VERSION
Definition: ata_shared.h:12
#define PCIIDEX_GET_CONTROLLER_INTERFACE_SIGNATURE
Definition: ata_shared.h:481
#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_DC_DISABLE_INTERRUPTS
Definition: atapi.h:145
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
#define READ_PORT_BUFFER_USHORT(port, buffer, count)
Definition: hardware.h:31
PDEVICE_OBJECT PhysicalDeviceObject
Definition: btrfs_drv.h:1157
Definition: bufpool.h:45
_In_ PCHAR _In_ ULONG DeviceNumber
Definition: classpnp.h:1230
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_Out_ PKIRQL Irql
Definition: csq.h:179
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
#define RTL_CONSTANT_STRING(s)
Definition: combase.c:35
ULONG_PTR KAFFINITY
Definition: compat.h:85
static const WCHAR Cleanup[]
Definition: register.c:80
#define L(x)
Definition: resources.c:13
#define ULONG_PTR
Definition: config.h:101
NTHALAPI ULONG NTAPI HalGetInterruptVector(INTERFACE_TYPE, ULONG, ULONG, ULONG, PKIRQL, PKAFFINITY)
UCHAR KIRQL
Definition: env_spec_w32.h:591
#define PagedPool
Definition: env_spec_w32.h:308
@ Success
Definition: eventcreate.c:712
unsigned int Mask
Definition: fpcontrol.c:82
Status
Definition: gdiplustypes.h:25
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
BOOLEAN NTAPI HalTranslateBusAddress(IN INTERFACE_TYPE InterfaceType, IN ULONG BusNumber, IN PHYSICAL_ADDRESS BusAddress, IN OUT PULONG AddressSpace, OUT PPHYSICAL_ADDRESS TranslatedAddress)
Definition: bus.c:140
#define MAX_IDE_DEVICE
Definition: ide.h:32
static ULONG ResourceCount
Definition: inbv.c:50
PCONFIGURATION_INFORMATION NTAPI IoGetConfigurationInformation(VOID)
Returns a pointer to the I/O manager's global configuration information structure.
Definition: iorsrce.c:998
VOID NTAPI MmUnmapIoSpace(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes)
Definition: iosup.c:193
PVOID NTAPI MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: iosup.c:47
static NTSTATUS AtaOpenRegistryKey(_Out_ PHANDLE KeyHandle, _In_ HANDLE RootKey, _In_ PUNICODE_STRING KeyName)
Definition: legide.c:673
#define ATA_IO_WAIT()
Definition: legide.c:33
static VOID AtaLegacyMakePortResource(_Out_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, _In_ ULONG IoBase, _In_ ULONG Length)
Definition: legide.c:308
static BOOLEAN AtaLegacyChannelBuildResources(_In_ PATA_LEGACY_CHANNEL LegacyChannel, _Inout_ PCM_RESOURCE_LIST ResourceList)
Definition: legide.c:338
DRIVER_INITIALIZE DriverEntry
Definition: legide.c:48
static BOOLEAN AtaLegacyFindAtaDevice(_In_ PIDE_REGISTERS Registers, _In_ ULONG DeviceNumber)
Definition: legide.c:213
static BOOLEAN AtaLegacyChannelPresent(_In_ PIDE_REGISTERS Registers)
Definition: legide.c:280
static BOOLEAN AtaLegacyShouldDetectChannels(_In_ PUNICODE_STRING RegistryPath)
Definition: legide.c:693
#define ATA_TIME_BUSY_RESET
Definition: legide.c:39
static BOOLEAN AtaLegacyDetectChannel(_In_ PDRIVER_OBJECT DriverObject, _In_ PPCIIDEX_LEGACY_CONTROLLER_INTERFACE ControllerInferface, _In_ PATA_LEGACY_CHANNEL LegacyChannel, _In_ PCM_RESOURCE_LIST ResourceList, _In_ ULONG ResourceListSize)
Definition: legide.c:514
#define CHANNEL_PC98_RESOURCE_COUNT
struct _ATA_LEGACY_CHANNEL ATA_LEGACY_CHANNEL
static UCHAR AtaWait(_In_ PIDE_REGISTERS Registers, _In_range_(>, 0) ULONG Timeout, _In_ UCHAR Mask, _In_ UCHAR Value)
Definition: legide.c:55
static BOOLEAN AtaLegacyPerformSoftwareReset(_In_ PIDE_REGISTERS Registers, _In_ ULONG DeviceNumber)
Definition: legide.c:161
static VOID AtaLegacyFetchIdentifyData(_In_ PIDE_REGISTERS Registers)
Definition: legide.c:82
static PVOID AtaLegacyTranslateBusAddress(_In_ ULONG Address, _In_ ULONG NumberOfBytes, _Out_ PBOOLEAN IsAddressMmio)
Definition: legide.c:444
#define ATA_TIME_DRQ_CLEAR
Definition: legide.c:37
static BOOLEAN AtaLegacyClaimHardwareResources(_In_ PDRIVER_OBJECT DriverObject, _In_ PCM_RESOURCE_LIST ResourceList, _In_ ULONG ResourceListSize)
Definition: legide.c:475
static VOID AtaLegacyMakeInterruptResource(_Out_ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor, _In_ ULONG Level)
Definition: legide.c:323
static VOID AtaLegacyChannelTranslateResources(_Inout_ PCM_RESOURCE_LIST ResourceList, _In_ PUCHAR CommandPortBase, _In_ PUCHAR ControlPortBase)
Definition: legide.c:407
#define ATA_WRITE(Port, Value)
Definition: legide.c:32
#define ATA_TIME_RESET_SELECT
Definition: legide.c:38
#define ATA_TIME_BUSY_IDENTIFY
Definition: legide.c:36
struct _ATA_LEGACY_CHANNEL * PATA_LEGACY_CHANNEL
static VOID AtaLegacyReleaseHardwareResources(_In_ PDRIVER_OBJECT DriverObject)
Definition: legide.c:503
#define ATAPORT_TAG
Definition: legide.c:27
#define ATA_TIME_BUSY_SELECT
Definition: legide.c:35
#define CHANNEL_PCAT_RESOURCE_COUNT
#define ATA_READ(Port)
Definition: legide.c:31
#define IDE_DRIVE_SELECT
Definition: legide.c:29
static BOOLEAN AtaLegacyIdentifyDevice(_In_ PIDE_REGISTERS Registers, _In_ ULONG DeviceNumber, _In_ UCHAR Command)
Definition: legide.c:93
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
static PVOID ExAllocatePoolZero(ULONG PoolType, SIZE_T NumberOfBytes, ULONG Tag)
Definition: precomp.h:45
#define KeStallExecutionProcessor(MicroSeconds)
Definition: precomp.h:27
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:106
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
#define CM_RESOURCE_PORT_IO
Definition: cmtypes.h:109
#define CM_RESOURCE_PORT_16_BIT_DECODE
Definition: cmtypes.h:112
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
_In_ PCWSTR _Inout_ _At_ QueryTable _Pre_unknown_ PRTL_QUERY_REGISTRY_TABLE QueryTable
Definition: rtlfuncs.h:4211
#define _Inout_
Definition: no_sal2.h:162
#define _Out_
Definition: no_sal2.h:160
#define _In_
Definition: no_sal2.h:158
#define _In_range_(l, h)
Definition: no_sal2.h:368
#define KEY_ALL_ACCESS
Definition: nt_native.h:1044
#define RTL_REGISTRY_ABSOLUTE
Definition: nt_native.h:161
#define RTL_QUERY_REGISTRY_REQUIRED
Definition: nt_native.h:132
#define RTL_QUERY_REGISTRY_DIRECT
Definition: nt_native.h:144
#define RTL_REGISTRY_HANDLE
Definition: nt_native.h:168
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
PVOID *typedef PHANDLE
Definition: ntsecpkg.h:455
#define STATUS_REVISION_MISMATCH
Definition: ntstatus.h:419
NTSTATUS NTAPI PciIdeXInitialize(_In_ PDRIVER_OBJECT DriverObject, _In_ PUNICODE_STRING RegistryPath, _In_ PCONTROLLER_PROPERTIES HwGetControllerProperties, _In_ ULONG ExtensionSize)
Definition: pciidex.c:514
short WCHAR
Definition: pedump.c:58
unsigned short USHORT
Definition: pedump.c:61
static WCHAR Address[46]
Definition: ping.c:68
static ULONG Timeout
Definition: ping.c:61
NTSTATUS NTAPI IoReportResourceForDetection(IN PDRIVER_OBJECT DriverObject, IN PCM_RESOURCE_LIST DriverList OPTIONAL, IN ULONG DriverListSize OPTIONAL, IN PDEVICE_OBJECT DeviceObject OPTIONAL, IN PCM_RESOURCE_LIST DeviceList OPTIONAL, IN ULONG DeviceListSize OPTIONAL, OUT PBOOLEAN ConflictDetected)
Definition: pnpreport.c:394
NTSTATUS NTAPI IoReportDetectedDevice(_In_ PDRIVER_OBJECT DriverObject, _In_ INTERFACE_TYPE LegacyBusType, _In_ ULONG BusNumber, _In_ ULONG SlotNumber, _In_opt_ PCM_RESOURCE_LIST ResourceList, _In_opt_ PIO_RESOURCE_REQUIREMENTS_LIST ResourceRequirements, _In_ BOOLEAN ResourceAssigned, _Inout_ PDEVICE_OBJECT *DeviceObject)
Definition: pnpreport.c:148
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
@ InterfaceTypeUndefined
Definition: restypes.h:120
@ Isa
Definition: restypes.h:122
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR CM_PARTIAL_RESOURCE_DESCRIPTOR
#define CmResourceTypePort
Definition: restypes.h:104
#define CM_RESOURCE_INTERRUPT_LATCHED
Definition: restypes.h:117
#define CmResourceTypeInterrupt
Definition: restypes.h:105
#define REG_DWORD
Definition: sdbapi.c:615
static PMEMKEY RootKey
Definition: registry.c:55
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_NOT_FOUND
Definition: shellext.h:72
#define DPRINT
Definition: sndvol32.h:73
Definition: shell.h:41
BOOLEAN AtDiskPrimaryAddressClaimed
Definition: iotypes.h:4485
BOOLEAN AtDiskSecondaryAddressClaimed
Definition: iotypes.h:4486
IDE_REG Error
Definition: hwidep.h:111
IDE_REG Control
Definition: hwidep.h:139
IDE_REG LbaLow
LBA bits 0-7, 24-31.
Definition: hwidep.h:118
IDE_REG LbaMid
LBA bits 8-15, 32-39.
Definition: hwidep.h:121
IDE_REG Data
Definition: hwidep.h:107
IDE_REG Status
Definition: hwidep.h:135
IDE_REG LbaHigh
LBA bits 16-23, 40-47.
Definition: hwidep.h:127
IDE_REG Device
Definition: hwidep.h:131
IDE_REG SectorCount
Definition: hwidep.h:115
struct _IO_RESOURCE_DESCRIPTOR::@2244::@2245 Port
union _IO_RESOURCE_DESCRIPTOR::@2244 u
Legacy detection interface with the PCIIDEX driver.
Definition: ata_shared.h:489
uint16_t * PWSTR
Definition: typedefs.h:56
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
unsigned char * PBOOLEAN
Definition: typedefs.h:53
#define NTAPI
Definition: typedefs.h:36
void * PVOID
Definition: typedefs.h:50
uint16_t * PUSHORT
Definition: typedefs.h:56
#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
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
#define STATUS_CANCELLED
Definition: udferr_usr.h:170
LONGLONG QuadPart
Definition: typedefs.h:114
_Must_inspect_result_ _In_ WDFDEVICE _In_ PCUNICODE_STRING KeyName
Definition: wdfdevice.h:2705
_Must_inspect_result_ _In_ PDRIVER_OBJECT _In_ PCUNICODE_STRING RegistryPath
Definition: wdfdriver.h:215
_Must_inspect_result_ _In_ PDRIVER_OBJECT DriverObject
Definition: wdfdriver.h:213
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_Must_inspect_result_ _In_ WDFIORESREQLIST _In_opt_ PWDF_OBJECT_ATTRIBUTES _Out_ WDFIORESLIST * ResourceList
Definition: wdfresource.h:309
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_Must_inspect_result_ _In_ WDFCMRESLIST List
Definition: wdfresource.h:550
NTSYSAPI NTSTATUS WINAPI RtlWriteRegistryValue(ULONG, PCWSTR, PCWSTR, ULONG, PVOID, ULONG)
NTSYSAPI NTSTATUS WINAPI RtlQueryRegistryValues(ULONG, PCWSTR, PRTL_QUERY_REGISTRY_TABLE, PVOID, PVOID)
_IRQL_requires_same_ typedef _In_ ULONG _In_ UCHAR Level
Definition: wmitypes.h:56
@ CmResourceShareDeviceExclusive
Definition: cmtypes.h:241
_In_ ULONG _In_ PHYSICAL_ADDRESS BusAddress
Definition: iofuncs.h:2273
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG _Out_ PPHYSICAL_ADDRESS TranslatedAddress
Definition: iofuncs.h:2275
_In_ ULONG _In_ PHYSICAL_ADDRESS _Inout_ PULONG AddressSpace
Definition: iofuncs.h:2274
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1036
#define IsNEC_98
Definition: ketypes.h:963
@ MmNonCached
Definition: mmtypes.h:129