Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1139 lines
31 KiB

/*++
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);
}