2 * PROJECT: ReactOS PCI Bus Driver
3 * LICENSE: BSD - See COPYING.ARM in the top level directory
4 * FILE: drivers/bus/pci/init.c
5 * PURPOSE: Driver Initialization
6 * PROGRAMMERS: ReactOS Portable Systems Group
9 /* INCLUDES *******************************************************************/
15 /* GLOBALS ********************************************************************/
17 BOOLEAN PciRunningDatacenter
;
18 PDRIVER_OBJECT PciDriverObject
;
21 KEVENT PciLegacyDescriptionLock
;
22 BOOLEAN PciLockDeviceResources
;
23 BOOLEAN PciEnableNativeModeATA
;
24 ULONG PciSystemWideHackFlags
;
25 PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable
;
26 PWATCHDOG_TABLE WdTable
;
27 PPCI_HACK_ENTRY PciHackTable
;
29 /* FUNCTIONS ******************************************************************/
33 PciAcpiFindRsdt(OUT PACPI_BIOS_MULTI_NODE
*AcpiMultiNode
)
37 HANDLE KeyHandle
, SubKey
;
38 ULONG NumberOfBytes
, i
, Length
;
39 PKEY_FULL_INFORMATION FullInfo
;
40 PKEY_BASIC_INFORMATION KeyInfo
;
41 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
42 PACPI_BIOS_MULTI_NODE NodeData
;
43 UNICODE_STRING ValueName
;
46 CM_FULL_RESOURCE_DESCRIPTOR Descriptor
;
47 ACPI_BIOS_MULTI_NODE Node
;
50 /* So we know what to free at the end of the body */
58 /* Open the ACPI BIOS key */
59 Result
= PciOpenKey(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\"
60 L
"System\\MultiFunctionAdapter",
67 /* Query how much space should be allocated for the key information */
68 Status
= ZwQueryKey(KeyHandle
,
73 if (Status
!= STATUS_BUFFER_TOO_SMALL
) break;
75 /* Allocate the space required */
76 Status
= STATUS_INSUFFICIENT_RESOURCES
;
77 FullInfo
= ExAllocatePoolWithTag(PagedPool
, NumberOfBytes
, PCI_POOL_TAG
);
78 if ( !FullInfo
) break;
80 /* Now query the key information that's needed */
81 Status
= ZwQueryKey(KeyHandle
,
86 if (!NT_SUCCESS(Status
)) break;
88 /* Allocate enough space to hold the value information plus the name */
89 Status
= STATUS_INSUFFICIENT_RESOURCES
;
90 Length
= FullInfo
->MaxNameLen
+ 26;
91 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, PCI_POOL_TAG
);
92 if ( !KeyInfo
) break;
94 /* Allocate the value information and name we expect to find */
95 ValueInfo
= ExAllocatePoolWithTag(PagedPool
,
96 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
99 if (!ValueInfo
) break;
101 /* Loop each sub-key */
105 /* Query each sub-key */
106 Status
= ZwEnumerateKey(KeyHandle
,
112 if (Status
== STATUS_NO_MORE_ENTRIES
) break;
114 /* Null-terminate the keyname, because the kernel does not */
115 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
117 /* Open this subkey */
118 Result
= PciOpenKey(KeyInfo
->Name
,
125 /* Query the identifier value for this subkey */
126 RtlInitUnicodeString(&ValueName
, L
"Identifier");
127 Status
= ZwQueryValueKey(SubKey
,
129 KeyValuePartialInformation
,
131 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
132 sizeof(L
"ACPI BIOS"),
134 if (NT_SUCCESS(Status
))
136 /* Check if this is the PCI BIOS subkey */
137 if (!wcsncmp((PWCHAR
)ValueInfo
->Data
,
139 ValueInfo
->DataLength
))
141 /* It is, proceed to query the PCI IRQ routing table */
142 Status
= PciGetRegistryValue(L
"Configuration Data",
145 REG_FULL_RESOURCE_DESCRIPTOR
,
153 /* Close the subkey and try the next one */
158 /* Check if we got here because the routing table was found */
159 if (!NT_SUCCESS(Status
))
161 /* This should only fail if we're out of entries */
162 ASSERT(Status
== STATUS_NO_MORE_ENTRIES
);
166 /* Check if a descriptor was found */
169 /* The configuration data is a resource list, and the BIOS node follows */
170 NodeData
= &Package
->Node
;
172 /* How many E820 memory entries are there? */
173 Length
= sizeof(ACPI_BIOS_MULTI_NODE
) +
174 (NodeData
->Count
- 1) * sizeof(ACPI_E820_ENTRY
);
176 /* Allocate the buffer needed to copy the information */
177 Status
= STATUS_INSUFFICIENT_RESOURCES
;
178 *AcpiMultiNode
= ExAllocatePoolWithTag(NonPagedPool
, Length
, PCI_POOL_TAG
);
179 if (!*AcpiMultiNode
) break;
182 RtlCopyMemory(*AcpiMultiNode
, NodeData
, Length
);
183 Status
= STATUS_SUCCESS
;
186 /* Close any opened keys, free temporary allocations, and return status */
187 if (Package
) ExFreePoolWithTag(Package
, 0);
188 if (ValueInfo
) ExFreePoolWithTag(ValueInfo
, 0);
189 if (KeyInfo
) ExFreePoolWithTag(KeyInfo
, 0);
190 if (FullInfo
) ExFreePoolWithTag(FullInfo
, 0);
191 if (KeyHandle
) ZwClose(KeyHandle
);
197 PciGetAcpiTable(IN ULONG TableCode
)
199 PDESCRIPTION_HEADER Header
;
200 PACPI_BIOS_MULTI_NODE AcpiMultiNode
;
203 ULONG EntryCount
, TableLength
, Offset
, CurrentEntry
;
204 PVOID TableBuffer
, MappedAddress
;
205 PHYSICAL_ADDRESS PhysicalAddress
;
208 /* Try to find the RSDT or XSDT */
209 Status
= PciAcpiFindRsdt(&AcpiMultiNode
);
210 if (!NT_SUCCESS(Status
))
212 /* No ACPI on the machine */
213 DPRINT1("AcpiFindRsdt() Failed!\n");
217 /* Map the RSDT with the minimum size allowed */
218 MappedAddress
= MmMapIoSpace(AcpiMultiNode
->RsdtAddress
,
219 sizeof(DESCRIPTION_HEADER
),
221 Header
= MappedAddress
;
222 if (!Header
) return NULL
;
224 /* Check how big the table really is and get rid of the temporary header */
225 TableLength
= Header
->Length
;
226 MmUnmapIoSpace(Header
, sizeof(DESCRIPTION_HEADER
));
229 /* Map its true size */
230 MappedAddress
= MmMapIoSpace(AcpiMultiNode
->RsdtAddress
,
233 Rsdt
= MappedAddress
;
234 Xsdt
= MappedAddress
;
235 ExFreePoolWithTag(AcpiMultiNode
, 0);
236 if (!Rsdt
) return NULL
;
238 /* Validate the table's signature */
239 if ((Rsdt
->Header
.Signature
!= RSDT_SIGNATURE
) &&
240 (Rsdt
->Header
.Signature
!= XSDT_SIGNATURE
))
242 /* Very bad: crash */
243 HalDisplayString("RSDT table contains invalid signature\n");
244 MmUnmapIoSpace(Rsdt
, TableLength
);
248 /* Smallest RSDT/XSDT is one without table entries */
249 Offset
= FIELD_OFFSET(RSDT
, Tables
);
250 if (Rsdt
->Header
.Signature
== XSDT_SIGNATURE
)
252 /* Figure out total size of table and the offset */
253 TableLength
= Xsdt
->Header
.Length
;
254 if (TableLength
< Offset
) Offset
= Xsdt
->Header
.Length
;
256 /* The entries are each 64-bits, so count them */
257 EntryCount
= (TableLength
- Offset
) / sizeof(PHYSICAL_ADDRESS
);
261 /* Figure out total size of table and the offset */
262 TableLength
= Rsdt
->Header
.Length
;
263 if (TableLength
< Offset
) Offset
= Rsdt
->Header
.Length
;
265 /* The entries are each 32-bits, so count them */
266 EntryCount
= (TableLength
- Offset
) / sizeof(ULONG
);
269 /* Start at the beginning of the array and loop it */
270 for (CurrentEntry
= 0; CurrentEntry
< EntryCount
; CurrentEntry
++)
272 /* Are we using the XSDT? */
273 if (Rsdt
->Header
.Signature
!= XSDT_SIGNATURE
)
275 /* Read the 32-bit physical address */
276 PhysicalAddress
.QuadPart
= Rsdt
->Tables
[CurrentEntry
];
280 /* Read the 64-bit physical address */
281 PhysicalAddress
= Xsdt
->Tables
[CurrentEntry
];
285 Header
= MmMapIoSpace(PhysicalAddress
,
286 sizeof(DESCRIPTION_HEADER
),
290 /* Check if this is the table that's being asked for */
291 if (Header
->Signature
== TableCode
)
293 /* Allocate a buffer for it */
294 TableBuffer
= ExAllocatePoolWithTag(PagedPool
,
297 if (!TableBuffer
) break;
299 /* Copy the table into the buffer */
300 RtlCopyMemory(TableBuffer
, Header
, Header
->Length
);
303 /* Done with this table, keep going */
304 MmUnmapIoSpace(Header
, sizeof(DESCRIPTION_HEADER
));
307 if (Header
) MmUnmapIoSpace(Header
, sizeof(DESCRIPTION_HEADER
));
313 PciGetIrqRoutingTableFromRegistry(OUT PPCI_IRQ_ROUTING_TABLE
*PciRoutingTable
)
317 HANDLE KeyHandle
, SubKey
;
318 ULONG NumberOfBytes
, i
, Length
;
319 PKEY_FULL_INFORMATION FullInfo
;
320 PKEY_BASIC_INFORMATION KeyInfo
;
321 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
322 UNICODE_STRING ValueName
;
325 CM_FULL_RESOURCE_DESCRIPTOR Descriptor
;
326 PCI_IRQ_ROUTING_TABLE Table
;
329 /* So we know what to free at the end of the body */
337 /* Open the BIOS key */
338 Result
= PciOpenKey(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\"
339 L
"System\\MultiFunctionAdapter",
346 /* Query how much space should be allocated for the key information */
347 Status
= ZwQueryKey(KeyHandle
,
352 if (Status
!= STATUS_BUFFER_TOO_SMALL
) break;
354 /* Allocate the space required */
355 Status
= STATUS_INSUFFICIENT_RESOURCES
;
356 FullInfo
= ExAllocatePoolWithTag(PagedPool
, NumberOfBytes
, PCI_POOL_TAG
);
357 if ( !FullInfo
) break;
359 /* Now query the key information that's needed */
360 Status
= ZwQueryKey(KeyHandle
,
365 if (!NT_SUCCESS(Status
)) break;
367 /* Allocate enough space to hold the value information plus the name */
368 Status
= STATUS_INSUFFICIENT_RESOURCES
;
369 Length
= FullInfo
->MaxNameLen
+ 26;
370 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, PCI_POOL_TAG
);
373 /* Allocate the value information and name we expect to find */
374 ValueInfo
= ExAllocatePoolWithTag(PagedPool
,
375 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
378 if (!ValueInfo
) break;
380 /* Loop each sub-key */
384 /* Query each sub-key */
385 Status
= ZwEnumerateKey(KeyHandle
,
391 if (Status
== STATUS_NO_MORE_ENTRIES
) break;
393 /* Null-terminate the keyname, because the kernel does not */
394 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
396 /* Open this subkey */
397 Result
= PciOpenKey(KeyInfo
->Name
,
404 /* Query the identifier value for this subkey */
405 RtlInitUnicodeString(&ValueName
, L
"Identifier");
406 Status
= ZwQueryValueKey(SubKey
,
408 KeyValuePartialInformation
,
410 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
413 if (NT_SUCCESS(Status
))
415 /* Check if this is the PCI BIOS subkey */
416 if (!wcsncmp((PWCHAR
)ValueInfo
->Data
,
418 ValueInfo
->DataLength
))
420 /* It is, proceed to query the PCI IRQ routing table */
421 Status
= PciGetRegistryValue(L
"Configuration Data",
422 L
"RealModeIrqRoutingTable"
425 REG_FULL_RESOURCE_DESCRIPTOR
,
433 /* Close the subkey and try the next one */
438 /* Check if we got here because the routing table was found */
439 if (!NT_SUCCESS(Status
)) break;
441 /* Check if a descriptor was found */
444 /* Make sure the buffer is large enough to hold the table */
445 if ((NumberOfBytes
< sizeof(*Package
)) ||
446 (Package
->Table
.TableSize
>
447 (NumberOfBytes
- sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))))
449 /* Invalid package size */
450 Status
= STATUS_UNSUCCESSFUL
;
454 /* Allocate space for the table */
455 Status
= STATUS_INSUFFICIENT_RESOURCES
;
456 *PciRoutingTable
= ExAllocatePoolWithTag(PagedPool
,
459 if (!*PciRoutingTable
) break;
461 /* Copy the registry data */
462 RtlCopyMemory(*PciRoutingTable
,
464 NumberOfBytes
- sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
465 Status
= STATUS_SUCCESS
;
468 /* Close any opened keys, free temporary allocations, and return status */
469 if (Package
) ExFreePoolWithTag(Package
, 0);
470 if (ValueInfo
) ExFreePoolWithTag(ValueInfo
, 0);
471 if (KeyInfo
) ExFreePoolWithTag(KeyInfo
, 0);
472 if (FullInfo
) ExFreePoolWithTag(FullInfo
, 0);
473 if (KeyHandle
) ZwClose(KeyHandle
);
479 PciBuildHackTable(IN HANDLE KeyHandle
)
481 PKEY_FULL_INFORMATION FullInfo
;
483 PKEY_VALUE_FULL_INFORMATION ValueInfo
;
484 PPCI_HACK_ENTRY Entry
;
486 ULONG NameLength
, ResultLength
;
489 /* So we know what to free at the end of the body */
494 /* Query the size required for full key information */
495 Status
= ZwQueryKey(KeyHandle
,
500 if (Status
!= STATUS_BUFFER_TOO_SMALL
) break;
502 /* Allocate the space required to hold the full key information */
503 Status
= STATUS_INSUFFICIENT_RESOURCES
;
504 ASSERT(ResultLength
> 0);
505 FullInfo
= ExAllocatePoolWithTag(PagedPool
, ResultLength
, PCI_POOL_TAG
);
506 if (!FullInfo
) break;
508 /* Go ahead and query the key information */
509 Status
= ZwQueryKey(KeyHandle
,
514 if (!NT_SUCCESS(Status
)) break;
516 /* The only piece of information that's needed is the count of values */
517 HackCount
= FullInfo
->Values
;
519 /* Free the structure now */
520 ExFreePoolWithTag(FullInfo
, 0);
523 /* Allocate the hack table, now that the number of entries is known */
524 Status
= STATUS_INSUFFICIENT_RESOURCES
;
525 ResultLength
= sizeof(PCI_HACK_ENTRY
) * HackCount
;
526 PciHackTable
= ExAllocatePoolWithTag(NonPagedPool
,
528 sizeof(PCI_HACK_ENTRY
),
530 if (!PciHackTable
) break;
532 /* Allocate the space needed to hold the full value information */
533 ValueInfo
= ExAllocatePoolWithTag(NonPagedPool
,
534 sizeof(KEY_VALUE_FULL_INFORMATION
) +
535 PCI_HACK_ENTRY_FULL_SIZE
,
537 if (!PciHackTable
) break;
539 /* Loop each value in the registry */
540 Entry
= &PciHackTable
[0];
541 for (i
= 0; i
< HackCount
; i
++)
543 /* Get the entry for this value */
544 Entry
= &PciHackTable
[i
];
546 /* Query the value in the key */
547 Status
= ZwEnumerateValueKey(KeyHandle
,
549 KeyValueFullInformation
,
551 sizeof(KEY_VALUE_FULL_INFORMATION
) +
552 PCI_HACK_ENTRY_FULL_SIZE
,
554 if (!NT_SUCCESS(Status
))
556 /* Check why the call failed */
557 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
558 (Status
!= STATUS_BUFFER_TOO_SMALL
))
560 /* The call failed due to an unknown error, bail out */
564 /* The data seems to mismatch, try the next key in the list */
568 /* Check if the value data matches what's expected */
569 if ((ValueInfo
->Type
!= REG_BINARY
) ||
570 (ValueInfo
->DataLength
!= sizeof(ULONGLONG
)))
572 /* It doesn't, try the next key in the list */
576 /* Read the actual hack flags */
577 HackFlags
= *(PULONGLONG
)((ULONG_PTR
)ValueInfo
+
578 ValueInfo
->DataOffset
);
580 /* Check what kind of errata entry this is, based on the name */
581 NameLength
= ValueInfo
->NameLength
;
582 if ((NameLength
!= PCI_HACK_ENTRY_SIZE
) &&
583 (NameLength
!= PCI_HACK_ENTRY_REV_SIZE
) &&
584 (NameLength
!= PCI_HACK_ENTRY_SUBSYS_SIZE
) &&
585 (NameLength
!= PCI_HACK_ENTRY_FULL_SIZE
))
587 /* It's an invalid entry, skip it */
588 DPRINT1("Skipping hack entry with invalid length name\n");
592 /* Initialize the entry */
593 RtlZeroMemory(Entry
, sizeof(PCI_HACK_ENTRY
));
595 /* Get the vendor and device data */
596 if (!(PciStringToUSHORT(ValueInfo
->Name
, &Entry
->VendorID
)) ||
597 !(PciStringToUSHORT(&ValueInfo
->Name
[4], &Entry
->DeviceID
)))
599 /* This failed, try the next entry */
603 /* Check if the entry contains subsystem information */
604 if ((NameLength
== PCI_HACK_ENTRY_SUBSYS_SIZE
) ||
605 (NameLength
== PCI_HACK_ENTRY_FULL_SIZE
))
608 if (!(PciStringToUSHORT(&ValueInfo
->Name
[8],
609 &Entry
->SubVendorID
)) ||
610 !(PciStringToUSHORT(&ValueInfo
->Name
[12],
611 &Entry
->SubSystemID
)))
613 /* This failed, try the next entry */
617 /* Save the fact this entry has finer controls */
618 Entry
->Flags
|= PCI_HACK_HAS_SUBSYSTEM_INFO
;
621 /* Check if the entry contains revision information */
622 if ((NameLength
== PCI_HACK_ENTRY_REV_SIZE
) ||
623 (NameLength
== PCI_HACK_ENTRY_FULL_SIZE
))
626 if (!PciStringToUSHORT(&ValueInfo
->Name
[16],
629 /* This failed, try the next entry */
633 /* Save the fact this entry has finer controls */
634 Entry
->Flags
|= PCI_HACK_HAS_REVISION_INFO
;
637 /* Only the last entry should have this set */
638 ASSERT(Entry
->VendorID
!= PCI_INVALID_VENDORID
);
640 /* Save the actual hack flags */
641 Entry
->HackFlags
= HackFlags
;
643 /* Print out for the debugger's sake */
645 DPRINT1("Adding Hack entry for Vendor:0x%04x Device:0x%04x ",
646 Entry
->VendorID
, Entry
->DeviceID
);
647 if (Entry
->Flags
& PCI_HACK_HAS_SUBSYSTEM_INFO
)
648 DbgPrint("SybSys:0x%04x SubVendor:0x%04x ",
649 Entry
->SubSystemID
, Entry
->SubVendorID
);
650 if (Entry
->Flags
& PCI_HACK_HAS_REVISION_INFO
)
651 DbgPrint("Revision:0x%02x", Entry
->RevisionID
);
652 DbgPrint(" = 0x%I64x\n", Entry
->HackFlags
);
656 /* Bail out in case of failure */
657 if (!NT_SUCCESS(Status
)) break;
659 /* Terminate the table with an invalid entry */
660 ASSERT(Entry
< (PciHackTable
+ HackCount
+ 1));
661 Entry
->VendorID
= PCI_INVALID_VENDORID
;
663 /* Success path, free the temporary registry data */
664 ExFreePoolWithTag(ValueInfo
, 0);
665 return STATUS_SUCCESS
;
668 /* Failure path, free temporary allocations and return failure code */
669 ASSERT(!NT_SUCCESS(Status
));
670 if (FullInfo
) ExFreePool(FullInfo
);
671 if (ValueInfo
) ExFreePool(ValueInfo
);
672 if (PciHackTable
) ExFreePool(PciHackTable
);
678 PciGetDebugPorts(IN HANDLE DebugKey
)
680 UNREFERENCED_PARAMETER(DebugKey
);
681 /* This function is not yet implemented */
682 UNIMPLEMENTED_DBGBREAK();
683 return STATUS_SUCCESS
;
686 DRIVER_UNLOAD PciDriverUnload
;
690 PciDriverUnload(IN PDRIVER_OBJECT DriverObject
)
692 UNREFERENCED_PARAMETER(DriverObject
);
693 /* This function is not yet implemented */
694 UNIMPLEMENTED_DBGBREAK("PCI: Unload\n");
699 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
700 IN PUNICODE_STRING RegistryPath
)
702 HANDLE KeyHandle
, ParametersKey
, DebugKey
, ControlSetKey
;
704 OBJECT_ATTRIBUTES ObjectAttributes
;
708 UNICODE_STRING OptionString
, PciLockString
;
710 DPRINT1("PCI: DriverEntry!\n");
712 /* Setup initial loop variables */
714 ParametersKey
= NULL
;
716 ControlSetKey
= NULL
;
719 /* Remember our object so we can get it to it later */
720 PciDriverObject
= DriverObject
;
722 /* Setup the IRP dispatcher */
723 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = PciDispatchIrp
;
724 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = PciDispatchIrp
;
725 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = PciDispatchIrp
;
726 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PciDispatchIrp
;
727 DriverObject
->DriverUnload
= PciDriverUnload
;
729 /* This is how we'll detect a new PCI bus */
730 DriverObject
->DriverExtension
->AddDevice
= PciAddDevice
;
732 /* Open the PCI key */
733 InitializeObjectAttributes(&ObjectAttributes
,
735 OBJ_CASE_INSENSITIVE
,
738 Status
= ZwOpenKey(&KeyHandle
, KEY_QUERY_VALUE
, &ObjectAttributes
);
739 if (!NT_SUCCESS(Status
)) break;
741 /* Open the Parameters subkey */
742 Result
= PciOpenKey(L
"Parameters",
747 //if (!Result) break;
749 /* Build the list of all known PCI erratas */
750 Status
= PciBuildHackTable(ParametersKey
);
751 //if (!NT_SUCCESS(Status)) break;
753 /* Open the debug key, if it exists */
754 Result
= PciOpenKey(L
"Debug",
761 /* There are PCI debug devices, go discover them */
762 Status
= PciGetDebugPorts(DebugKey
);
763 if (!NT_SUCCESS(Status
)) break;
766 /* Initialize the synchronization locks */
767 KeInitializeEvent(&PciGlobalLock
, SynchronizationEvent
, TRUE
);
768 KeInitializeEvent(&PciBusLock
, SynchronizationEvent
, TRUE
);
769 KeInitializeEvent(&PciLegacyDescriptionLock
, SynchronizationEvent
, TRUE
);
771 /* Open the control set key */
772 Result
= PciOpenKey(L
"\\Registry\\Machine\\System\\CurrentControlSet",
779 /* Read the command line */
780 Status
= PciGetRegistryValue(L
"SystemStartOptions",
784 (PVOID
*)&StartOptions
,
786 if (NT_SUCCESS(Status
))
788 /* Initialize the command-line as a string */
789 OptionString
.Buffer
= StartOptions
;
790 OptionString
.MaximumLength
= OptionString
.Length
= ResultLength
;
792 /* Check if the command-line has the PCILOCK argument */
793 RtlInitUnicodeString(&PciLockString
, L
"PCILOCK");
794 if (PciUnicodeStringStrStr(&OptionString
, &PciLockString
, TRUE
))
796 /* The PCI Bus driver will keep the BIOS-assigned resources */
797 PciLockDeviceResources
= TRUE
;
800 /* This data isn't needed anymore */
801 ExFreePoolWithTag(StartOptions
, 0);
804 /* The PCILOCK feature can also be enabled per-system in the registry */
805 Status
= PciGetRegistryValue(L
"PCILock",
806 L
"Control\\BiosInfo\\PCI",
811 if (NT_SUCCESS(Status
))
813 /* Read the value it's been set to. This overrides /PCILOCK */
814 if (ResultLength
== sizeof(ULONG
)) PciLockDeviceResources
= *Value
;
815 ExFreePoolWithTag(Value
, 0);
818 /* The system can have global PCI erratas in the registry */
819 Status
= PciGetRegistryValue(L
"HackFlags",
820 L
"Control\\PnP\\PCI",
825 if (NT_SUCCESS(Status
))
828 if (ResultLength
== sizeof(ULONG
)) PciSystemWideHackFlags
= *Value
;
829 ExFreePoolWithTag(Value
, 0);
832 /* Check if the system should allow native ATA support */
833 Status
= PciGetRegistryValue(L
"EnableNativeModeATA",
834 L
"Control\\PnP\\PCI",
839 if (NT_SUCCESS(Status
))
841 /* This key is typically set by drivers, but users can force it */
842 if (ResultLength
== sizeof(ULONG
)) PciEnableNativeModeATA
= *Value
;
843 ExFreePoolWithTag(Value
, 0);
846 /* Build the range lists for all the excluded resource areas */
847 Status
= PciBuildDefaultExclusionLists();
848 if (!NT_SUCCESS(Status
)) break;
850 /* Read the PCI IRQ Routing Table that the loader put in the registry */
851 PciGetIrqRoutingTableFromRegistry(&PciIrqRoutingTable
);
853 /* Take over the HAL's default PCI Bus Handler routines */
856 /* Initialize verification of PCI BIOS and devices, if requested */
857 PciVerifierInit(DriverObject
);
859 /* Check if this is a Datacenter SKU, which impacts IRQ alignment */
860 PciRunningDatacenter
= PciIsDatacenter();
861 if (PciRunningDatacenter
) DPRINT1("PCI running on datacenter build\n");
863 /* Check if the system has an ACPI Hardware Watchdog Timer */
864 //WdTable = PciGetAcpiTable(WDRT_SIGNATURE);
865 Status
= STATUS_SUCCESS
;
868 /* Close all opened keys, return driver status to PnP Manager */
869 if (KeyHandle
) ZwClose(KeyHandle
);
870 if (ControlSetKey
) ZwClose(ControlSetKey
);
871 if (ParametersKey
) ZwClose(ParametersKey
);
872 if (DebugKey
) ZwClose(DebugKey
);