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_VALUE_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 /* Query each sub-key */
102 Status
= ZwEnumerateKey(KeyHandle
,
104 KeyValueBasicInformation
,
108 for (i
= 0; Status
!= STATUS_NO_MORE_ENTRIES
; i
++)
110 /* Null-terminate the keyname, because the kernel does not */
111 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
113 /* Open this subkey */
114 Result
= PciOpenKey(KeyInfo
->Name
,
121 /* Query the identifier value for this subkey */
122 RtlInitUnicodeString(&ValueName
, L
"Identifier");
123 Status
= ZwQueryValueKey(SubKey
,
125 KeyValuePartialInformation
,
127 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
128 sizeof(L
"ACPI BIOS"),
130 if (NT_SUCCESS(Status
))
132 /* Check if this is the PCI BIOS subkey */
133 if (!wcsncmp((PWCHAR
)ValueInfo
->Data
,
135 ValueInfo
->DataLength
))
137 /* It is, proceed to query the PCI IRQ routing table */
138 Status
= PciGetRegistryValue(L
"Configuration Data",
141 REG_FULL_RESOURCE_DESCRIPTOR
,
149 /* Close the subkey and try the next one */
154 /* Check if we got here because the routing table was found */
155 if (!NT_SUCCESS(Status
))
157 /* This should only fail if we're out of entries */
158 ASSERT(Status
== STATUS_NO_MORE_ENTRIES
);
162 /* Check if a descriptor was found */
165 /* The configuration data is a resource list, and the BIOS node follows */
166 NodeData
= &Package
->Node
;
168 /* How many E820 memory entries are there? */
169 Length
= sizeof(ACPI_BIOS_MULTI_NODE
) +
170 (NodeData
->Count
- 1) * sizeof(ACPI_E820_ENTRY
);
172 /* Allocate the buffer needed to copy the information */
173 Status
= STATUS_INSUFFICIENT_RESOURCES
;
174 *AcpiMultiNode
= ExAllocatePoolWithTag(NonPagedPool
, Length
, PCI_POOL_TAG
);
175 if (!*AcpiMultiNode
) break;
178 RtlCopyMemory(*AcpiMultiNode
, NodeData
, Length
);
181 /* Close any opened keys, free temporary allocations, and return status */
182 if (Package
) ExFreePoolWithTag(Package
, 0);
183 if (ValueInfo
) ExFreePoolWithTag(ValueInfo
, 0);
184 if (KeyInfo
) ExFreePoolWithTag(KeyInfo
, 0);
185 if (FullInfo
) ExFreePoolWithTag(FullInfo
, 0);
186 if (KeyHandle
) ZwClose(KeyHandle
);
192 PciGetAcpiTable(IN ULONG TableCode
)
194 PDESCRIPTION_HEADER Header
;
195 PACPI_BIOS_MULTI_NODE AcpiMultiNode
;
198 ULONG EntryCount
, TableLength
, Offset
, CurrentEntry
;
199 PVOID TableBuffer
, MappedAddress
;
200 PHYSICAL_ADDRESS PhysicalAddress
;
203 /* Try to find the RSDT or XSDT */
204 Status
= PciAcpiFindRsdt(&AcpiMultiNode
);
205 if (NT_SUCCESS(Status
))
207 /* No ACPI on the machine */
208 DPRINT1("AcpiFindRsdt() Failed!\n");
212 /* Map the RSDT with the minimum size allowed */
213 MappedAddress
= MmMapIoSpace(AcpiMultiNode
->RsdtAddress
,
214 sizeof(DESCRIPTION_HEADER
),
216 Header
= MappedAddress
;
217 if (!Header
) return NULL
;
219 /* Check how big the table really is and get rid of the temporary header */
220 TableLength
= Header
->Length
;
221 MmUnmapIoSpace(Header
, sizeof(DESCRIPTION_HEADER
));
224 /* Map its true size */
225 MappedAddress
= MmMapIoSpace(AcpiMultiNode
->RsdtAddress
,
228 Rsdt
= MappedAddress
;
229 Xsdt
= MappedAddress
;
230 ExFreePoolWithTag(AcpiMultiNode
, 0);
231 if (!Rsdt
) return NULL
;
233 /* Validate the table's signature */
234 DPRINT1("ACPI RSDT/XSDT at 0x%p\n", Rsdt
);
235 if ((Rsdt
->Header
.Signature
!= RSDT_SIGNATURE
) &&
236 (Rsdt
->Header
.Signature
!= XSDT_SIGNATURE
))
238 /* Very bad: crash */
239 HalDisplayString("RSDT table contains invalid signature\n");
240 MmUnmapIoSpace(Rsdt
, TableLength
);
244 /* Smallest RSDT/XSDT is one without table entries */
245 Offset
= FIELD_OFFSET(RSDT
, Tables
);
246 if (Rsdt
->Header
.Signature
== XSDT_SIGNATURE
)
248 /* Figure out total size of table and the offset */
249 TableLength
= Xsdt
->Header
.Length
;
250 if (TableLength
< Offset
) Offset
= Xsdt
->Header
.Length
;
252 /* The entries are each 64-bits, so count them */
253 EntryCount
= (TableLength
- Offset
) / sizeof(PHYSICAL_ADDRESS
);
257 /* Figure out total size of table and the offset */
258 TableLength
= Rsdt
->Header
.Length
;
259 if (TableLength
< Offset
) Offset
= Rsdt
->Header
.Length
;
261 /* The entries are each 32-bits, so count them */
262 EntryCount
= (TableLength
- Offset
) / sizeof(ULONG
);
265 /* Start at the beginning of the array and loop it */
266 for (CurrentEntry
= 0; CurrentEntry
< EntryCount
; CurrentEntry
++)
268 /* Are we using the XSDT? */
269 if (Rsdt
->Header
.Signature
!= XSDT_SIGNATURE
)
271 /* Read the 32-bit physical address */
272 PhysicalAddress
.LowPart
= Rsdt
->Tables
[CurrentEntry
];
276 /* Read the 64-bit physical address */
277 PhysicalAddress
= Xsdt
->Tables
[CurrentEntry
];
281 Header
= MmMapIoSpace(PhysicalAddress
,
282 sizeof(DESCRIPTION_HEADER
),
286 /* Check if this is the table that's being asked for */
287 if (Header
->Signature
== TableCode
)
289 /* Allocate a buffer for it */
290 TableBuffer
= ExAllocatePoolWithTag(PagedPool
,
293 if (!TableBuffer
) break;
295 /* Copy the table into the buffer */
296 RtlCopyMemory(TableBuffer
, Header
, Header
->Length
);
299 /* Done with this table, keep going */
300 MmUnmapIoSpace(Header
, sizeof(DESCRIPTION_HEADER
));
303 if (Header
) MmUnmapIoSpace(Header
, sizeof(DESCRIPTION_HEADER
));
309 PciGetIrqRoutingTableFromRegistry(OUT PPCI_IRQ_ROUTING_TABLE
*PciRoutingTable
)
313 HANDLE KeyHandle
, SubKey
;
314 ULONG NumberOfBytes
, i
, Length
;
315 PKEY_FULL_INFORMATION FullInfo
;
316 PKEY_VALUE_BASIC_INFORMATION KeyInfo
;
317 PKEY_VALUE_PARTIAL_INFORMATION ValueInfo
;
318 UNICODE_STRING ValueName
;
321 CM_FULL_RESOURCE_DESCRIPTOR Descriptor
;
322 PCI_IRQ_ROUTING_TABLE Table
;
325 /* So we know what to free at the end of the body */
333 /* Open the BIOS key */
334 Result
= PciOpenKey(L
"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\"
335 L
"System\\MultiFunctionAdapter",
342 /* Query how much space should be allocated for the key information */
343 Status
= ZwQueryKey(KeyHandle
,
348 if (Status
!= STATUS_BUFFER_TOO_SMALL
) break;
350 /* Allocate the space required */
351 Status
= STATUS_INSUFFICIENT_RESOURCES
;
352 FullInfo
= ExAllocatePoolWithTag(PagedPool
, NumberOfBytes
, PCI_POOL_TAG
);
353 if ( !FullInfo
) break;
355 /* Now query the key information that's needed */
356 Status
= ZwQueryKey(KeyHandle
,
361 if (!NT_SUCCESS(Status
)) break;
363 /* Allocate enough space to hold the value information plus the name */
364 Status
= STATUS_INSUFFICIENT_RESOURCES
;
365 Length
= FullInfo
->MaxNameLen
+ 26;
366 KeyInfo
= ExAllocatePoolWithTag(PagedPool
, Length
, PCI_POOL_TAG
);
367 if ( !KeyInfo
) break;
369 /* Allocate the value information and name we expect to find */
370 ValueInfo
= ExAllocatePoolWithTag(PagedPool
,
371 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
374 if ( !ValueInfo
) break;
376 /* Query each sub-key */
377 Status
= ZwEnumerateKey(KeyHandle
,
379 KeyValueBasicInformation
,
383 for (i
= 0; Status
!= STATUS_NO_MORE_ENTRIES
; i
++)
385 /* Null-terminate the keyname, because the kernel does not */
386 KeyInfo
->Name
[KeyInfo
->NameLength
/ sizeof(WCHAR
)] = UNICODE_NULL
;
388 /* Open this subkey */
389 Result
= PciOpenKey(KeyInfo
->Name
,
396 /* Query the identifier value for this subkey */
397 RtlInitUnicodeString(&ValueName
, L
"Identifier");
398 Status
= ZwQueryValueKey(SubKey
,
400 KeyValuePartialInformation
,
402 sizeof(KEY_VALUE_PARTIAL_INFORMATION
) +
405 if (NT_SUCCESS(Status
))
407 /* Check if this is the PCI BIOS subkey */
408 if (!wcsncmp((PWCHAR
)ValueInfo
->Data
,
410 ValueInfo
->DataLength
))
412 /* It is, proceed to query the PCI IRQ routing table */
413 Status
= PciGetRegistryValue(L
"Configuration Data",
414 L
"RealModeIrqRoutingTable"
417 REG_FULL_RESOURCE_DESCRIPTOR
,
425 /* Close the subkey and try the next one */
430 /* Check if we got here because the routing table was found */
431 if (!NT_SUCCESS(Status
)) break;
433 /* Check if a descriptor was found */
436 /* Make sure the buffer is large enough to hold the table */
437 if ((NumberOfBytes
< sizeof(*Package
)) ||
438 (Package
->Table
.TableSize
>
439 (NumberOfBytes
- sizeof(CM_FULL_RESOURCE_DESCRIPTOR
))))
441 /* Invalid package size */
442 Status
= STATUS_UNSUCCESSFUL
;
446 /* Allocate space for the table */
447 Status
= STATUS_INSUFFICIENT_RESOURCES
;
448 *PciRoutingTable
= ExAllocatePoolWithTag(PagedPool
,
451 if (!*PciRoutingTable
) break;
453 /* Copy the registry data */
454 RtlCopyMemory(*PciRoutingTable
,
456 NumberOfBytes
- sizeof(CM_FULL_RESOURCE_DESCRIPTOR
));
457 Status
= STATUS_SUCCESS
;
460 /* Close any opened keys, free temporary allocations, and return status */
461 if (Package
) ExFreePoolWithTag(Package
, 0);
462 if (ValueInfo
) ExFreePoolWithTag(ValueInfo
, 0);
463 if (KeyInfo
) ExFreePoolWithTag(KeyInfo
, 0);
464 if (FullInfo
) ExFreePoolWithTag(FullInfo
, 0);
465 if (KeyHandle
) ZwClose(KeyHandle
);
471 PciBuildHackTable(IN HANDLE KeyHandle
)
473 PKEY_FULL_INFORMATION FullInfo
;
475 PKEY_VALUE_FULL_INFORMATION ValueInfo
;
476 PPCI_HACK_ENTRY Entry
;
478 ULONG NameLength
, ResultLength
;
481 /* So we know what to free at the end of the body */
486 /* Query the size required for full key information */
487 Status
= ZwQueryKey(KeyHandle
,
492 if (Status
!= STATUS_BUFFER_TOO_SMALL
) break;
494 /* Allocate the space required to hold the full key information */
495 Status
= STATUS_INSUFFICIENT_RESOURCES
;
496 ASSERT(ResultLength
> 0);
497 FullInfo
= ExAllocatePoolWithTag(PagedPool
, ResultLength
, PCI_POOL_TAG
);
498 if (!FullInfo
) break;
500 /* Go ahead and query the key information */
501 Status
= ZwQueryKey(KeyHandle
,
506 if (!NT_SUCCESS(Status
)) break;
508 /* The only piece of information that's needed is the count of values */
509 HackCount
= FullInfo
->Values
;
511 /* Free the structure now */
512 ExFreePoolWithTag(FullInfo
, 0);
515 /* Allocate the hack table, now that the number of entries is known */
516 Status
= STATUS_INSUFFICIENT_RESOURCES
;
517 ResultLength
= sizeof(PCI_HACK_ENTRY
) * HackCount
;
518 PciHackTable
= ExAllocatePoolWithTag(NonPagedPool
,
520 sizeof(PCI_HACK_ENTRY
),
522 if (!PciHackTable
) break;
524 /* Allocate the space needed to hold the full value information */
525 ValueInfo
= ExAllocatePoolWithTag(NonPagedPool
,
526 sizeof(KEY_VALUE_FULL_INFORMATION
) +
527 PCI_HACK_ENTRY_FULL_SIZE
,
529 if (!PciHackTable
) break;
531 /* Loop each value in the registry */
532 Entry
= &PciHackTable
[0];
533 for (i
= 0; i
< HackCount
; i
++)
535 /* Get the entry for this value */
536 Entry
= &PciHackTable
[i
];
538 /* Query the value in the key */
539 Status
= ZwEnumerateValueKey(KeyHandle
,
541 KeyValueFullInformation
,
543 sizeof(KEY_VALUE_FULL_INFORMATION
) +
544 PCI_HACK_ENTRY_FULL_SIZE
,
546 if (!NT_SUCCESS(Status
))
548 /* Check why the call failed */
549 if ((Status
!= STATUS_BUFFER_OVERFLOW
) &&
550 (Status
!= STATUS_BUFFER_TOO_SMALL
))
552 /* The call failed due to an unknown error, bail out */
556 /* The data seems to mismatch, try the next key in the list */
560 /* Check if the value data matches what's expected */
561 if ((ValueInfo
->Type
!= REG_BINARY
) ||
562 (ValueInfo
->DataLength
!= sizeof(ULONGLONG
)))
564 /* It doesn't, try the next key in the list */
568 /* Read the actual hack flags */
569 HackFlags
= *(PULONGLONG
)((ULONG_PTR
)ValueInfo
+
570 ValueInfo
->DataOffset
);
572 /* Check what kind of errata entry this is, based on the name */
573 NameLength
= ValueInfo
->NameLength
;
574 if ((NameLength
!= PCI_HACK_ENTRY_SIZE
) &&
575 (NameLength
!= PCI_HACK_ENTRY_REV_SIZE
) &&
576 (NameLength
!= PCI_HACK_ENTRY_SUBSYS_SIZE
) &&
577 (NameLength
!= PCI_HACK_ENTRY_FULL_SIZE
))
579 DPRINT1("Skipping hack entry with invalid length name\n");
582 /* Initialize the entry */
583 RtlZeroMemory(Entry
, sizeof(PCI_HACK_ENTRY
));
585 /* Get the vendor and device data */
586 if (!(PciStringToUSHORT(ValueInfo
->Name
, &Entry
->VendorID
)) ||
587 !(PciStringToUSHORT(&ValueInfo
->Name
[4], &Entry
->DeviceID
)))
589 /* This failed, try the next entry */
593 /* Check if the entry contains subsystem information */
594 if ((NameLength
== PCI_HACK_ENTRY_SUBSYS_SIZE
) ||
595 (NameLength
== PCI_HACK_ENTRY_FULL_SIZE
))
598 if (!(PciStringToUSHORT(&ValueInfo
->Name
[8],
599 &Entry
->SubVendorID
)) ||
600 !(PciStringToUSHORT(&ValueInfo
->Name
[12],
601 &Entry
->SubSystemID
)))
603 /* This failed, try the next entry */
607 /* Save the fact this entry has finer controls */
608 Entry
->Flags
|= PCI_HACK_HAS_SUBSYSTEM_INFO
;
611 /* Check if the entry contains revision information */
612 if ((NameLength
== PCI_HACK_ENTRY_REV_SIZE
) ||
613 (NameLength
== PCI_HACK_ENTRY_FULL_SIZE
))
616 if (!PciStringToUSHORT(&ValueInfo
->Name
[16],
619 /* This failed, try the next entry */
623 /* Save the fact this entry has finer controls */
624 Entry
->Flags
|= PCI_HACK_HAS_REVISION_INFO
;
627 /* Only the last entry should have this set */
628 ASSERT(Entry
->VendorID
!= PCI_INVALID_VENDORID
);
630 /* Save the actual hack flags */
631 Entry
->HackFlags
= HackFlags
;
633 /* Print out for the debugger's sake */
634 DPRINT1("Adding Hack entry for Vendor:0x%04x Device:0x%04x ",
635 Entry
->VendorID
, Entry
->DeviceID
);
636 if (Entry
->Flags
& PCI_HACK_HAS_SUBSYSTEM_INFO
)
637 DPRINT1("SybSys:0x%04x SubVendor:0x%04x ",
638 Entry
->SubSystemID
, Entry
->SubVendorID
);
639 if (Entry
->Flags
& PCI_HACK_HAS_REVISION_INFO
)
640 DPRINT1("Revision:0x%02x", Entry
->RevisionID
);
641 DPRINT1(" = 0x%I64x\n", Entry
->HackFlags
);
644 /* Bail out in case of failure */
645 if (!NT_SUCCESS(Status
)) break;
647 /* Terminate the table with an invalid entry */
648 ASSERT(Entry
< (PciHackTable
+ HackCount
+ 1));
649 Entry
->VendorID
= PCI_INVALID_VENDORID
;
651 /* Success path, free the temporary registry data */
652 ExFreePoolWithTag(ValueInfo
, 0);
653 return STATUS_SUCCESS
;
656 /* Failure path, free temporary allocations and return failure code */
657 ASSERT(!NT_SUCCESS(Status
));
658 if (FullInfo
) ExFreePool(FullInfo
);
659 if (ValueInfo
) ExFreePool(ValueInfo
);
660 if (PciHackTable
) ExFreePool(PciHackTable
);
666 PciGetDebugPorts(IN HANDLE DebugKey
)
668 /* This function is not yet implemented */
671 return STATUS_SUCCESS
;
676 PciDriverUnload(IN PDRIVER_OBJECT DriverObject
)
678 /* This function is not yet implemented */
679 DPRINT1("PCI: Unload\n");
686 DriverEntry(IN PDRIVER_OBJECT DriverObject
,
687 IN PUNICODE_STRING RegistryPath
)
689 HANDLE KeyHandle
, ParametersKey
, DebugKey
, ControlSetKey
;
691 OBJECT_ATTRIBUTES ObjectAttributes
;
695 UNICODE_STRING OptionString
, PciLockString
;
697 DPRINT1("PCI: DriverEntry!\n");
700 /* Remember our object so we can get it to it later */
701 PciDriverObject
= DriverObject
;
703 /* Setup the IRP dispatcher */
704 DriverObject
->MajorFunction
[IRP_MJ_POWER
] = PciDispatchIrp
;
705 DriverObject
->MajorFunction
[IRP_MJ_DEVICE_CONTROL
] = PciDispatchIrp
;
706 DriverObject
->MajorFunction
[IRP_MJ_SYSTEM_CONTROL
] = PciDispatchIrp
;
707 DriverObject
->MajorFunction
[IRP_MJ_PNP
] = PciDispatchIrp
;
708 DriverObject
->DriverUnload
= PciDriverUnload
;
710 /* This is how we'll detect a new PCI bus */
711 DriverObject
->DriverExtension
->AddDevice
= PciAddDevice
;
713 /* Open the PCI key */
714 InitializeObjectAttributes(&ObjectAttributes
,
716 OBJ_CASE_INSENSITIVE
,
719 Status
= ZwOpenKey(&KeyHandle
, KEY_QUERY_VALUE
, &ObjectAttributes
);
720 if (!NT_SUCCESS(Status
)) break;
722 /* Open the Parameters subkey */
723 Result
= PciOpenKey(L
"Parameters",
730 /* Build the list of all known PCI erratas */
731 Status
= PciBuildHackTable(ParametersKey
);
732 if (!NT_SUCCESS(Status
)) break;
734 /* Open the debug key, if it exists */
735 Result
= PciOpenKey(L
"Debug",
742 /* There are PCI debug devices, go discover them */
743 Status
= PciGetDebugPorts(DebugKey
);
744 if (!NT_SUCCESS(Status
)) break;
747 /* Initialize the synchronization locks */
748 KeInitializeEvent(&PciGlobalLock
, SynchronizationEvent
, TRUE
);
749 KeInitializeEvent(&PciBusLock
, SynchronizationEvent
, TRUE
);
750 KeInitializeEvent(&PciLegacyDescriptionLock
, SynchronizationEvent
, TRUE
);
752 /* Open the control set key */
753 Status
= PciOpenKey(L
"\\Registry\\Machine\\System\\CurrentControlSet",
758 if (!NT_SUCCESS(Status
)) break;
760 /* Read the command line */
761 Status
= PciGetRegistryValue(L
"SystemStartOptions",
765 (PVOID
*)&StartOptions
,
767 if (NT_SUCCESS(Status
))
769 /* Initialize the command-line as a string */
770 OptionString
.Buffer
= StartOptions
;
771 OptionString
.MaximumLength
= OptionString
.Length
= ResultLength
;
773 /* Check if the command-line has the PCILOCK argument */
774 RtlInitUnicodeString(&PciLockString
, L
"PCILOCK");
775 if (PciUnicodeStringStrStr(&OptionString
, &PciLockString
, TRUE
))
777 /* The PCI Bus driver will keep the BIOS-assigned resources */
778 PciLockDeviceResources
= TRUE
;
781 /* This data isn't needed anymore */
782 ExFreePoolWithTag(StartOptions
, 0);
785 /* The PCILOCK feature can also be enabled per-system in the registry */
786 Status
= PciGetRegistryValue(L
"PCILock",
787 L
"Control\\BiosInfo\\PCI",
792 if (NT_SUCCESS(Status
))
794 /* Read the value it's been set to. This overrides /PCILOCK */
795 if (ResultLength
== sizeof(ULONG
)) PciLockDeviceResources
= *Value
;
796 ExFreePoolWithTag(Value
, 0);
799 /* The system can have global PCI erratas in the registry */
800 Status
= PciGetRegistryValue(L
"HackFlags",
801 L
"Control\\PnP\\PCI",
806 if (NT_SUCCESS(Status
))
809 if (ResultLength
== sizeof(ULONG
)) PciSystemWideHackFlags
= *Value
;
810 ExFreePoolWithTag(Value
, 0);
813 /* Check if the system should allow native ATA support */
814 Status
= PciGetRegistryValue(L
"EnableNativeModeATA",
815 L
"Control\\PnP\\PCI",
820 if (NT_SUCCESS(Status
))
822 /* This key is typically set by drivers, but users can force it */
823 if (ResultLength
== sizeof(ULONG
)) PciEnableNativeModeATA
= *Value
;
824 ExFreePoolWithTag(Value
, 0);
827 /* Build the range lists for all the excluded resource areas */
828 Status
= PciBuildDefaultExclusionLists();
829 if (!NT_SUCCESS(Status
)) break;
831 /* Read the PCI IRQ Routing Table that the loader put in the registry */
832 PciGetIrqRoutingTableFromRegistry(&PciIrqRoutingTable
);
834 /* Take over the HAL's default PCI Bus Handler routines */
837 /* Initialize verification of PCI BIOS and devices, if requested */
838 PciVerifierInit(DriverObject
);
840 /* Check if this is a Datacenter SKU, which impacts IRQ alignment */
841 PciRunningDatacenter
= PciIsDatacenter();
842 if (PciRunningDatacenter
) DPRINT1("PCI running on datacenter build\n");
844 /* Check if the system has an ACPI Hardware Watchdog Timer */
845 WdTable
= PciGetAcpiTable(WDRT_SIGNATURE
);
848 /* Close all opened keys, return driver status to PnP Manager */
849 if (KeyHandle
) ZwClose(KeyHandle
);
850 if (ControlSetKey
) ZwClose(ControlSetKey
);
851 if (ParametersKey
) ZwClose(ParametersKey
);
852 if (DebugKey
) ZwClose(DebugKey
);