ReactOS 0.4.17-dev-1190-g4c812f4
init.c
Go to the documentation of this file.
1/*
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
7 */
8
9/* INCLUDES *******************************************************************/
10
11#include <pci.h>
12
13#define NDEBUG
14#include <debug.h>
15
16/* GLOBALS ********************************************************************/
17
29
30/* FUNCTIONS ******************************************************************/
31
35{
38 HANDLE KeyHandle, SubKey;
40 PKEY_FULL_INFORMATION FullInfo;
43 PACPI_BIOS_MULTI_NODE NodeData;
45 struct
46 {
49 } *Package;
50
51 /* So we know what to free at the end of the body */
52 ValueInfo = NULL;
53 KeyInfo = NULL;
55 FullInfo = NULL;
56 Package = NULL;
57 do
58 {
59 /* Open the ACPI BIOS key */
60 Result = PciOpenKey(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\"
61 L"System\\MultiFunctionAdapter",
62 NULL,
64 &KeyHandle,
65 &Status);
66 if (!Result) break;
67
68 /* Query how much space should be allocated for the key information */
69 Status = ZwQueryKey(KeyHandle,
71 NULL,
72 sizeof(ULONG),
74 if (Status != STATUS_BUFFER_TOO_SMALL) break;
75
76 /* Allocate the space required */
79 if ( !FullInfo ) break;
80
81 /* Now query the key information that's needed */
82 Status = ZwQueryKey(KeyHandle,
84 FullInfo,
87 if (!NT_SUCCESS(Status)) break;
88
89 /* Allocate enough space to hold the value information plus the name */
91 Length = FullInfo->MaxNameLen + 26;
93 if ( !KeyInfo ) break;
94
95 /* Allocate the value information and name we expect to find */
98 sizeof(L"ACPI BIOS"),
100 if (!ValueInfo) break;
101
102 /* Loop each sub-key */
103 i = 0;
104 while (TRUE)
105 {
106 /* Query each sub-key */
107 Status = ZwEnumerateKey(KeyHandle,
108 i++,
110 KeyInfo,
111 Length,
113 if (Status == STATUS_NO_MORE_ENTRIES) break;
114
115 /* Null-terminate the keyname, because the kernel does not */
116 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
117
118 /* Open this subkey */
119 Result = PciOpenKey(KeyInfo->Name,
120 KeyHandle,
122 &SubKey,
123 &Status);
124 if (Result)
125 {
126 /* Query the identifier value for this subkey */
127 RtlInitUnicodeString(&ValueName, L"Identifier");
128 Status = ZwQueryValueKey(SubKey,
129 &ValueName,
131 ValueInfo,
133 sizeof(L"ACPI BIOS"),
135 if (NT_SUCCESS(Status))
136 {
137 /* Check if this is the ACPI BIOS subkey */
138 if (!wcsncmp((PWCHAR)ValueInfo->Data,
139 L"ACPI BIOS",
140 ValueInfo->DataLength))
141 {
142 /* It is, proceed to query the PCI IRQ routing table */
143 Status = PciGetRegistryValue(L"Configuration Data",
144 KeyInfo->Name,
145 KeyHandle,
147 (PVOID*)&Package,
149 ZwClose(SubKey);
150 break;
151 }
152 }
153
154 /* Close the subkey and try the next one */
155 ZwClose(SubKey);
156 }
157 }
158
159 /* Check if we got here because the routing table was found */
160 if (!NT_SUCCESS(Status))
161 {
162 /* This should only fail if we're out of entries */
164 break;
165 }
166
167 /* Check if a descriptor was found */
168 if (!Package) break;
169
170 /* The configuration data is a resource list, and the BIOS node follows */
171 NodeData = &Package->Node;
172
173 /* How many E820 memory entries are there? */
174 Length = sizeof(ACPI_BIOS_MULTI_NODE) +
175 (NodeData->Count - 1) * sizeof(ACPI_E820_ENTRY);
176
177 /* Allocate the buffer needed to copy the information */
180 if (!*AcpiMultiNode) break;
181
182 /* Copy the data */
183 RtlCopyMemory(*AcpiMultiNode, NodeData, Length);
185 } while (FALSE);
186
187 /* Close any opened keys, free temporary allocations, and return status */
188 if (Package) ExFreePoolWithTag(Package, 0);
189 if (ValueInfo) ExFreePoolWithTag(ValueInfo, 0);
190 if (KeyInfo) ExFreePoolWithTag(KeyInfo, 0);
191 if (FullInfo) ExFreePoolWithTag(FullInfo, 0);
193 return Status;
194}
195
196PVOID
197NTAPI
199{
201 PACPI_BIOS_MULTI_NODE AcpiMultiNode;
202 PRSDT Rsdt;
203 PXSDT Xsdt;
204 ULONG EntryCount, TableLength, Offset, CurrentEntry;
205 PVOID TableBuffer, MappedAddress;
208
209 /* Try to find the RSDT or XSDT */
210 Status = PciAcpiFindRsdt(&AcpiMultiNode);
211 if (!NT_SUCCESS(Status))
212 {
213 /* No ACPI on the machine */
214 DPRINT1("PCIX - AcpiFindRsdt() Failed!\n");
215 return NULL;
216 }
217
218 /* Map the RSDT with the minimum size allowed */
219 MappedAddress = MmMapIoSpace(AcpiMultiNode->RsdtAddress,
220 sizeof(DESCRIPTION_HEADER),
222 Header = MappedAddress;
223 if (!Header) return NULL;
224
225 /* Check how big the table really is and get rid of the temporary header */
226 TableLength = Header->Length;
228 Header = NULL;
229
230 /* Map its true size */
231 MappedAddress = MmMapIoSpace(AcpiMultiNode->RsdtAddress,
232 TableLength,
234 Rsdt = MappedAddress;
235 Xsdt = MappedAddress;
236 ExFreePoolWithTag(AcpiMultiNode, 0);
237 if (!Rsdt) return NULL;
238
239 /* Validate the table's signature */
240 if ((Rsdt->Header.Signature != RSDT_SIGNATURE) &&
242 {
243 /* Very bad: crash */
244 HalDisplayString("RSDT table contains invalid signature\r\n");
245 MmUnmapIoSpace(Rsdt, TableLength);
246 return NULL;
247 }
248
249 /* Smallest RSDT/XSDT is one without table entries */
250 Offset = FIELD_OFFSET(RSDT, Tables);
251 if (Rsdt->Header.Signature == XSDT_SIGNATURE)
252 {
253 /* Figure out total size of table and the offset */
254 TableLength = Xsdt->Header.Length;
255 if (TableLength < Offset) Offset = Xsdt->Header.Length;
256
257 /* The entries are each 64-bits, so count them */
258 EntryCount = (TableLength - Offset) / sizeof(PHYSICAL_ADDRESS);
259 }
260 else
261 {
262 /* Figure out total size of table and the offset */
263 TableLength = Rsdt->Header.Length;
264 if (TableLength < Offset) Offset = Rsdt->Header.Length;
265
266 /* The entries are each 32-bits, so count them */
267 EntryCount = (TableLength - Offset) / sizeof(ULONG);
268 }
269
270 /* Start at the beginning of the array and loop it */
271 for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++)
272 {
273 /* Are we using the XSDT? */
274 if (Rsdt->Header.Signature != XSDT_SIGNATURE)
275 {
276 /* Read the 32-bit physical address */
277 PhysicalAddress.QuadPart = Rsdt->Tables[CurrentEntry];
278 }
279 else
280 {
281 /* Read the 64-bit physical address */
282 PhysicalAddress = Xsdt->Tables[CurrentEntry];
283 }
284
285 /* Map this table */
287 sizeof(DESCRIPTION_HEADER),
289 if (!Header) break;
290
291 /* Check if this is the table that's being asked for */
292 if (Header->Signature == TableCode)
293 {
294 /* Allocate a buffer for it */
295 TableBuffer = ExAllocatePoolWithTag(PagedPool,
296 Header->Length,
298 if (!TableBuffer) break;
299
300 /* Copy the table into the buffer */
301 RtlCopyMemory(TableBuffer, Header, Header->Length);
302 }
303
304 /* Done with this table, keep going */
306 }
307
309 return NULL;
310}
311
313NTAPI
315{
318 HANDLE KeyHandle, SubKey;
320 PKEY_FULL_INFORMATION FullInfo;
327 ULONG Offset, DataLength, HeaderLength;
328 UCHAR Checksum;
329
330 /* So we know what to free at the end of the body */
331 Package = NULL;
332 ValueInfo = NULL;
333 KeyInfo = NULL;
334 KeyHandle = NULL;
335 FullInfo = NULL;
336 do
337 {
338 /* Open the BIOS key */
339 Result = PciOpenKey(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\"
340 L"System\\MultiFunctionAdapter",
341 NULL,
343 &KeyHandle,
344 &Status);
345 if (!Result) break;
346
347 /* Query how much space should be allocated for the key information */
348 Status = ZwQueryKey(KeyHandle,
350 NULL,
351 sizeof(ULONG),
353 if (Status != STATUS_BUFFER_TOO_SMALL) break;
354
355 /* Allocate the space required */
358 if ( !FullInfo ) break;
359
360 /* Now query the key information that's needed */
361 Status = ZwQueryKey(KeyHandle,
363 FullInfo,
366 if (!NT_SUCCESS(Status)) break;
367
368 /* Allocate enough space to hold the value information plus the name */
370 Length = FullInfo->MaxNameLen + 26;
372 if (!KeyInfo) break;
373
374 /* Allocate the value information and name we expect to find */
377 sizeof(L"PCI BIOS"),
379 if (!ValueInfo) break;
380
381 /* Loop each sub-key */
382 i = 0;
383 while (TRUE)
384 {
385 /* Query each sub-key */
386 Status = ZwEnumerateKey(KeyHandle,
387 i++,
389 KeyInfo,
390 Length,
392 if (Status == STATUS_NO_MORE_ENTRIES) break;
393
394 /* Null-terminate the keyname, because the kernel does not */
395 KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
396
397 /* Open this subkey */
398 Result = PciOpenKey(KeyInfo->Name,
399 KeyHandle,
401 &SubKey,
402 &Status);
403 if (Result)
404 {
405 /* Query the identifier value for this subkey */
406 RtlInitUnicodeString(&ValueName, L"Identifier");
407 Status = ZwQueryValueKey(SubKey,
408 &ValueName,
410 ValueInfo,
412 sizeof(L"PCI BIOS"),
414 if (NT_SUCCESS(Status))
415 {
416 /* Check if this is the PCI BIOS subkey */
417 if (!wcsncmp((PWCHAR)ValueInfo->Data,
418 L"PCI BIOS",
419 ValueInfo->DataLength))
420 {
421 /* It is, proceed to query the PCI IRQ routing table */
422 Status = PciGetRegistryValue(L"Configuration Data",
423 L"RealModeIrqRoutingTable"
424 L"\\0",
425 SubKey,
427 (PVOID*)&Package,
429 ZwClose(SubKey);
430 break;
431 }
432 }
433
434 /* Close the subkey and try the next one */
435 ZwClose(SubKey);
436 }
437 }
438
439 /* Check if we got here because the routing table was found */
440 if (!NT_SUCCESS(Status)) break;
441
442 /* Check if a descriptor was found */
443 if (!Package) break;
444
445 /* The loader lists the bus ahead of the table, so find the data descriptor */
447 Table = NULL;
448 DataLength = 0;
450 PartialResourceList.PartialDescriptors);
451 if (NumberOfBytes < Offset)
452 break;
453
454 Partial = Package->PartialResourceList.PartialDescriptors;
455 for (i = 0; i < Package->PartialResourceList.Count; i++)
456 {
457 Offset += sizeof(*Partial);
458 if (Offset > NumberOfBytes)
459 break;
460
461 if (Partial->Type == CmResourceTypeDeviceSpecific)
462 {
463 DataLength = Partial->u.DeviceSpecificData.DataSize;
464 Table = (PPCI_IRQ_ROUTING_TABLE)(Partial + 1);
465 break;
466 }
467
468 Partial++;
469 }
470
471 /* The data must hold at least a $PIR header */
472 HeaderLength = FIELD_OFFSET(PCI_IRQ_ROUTING_TABLE, Slot);
473 if (!Table ||
475 (DataLength < HeaderLength))
476 {
477 break;
478 }
479
480 /* Accept only a version 1.0 table that fits in the data and ends on a slot entry */
481 if ((Table->Signature != PCI_IRQ_ROUTING_TABLE_SIGNATURE) ||
482 (Table->Version != PCI_IRQ_ROUTING_TABLE_VERSION) ||
483 (Table->TableSize < HeaderLength) ||
484 (Table->TableSize > DataLength) ||
485 (((Table->TableSize - HeaderLength) % sizeof(Table->Slot[0])) != 0))
486 {
487 break;
488 }
489
490 /* All bytes of the table must add up to zero */
491 Checksum = 0;
492 for (i = 0; i < Table->TableSize; i++)
493 {
494 Checksum += ((PUCHAR)Table)[i];
495 }
496 if (Checksum != 0)
497 break;
498
499 /* Allocate space for the table */
501 *PciRoutingTable = ExAllocatePoolWithTag(PagedPool,
502 Table->TableSize,
504 if (!*PciRoutingTable) break;
505
506 /* Copy the table out of the registry data */
507 RtlCopyMemory(*PciRoutingTable, Table, Table->TableSize);
509 } while (FALSE);
510
511 /* Close any opened keys, free temporary allocations, and return status */
512 if (Package) ExFreePoolWithTag(Package, 0);
513 if (ValueInfo) ExFreePoolWithTag(ValueInfo, 0);
514 if (KeyInfo) ExFreePoolWithTag(KeyInfo, 0);
515 if (FullInfo) ExFreePoolWithTag(FullInfo, 0);
517 return Status;
518}
519
521NTAPI
523{
524 PKEY_FULL_INFORMATION FullInfo;
525 ULONG i, HackCount;
529 ULONG NameLength, ResultLength;
531
532 /* So we know what to free at the end of the body */
533 FullInfo = NULL;
534 ValueInfo = NULL;
535 do
536 {
537 /* Query the size required for full key information */
538 Status = ZwQueryKey(KeyHandle,
540 NULL,
541 0,
542 &ResultLength);
543 if (Status != STATUS_BUFFER_TOO_SMALL) break;
544
545 /* Allocate the space required to hold the full key information */
547 ASSERT(ResultLength > 0);
549 if (!FullInfo) break;
550
551 /* Go ahead and query the key information */
552 Status = ZwQueryKey(KeyHandle,
554 FullInfo,
556 &ResultLength);
557 if (!NT_SUCCESS(Status)) break;
558
559 /* The only piece of information that's needed is the count of values */
560 HackCount = FullInfo->Values;
561
562 /* Free the structure now */
563 ExFreePoolWithTag(FullInfo, 0);
564 FullInfo = NULL;
565
566 /* Allocate the hack table, now that the number of entries is known */
568 ResultLength = sizeof(PCI_HACK_ENTRY) * HackCount;
571 sizeof(PCI_HACK_ENTRY),
573 if (!PciHackTable) break;
574
575 /* Allocate room for the longest valid name plus the 8 bytes of flags */
577 sizeof(*ValueInfo) +
579 sizeof(Entry->HackFlags),
581 if (!ValueInfo)
582 break;
583
584 /* Entry only advances once filled */
585 Entry = &PciHackTable[0];
586 for (i = 0; i < HackCount; i++)
587 {
588 /* Query the value in the key */
589 Status = ZwEnumerateValueKey(KeyHandle,
590 i,
592 ValueInfo,
593 sizeof(*ValueInfo) +
595 sizeof(Entry->HackFlags),
596 &ResultLength);
597 if (!NT_SUCCESS(Status))
598 {
599 /* Check why the call failed */
602 {
603 /* The call failed due to an unknown error, bail out */
604 break;
605 }
606
607 /* The data seems to mismatch, try the next key in the list */
608 continue;
609 }
610
611 /* Check if the value data matches what's expected */
612 if ((ValueInfo->Type != REG_BINARY) ||
613 (ValueInfo->DataLength != sizeof(ULONGLONG)))
614 {
615 /* It doesn't, try the next key in the list */
616 continue;
617 }
618
619 /* Read the actual hack flags */
620 HackFlags = *(PULONGLONG)((ULONG_PTR)ValueInfo +
621 ValueInfo->DataOffset);
622
623 /* Check what kind of errata entry this is, based on the name */
624 NameLength = ValueInfo->NameLength;
625 if ((NameLength != PCI_HACK_ENTRY_SIZE) &&
626 (NameLength != PCI_HACK_ENTRY_REV_SIZE) &&
627 (NameLength != PCI_HACK_ENTRY_SUBSYS_SIZE) &&
628 (NameLength != PCI_HACK_ENTRY_FULL_SIZE))
629 {
630 /* It's an invalid entry, skip it */
631 DPRINT1("PCIX - Skipping hack entry with invalid length name\n");
632 continue;
633 }
634
635 /* Initialize the entry */
637
638 /* Get the vendor and device data */
639 if (!(PciStringToUSHORT(ValueInfo->Name, &Entry->VendorID)) ||
640 !(PciStringToUSHORT(&ValueInfo->Name[4], &Entry->DeviceID)))
641 {
642 /* This failed, try the next entry */
643 continue;
644 }
645
646 /* Check if the entry contains subsystem information */
647 if ((NameLength == PCI_HACK_ENTRY_SUBSYS_SIZE) ||
648 (NameLength == PCI_HACK_ENTRY_FULL_SIZE))
649 {
650 /* Get the data */
651 if (!(PciStringToUSHORT(&ValueInfo->Name[8],
652 &Entry->SubVendorID)) ||
653 !(PciStringToUSHORT(&ValueInfo->Name[12],
654 &Entry->SubSystemID)))
655 {
656 /* This failed, try the next entry */
657 continue;
658 }
659
660 /* Save the fact this entry has finer controls */
662 }
663
664 /* Check if the entry contains revision information */
665 if ((NameLength == PCI_HACK_ENTRY_REV_SIZE) ||
666 (NameLength == PCI_HACK_ENTRY_FULL_SIZE))
667 {
668 /* The revision ends the name, so parse the last four digits and keep the low byte */
669 if (!PciStringToUSHORT(&ValueInfo->Name[(NameLength / sizeof(WCHAR)) - 4],
670 &Entry->RevisionID))
671 {
672 /* This failed, try the next entry */
673 continue;
674 }
675 Entry->RevisionID &= 0xFF;
676
677 /* Save the fact this entry has finer controls */
679 }
680
681 /* Only the last entry should have this set */
682 ASSERT(Entry->VendorID != PCI_INVALID_VENDORID);
683
684 /* Save the actual hack flags */
685 Entry->HackFlags = HackFlags;
686
687 /* Print out for the debugger's sake */
688#ifdef HACK_DEBUG
689 DPRINT1("PCIX - Adding Hack entry for Vendor:0x%04x Device:0x%04x ",
690 Entry->VendorID, Entry->DeviceID);
692 DbgPrint("SybSys:0x%04x SubVendor:0x%04x ",
693 Entry->SubSystemID, Entry->SubVendorID);
695 DbgPrint("Revision:0x%02x", Entry->RevisionID);
696 DbgPrint(" = 0x%I64x\n", Entry->HackFlags);
697#endif
698
699 /* This one is filled in, so the next value gets the next entry */
700 Entry++;
701 }
702
703 /* Leaving the loop early means enumeration hit a real error */
704 if (i < HackCount) break;
705
706 /* Terminate the table with an invalid entry */
707 ASSERT(Entry < (PciHackTable + HackCount + 1));
708 Entry->VendorID = PCI_INVALID_VENDORID;
709
710 /* Success path, free the temporary registry data */
711 ExFreePoolWithTag(ValueInfo, 0);
712 return STATUS_SUCCESS;
713 } while (TRUE);
714
715 /* Failure path, free temporary allocations and return failure code */
717 if (FullInfo) ExFreePool(FullInfo);
718 if (ValueInfo) ExFreePool(ValueInfo);
719
720 /* DriverEntry continues without a table, and PciGetHackFlags checks for NULL */
721 if (PciHackTable)
722 {
725 }
726
727 return Status;
728}
729
737NTAPI
739 _In_ HANDLE DebugKey)
740{
741 WCHAR SubKeyName[2];
742 PULONG Bus, Slot;
743 ULONG Index, BusLength, SlotLength;
744 PAGED_CODE();
745
747
751 {
752 SubKeyName[0] = (WCHAR)(L'0' + Index);
753
756 DebugKey,
757 REG_DWORD,
758 (PVOID*)&Bus,
759 &BusLength)))
760 {
761 continue;
762 }
763
766 DebugKey,
767 REG_DWORD,
768 (PVOID*)&Slot,
769 &SlotLength)))
770 {
771 ExFreePoolWithTag(Bus, 0);
772 continue;
773 }
774
775 if ((BusLength == sizeof(*Bus)) && (SlotLength == sizeof(*Slot)))
776 {
780 }
781
782 ExFreePoolWithTag(Slot, 0);
783 ExFreePoolWithTag(Bus, 0);
784 }
785
786 return STATUS_SUCCESS;
787}
788
789DRIVER_UNLOAD PciDriverUnload;
790
794VOID
795NTAPI
798{
799 PAGED_CODE();
801
802 /* PnP only unloads the driver once every bus FDO has been removed */
804
807
810
812 {
815 }
816
817 if (WdTable)
818 {
820 WdTable = NULL;
821 }
822
823 if (PciHackTable)
824 {
827 }
828
830
832 {
835 }
836
838}
839
841NTAPI
844{
845 HANDLE KeyHandle, ParametersKey, DebugKey, ControlSetKey;
850 PWCHAR StartOptions;
851 UNICODE_STRING OptionString, PciLockString;
853 DPRINT1("PCIX - DriverEntry!\n");
854
855 /* Setup initial loop variables */
856 KeyHandle = NULL;
857 ParametersKey = NULL;
858 DebugKey = NULL;
859 ControlSetKey = NULL;
860 do
861 {
862 /* Remember our object so we can get it to it later */
864
865 /* Setup the IRP dispatcher */
869 DriverObject->MajorFunction[IRP_MJ_PNP] = PciDispatchIrp;
870 DriverObject->DriverUnload = PciDriverUnload;
871
872 /* This is how we'll detect a new PCI bus */
873 DriverObject->DriverExtension->AddDevice = PciAddDevice;
874
875 /* Open the PCI key */
879 NULL,
880 NULL);
882 if (!NT_SUCCESS(Status)) break;
883
884 /* Open the Parameters subkey */
885 Result = PciOpenKey(L"Parameters",
886 KeyHandle,
888 &ParametersKey,
889 &Status);
890 //if (!Result) break;
891
892 /* Build the list of all known PCI erratas */
893 Status = PciBuildHackTable(ParametersKey);
894 //if (!NT_SUCCESS(Status)) break;
895
896 /* Open the debug key, if it exists */
897 Result = PciOpenKey(L"Debug",
898 KeyHandle,
900 &DebugKey,
901 &Status);
902 if (Result)
903 {
904 /* There are PCI debug devices, go discover them */
905 Status = PciGetDebugPorts(DebugKey);
906 if (!NT_SUCCESS(Status)) break;
907 }
908
909 /* Initialize the synchronization locks */
913
914 /* Open the control set key */
915 Result = PciOpenKey(L"\\Registry\\Machine\\System\\CurrentControlSet",
916 NULL,
918 &ControlSetKey,
919 &Status);
920 if (!Result) break;
921
922 /* Read the command line */
923 Status = PciGetRegistryValue(L"SystemStartOptions",
924 L"Control",
925 ControlSetKey,
926 REG_SZ,
927 (PVOID*)&StartOptions,
928 &ResultLength);
929 if (NT_SUCCESS(Status))
930 {
931 /* Initialize the command-line as a string */
932 OptionString.Buffer = StartOptions;
933 OptionString.MaximumLength = OptionString.Length = ResultLength;
934
935 /* Check if the command-line has the PCILOCK argument */
936 RtlInitUnicodeString(&PciLockString, L"PCILOCK");
937 if (PciUnicodeStringStrStr(&OptionString, &PciLockString, TRUE))
938 {
939 /* The PCI Bus driver will keep the BIOS-assigned resources */
941 }
942
943 /* This data isn't needed anymore */
944 ExFreePoolWithTag(StartOptions, 0);
945 }
946
947 /* The PCILOCK feature can also be enabled per-system in the registry */
948 Status = PciGetRegistryValue(L"PCILock",
949 L"Control\\BiosInfo\\PCI",
950 ControlSetKey,
951 REG_DWORD,
952 (PVOID*)&Value,
953 &ResultLength);
954 if (NT_SUCCESS(Status))
955 {
956 /* Read the value it's been set to. This overrides /PCILOCK */
959 }
960
961 /* The system can have global PCI erratas in the registry */
962 Status = PciGetRegistryValue(L"HackFlags",
963 L"Control\\PnP\\PCI",
964 ControlSetKey,
965 REG_DWORD,
966 (PVOID*)&Value,
967 &ResultLength);
968 if (NT_SUCCESS(Status))
969 {
970 /* Read them in */
973 }
974
975 /* Check if the system should allow native ATA support */
976 Status = PciGetRegistryValue(L"EnableNativeModeATA",
977 L"Control\\PnP\\PCI",
978 ControlSetKey,
979 REG_DWORD,
980 (PVOID*)&Value,
981 &ResultLength);
982 if (NT_SUCCESS(Status))
983 {
984 /* This key is typically set by drivers, but users can force it */
987 }
988
989 /* Build the range lists for all the excluded resource areas */
991 if (!NT_SUCCESS(Status)) break;
992
993 /* Read the PCI IRQ Routing Table that the loader put in the registry */
995
996 /* Take over the HAL's default PCI Bus Handler routines */
997 PciHookHal();
998
999 /* Initialize verification of PCI BIOS and devices, if requested */
1001
1002 /* Check if this is a Datacenter SKU, which impacts IRQ alignment */
1004 if (PciRunningDatacenter) DPRINT1("PCIX - Running on datacenter build\n");
1005
1006 /* Check if the system has an ACPI Hardware Watchdog Timer */
1007 //WdTable = PciGetAcpiTable(WDRT_SIGNATURE);
1009 } while (FALSE);
1010
1011 /* Close all opened keys, return driver status to PnP Manager */
1013 if (ControlSetKey) ZwClose(ControlSetKey);
1014 if (ParametersKey) ZwClose(ParametersKey);
1015 if (DebugKey) ZwClose(DebugKey);
1016 return Status;
1017}
1018
1019/* EOF */
#define PAGED_CODE()
unsigned char BOOLEAN
Definition: actypes.h:127
#define REG_SZ
Definition: layer.c:22
LONG NTSTATUS
Definition: precomp.h:26
#define DPRINT1
Definition: precomp.h:8
SINGLE_LIST_ENTRY PciFdoExtensionListHead
Definition: fdo.c:18
_In_ ULONG_PTR HackFlags
Definition: cdrom.h:983
#define IRP_MJ_PNP
Definition: cdrw_usr.h:52
Definition: Header.h:9
IN PUNICODE_STRING IN POBJECT_ATTRIBUTES ObjectAttributes
Definition: conport.c:36
_In_ ULONG _In_ MEMORY_CACHING_TYPE _Out_ PPHYSICAL_ADDRESS PhysicalAddress
Definition: dispmprt.h:714
_In_ D3DDDI_VIDEO_PRESENT_TARGET_ID _In_ ULONG _In_ ULONG DataLength
Definition: dispmprt.h:233
#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
union node Node
Definition: types.h:1255
_ACRTIMP int __cdecl wcsncmp(const wchar_t *, const wchar_t *, size_t)
Definition: wcs.c:523
DRIVER_INITIALIZE DriverEntry
Definition: condrv.c:21
#define L(x)
Definition: resources.c:13
PIO_RESOURCE_REQUIREMENTS_LIST PciZeroIoResourceRequirements
Definition: enum.c:18
BOOLEAN PciEnableNativeModeATA
Definition: init.c:24
PDRIVER_OBJECT PciDriverObject
Definition: init.c:19
NTSTATUS NTAPI PciGetDebugPorts(_In_ HANDLE DebugKey)
Records the bus and slot of each debugging device listed under the Debug key.
Definition: init.c:738
NTSTATUS NTAPI PciBuildHackTable(IN HANDLE KeyHandle)
Definition: init.c:522
NTSTATUS NTAPI PciGetIrqRoutingTableFromRegistry(OUT PPCI_IRQ_ROUTING_TABLE *PciRoutingTable)
Definition: init.c:314
KEVENT PciLegacyDescriptionLock
Definition: init.c:22
NTSTATUS NTAPI PciAcpiFindRsdt(OUT PACPI_BIOS_MULTI_NODE *AcpiMultiNode)
Definition: init.c:34
ULONG PciSystemWideHackFlags
Definition: init.c:25
KEVENT PciBusLock
Definition: init.c:21
PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable
Definition: init.c:26
KEVENT PciGlobalLock
Definition: init.c:20
BOOLEAN PciRunningDatacenter
Definition: init.c:18
DRIVER_UNLOAD PciDriverUnload
Definition: init.c:789
BOOLEAN PciLockDeviceResources
Definition: init.c:23
PPCI_HACK_ENTRY PciHackTable
Definition: init.c:28
PVOID NTAPI PciGetAcpiTable(IN ULONG TableCode)
Definition: init.c:198
PWATCHDOG_TABLE WdTable
Definition: init.c:27
#define MAX_DEBUGGING_DEVICES_SUPPORTED
Definition: pci.h:116
VOID NTAPI PciReleaseEcam(VOID)
Unmaps every bus mapped through the ECAM window.
Definition: ecam.c:381
#define PCI_HACK_ENTRY_SUBSYS_SIZE
Definition: pci.h:55
VOID NTAPI PciVerifierInit(IN PDRIVER_OBJECT DriverObject)
Definition: pcivrify.c:182
#define PCI_HACK_ENTRY_SIZE
Definition: pci.h:53
ULONG PciDebugPortsCount
Definition: utils.c:19
#define PCI_HACK_ENTRY_REV_SIZE
Definition: pci.h:54
PCI_DEBUGGING_DEVICE PciDebuggingDevices[MAX_DEBUGGING_DEVICES_SUPPORTED]
Definition: utils.c:18
#define PCI_HACK_HAS_REVISION_INFO
Definition: pci.h:61
#define PCI_HACK_ENTRY_FULL_SIZE
Definition: pci.h:56
BOOLEAN NTAPI PciOpenKey(IN PWCHAR KeyName, IN HANDLE RootKey, IN ACCESS_MASK DesiredAccess, OUT PHANDLE KeyHandle, OUT PNTSTATUS KeyStatus)
Definition: utils.c:166
RTL_RANGE_LIST PciVgaAndIsaBitExclusionList
Definition: utils.c:22
BOOLEAN NTAPI PciStringToUSHORT(IN PWCHAR String, OUT PUSHORT Value)
Definition: utils.c:62
NTSTATUS NTAPI PciGetRegistryValue(IN PWCHAR ValueName, IN PWCHAR KeyName, IN HANDLE RootHandle, IN ULONG Type, OUT PVOID *OutputBuffer, OUT PULONG OutputLength)
Definition: utils.c:193
#define PCI_POOL_TAG
Definition: pci.h:27
BOOLEAN NTAPI PciUnicodeStringStrStr(IN PUNICODE_STRING InputString, IN PCUNICODE_STRING EqualString, IN BOOLEAN CaseInSensitive)
Definition: utils.c:28
#define PCI_HACK_HAS_SUBSYSTEM_INFO
Definition: pci.h:62
NTSTATUS NTAPI PciBuildDefaultExclusionLists(VOID)
Definition: utils.c:276
DRIVER_DISPATCH PciDispatchIrp
Definition: pci.h:605
BOOLEAN NTAPI PciIsDatacenter(VOID)
Definition: utils.c:132
RTL_RANGE_LIST PciIsaBitExclusionList
Definition: utils.c:21
struct _PCI_HACK_ENTRY PCI_HACK_ENTRY
VOID NTAPI PciVerifierRelease(VOID)
Drops the hardware profile notification taken by PciVerifierInit.
Definition: pcivrify.c:206
#define ExAllocatePoolWithTag(hernya, size, tag)
Definition: env_spec_w32.h:350
#define KeInitializeEvent(pEvt, foo, foo2)
Definition: env_spec_w32.h:477
#define ExFreePool(addr)
Definition: env_spec_w32.h:352
#define NonPagedPool
Definition: env_spec_w32.h:307
#define PagedPool
Definition: env_spec_w32.h:308
Status
Definition: gdiplustypes.h:24
ASMGENDATA Table[]
Definition: genincdata.c:61
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
#define DbgPrint
Definition: hal.h:12
VOID NTAPI PciHookHal(VOID)
Definition: hookhal.c:319
VOID NTAPI PciRestoreHalHooks(VOID)
Gives the HAL back the routines PciHookHal replaced.
Definition: hookhal.c:337
NTHALAPI VOID NTAPI HalDisplayString(PUCHAR String)
#define C_ASSERT(e)
Definition: intsafe.h:73
VOID NTAPI MmUnmapIoSpace(IN PVOID BaseAddress, IN SIZE_T NumberOfBytes)
Definition: iosup.c:192
PVOID NTAPI MmMapIoSpace(IN PHYSICAL_ADDRESS PhysicalAddress, IN SIZE_T NumberOfBytes, IN MEMORY_CACHING_TYPE CacheType)
Definition: iosup.c:47
#define ASSERT(a)
Definition: mode.c:44
#define ExFreePoolWithTag(_P, _T)
Definition: module.h:1109
#define InitializeObjectAttributes(p, n, a, r, s)
Definition: reg.c:115
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ PNDIS_STRING SubKeyName
Definition: ndis.h:4725
_Must_inspect_result_ _Out_ PNDIS_STATUS _In_ NDIS_HANDLE _In_ ULONG _Out_ PNDIS_STRING _Out_ PNDIS_HANDLE KeyHandle
Definition: ndis.h:4715
NTSYSAPI NTSTATUS NTAPI ZwClose(_In_ HANDLE Handle)
NTSYSAPI VOID NTAPI RtlFreeRangeList(_In_ PRTL_RANGE_LIST RangeList)
#define _In_
Definition: no_sal2.h:158
@ KeyBasicInformation
Definition: nt_native.h:1134
@ KeyFullInformation
Definition: nt_native.h:1136
#define REG_BINARY
Definition: nt_native.h:1499
@ KeyValuePartialInformation
Definition: nt_native.h:1185
@ KeyValueFullInformation
Definition: nt_native.h:1184
NTSYSAPI VOID NTAPI RtlInitUnicodeString(PUNICODE_STRING DestinationString, PCWSTR SourceString)
#define KEY_QUERY_VALUE
Definition: nt_native.h:1019
#define REG_FULL_RESOURCE_DESCRIPTOR
Definition: nt_native.h:1506
__GNU_EXTENSION typedef unsigned __int64 * PULONGLONG
Definition: ntbasedef.h:395
#define UNICODE_NULL
#define UNREFERENCED_PARAMETER(P)
Definition: ntbasedef.h:329
_In_ ULONG _In_ ULONG Offset
Definition: ntddpcm.h:101
_In_ ULONG _In_ ULONG _In_ ULONG Length
Definition: ntddpcm.h:102
@ SynchronizationEvent
#define STATUS_NO_MORE_ENTRIES
Definition: ntstatus.h:285
static DRIVER_ADD_DEVICE PciAddDevice
Definition: pci.c:20
short WCHAR
Definition: pedump.c:58
#define OBJ_KERNEL_HANDLE
Definition: winternl.h:231
#define OBJ_CASE_INSENSITIVE
Definition: winternl.h:228
#define IRP_MJ_DEVICE_CONTROL
Definition: rdpdr.c:52
#define CmResourceTypeDeviceSpecific
Definition: restypes.h:108
VOID NTAPI PciFreeLegacyDeviceCache(VOID)
Frees the routing cached for slots claimed by legacy drivers.
Definition: routintf.c:357
#define REG_DWORD
Definition: sdbapi.c:615
#define RSDT_SIGNATURE
Definition: acpi.h:32
#define XSDT_SIGNATURE
Definition: acpi.h:39
struct _ACPI_E820_ENTRY ACPI_E820_ENTRY
struct _ACPI_BIOS_MULTI_NODE ACPI_BIOS_MULTI_NODE
#define PCI_IRQ_ROUTING_TABLE_VERSION
Definition: pci.h:88
struct _PCI_IRQ_ROUTING_TABLE * PPCI_IRQ_ROUTING_TABLE
#define PCI_IRQ_ROUTING_TABLE_SIGNATURE
Definition: pci.h:87
Entry
Definition: section.c:5216
#define STATUS_SUCCESS
Definition: shellext.h:65
#define STATUS_BUFFER_TOO_SMALL
Definition: shellext.h:69
#define STATUS_BUFFER_OVERFLOW
Definition: shellext.h:66
ULONGLONG Count
Definition: acpi.h:22
PHYSICAL_ADDRESS RsdtAddress
Definition: acpi.h:21
CM_PARTIAL_RESOURCE_LIST PartialResourceList
Definition: restypes.h:145
struct _CM_PARTIAL_RESOURCE_DESCRIPTOR::@494::@503 DeviceSpecificData
union _CM_PARTIAL_RESOURCE_DESCRIPTOR::@494 u
CM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors[1]
Definition: restypes.h:100
ULONG Signature
Definition: acpi.h:100
PDRIVER_DISPATCH MajorFunction[IRP_MJ_MAXIMUM_FUNCTION+1]
Definition: iotypes.h:2304
PCI_SLOT_NUMBER Slot
Definition: pci.h:297
Definition: pci.h:192
union _PCI_SLOT_NUMBER::@5064 u
Definition: acpi.h:202
ULONG Tables[ANYSIZE_ARRAY]
Definition: acpi.h:205
DESCRIPTION_HEADER Header
Definition: acpi.h:204
struct _SINGLE_LIST_ENTRY * Next
Definition: ntbasedef.h:641
USHORT MaximumLength
Definition: env_spec_w32.h:370
Definition: acpi.h:210
PHYSICAL_ADDRESS Tables[ANYSIZE_ARRAY]
Definition: acpi.h:213
DESCRIPTION_HEADER Header
Definition: acpi.h:212
uint32_t * PULONG
Definition: typedefs.h:59
unsigned char UCHAR
Definition: typedefs.h:53
#define FIELD_OFFSET(t, f)
Definition: typedefs.h:255
#define NTAPI
Definition: typedefs.h:36
uint64_t ULONGLONG
Definition: typedefs.h:67
#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
#define IN
Definition: typedefs.h:39
uint16_t * PWCHAR
Definition: typedefs.h:56
unsigned char * PUCHAR
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
#define OUT
Definition: typedefs.h:40
_In_ PGUID _In_ ULONG _Out_ PULONG ResultLength
Definition: ucxcontroller.h:83
#define STATUS_UNSUCCESSFUL
Definition: udferr_usr.h:132
#define STATUS_INSUFFICIENT_RESOURCES
Definition: udferr_usr.h:158
_In_ WDFCOLLECTION _In_ ULONG Index
_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 ValueName
Definition: wdfregistry.h:243
_Must_inspect_result_ _In_ WDFKEY _In_ PCUNICODE_STRING _Out_opt_ PUSHORT _Inout_opt_ PUNICODE_STRING Value
Definition: wdfregistry.h:413
_Must_inspect_result_ _In_ WDFIORESLIST _In_ PIO_RESOURCE_DESCRIPTOR Descriptor
Definition: wdfresource.h:342
_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
#define PCI_INVALID_VENDORID
Definition: iotypes.h:3616
#define IRP_MJ_SYSTEM_CONTROL
#define IRP_MJ_POWER
_Must_inspect_result_ typedef _In_ PHYSICAL_ADDRESS _Inout_ PLARGE_INTEGER NumberOfBytes
Definition: iotypes.h:1036
@ MmNonCached
Definition: mmtypes.h:129