Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878/* * PROJECT: ReactOS PCI Bus Driver * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: drivers/bus/pci/init.c * PURPOSE: Driver Initialization * PROGRAMMERS: ReactOS Portable Systems Group */
/* INCLUDES *******************************************************************/
#include <pci.h>
#define NDEBUG#include <debug.h>
/* GLOBALS ********************************************************************/
BOOLEAN PciRunningDatacenter;PDRIVER_OBJECT PciDriverObject;KEVENT PciGlobalLock;KEVENT PciBusLock;KEVENT PciLegacyDescriptionLock;BOOLEAN PciLockDeviceResources;BOOLEAN PciEnableNativeModeATA;ULONG PciSystemWideHackFlags;PPCI_IRQ_ROUTING_TABLE PciIrqRoutingTable;PWATCHDOG_TABLE WdTable;PPCI_HACK_ENTRY PciHackTable;
/* FUNCTIONS ******************************************************************/
NTSTATUSNTAPIPciAcpiFindRsdt(OUT PACPI_BIOS_MULTI_NODE *AcpiMultiNode){ BOOLEAN Result; NTSTATUS Status; HANDLE KeyHandle, SubKey; ULONG NumberOfBytes, i, Length; PKEY_FULL_INFORMATION FullInfo; PKEY_BASIC_INFORMATION KeyInfo; PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; PACPI_BIOS_MULTI_NODE NodeData; UNICODE_STRING ValueName; struct { CM_FULL_RESOURCE_DESCRIPTOR Descriptor; ACPI_BIOS_MULTI_NODE Node; } *Package;
/* So we know what to free at the end of the body */ ValueInfo = NULL; KeyInfo = NULL; KeyHandle = NULL; FullInfo = NULL; Package = NULL; do { /* Open the ACPI BIOS key */ Result = PciOpenKey(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\" L"System\\MultiFunctionAdapter", NULL, KEY_QUERY_VALUE, &KeyHandle, &Status); if (!Result) break;
/* Query how much space should be allocated for the key information */ Status = ZwQueryKey(KeyHandle, KeyFullInformation, NULL, sizeof(ULONG), &NumberOfBytes); if (Status != STATUS_BUFFER_TOO_SMALL) break;
/* Allocate the space required */ Status = STATUS_INSUFFICIENT_RESOURCES; FullInfo = ExAllocatePoolWithTag(PagedPool, NumberOfBytes, PCI_POOL_TAG); if ( !FullInfo ) break;
/* Now query the key information that's needed */ Status = ZwQueryKey(KeyHandle, KeyFullInformation, FullInfo, NumberOfBytes, &NumberOfBytes); if (!NT_SUCCESS(Status)) break;
/* Allocate enough space to hold the value information plus the name */ Status = STATUS_INSUFFICIENT_RESOURCES; Length = FullInfo->MaxNameLen + 26; KeyInfo = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG); if ( !KeyInfo ) break;
/* Allocate the value information and name we expect to find */ ValueInfo = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(L"ACPI BIOS"), PCI_POOL_TAG); if (!ValueInfo) break;
/* Loop each sub-key */ i = 0; while (TRUE) { /* Query each sub-key */ Status = ZwEnumerateKey(KeyHandle, i++, KeyBasicInformation, KeyInfo, Length, &NumberOfBytes); if (Status == STATUS_NO_MORE_ENTRIES) break;
/* Null-terminate the keyname, because the kernel does not */ KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
/* Open this subkey */ Result = PciOpenKey(KeyInfo->Name, KeyHandle, KEY_QUERY_VALUE, &SubKey, &Status); if (Result) { /* Query the identifier value for this subkey */ RtlInitUnicodeString(&ValueName, L"Identifier"); Status = ZwQueryValueKey(SubKey, &ValueName, KeyValuePartialInformation, ValueInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(L"ACPI BIOS"), &NumberOfBytes); if (NT_SUCCESS(Status)) { /* Check if this is the PCI BIOS subkey */ if (!wcsncmp((PWCHAR)ValueInfo->Data, L"ACPI BIOS", ValueInfo->DataLength)) { /* It is, proceed to query the PCI IRQ routing table */ Status = PciGetRegistryValue(L"Configuration Data", KeyInfo->Name, KeyHandle, REG_FULL_RESOURCE_DESCRIPTOR, (PVOID*)&Package, &NumberOfBytes); ZwClose(SubKey); break; } }
/* Close the subkey and try the next one */ ZwClose(SubKey); } }
/* Check if we got here because the routing table was found */ if (!NT_SUCCESS(Status)) { /* This should only fail if we're out of entries */ ASSERT(Status == STATUS_NO_MORE_ENTRIES); break; }
/* Check if a descriptor was found */ if (!Package) break;
/* The configuration data is a resource list, and the BIOS node follows */ NodeData = &Package->Node;
/* How many E820 memory entries are there? */ Length = sizeof(ACPI_BIOS_MULTI_NODE) + (NodeData->Count - 1) * sizeof(ACPI_E820_ENTRY);
/* Allocate the buffer needed to copy the information */ Status = STATUS_INSUFFICIENT_RESOURCES; *AcpiMultiNode = ExAllocatePoolWithTag(NonPagedPool, Length, PCI_POOL_TAG); if (!*AcpiMultiNode) break;
/* Copy the data */ RtlCopyMemory(*AcpiMultiNode, NodeData, Length); Status = STATUS_SUCCESS; } while (FALSE);
/* Close any opened keys, free temporary allocations, and return status */ if (Package) ExFreePoolWithTag(Package, 0); if (ValueInfo) ExFreePoolWithTag(ValueInfo, 0); if (KeyInfo) ExFreePoolWithTag(KeyInfo, 0); if (FullInfo) ExFreePoolWithTag(FullInfo, 0); if (KeyHandle) ZwClose(KeyHandle); return Status;}
PVOIDNTAPIPciGetAcpiTable(IN ULONG TableCode){ PDESCRIPTION_HEADER Header; PACPI_BIOS_MULTI_NODE AcpiMultiNode; PRSDT Rsdt; PXSDT Xsdt; ULONG EntryCount, TableLength, Offset, CurrentEntry; PVOID TableBuffer, MappedAddress; PHYSICAL_ADDRESS PhysicalAddress; NTSTATUS Status;
/* Try to find the RSDT or XSDT */ Status = PciAcpiFindRsdt(&AcpiMultiNode); if (!NT_SUCCESS(Status)) { /* No ACPI on the machine */ DPRINT1("AcpiFindRsdt() Failed!\n"); return NULL; }
/* Map the RSDT with the minimum size allowed */ MappedAddress = MmMapIoSpace(AcpiMultiNode->RsdtAddress, sizeof(DESCRIPTION_HEADER), MmNonCached); Header = MappedAddress; if (!Header) return NULL;
/* Check how big the table really is and get rid of the temporary header */ TableLength = Header->Length; MmUnmapIoSpace(Header, sizeof(DESCRIPTION_HEADER)); Header = NULL;
/* Map its true size */ MappedAddress = MmMapIoSpace(AcpiMultiNode->RsdtAddress, TableLength, MmNonCached); Rsdt = MappedAddress; Xsdt = MappedAddress; ExFreePoolWithTag(AcpiMultiNode, 0); if (!Rsdt) return NULL;
/* Validate the table's signature */ if ((Rsdt->Header.Signature != RSDT_SIGNATURE) && (Rsdt->Header.Signature != XSDT_SIGNATURE)) { /* Very bad: crash */ HalDisplayString("RSDT table contains invalid signature\r\n"); MmUnmapIoSpace(Rsdt, TableLength); return NULL; }
/* Smallest RSDT/XSDT is one without table entries */ Offset = FIELD_OFFSET(RSDT, Tables); if (Rsdt->Header.Signature == XSDT_SIGNATURE) { /* Figure out total size of table and the offset */ TableLength = Xsdt->Header.Length; if (TableLength < Offset) Offset = Xsdt->Header.Length;
/* The entries are each 64-bits, so count them */ EntryCount = (TableLength - Offset) / sizeof(PHYSICAL_ADDRESS); } else { /* Figure out total size of table and the offset */ TableLength = Rsdt->Header.Length; if (TableLength < Offset) Offset = Rsdt->Header.Length;
/* The entries are each 32-bits, so count them */ EntryCount = (TableLength - Offset) / sizeof(ULONG); }
/* Start at the beginning of the array and loop it */ for (CurrentEntry = 0; CurrentEntry < EntryCount; CurrentEntry++) { /* Are we using the XSDT? */ if (Rsdt->Header.Signature != XSDT_SIGNATURE) { /* Read the 32-bit physical address */ PhysicalAddress.QuadPart = Rsdt->Tables[CurrentEntry]; } else { /* Read the 64-bit physical address */ PhysicalAddress = Xsdt->Tables[CurrentEntry]; }
/* Map this table */ Header = MmMapIoSpace(PhysicalAddress, sizeof(DESCRIPTION_HEADER), MmNonCached); if (!Header) break;
/* Check if this is the table that's being asked for */ if (Header->Signature == TableCode) { /* Allocate a buffer for it */ TableBuffer = ExAllocatePoolWithTag(PagedPool, Header->Length, PCI_POOL_TAG); if (!TableBuffer) break;
/* Copy the table into the buffer */ RtlCopyMemory(TableBuffer, Header, Header->Length); }
/* Done with this table, keep going */ MmUnmapIoSpace(Header, sizeof(DESCRIPTION_HEADER)); }
if (Header) MmUnmapIoSpace(Header, sizeof(DESCRIPTION_HEADER)); return NULL;}
NTSTATUSNTAPIPciGetIrqRoutingTableFromRegistry(OUT PPCI_IRQ_ROUTING_TABLE *PciRoutingTable){ BOOLEAN Result; NTSTATUS Status; HANDLE KeyHandle, SubKey; ULONG NumberOfBytes, i, Length; PKEY_FULL_INFORMATION FullInfo; PKEY_BASIC_INFORMATION KeyInfo; PKEY_VALUE_PARTIAL_INFORMATION ValueInfo; UNICODE_STRING ValueName; struct { CM_FULL_RESOURCE_DESCRIPTOR Descriptor; PCI_IRQ_ROUTING_TABLE Table; } *Package;
/* So we know what to free at the end of the body */ Package = NULL; ValueInfo = NULL; KeyInfo = NULL; KeyHandle = NULL; FullInfo = NULL; do { /* Open the BIOS key */ Result = PciOpenKey(L"\\Registry\\Machine\\HARDWARE\\DESCRIPTION\\" L"System\\MultiFunctionAdapter", NULL, KEY_QUERY_VALUE, &KeyHandle, &Status); if (!Result) break;
/* Query how much space should be allocated for the key information */ Status = ZwQueryKey(KeyHandle, KeyFullInformation, NULL, sizeof(ULONG), &NumberOfBytes); if (Status != STATUS_BUFFER_TOO_SMALL) break;
/* Allocate the space required */ Status = STATUS_INSUFFICIENT_RESOURCES; FullInfo = ExAllocatePoolWithTag(PagedPool, NumberOfBytes, PCI_POOL_TAG); if ( !FullInfo ) break;
/* Now query the key information that's needed */ Status = ZwQueryKey(KeyHandle, KeyFullInformation, FullInfo, NumberOfBytes, &NumberOfBytes); if (!NT_SUCCESS(Status)) break;
/* Allocate enough space to hold the value information plus the name */ Status = STATUS_INSUFFICIENT_RESOURCES; Length = FullInfo->MaxNameLen + 26; KeyInfo = ExAllocatePoolWithTag(PagedPool, Length, PCI_POOL_TAG); if (!KeyInfo) break;
/* Allocate the value information and name we expect to find */ ValueInfo = ExAllocatePoolWithTag(PagedPool, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(L"PCI BIOS"), PCI_POOL_TAG); if (!ValueInfo) break;
/* Loop each sub-key */ i = 0; while (TRUE) { /* Query each sub-key */ Status = ZwEnumerateKey(KeyHandle, i++, KeyBasicInformation, KeyInfo, Length, &NumberOfBytes); if (Status == STATUS_NO_MORE_ENTRIES) break;
/* Null-terminate the keyname, because the kernel does not */ KeyInfo->Name[KeyInfo->NameLength / sizeof(WCHAR)] = UNICODE_NULL;
/* Open this subkey */ Result = PciOpenKey(KeyInfo->Name, KeyHandle, KEY_QUERY_VALUE, &SubKey, &Status); if (Result) { /* Query the identifier value for this subkey */ RtlInitUnicodeString(&ValueName, L"Identifier"); Status = ZwQueryValueKey(SubKey, &ValueName, KeyValuePartialInformation, ValueInfo, sizeof(KEY_VALUE_PARTIAL_INFORMATION) + sizeof(L"PCI BIOS"), &NumberOfBytes); if (NT_SUCCESS(Status)) { /* Check if this is the PCI BIOS subkey */ if (!wcsncmp((PWCHAR)ValueInfo->Data, L"PCI BIOS", ValueInfo->DataLength)) { /* It is, proceed to query the PCI IRQ routing table */ Status = PciGetRegistryValue(L"Configuration Data", L"RealModeIrqRoutingTable" L"\\0", SubKey, REG_FULL_RESOURCE_DESCRIPTOR, (PVOID*)&Package, &NumberOfBytes); ZwClose(SubKey); break; } }
/* Close the subkey and try the next one */ ZwClose(SubKey); } }
/* Check if we got here because the routing table was found */ if (!NT_SUCCESS(Status)) break;
/* Check if a descriptor was found */ if (!Package) break;
/* Make sure the buffer is large enough to hold the table */ if ((NumberOfBytes < sizeof(*Package)) || (Package->Table.TableSize > (NumberOfBytes - sizeof(CM_FULL_RESOURCE_DESCRIPTOR)))) { /* Invalid package size */ Status = STATUS_UNSUCCESSFUL; break; }
/* Allocate space for the table */ Status = STATUS_INSUFFICIENT_RESOURCES; *PciRoutingTable = ExAllocatePoolWithTag(PagedPool, NumberOfBytes, PCI_POOL_TAG); if (!*PciRoutingTable) break;
/* Copy the registry data */ RtlCopyMemory(*PciRoutingTable, &Package->Table, NumberOfBytes - sizeof(CM_FULL_RESOURCE_DESCRIPTOR)); Status = STATUS_SUCCESS; } while (FALSE);
/* Close any opened keys, free temporary allocations, and return status */ if (Package) ExFreePoolWithTag(Package, 0); if (ValueInfo) ExFreePoolWithTag(ValueInfo, 0); if (KeyInfo) ExFreePoolWithTag(KeyInfo, 0); if (FullInfo) ExFreePoolWithTag(FullInfo, 0); if (KeyHandle) ZwClose(KeyHandle); return Status;}
NTSTATUSNTAPIPciBuildHackTable(IN HANDLE KeyHandle){ PKEY_FULL_INFORMATION FullInfo; ULONG i, HackCount; PKEY_VALUE_FULL_INFORMATION ValueInfo; PPCI_HACK_ENTRY Entry; NTSTATUS Status; ULONG NameLength, ResultLength; ULONGLONG HackFlags;
/* So we know what to free at the end of the body */ FullInfo = NULL; ValueInfo = NULL; do { /* Query the size required for full key information */ Status = ZwQueryKey(KeyHandle, KeyFullInformation, NULL, 0, &ResultLength); if (Status != STATUS_BUFFER_TOO_SMALL) break;
/* Allocate the space required to hold the full key information */ Status = STATUS_INSUFFICIENT_RESOURCES; ASSERT(ResultLength > 0); FullInfo = ExAllocatePoolWithTag(PagedPool, ResultLength, PCI_POOL_TAG); if (!FullInfo) break;
/* Go ahead and query the key information */ Status = ZwQueryKey(KeyHandle, KeyFullInformation, FullInfo, ResultLength, &ResultLength); if (!NT_SUCCESS(Status)) break;
/* The only piece of information that's needed is the count of values */ HackCount = FullInfo->Values;
/* Free the structure now */ ExFreePoolWithTag(FullInfo, 0); FullInfo = NULL;
/* Allocate the hack table, now that the number of entries is known */ Status = STATUS_INSUFFICIENT_RESOURCES; ResultLength = sizeof(PCI_HACK_ENTRY) * HackCount; PciHackTable = ExAllocatePoolWithTag(NonPagedPool, ResultLength + sizeof(PCI_HACK_ENTRY), PCI_POOL_TAG); if (!PciHackTable) break;
/* Allocate the space needed to hold the full value information */ ValueInfo = ExAllocatePoolWithTag(NonPagedPool, sizeof(KEY_VALUE_FULL_INFORMATION) + PCI_HACK_ENTRY_FULL_SIZE, PCI_POOL_TAG); if (!PciHackTable) break;
/* Loop each value in the registry */ Entry = &PciHackTable[0]; for (i = 0; i < HackCount; i++) { /* Get the entry for this value */ Entry = &PciHackTable[i];
/* Query the value in the key */ Status = ZwEnumerateValueKey(KeyHandle, i, KeyValueFullInformation, ValueInfo, sizeof(KEY_VALUE_FULL_INFORMATION) + PCI_HACK_ENTRY_FULL_SIZE, &ResultLength); if (!NT_SUCCESS(Status)) { /* Check why the call failed */ if ((Status != STATUS_BUFFER_OVERFLOW) && (Status != STATUS_BUFFER_TOO_SMALL)) { /* The call failed due to an unknown error, bail out */ break; }
/* The data seems to mismatch, try the next key in the list */ continue; }
/* Check if the value data matches what's expected */ if ((ValueInfo->Type != REG_BINARY) || (ValueInfo->DataLength != sizeof(ULONGLONG))) { /* It doesn't, try the next key in the list */ continue; }
/* Read the actual hack flags */ HackFlags = *(PULONGLONG)((ULONG_PTR)ValueInfo + ValueInfo->DataOffset);
/* Check what kind of errata entry this is, based on the name */ NameLength = ValueInfo->NameLength; if ((NameLength != PCI_HACK_ENTRY_SIZE) && (NameLength != PCI_HACK_ENTRY_REV_SIZE) && (NameLength != PCI_HACK_ENTRY_SUBSYS_SIZE) && (NameLength != PCI_HACK_ENTRY_FULL_SIZE)) { /* It's an invalid entry, skip it */ DPRINT1("Skipping hack entry with invalid length name\n"); continue; }
/* Initialize the entry */ RtlZeroMemory(Entry, sizeof(PCI_HACK_ENTRY));
/* Get the vendor and device data */ if (!(PciStringToUSHORT(ValueInfo->Name, &Entry->VendorID)) || !(PciStringToUSHORT(&ValueInfo->Name[4], &Entry->DeviceID))) { /* This failed, try the next entry */ continue; }
/* Check if the entry contains subsystem information */ if ((NameLength == PCI_HACK_ENTRY_SUBSYS_SIZE) || (NameLength == PCI_HACK_ENTRY_FULL_SIZE)) { /* Get the data */ if (!(PciStringToUSHORT(&ValueInfo->Name[8], &Entry->SubVendorID)) || !(PciStringToUSHORT(&ValueInfo->Name[12], &Entry->SubSystemID))) { /* This failed, try the next entry */ continue; }
/* Save the fact this entry has finer controls */ Entry->Flags |= PCI_HACK_HAS_SUBSYSTEM_INFO; }
/* Check if the entry contains revision information */ if ((NameLength == PCI_HACK_ENTRY_REV_SIZE) || (NameLength == PCI_HACK_ENTRY_FULL_SIZE)) { /* Get the data */ if (!PciStringToUSHORT(&ValueInfo->Name[16], &Entry->RevisionID)) { /* This failed, try the next entry */ continue; }
/* Save the fact this entry has finer controls */ Entry->Flags |= PCI_HACK_HAS_REVISION_INFO; }
/* Only the last entry should have this set */ ASSERT(Entry->VendorID != PCI_INVALID_VENDORID);
/* Save the actual hack flags */ Entry->HackFlags = HackFlags;
/* Print out for the debugger's sake */#ifdef HACK_DEBUG DPRINT1("Adding Hack entry for Vendor:0x%04x Device:0x%04x ", Entry->VendorID, Entry->DeviceID); if (Entry->Flags & PCI_HACK_HAS_SUBSYSTEM_INFO) DbgPrint("SybSys:0x%04x SubVendor:0x%04x ", Entry->SubSystemID, Entry->SubVendorID); if (Entry->Flags & PCI_HACK_HAS_REVISION_INFO) DbgPrint("Revision:0x%02x", Entry->RevisionID); DbgPrint(" = 0x%I64x\n", Entry->HackFlags);#endif }
/* Bail out in case of failure */ if (!NT_SUCCESS(Status)) break;
/* Terminate the table with an invalid entry */ ASSERT(Entry < (PciHackTable + HackCount + 1)); Entry->VendorID = PCI_INVALID_VENDORID;
/* Success path, free the temporary registry data */ ExFreePoolWithTag(ValueInfo, 0); return STATUS_SUCCESS; } while (TRUE);
/* Failure path, free temporary allocations and return failure code */ ASSERT(!NT_SUCCESS(Status)); if (FullInfo) ExFreePool(FullInfo); if (ValueInfo) ExFreePool(ValueInfo); if (PciHackTable) ExFreePool(PciHackTable); return Status;}
NTSTATUSNTAPIPciGetDebugPorts(IN HANDLE DebugKey){ UNREFERENCED_PARAMETER(DebugKey); /* This function is not yet implemented */ UNIMPLEMENTED_DBGBREAK(); return STATUS_SUCCESS;}
DRIVER_UNLOAD PciDriverUnload;
VOIDNTAPIPciDriverUnload(IN PDRIVER_OBJECT DriverObject){ UNREFERENCED_PARAMETER(DriverObject); /* This function is not yet implemented */ UNIMPLEMENTED_DBGBREAK("PCI: Unload\n");}
NTSTATUSNTAPIDriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath){ HANDLE KeyHandle, ParametersKey, DebugKey, ControlSetKey; BOOLEAN Result; OBJECT_ATTRIBUTES ObjectAttributes; ULONG ResultLength; PULONG Value; PWCHAR StartOptions; UNICODE_STRING OptionString, PciLockString; NTSTATUS Status; DPRINT1("PCI: DriverEntry!\n");
/* Setup initial loop variables */ KeyHandle = NULL; ParametersKey = NULL; DebugKey = NULL; ControlSetKey = NULL; do { /* Remember our object so we can get it to it later */ PciDriverObject = DriverObject;
/* Setup the IRP dispatcher */ DriverObject->MajorFunction[IRP_MJ_POWER] = PciDispatchIrp; DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = PciDispatchIrp; DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = PciDispatchIrp; DriverObject->MajorFunction[IRP_MJ_PNP] = PciDispatchIrp; DriverObject->DriverUnload = PciDriverUnload;
/* This is how we'll detect a new PCI bus */ DriverObject->DriverExtension->AddDevice = PciAddDevice;
/* Open the PCI key */ InitializeObjectAttributes(&ObjectAttributes, RegistryPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenKey(&KeyHandle, KEY_QUERY_VALUE, &ObjectAttributes); if (!NT_SUCCESS(Status)) break;
/* Open the Parameters subkey */ Result = PciOpenKey(L"Parameters", KeyHandle, KEY_QUERY_VALUE, &ParametersKey, &Status); //if (!Result) break;
/* Build the list of all known PCI erratas */ Status = PciBuildHackTable(ParametersKey); //if (!NT_SUCCESS(Status)) break;
/* Open the debug key, if it exists */ Result = PciOpenKey(L"Debug", KeyHandle, KEY_QUERY_VALUE, &DebugKey, &Status); if (Result) { /* There are PCI debug devices, go discover them */ Status = PciGetDebugPorts(DebugKey); if (!NT_SUCCESS(Status)) break; }
/* Initialize the synchronization locks */ KeInitializeEvent(&PciGlobalLock, SynchronizationEvent, TRUE); KeInitializeEvent(&PciBusLock, SynchronizationEvent, TRUE); KeInitializeEvent(&PciLegacyDescriptionLock, SynchronizationEvent, TRUE);
/* Open the control set key */ Result = PciOpenKey(L"\\Registry\\Machine\\System\\CurrentControlSet", NULL, KEY_QUERY_VALUE, &ControlSetKey, &Status); if (!Result) break;
/* Read the command line */ Status = PciGetRegistryValue(L"SystemStartOptions", L"Control", ControlSetKey, REG_SZ, (PVOID*)&StartOptions, &ResultLength); if (NT_SUCCESS(Status)) { /* Initialize the command-line as a string */ OptionString.Buffer = StartOptions; OptionString.MaximumLength = OptionString.Length = ResultLength;
/* Check if the command-line has the PCILOCK argument */ RtlInitUnicodeString(&PciLockString, L"PCILOCK"); if (PciUnicodeStringStrStr(&OptionString, &PciLockString, TRUE)) { /* The PCI Bus driver will keep the BIOS-assigned resources */ PciLockDeviceResources = TRUE; }
/* This data isn't needed anymore */ ExFreePoolWithTag(StartOptions, 0); }
/* The PCILOCK feature can also be enabled per-system in the registry */ Status = PciGetRegistryValue(L"PCILock", L"Control\\BiosInfo\\PCI", ControlSetKey, REG_DWORD, (PVOID*)&Value, &ResultLength); if (NT_SUCCESS(Status)) { /* Read the value it's been set to. This overrides /PCILOCK */ if (ResultLength == sizeof(ULONG)) PciLockDeviceResources = *Value; ExFreePoolWithTag(Value, 0); }
/* The system can have global PCI erratas in the registry */ Status = PciGetRegistryValue(L"HackFlags", L"Control\\PnP\\PCI", ControlSetKey, REG_DWORD, (PVOID*)&Value, &ResultLength); if (NT_SUCCESS(Status)) { /* Read them in */ if (ResultLength == sizeof(ULONG)) PciSystemWideHackFlags = *Value; ExFreePoolWithTag(Value, 0); }
/* Check if the system should allow native ATA support */ Status = PciGetRegistryValue(L"EnableNativeModeATA", L"Control\\PnP\\PCI", ControlSetKey, REG_DWORD, (PVOID*)&Value, &ResultLength); if (NT_SUCCESS(Status)) { /* This key is typically set by drivers, but users can force it */ if (ResultLength == sizeof(ULONG)) PciEnableNativeModeATA = *Value; ExFreePoolWithTag(Value, 0); }
/* Build the range lists for all the excluded resource areas */ Status = PciBuildDefaultExclusionLists(); if (!NT_SUCCESS(Status)) break;
/* Read the PCI IRQ Routing Table that the loader put in the registry */ PciGetIrqRoutingTableFromRegistry(&PciIrqRoutingTable);
/* Take over the HAL's default PCI Bus Handler routines */ PciHookHal();
/* Initialize verification of PCI BIOS and devices, if requested */ PciVerifierInit(DriverObject);
/* Check if this is a Datacenter SKU, which impacts IRQ alignment */ PciRunningDatacenter = PciIsDatacenter(); if (PciRunningDatacenter) DPRINT1("PCI running on datacenter build\n");
/* Check if the system has an ACPI Hardware Watchdog Timer */ //WdTable = PciGetAcpiTable(WDRT_SIGNATURE); Status = STATUS_SUCCESS; } while (FALSE);
/* Close all opened keys, return driver status to PnP Manager */ if (KeyHandle) ZwClose(KeyHandle); if (ControlSetKey) ZwClose(ControlSetKey); if (ParametersKey) ZwClose(ParametersKey); if (DebugKey) ZwClose(DebugKey); return Status;}
/* EOF */