summaryrefslogtreecommitdiffstats
path: root/private/ntos/nthals/extender/pci/devres.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/ntos/nthals/extender/pci/devres.c')
-rw-r--r--private/ntos/nthals/extender/pci/devres.c1139
1 files changed, 1139 insertions, 0 deletions
diff --git a/private/ntos/nthals/extender/pci/devres.c b/private/ntos/nthals/extender/pci/devres.c
new file mode 100644
index 000000000..578c4ac46
--- /dev/null
+++ b/private/ntos/nthals/extender/pci/devres.c
@@ -0,0 +1,1139 @@
+/*++
+
+Copyright (c) 1995 Microsoft Corporation
+
+Module Name:
+
+ devres.c
+
+Abstract:
+
+ Device Resources
+
+Author:
+
+ Ken Reneris (kenr) March-13-1885
+
+Environment:
+
+ Kernel mode only.
+
+Revision History:
+
+--*/
+
+#include "pciport.h"
+
+
+NTSTATUS
+PcipQueryResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList
+ );
+
+NTSTATUS
+PcipSetResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PCM_RESOURCE_LIST ResourceList,
+ ULONG ListSize
+ );
+
+
+#pragma alloc_text(PAGE,PciCtlQueryDeviceId)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceUniqueId)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceResources)
+#pragma alloc_text(PAGE,PciCtlQueryDeviceResourceRequirements)
+#pragma alloc_text(PAGE,PciCtlSetDeviceResources)
+#pragma alloc_text(PAGE,PciCtlAssignSlotResources)
+#pragma alloc_text(PAGE,PcipQueryResourceRequirements)
+#pragma alloc_text(PAGE,PcipSetResources)
+
+
+
+
+VOID
+PciCtlQueryDeviceId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns the device id for the particular slot.
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+ PPCI_COMMON_CONFIG PciData;
+ PWCHAR DeviceID;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ ULONG length;
+ ULONG IDNumber;
+
+ PAGED_CODE();
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciData = (PPCI_COMMON_CONFIG) buffer;
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Determine which device ID the caller wants back
+ //
+
+ IDNumber = *((PULONG) Context->DeviceControl.Buffer);
+
+ //
+ // For PCI devices:
+ // ID #0 is the specific PCI device ID.
+ // ID #1 is the compatible device ID based on the BaseClass & SubClass fields
+ //
+
+ Status = STATUS_NO_MORE_ENTRIES;
+ DeviceID = (PWCHAR) Context->DeviceControl.Buffer;
+
+ if (IDNumber == 0) {
+
+ //
+ // Return the PCI device ID
+ //
+
+ swprintf (DeviceID, PCI_ID, PciData->VendorID, PciData->DeviceID);
+ Status = STATUS_SUCCESS;
+ }
+
+ if (IDNumber == 1) {
+
+ //
+ // Return the first compatible device id for the device
+ //
+
+ if ( (PciData->BaseClass == 0 &&
+ PciData->SubClass == 1 &&
+ PciData->ProgIf == 0) ||
+
+ (PciData->BaseClass == 3 &&
+ PciData->SubClass == 0 &&
+ PciData->ProgIf == 0) ) {
+
+ //
+ // This is an industry standard VGA controller
+ //
+
+ swprintf (DeviceID, PNP_VGA);
+ Status = STATUS_SUCCESS;
+ }
+
+ if (PciData->BaseClass == 1 &&
+ PciData->SubClass == 0 &&
+ PciData->ProgIf == 0) {
+
+ //
+ // This is an industry standard IDE controller
+ //
+
+ swprintf (DeviceID, PNP_IDE);
+ Status = STATUS_SUCCESS;
+
+ }
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+VOID
+PciCtlQueryDeviceUniqueId (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function returns a unique device id for the particular slot.
+ The id is a sequence of numbers separated by dots ('.'). The first
+ number is the bus number of the root of the heirarchy of PCI buses
+ that the slot belongs to. The last number in the sequence is the
+ slot number in question. A possibly empty set of numbers in between
+ these two, represents the slot numbers of intermediate PCI-PCI bridges
+ in the hierarchy between the root bus and the slot.
+
+ For example, L"0.1.2.3":
+ 0 PCI bus number of the root of the heirarchy.
+ 1 Slot number within PCI bus 0 were a PCI-PCI bridge is
+ located, the secondary bus that it bridges to is PCI bus X.
+ 2 Slot number within PCI bus X were a PCI-PCI bridge is
+ located, the secondary bus that it bridges to is PCI bus Y.
+ 3 Slot number within PCI bus Y for which we are wanting to
+ obtain the unique id (i.e. the targer of this control operation).
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+ PBUS_HANDLER BusHandler;
+ PBUS_HANDLER ParentHandler;
+ PWCHAR UniqueDeviceId;
+ PWCHAR UniqueDeviceIdEnd;
+ PDEVICE_HANDLER_OBJECT DeviceHandler;
+ BOOLEAN Done;
+ UCHAR UidComponent;
+ PPCIBUSDATA PciBusData;
+ PWCHAR DelimiterPointer;
+ WCHAR Delimiter;
+
+ PAGED_CODE();
+
+ //
+ // Set [UniqueDeviceId, UniqueDeviceIdEnd) to the range of
+ // wide characters for which the caller provided storage.
+ //
+
+ Status = STATUS_SUCCESS;
+ UniqueDeviceId = (PWCHAR) Context->DeviceControl.Buffer;
+ UniqueDeviceIdEnd = UniqueDeviceId
+ + *Context->DeviceControl.BufferLength / sizeof(WCHAR);
+ DeviceHandler = DeviceData2DeviceHandler(DeviceData);
+
+ //
+ // Determine the memory required for the unique id.
+ // Note that this loop exits in the middle and that it will
+ // always be executed at least 1.5 times. If there are PCI-PCI
+ // bridges between the slot's bus and the root bus of the PCI
+ // hierarchy, then an extra iteration of the loop will be done
+ // for each one of them.
+ //
+ // The bus hierarchy is being walked backwards (from leaf to root).
+ // Finally, note that the rightmost uid component is the slot's
+ // number (set before we enter the loop).
+ //
+
+ BusHandler = DeviceHandler->BusHandler;
+ UidComponent = (UCHAR) DeviceHandler->SlotNumber;
+ Done = FALSE;
+
+ for (;;) {
+
+ //
+ // On each iteration, given the value of one of the components of
+ // the unique id, determine how much memory the swprintf would use
+ // for it (note that the 2, 3 & 4 below include a +1, which is
+ // for the nul terminator or for the '.' delimiter between two
+ // unique id components.
+ //
+
+ if (UidComponent <= 9) {
+ UniqueDeviceId += 2;
+ } else if (UidComponent <= 99) {
+ UniqueDeviceId += 3;
+ } else {
+ UniqueDeviceId += 4;
+ }
+
+ if (Done) {
+ break;
+ }
+
+ //
+ // If there is no parent bus handler for the current bus,
+ // or if it is not a PCI bus, then we are at the root of
+ // this hierarchy of PCI buses. In this case the unique id
+ // component is the bus number (instead of a slot number),
+ // furthermore, we are almost done (just account for the
+ // space required in the unique id for it).
+ //
+ // Otherwise, the current bus is a PCI-PCI bridge and its
+ // unique id component is the slot number of the bridge
+ // within its parent bus.
+ //
+
+ ParentHandler = BusHandler->ParentHandler;
+ if (!ParentHandler || ParentHandler->InterfaceType != PCIBus) {
+ UidComponent = (UCHAR) BusHandler->BusNumber;
+ Done = TRUE;
+ } else {
+ PciBusData = (PPCIBUSDATA) BusHandler->BusData;
+ UidComponent = (UCHAR) PciBusData->ParentSlot.u.AsULONG;
+ BusHandler = ParentHandler;
+ }
+ }
+
+ //
+ // If there is not enough space for the unique id, fail
+ // and return the size required.
+ //
+
+ if (UniqueDeviceId > UniqueDeviceIdEnd) {
+ *Context->DeviceControl.BufferLength = (UniqueDeviceIdEnd
+ - (PWCHAR) Context->DeviceControl.Buffer) * sizeof(WCHAR);
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+
+ //
+ // Otherwise, traverse the bus heirarchy again (just like
+ // above), except that this time we decrement the UniqueDeviceId
+ // on each iteration and swprintf the uid component. Note that
+ // for all components except for the right most one we store
+ // a delimiter after it (i.e. a '.').
+ //
+
+ BusHandler = DeviceHandler->BusHandler;
+ UidComponent = (UCHAR) DeviceHandler->SlotNumber;
+ Done = FALSE;
+ Delimiter = L'\0';
+ for (;;) {
+ DelimiterPointer = UniqueDeviceId;
+ if (UidComponent <= 9) {
+ UniqueDeviceId -= 2;
+ } else if (UidComponent <= 99) {
+ UniqueDeviceId -= 3;
+ } else {
+ UniqueDeviceId -= 4;
+ }
+ swprintf(UniqueDeviceId, L"%d", UidComponent);
+ DelimiterPointer[-1] = Delimiter;
+ Delimiter = L'.';
+
+ if (Done) {
+ break;
+ }
+
+ ParentHandler = BusHandler->ParentHandler;
+ if (!ParentHandler || ParentHandler->InterfaceType != PCIBus) {
+ UidComponent = (UCHAR) BusHandler->BusNumber;
+ Done = TRUE;
+ } else {
+ PciBusData = (PPCIBUSDATA) BusHandler->BusData;
+ UidComponent = (UCHAR) PciBusData->ParentSlot.u.AsULONG;
+ BusHandler = ParentHandler;
+ }
+ }
+ }
+
+ PcipCompleteDeviceControl(Status, Context, DeviceData);
+}
+
+
+VOID
+PciCtlQueryDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCES DeviceControl
+ which returns the bus resources being used by the specified device
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PCM_RESOURCE_LIST CompleteList;
+ PCM_PARTIAL_RESOURCE_LIST PartialList;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
+ LONGLONG base, length, max;
+ NTSTATUS Status;
+ PUCHAR WorkingPool;
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+// BUGBUG if the device is a pci-2-pci bus controller, then
+// this function should return the addresses which are bridged
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (CM_RESOURCE_LIST) +
+ sizeof (CM_PARTIAL_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) +
+ PCI_COMMON_HDR_LENGTH;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ if (!WorkingPool) {
+ PcipCompleteDeviceControl (STATUS_INSUFFICIENT_RESOURCES, Context, DeviceData);
+ return ;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PCM_RESOURCE_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Build a CM_RESOURCE_LIST for the PCI device
+ //
+
+ CompleteList->Count = 1;
+ CompleteList->List[0].InterfaceType = Context->RootHandler->InterfaceType;
+ CompleteList->List[0].BusNumber = Context->RootHandler->BusNumber;
+
+ PartialList = &CompleteList->List[0].PartialResourceList;
+ Descriptor = PartialList->PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+
+ PciBusData->Pin2Line (
+ Context->Handler,
+ Context->RootHandler,
+ SlotNumber,
+ PciData
+ );
+
+ Descriptor->u.Interrupt.Level = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Vector = PciData->u.type0.InterruptLine;
+ Descriptor->u.Interrupt.Affinity = 0xFFFFFFFF;
+
+ PartialList->Count++;
+ Descriptor++;
+ }
+
+ //
+ // Add any memory / port resources being used
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+
+ ASSERT (DeviceData->BARBitsSet);
+ PcipCrackBAR (BaseAddress, DeviceData->BARBits, &j, &base, &length, &max);
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+
+ if (PciData->Command & PCI_ENABLE_IO_SPACE) {
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ Descriptor->u.Port.Start.QuadPart = base & ~0x3;
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Port.Length = (ULONG) length;
+ }
+
+
+ } else {
+
+ if (PciData->Command & PCI_ENABLE_MEMORY_SPACE) {
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == RomIndex) {
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (base & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ Descriptor->u.Memory.Start.QuadPart = base & ~0xF;
+ ASSERT (length < 0xFFFFFFFF);
+ Descriptor->u.Memory.Length = (ULONG) length;
+ }
+ }
+
+ PartialList->Count++;
+ Descriptor++;
+ }
+ }
+
+ //
+ // Return results
+ //
+
+ i = (ULONG) ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+ if (i > *Context->DeviceControl.BufferLength) {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, CompleteList, i);
+ Status = STATUS_SUCCESS;
+ }
+
+ *Context->DeviceControl.BufferLength = i;
+ ExFreePool (WorkingPool);
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+VOID
+PciCtlQueryDeviceResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the QUERY_DEVICE_RESOURCE_REQUIREMENTS DeviceControl
+ which returns the possible bus resources that this device may be
+ satisfied with.
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipQueryResourceRequirements (DeviceData, Context, &ResourceList);
+
+ if (NT_SUCCESS(Status)) {
+
+ //
+ // Return results
+ //
+
+ if (ResourceList->ListSize > *Context->DeviceControl.BufferLength) {
+ Status = STATUS_BUFFER_TOO_SMALL;
+ } else {
+ RtlCopyMemory (Context->DeviceControl.Buffer, ResourceList, ResourceList->ListSize);
+ Status = STATUS_SUCCESS;
+ }
+
+ *Context->DeviceControl.BufferLength = ResourceList->ListSize;
+
+ }
+
+ if (ResourceList) {
+ ExFreePool (ResourceList);
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+
+NTSTATUS
+PcipQueryResourceRequirements (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PIO_RESOURCE_REQUIREMENTS_LIST *ResourceList
+ )
+/*++
+
+Routine Description:
+
+ This function allocates and returns the specified devices
+ IO_RESOURCE_REQUIREMENTS_LIST
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PIO_RESOURCE_REQUIREMENTS_LIST CompleteList;
+ PIO_RESOURCE_DESCRIPTOR Descriptor;
+ LONGLONG base, length, max;
+ NTSTATUS Status;
+ PUCHAR WorkingPool;
+
+ PAGED_CODE();
+
+ //
+ // Allocate some pool for working space
+ //
+
+ i = sizeof (IO_RESOURCE_REQUIREMENTS_LIST) +
+ sizeof (IO_RESOURCE_DESCRIPTOR) * (PCI_TYPE0_ADDRESSES + 2) * 2 +
+ PCI_COMMON_HDR_LENGTH;
+
+ WorkingPool = (PUCHAR) ExAllocatePool (PagedPool, i);
+ *ResourceList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ if (!*ResourceList) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ //
+ // Zero initialize pool, and get pointers into memory
+ //
+
+ RtlZeroMemory (WorkingPool, i);
+ CompleteList = (PIO_RESOURCE_REQUIREMENTS_LIST) WorkingPool;
+ PciData = (PPCI_COMMON_CONFIG) (WorkingPool + i - PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Build an IO_RESOURCE_REQUIREMENTS_LIST for the PCI device
+ //
+
+ CompleteList->InterfaceType = Context->RootHandler->InterfaceType;
+ CompleteList->BusNumber = Context->RootHandler->BusNumber;
+ CompleteList->SlotNumber = DeviceDataSlot(DeviceData);
+ CompleteList->AlternativeLists = 1;
+
+ CompleteList->List[0].Version = 1;
+ CompleteList->List[0].Revision = 1;
+
+ Descriptor = CompleteList->List[0].Descriptors;
+
+ //
+ // If PCI device has an interrupt resource, add it
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+ Descriptor->Type = CmResourceTypeInterrupt;
+ Descriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
+ Descriptor->ShareDisposition = CmResourceShareShared;
+
+ // BUGBUG: this is not correct
+ Descriptor->u.Interrupt.MinimumVector = 0;
+ Descriptor->u.Interrupt.MaximumVector = 0xff;
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ }
+
+ //
+ // Add any memory / port resources being used
+ //
+
+ for (j=0; j < NoBaseAddress; j++) {
+ if (*BaseAddress[j]) {
+
+ PcipCrackBAR (BaseAddress, DeviceData->BARBits, &j, &base, &length, &max);
+
+ //
+ // Add a descriptor for this address
+ //
+
+ Descriptor->Option = 0;
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ Descriptor->Type = CmResourceTypePort;
+ Descriptor->Flags = CM_RESOURCE_PORT_IO;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Port.Alignment = (ULONG) length;
+ Descriptor->u.Port.Length = (ULONG) length;
+ Descriptor->u.Port.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Port.MaximumAddress.QuadPart = max;
+
+ } else {
+ Descriptor->Type = CmResourceTypeMemory;
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_WRITE;
+ Descriptor->ShareDisposition = CmResourceShareDeviceExclusive;
+
+ if (j == RomIndex) {
+ // this is a ROM address
+ Descriptor->Flags = CM_RESOURCE_MEMORY_READ_ONLY;
+ }
+
+ if (base & PCI_ADDRESS_MEMORY_PREFETCHABLE) {
+ Descriptor->Flags |= CM_RESOURCE_MEMORY_PREFETCHABLE;
+ }
+
+ ASSERT (length <= 0xFFFFFFFF);
+ Descriptor->u.Memory.Alignment = (ULONG) length;
+ Descriptor->u.Memory.Length = (ULONG) length;
+ Descriptor->u.Memory.MinimumAddress.QuadPart = 0;
+ Descriptor->u.Memory.MaximumAddress.QuadPart = max;
+ }
+
+ CompleteList->List[0].Count++;
+ Descriptor++;
+ }
+ }
+
+ if (DeviceData->BrokenDevice) {
+
+ //
+ // This device has something wrong with its base address register implementation
+ //
+
+ ExFreePool (WorkingPool);
+ return STATUS_DEVICE_PROTOCOL_ERROR;
+ }
+
+ //
+ // Return results
+ //
+
+ CompleteList->ListSize = (ULONG) ((PUCHAR) Descriptor - (PUCHAR) CompleteList);
+ *ResourceList = CompleteList;
+ return STATUS_SUCCESS;
+}
+
+VOID
+PciCtlSetDeviceResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the SET_DEVICE_RESOURCES DeviceControl
+ which configures the device to the specified device setttings
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ NTSTATUS Status;
+
+ PAGED_CODE();
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipSetResources (
+ DeviceData,
+ Context,
+ (PCM_RESOURCE_LIST) Context->DeviceControl.Buffer,
+ *Context->DeviceControl.BufferLength
+ );
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}
+
+
+NTSTATUS
+PcipSetResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context,
+ PCM_RESOURCE_LIST ResourceList,
+ ULONG ListSize
+ )
+/*++
+
+Routine Description:
+
+ This function set the specified device to the CM_RESOURCE_LIST
+
+Arguments:
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PPCIBUSDATA PciBusData;
+ PPCI_COMMON_CONFIG PciData, PciOrigData;
+ ULONG NoBaseAddress, RomIndex;
+ PULONG BaseAddress[PCI_TYPE0_ADDRESSES + 1];
+ ULONG i, j;
+ PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor;
+ LONGLONG base, length;
+ NTSTATUS Status;
+ UCHAR buffer[PCI_COMMON_HDR_LENGTH];
+ PCI_SLOT_NUMBER SlotNumber;
+
+ PAGED_CODE();
+
+ PciBusData = (PPCIBUSDATA) (Context->Handler->BusData);
+ SlotNumber.u.AsULONG = DeviceDataSlot(DeviceData);
+
+ //
+ // If BARBits haven't been deteremined, go do it now
+ //
+
+ Status = PcipVerifyBarBits (DeviceData, Context->Handler);
+ if (!NT_SUCCESS(Status)) {
+ return Status;
+ }
+
+
+ //
+ // Get current device configuration
+ //
+
+ if (DeviceData->Power) {
+ ASSERT (DeviceData->CurrentConfig == NULL);
+ DeviceData->CurrentConfig = (PPCI_COMMON_CONFIG)
+ ExAllocatePool (NonPagedPool, PCI_COMMON_HDR_LENGTH);
+
+ if (!DeviceData->CurrentConfig) {
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+ }
+
+ //
+ // Read the PCI device's info
+ //
+
+ PciData = DeviceData->CurrentConfig;
+ PciOrigData = (PPCI_COMMON_CONFIG) buffer;
+ PcipReadConfig (Context->Handler, DeviceData, PciData);
+
+ //
+ // Save current config
+ //
+
+ RtlCopyMemory (PciOrigData, PciData, PCI_COMMON_HDR_LENGTH);
+
+ //
+ // Initialize base addresses base on configuration data type
+ //
+
+ PcipCalcBaseAddrPointers (
+ DeviceData,
+ PciData,
+ BaseAddress,
+ &NoBaseAddress,
+ &RomIndex
+ );
+
+ //
+ // Slurp the assigments back into the PciData structure and
+ // perform them
+ //
+
+ CmDescriptor = ResourceList->List[0].PartialResourceList.PartialDescriptors;
+
+ //
+ // If PCI device has an interrupt resource then that was
+ // passed in as the first requested resource
+ //
+
+ if (PciData->u.type0.InterruptPin) {
+
+ //
+ // Assign the interrupt line
+ //
+
+ if (CmDescriptor->Type != CmResourceTypeInterrupt) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ PciData->u.type0.InterruptLine = (UCHAR) CmDescriptor->u.Interrupt.Vector;
+
+ PciBusData->Pin2Line (
+ Context->Handler,
+ Context->RootHandler,
+ SlotNumber,
+ PciData
+ );
+
+ CmDescriptor++;
+ }
+
+ for (j=0; j < NoBaseAddress; j++) {
+ base = *BaseAddress[j];
+ if (base) {
+ //
+ // Set 32bits and mask
+ //
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ if (CmDescriptor->Type != CmResourceTypePort) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ *BaseAddress[j] = CmDescriptor->u.Port.Start.LowPart;
+
+ } else {
+ if (CmDescriptor->Type != CmResourceTypeMemory) {
+ Status = STATUS_INVALID_PARAMETER;
+ goto CleanUp;
+ }
+
+ *BaseAddress[j] = CmDescriptor->u.Memory.Start.LowPart;
+ }
+
+ if (Is64BitBaseAddress(base)) {
+
+ //
+ // Set upper 32bits
+ //
+
+ if (base & PCI_ADDRESS_IO_SPACE) {
+ *BaseAddress[j+1] = CmDescriptor->u.Port.Start.HighPart;
+ } else {
+ *BaseAddress[j+1] = CmDescriptor->u.Memory.Start.HighPart;
+ }
+
+ j++;
+ }
+
+ CmDescriptor++;
+ }
+ }
+
+ //
+ // Enabel decodes and set the new addresses
+ //
+
+ if (DeviceData->EnableRom && *BaseAddress[RomIndex]) {
+ // a rom address was allocated and should be enabled
+ *BaseAddress[RomIndex] |= PCI_ROMADDRESS_ENABLED;
+ }
+
+ PciData->Command |= PCI_ENABLE_IO_SPACE |
+ PCI_ENABLE_MEMORY_SPACE |
+ PCI_ENABLE_BUS_MASTER;
+
+ //
+ // If the device is powered on, flush the cached config information
+ // to the device; otherwise, leave the new configuration in memory -
+ // it will get flushed to the device when it's powered on
+ //
+
+ Status = STATUS_SUCCESS;
+ if (DeviceData->Power) {
+ Status = PcipFlushConfig (Context->Handler, DeviceData);
+ }
+
+CleanUp:
+ //
+ // If there was an error, and the device still has a cached current
+ // config, put the configuration back as it was when we found it
+ //
+
+ if (!NT_SUCCESS (Status) && DeviceData->CurrentConfig) {
+ RtlCopyMemory (DeviceData->CurrentConfig, PciOrigData, PCI_COMMON_HDR_LENGTH);
+ }
+
+ return Status;
+}
+
+
+VOID
+PciCtlAssignSlotResources (
+ PDEVICE_DATA DeviceData,
+ PHAL_DEVICE_CONTROL_CONTEXT Context
+ )
+/*++
+
+Routine Description:
+
+ This function completes the internal AssignSlotResources DeviceControl
+
+Arguments:
+
+ DeviceData - Slot data information for the specificied slot
+
+ Context - Slot control context of the request
+
+Return Value:
+
+ The slot control is completed
+
+--*/
+{
+ PIO_RESOURCE_REQUIREMENTS_LIST ResourceList;
+ PCTL_ASSIGN_RESOURCES AssignResources;
+ PCM_RESOURCE_LIST AllocatedResources;
+ NTSTATUS Status;
+ ULONG l;
+ POWER_STATE PowerControl;
+
+ PAGED_CODE();
+
+ ResourceList = NULL;
+ AllocatedResources = NULL;
+ AssignResources = (PCTL_ASSIGN_RESOURCES) Context->DeviceControl.Buffer;
+
+ //
+ // If BARBits haven't been deteremined, go do it now
+ //
+
+ Status = PcipVerifyBarBits (DeviceData, Context->Handler);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Get the resource requirements list for the device
+ //
+
+ Status = PcipQueryResourceRequirements (DeviceData, Context, &ResourceList);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Get device settings from IO
+ //
+
+ Status = IoAssignResources (
+ AssignResources->RegistryPath,
+ AssignResources->DriverClassName,
+ AssignResources->DriverObject,
+ Context->DeviceControl.DeviceObject,
+ ResourceList,
+ &AllocatedResources
+ );
+
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Set the resources into the device
+ //
+
+ Status = PcipSetResources (DeviceData, Context, AllocatedResources, 0xFFFFFFFF);
+ if (!NT_SUCCESS(Status)) {
+ goto CleanUp;
+ }
+
+ //
+ // Turn the device on
+ //
+
+ PowerControl = PowerUp;
+ l = sizeof (PowerControl);
+
+ Status = HalDeviceControl (
+ Context->DeviceControl.DeviceHandler,
+ Context->DeviceControl.DeviceObject,
+ BCTL_SET_POWER,
+ &PowerControl,
+ &l,
+ NULL,
+ NULL
+ );
+
+CleanUp:
+ *AssignResources->AllocatedResources = AllocatedResources;
+
+ if (!NT_SUCCESS(Status)) {
+
+ //
+ // Failure, if there are any allocated resources free them
+ //
+
+ if (AllocatedResources) {
+ IoAssignResources (
+ AssignResources->RegistryPath,
+ AssignResources->DriverClassName,
+ AssignResources->DriverObject,
+ Context->DeviceControl.DeviceObject,
+ NULL,
+ NULL
+ );
+
+ ExFreePool (AllocatedResources);
+ *AssignResources->AllocatedResources = NULL;
+ }
+ }
+
+ if (ResourceList) {
+ ExFreePool (ResourceList);
+ }
+
+ PcipCompleteDeviceControl (Status, Context, DeviceData);
+}