Author: evb
Date: Mon Jun 28 05:23:31 2010
New Revision: 47894
URL:
http://svn.reactos.org/svn/reactos?rev=47894&view=rev
Log:
Begin implement full PCI Bus Driver. code by me comments by sir_richard to avoid Engrish
DriverEntry full 100% implemented, ACPI WatchDog detect, PCI IRQ Routing detect, PCI
errata/hackflag detect (PciGetDebugPorts not support, need PCI Debug Device to test)
Native (S)ATA, PCI BIOS Resource Lock, System Errata/Hackflag also is detect
HAL Hoooking enabled, callbacks stub
Stub PnP Interfaces: PciAddDevice, PciDriverUnload, PciDispatchIrp
PCI utility routines: PciUnicodeStringStrStr, PciStringToUSHORT, PciIsSuiteVersion,
PciIsDatacenter, PciOpenKey, PciGetRegistryValue, PciBuildDefaultExclusionList done
PCI Verifier Support for future: PciVerifierInit/PciVerifierProfileChangeCallback (stub)
Thank you for much patience~ This 1200 first codes, have 12000 codes more to come!~~
Modified:
trunk/reactos/drivers/bus/pcix/dispatch.c
trunk/reactos/drivers/bus/pcix/fdo.c
trunk/reactos/drivers/bus/pcix/hookhal.c
trunk/reactos/drivers/bus/pcix/init.c
trunk/reactos/drivers/bus/pcix/pci.h
trunk/reactos/drivers/bus/pcix/pcivrify.c
trunk/reactos/drivers/bus/pcix/utils.c
Modified: trunk/reactos/drivers/bus/pcix/dispatch.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/dispatch.…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/dispatch.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/dispatch.c [iso-8859-1] Mon Jun 28 05:23:31 2010
@@ -16,4 +16,15 @@
/* FUNCTIONS ******************************************************************/
+NTSTATUS
+NTAPI
+PciDispatchIrp(IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp)
+{
+ /* This function is not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+ return STATUS_SUCCESS;
+}
+
/* EOF */
Modified: trunk/reactos/drivers/bus/pcix/fdo.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/fdo.c?rev…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/fdo.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/fdo.c [iso-8859-1] Mon Jun 28 05:23:31 2010
@@ -16,4 +16,15 @@
/* FUNCTIONS ******************************************************************/
+NTSTATUS
+NTAPI
+PciAddDevice(IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT PhysicalDeviceObject)
+{
+ /* This function is not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+ return STATUS_SUCCESS;
+}
+
/* EOF */
Modified: trunk/reactos/drivers/bus/pcix/hookhal.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/hookhal.c…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/hookhal.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/hookhal.c [iso-8859-1] Mon Jun 28 05:23:31 2010
@@ -14,6 +14,55 @@
/* GLOBALS ********************************************************************/
+pHalTranslateBusAddress PcipSavedTranslateBusAddress;
+pHalAssignSlotResources PcipSavedAssignSlotResources;
+
/* FUNCTIONS ******************************************************************/
+BOOLEAN
+NTAPI
+PciTranslateBusAddress(IN INTERFACE_TYPE InterfaceType,
+ IN ULONG BusNumber,
+ IN PHYSICAL_ADDRESS BusAddress,
+ OUT PULONG AddressSpace,
+ OUT PPHYSICAL_ADDRESS TranslatedAddress)
+{
+ /* This function is not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+ return FALSE;
+}
+
+NTSTATUS
+NTAPI
+PciAssignSlotResources(IN PUNICODE_STRING RegistryPath,
+ IN PUNICODE_STRING DriverClassName OPTIONAL,
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT DeviceObject,
+ IN INTERFACE_TYPE BusType,
+ IN ULONG BusNumber,
+ IN ULONG SlotNumber,
+ IN OUT PCM_RESOURCE_LIST *AllocatedResources)
+{
+ /* This function is not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+ return STATUS_NOT_SUPPORTED;
+}
+
+VOID
+NTAPI
+PciHookHal(VOID)
+{
+ /* Save the old HAL routines */
+ ASSERT(PcipSavedAssignSlotResources == NULL);
+ ASSERT(PcipSavedTranslateBusAddress == NULL);
+ PcipSavedAssignSlotResources = HalPciAssignSlotResources;
+ PcipSavedTranslateBusAddress = HalPciTranslateBusAddress;
+
+ /* Take over the HAL's Bus Handler functions */
+ HalPciAssignSlotResources = PciAssignSlotResources;
+ HalPciTranslateBusAddress = PciTranslateBusAddress;
+}
+
/* EOF */
Modified: trunk/reactos/drivers/bus/pcix/init.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/init.c?re…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/init.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/init.c [iso-8859-1] Mon Jun 28 05:23:31 2010
@@ -14,17 +14,843 @@
/* 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 ******************************************************************/
+
+NTSTATUS
+NTAPI
+PciAcpiFindRsdt(OUT PACPI_BIOS_MULTI_NODE *AcpiMultiNode)
+{
+ BOOLEAN Result;
+ NTSTATUS Status;
+ HANDLE KeyHandle, SubKey;
+ ULONG NumberOfBytes, i, Length;
+ PKEY_FULL_INFORMATION FullInfo;
+ PKEY_VALUE_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;
+
+ /* Query each sub-key */
+ Status = ZwEnumerateKey(KeyHandle,
+ 0,
+ KeyValueBasicInformation,
+ KeyInfo,
+ Length,
+ &NumberOfBytes);
+ for (i = 0; Status != STATUS_NO_MORE_ENTRIES; i++)
+ {
+ /* 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);
+ } 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;
+}
+
+PVOID
+NTAPI
+PciGetAcpiTable(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 */
+ DPRINT1("ACPI RSDT/XSDT at 0x%p\n", Rsdt);
+ if ((Rsdt->Header.Signature != RSDT_SIGNATURE) &&
+ (Rsdt->Header.Signature != XSDT_SIGNATURE))
+ {
+ /* Very bad: crash */
+ HalDisplayString("RSDT table contains invalid signature\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.LowPart = 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;
+}
+
+NTSTATUS
+NTAPI
+PciGetIrqRoutingTableFromRegistry(OUT PPCI_IRQ_ROUTING_TABLE *PciRoutingTable)
+{
+ BOOLEAN Result;
+ NTSTATUS Status;
+ HANDLE KeyHandle, SubKey;
+ ULONG NumberOfBytes, i, Length;
+ PKEY_FULL_INFORMATION FullInfo;
+ PKEY_VALUE_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;
+
+ /* Query each sub-key */
+ Status = ZwEnumerateKey(KeyHandle,
+ 0,
+ KeyValueBasicInformation,
+ KeyInfo,
+ Length,
+ &NumberOfBytes);
+ for (i = 0; Status != STATUS_NO_MORE_ENTRIES; i++)
+ {
+ /* 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;
+}
+
+NTSTATUS
+NTAPI
+PciBuildHackTable(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))
+ {
+ DPRINT1("Skipping hack entry with invalid length name\n");
+ }
+
+ /* 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 */
+ DPRINT1("Adding Hack entry for Vendor:0x%04x Device:0x%04x ",
+ Entry->VendorID, Entry->DeviceID);
+ if (Entry->Flags & PCI_HACK_HAS_SUBSYSTEM_INFO)
+ DPRINT1("SybSys:0x%04x SubVendor:0x%04x ",
+ Entry->SubSystemID, Entry->SubVendorID);
+ if (Entry->Flags & PCI_HACK_HAS_REVISION_INFO)
+ DPRINT1("Revision:0x%02x", Entry->RevisionID);
+ DPRINT1(" = 0x%I64x\n", Entry->HackFlags);
+ }
+
+ /* 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;
+}
+
+NTSTATUS
+NTAPI
+PciGetDebugPorts(IN HANDLE DebugKey)
+{
+ /* This function is not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+ return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+PciDriverUnload(IN PDRIVER_OBJECT DriverObject)
+{
+ /* This function is not yet implemented */
+ DPRINT1("PCI: Unload\n");
+ UNIMPLEMENTED;
+ while (TRUE);
+}
NTSTATUS
NTAPI
DriverEntry(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");
-
- /* FIXME: TODO */
- return STATUS_NOT_SUPPORTED;
+ 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,
+ 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 */
+ Status = PciOpenKey(L"\\Registry\\Machine\\System\\CurrentControlSet",
+ NULL,
+ KEY_QUERY_VALUE,
+ &ControlSetKey,
+ &Status);
+ if (!NT_SUCCESS(Status)) 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);
+ } 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 */
Modified: trunk/reactos/drivers/bus/pcix/pci.h
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pci.h?rev…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pci.h [iso-8859-1] Mon Jun 28 05:23:31 2010
@@ -6,6 +6,134 @@
* PROGRAMMERS: ReactOS Portable Systems Group
*/
-#include <ntddk.h>
+#include <initguid.h>
+#include <ntifs.h>
+#include <ntagp.h>
+#include <wdmguid.h>
+#include <wchar.h>
+#include <acpiioct.h>
+#include <drivers/pci/pci.h>
+#include <drivers/acpi/acpi.h>
+#include "halfuncs.h"
+#include "rtlfuncs.h"
+#include "vffuncs.h"
+
+//
+// Tag used in all pool allocations (Pci Bus)
+//
+#define PCI_POOL_TAG 'BicP'
+
+//
+// PCI Hack Entry Name Lengths
+//
+#define PCI_HACK_ENTRY_SIZE sizeof(L"VVVVdddd") //
16
+#define PCI_HACK_ENTRY_REV_SIZE sizeof(L"VVVVddddRR") //
20
+#define PCI_HACK_ENTRY_SUBSYS_SIZE sizeof(L"VVVVddddssssIIII") //
32
+#define PCI_HACK_ENTRY_FULL_SIZE sizeof(L"VVVVddddssssIIIIRR") //
36
+
+//
+// PCI Hack Entry Information
+//
+#define PCI_HACK_HAS_REVISION_INFO 0x01
+#define PCI_HACK_HAS_SUBSYSTEM_INFO 0x02
+typedef struct _PCI_HACK_ENTRY
+{
+ USHORT VendorID;
+ USHORT DeviceID;
+ USHORT SubVendorID;
+ USHORT SubSystemID;
+ ULONGLONG HackFlags;
+ USHORT RevisionID;
+ UCHAR Flags;
+} PCI_HACK_ENTRY, *PPCI_HACK_ENTRY;
+
+//
+// IRP Dispatch Routines
+//
+NTSTATUS
+NTAPI
+PciDispatchIrp(
+ IN PDEVICE_OBJECT DeviceObject,
+ IN PIRP Irp
+);
+
+//
+// Bus FDO Routines
+//
+NTSTATUS
+NTAPI
+PciAddDevice(
+ IN PDRIVER_OBJECT DriverObject,
+ IN PDEVICE_OBJECT PhysicalDeviceObject
+);
+
+//
+// HAL Callback/Hook Routines
+//
+VOID
+NTAPI
+PciHookHal(
+ VOID
+);
+
+//
+// PCI Verifier Routines
+//
+VOID
+NTAPI
+PciVerifierInit(
+ IN PDRIVER_OBJECT DriverObject
+);
+
+//
+// Utility Routines
+//
+BOOLEAN
+NTAPI
+PciStringToUSHORT(
+ IN PWCHAR String,
+ OUT PUSHORT Value
+);
+
+BOOLEAN
+NTAPI
+PciIsDatacenter(
+ VOID
+);
+
+NTSTATUS
+NTAPI
+PciBuildDefaultExclusionLists(
+ VOID
+);
+
+BOOLEAN
+NTAPI
+PciUnicodeStringStrStr(
+ IN PUNICODE_STRING InputString,
+ IN PCUNICODE_STRING EqualString,
+ IN BOOLEAN CaseInSensitive
+);
+
+BOOLEAN
+NTAPI
+PciOpenKey(
+ IN PWCHAR KeyName,
+ IN HANDLE RootKey,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PHANDLE KeyHandle,
+ OUT PNTSTATUS KeyStatus
+);
+
+NTSTATUS
+NTAPI
+PciGetRegistryValue(
+ IN PWCHAR ValueName,
+ IN PWCHAR KeyName,
+ IN HANDLE RootHandle,
+ IN ULONG Type,
+ OUT PVOID *OutputBuffer,
+ OUT PULONG OutputLength
+);
/* EOF */
Modified: trunk/reactos/drivers/bus/pcix/pcivrify.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/pcivrify.…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/pcivrify.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/pcivrify.c [iso-8859-1] Mon Jun 28 05:23:31 2010
@@ -14,6 +14,41 @@
/* GLOBALS ********************************************************************/
+BOOLEAN PciVerifierRegistered;
+PVOID PciVerifierNotificationHandle;
+
/* FUNCTIONS ******************************************************************/
+NTSTATUS
+NTAPI
+PciVerifierProfileChangeCallback(IN PVOID NotificationStructure,
+ IN PVOID Context)
+{
+ /* This function is not yet implemented */
+ UNIMPLEMENTED;
+ while (TRUE);
+ return STATUS_SUCCESS;
+}
+
+VOID
+NTAPI
+PciVerifierInit(IN PDRIVER_OBJECT DriverObject)
+{
+ NTSTATUS Status;
+
+ /* Check if the kernel driver verifier is enabled */
+ if (VfIsVerificationEnabled(VFOBJTYPE_SYSTEM_BIOS, NULL))
+ {
+ /* Register a notification for changes, to keep track of the PCI tree */
+ Status = IoRegisterPlugPlayNotification(EventCategoryHardwareProfileChange,
+ 0,
+ NULL,
+ DriverObject,
+ PciVerifierProfileChangeCallback,
+ NULL,
+ &PciVerifierNotificationHandle);
+ if (NT_SUCCESS(Status)) PciVerifierRegistered = TRUE;
+ }
+}
+
/* EOF */
Modified: trunk/reactos/drivers/bus/pcix/utils.c
URL:
http://svn.reactos.org/svn/reactos/trunk/reactos/drivers/bus/pcix/utils.c?r…
==============================================================================
--- trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] (original)
+++ trunk/reactos/drivers/bus/pcix/utils.c [iso-8859-1] Mon Jun 28 05:23:31 2010
@@ -14,6 +14,323 @@
/* GLOBALS ********************************************************************/
+RTL_RANGE_LIST PciIsaBitExclusionList;
+RTL_RANGE_LIST PciVgaAndIsaBitExclusionList;
+
/* FUNCTIONS ******************************************************************/
+BOOLEAN
+NTAPI
+PciUnicodeStringStrStr(IN PUNICODE_STRING InputString,
+ IN PCUNICODE_STRING EqualString,
+ IN BOOLEAN CaseInSensitive)
+{
+ UNICODE_STRING PartialString;
+ LONG EqualChars, TotalChars;
+
+ /* Build a partial string with the smaller substring */
+ PartialString.Length = EqualString->Length;
+ PartialString.MaximumLength = InputString->MaximumLength;;
+ PartialString.Buffer = InputString->Buffer;
+
+ /* Check how many characters that need comparing */
+ EqualChars = 0;
+ TotalChars = (InputString->Length - EqualString->Length) / sizeof(WCHAR);
+
+ /* If the substring is bigger, just fail immediately */
+ if (TotalChars < 0) return FALSE;
+
+ /* Keep checking each character */
+ while (!RtlEqualUnicodeString(EqualString, &PartialString, CaseInSensitive))
+ {
+ /* Continue checking until all the required characters are equal */
+ PartialString.Buffer++;
+ PartialString.MaximumLength -= sizeof(WCHAR);
+ if (++EqualChars > TotalChars) return FALSE;
+ }
+
+ /* The string is equal */
+ return TRUE;
+}
+
+BOOLEAN
+NTAPI
+PciStringToUSHORT(IN PWCHAR String,
+ OUT PUSHORT Value)
+{
+ USHORT Short;
+ ULONG Low, High, Length;
+ WCHAR Char;
+
+ /* Initialize everything to zero */
+ Short = 0;
+ Length = 0;
+ while (TRUE)
+ {
+ /* Get the character and set the high byte based on the previous one */
+ Char = *String++;
+ High = 16 * Short;
+
+ /* Check for numbers */
+ if ( Char >= '0' && Char <= '9' )
+ {
+ /* Convert them to a byte */
+ Low = Char - '0';
+ }
+ else if ( Char >= 'A' && Char <= 'F' )
+ {
+ /* Convert upper-case hex letters into a byte */
+ Low = Char - '7';
+ }
+ else if ( Char >= 'a' && Char <= 'f' )
+ {
+ /* Convert lower-case hex letters into a byte */
+ Low = Char - 'W';
+ }
+ else
+ {
+ /* Invalid string, fail the conversion */
+ return FALSE;
+ }
+
+ /* Combine the high and low byte */
+ Short = High | Low;
+
+ /* If 4 letters have been reached, the 16-bit integer should exist */
+ if (++Length >= 4)
+ {
+ /* Return it to the caller */
+ *Value = Short;
+ return TRUE;
+ }
+ }
+}
+
+BOOLEAN
+NTAPI
+PciIsSuiteVersion(IN USHORT SuiteMask)
+{
+ ULONGLONG Mask = 0;
+ RTL_OSVERSIONINFOEXW VersionInfo;
+
+ /* Initialize the version information */
+ RtlZeroMemory(&VersionInfo, sizeof(RTL_OSVERSIONINFOEXW));
+ VersionInfo.dwOSVersionInfoSize = sizeof(RTL_OSVERSIONINFOEXW);
+ VersionInfo.wSuiteMask = SuiteMask;
+
+ /* Set the comparison mask and return if the passed suite mask matches */
+ VER_SET_CONDITION(Mask, VER_SUITENAME, VER_AND);
+ return NT_SUCCESS(RtlVerifyVersionInfo(&VersionInfo, VER_SUITENAME, Mask));
+}
+
+BOOLEAN
+NTAPI
+PciIsDatacenter(VOID)
+{
+ BOOLEAN Result;
+ PVOID Value;
+ ULONG ResultLength;
+ NTSTATUS Status;
+
+ /* Assume this isn't Datacenter */
+ Result = FALSE;
+
+ /* First, try opening the setup key */
+ Status = PciGetRegistryValue(L"",
+
L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\setupdd",
+ 0,
+ REG_BINARY,
+ &Value,
+ &ResultLength);
+ if (!NT_SUCCESS(Status))
+ {
+ /* This is not an in-progress Setup boot, so query the suite version */
+ Result = PciIsSuiteVersion(VER_SUITE_DATACENTER);
+ }
+ else
+ {
+ /* This scenario shouldn't happen yet, since SetupDD isn't used */
+ UNIMPLEMENTED;
+ while (TRUE);
+ }
+
+ /* Return if this is Datacenter or not */
+ return Result;
+}
+
+BOOLEAN
+NTAPI
+PciOpenKey(IN PWCHAR KeyName,
+ IN HANDLE RootKey,
+ IN ACCESS_MASK DesiredAccess,
+ OUT PHANDLE KeyHandle,
+ OUT PNTSTATUS KeyStatus)
+{
+ NTSTATUS Status;
+ OBJECT_ATTRIBUTES ObjectAttributes;
+ UNICODE_STRING KeyString;
+ PAGED_CODE();
+
+ /* Initialize the object attributes */
+ RtlInitUnicodeString(&KeyString, KeyName);
+ InitializeObjectAttributes(&ObjectAttributes,
+ &KeyString,
+ OBJ_CASE_INSENSITIVE,
+ RootKey,
+ NULL);
+
+ /* Open the key, returning a boolean, and the status, if requested */
+ Status = ZwOpenKey(KeyHandle, DesiredAccess, &ObjectAttributes);
+ if (KeyStatus) *KeyStatus = Status;
+ return NT_SUCCESS(Status);
+}
+
+NTSTATUS
+NTAPI
+PciGetRegistryValue(IN PWCHAR ValueName,
+ IN PWCHAR KeyName,
+ IN HANDLE RootHandle,
+ IN ULONG Type,
+ OUT PVOID *OutputBuffer,
+ OUT PULONG OutputLength)
+{
+ NTSTATUS Status;
+ PKEY_VALUE_PARTIAL_INFORMATION PartialInfo;
+ ULONG NeededLength, ActualLength;
+ UNICODE_STRING ValueString;
+ HANDLE KeyHandle;
+ BOOLEAN Result;
+
+ /* So we know what to free at the end of the body */
+ PartialInfo = NULL;
+ KeyHandle = NULL;
+ do
+ {
+ /* Open the key by name, rooted off the handle passed */
+ Result = PciOpenKey(KeyName,
+ RootHandle,
+ KEY_QUERY_VALUE,
+ &KeyHandle,
+ &Status);
+ if (!Result) break;
+
+ /* Query for the size that's needed for the value that was passed in */
+ RtlInitUnicodeString(&ValueString, ValueName);
+ Status = ZwQueryValueKey(KeyHandle,
+ &ValueString,
+ KeyValuePartialInformation,
+ NULL,
+ 0,
+ &NeededLength);
+ ASSERT(!NT_SUCCESS(Status));
+ if (Status != STATUS_BUFFER_TOO_SMALL) break;
+
+ /* Allocate an appropriate buffer for the size that was returned */
+ ASSERT(NeededLength != 0);
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ PartialInfo = ExAllocatePoolWithTag(PagedPool,
+ NeededLength,
+ PCI_POOL_TAG);
+ if (!PartialInfo) break;
+
+ /* Query the actual value information now that the size is known */
+ Status = ZwQueryValueKey(KeyHandle,
+ &ValueString,
+ KeyValuePartialInformation,
+ PartialInfo,
+ NeededLength,
+ &ActualLength);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Make sure it's of the type that the caller expects */
+ Status = STATUS_INVALID_PARAMETER;
+ if (PartialInfo->Type != Type) break;
+
+ /* Subtract the registry-specific header, to get the data size */
+ ASSERT(NeededLength == ActualLength);
+ NeededLength -= sizeof(KEY_VALUE_PARTIAL_INFORMATION);
+
+ /* Allocate a buffer to hold the data and return it to the caller */
+ Status = STATUS_INSUFFICIENT_RESOURCES;
+ *OutputBuffer = ExAllocatePoolWithTag(PagedPool,
+ NeededLength,
+ PCI_POOL_TAG);
+ if (!*OutputBuffer) break;
+
+ /* Copy the data into the buffer and return its length to the caller */
+ RtlCopyMemory(*OutputBuffer, PartialInfo->Data, NeededLength);
+ if (OutputLength) *OutputLength = NeededLength;
+ } while (0);
+
+ /* Close any opened keys and free temporary allocations */
+ if (KeyHandle) ZwClose(KeyHandle);
+ if (PartialInfo) ExFreePoolWithTag(PartialInfo, 0);
+ return Status;
+}
+
+NTSTATUS
+NTAPI
+PciBuildDefaultExclusionLists(VOID)
+{
+ ULONG Start;
+ NTSTATUS Status;
+ ASSERT(PciIsaBitExclusionList.Count == 0);
+ ASSERT(PciVgaAndIsaBitExclusionList.Count == 0);
+
+ /* Initialize the range lists */
+ RtlInitializeRangeList(&PciIsaBitExclusionList);
+ RtlInitializeRangeList(&PciVgaAndIsaBitExclusionList);
+
+ /* Loop x86 I/O ranges */
+ for (Start = 0x100; Start <= 0xFEFF; Start += 0x400)
+ {
+ /* Add the ISA I/O ranges */
+ Status = RtlAddRange(&PciIsaBitExclusionList,
+ Start,
+ Start + 0x2FF,
+ 0,
+ RTL_RANGE_LIST_ADD_IF_CONFLICT,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Add the ISA I/O ranges */
+ Status = RtlAddRange(&PciVgaAndIsaBitExclusionList,
+ Start,
+ Start + 0x2AF,
+ 0,
+ RTL_RANGE_LIST_ADD_IF_CONFLICT,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Add the VGA I/O range for Monochrome Video */
+ Status = RtlAddRange(&PciVgaAndIsaBitExclusionList,
+ Start + 0x2BC,
+ Start + 0x2BF,
+ 0,
+ RTL_RANGE_LIST_ADD_IF_CONFLICT,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Add the VGA I/O range for certain CGA adapters */
+ Status = RtlAddRange(&PciVgaAndIsaBitExclusionList,
+ Start + 0x2E0,
+ Start + 0x2FF,
+ 0,
+ RTL_RANGE_LIST_ADD_IF_CONFLICT,
+ NULL,
+ NULL);
+ if (!NT_SUCCESS(Status)) break;
+
+ /* Success, ranges added done */
+ return STATUS_SUCCESS;
+ };
+
+ RtlFreeRangeList(&PciIsaBitExclusionList);
+ RtlFreeRangeList(&PciVgaAndIsaBitExclusionList);
+ return Status;
+}
+
/* EOF */