1986 lines
63 KiB
C
1986 lines
63 KiB
C
/*++
|
||
|
||
Copyright (c) 1995-2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
devres.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the high level device resources support routines.
|
||
|
||
Author:
|
||
|
||
Shie-Lin Tzong (shielint) July-27-1995
|
||
|
||
Environment:
|
||
|
||
Kernel mode only.
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "busp.h"
|
||
#include "pnpisa.h"
|
||
#include "pbios.h"
|
||
#include "pnpcvrt.h"
|
||
|
||
#if ISOLATE_CARDS
|
||
|
||
#define IDBG 0
|
||
|
||
#if 0
|
||
NTSTATUS
|
||
PipFilterResourceRequirementsList(
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources
|
||
);
|
||
#endif
|
||
|
||
PIO_RESOURCE_REQUIREMENTS_LIST
|
||
PipCmResourcesToIoResources (
|
||
IN PCM_RESOURCE_LIST CmResourceList
|
||
);
|
||
|
||
NTSTATUS
|
||
PipMergeResourceRequirementsLists (
|
||
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList1,
|
||
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList2,
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *MergedList
|
||
);
|
||
|
||
NTSTATUS
|
||
PipBuildBootResourceRequirementsList (
|
||
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList,
|
||
IN PCM_RESOURCE_LIST CmList,
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *FilteredList,
|
||
OUT PBOOLEAN ExactMatch
|
||
);
|
||
|
||
VOID
|
||
PipMergeBootResourcesToRequirementsList(
|
||
PDEVICE_INFORMATION DeviceInfo,
|
||
PCM_RESOURCE_LIST BootResources,
|
||
PIO_RESOURCE_REQUIREMENTS_LIST *IoResources
|
||
);
|
||
|
||
#pragma alloc_text(PAGE, PipGetCardIdentifier)
|
||
#pragma alloc_text(PAGE, PipGetFunctionIdentifier)
|
||
#pragma alloc_text(PAGE, PipGetCompatibleDeviceId)
|
||
#pragma alloc_text(PAGE, PipQueryDeviceId)
|
||
#pragma alloc_text(PAGE, PipQueryDeviceUniqueId)
|
||
//#pragma alloc_text(PAGE, PipQueryDeviceResources)
|
||
#pragma alloc_text(PAGE, PipQueryDeviceResourceRequirements)
|
||
//#pragma alloc_text(PAGE, PipFilterResourceRequirementsList)
|
||
#pragma alloc_text(PAGE, PipCmResourcesToIoResources)
|
||
#pragma alloc_text(PAGE, PipMergeResourceRequirementsLists)
|
||
#pragma alloc_text(PAGE, PipBuildBootResourceRequirementsList)
|
||
#pragma alloc_text(PAGE, PipMergeBootResourcesToRequirementsList)
|
||
//#pragma alloc_text(PAGE, PipSetDeviceResources)
|
||
|
||
|
||
NTSTATUS
|
||
PipGetCardIdentifier (
|
||
PUCHAR CardData,
|
||
PWCHAR *Buffer,
|
||
PULONG BufferLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the identifier for a pnpisa card.
|
||
|
||
Arguments:
|
||
|
||
CardData - supplies a pointer to the pnp isa device data.
|
||
|
||
Buffer - supplies a pointer to variable to receive a pointer to the Id.
|
||
|
||
BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS code
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
UCHAR tag;
|
||
LONG size, length;
|
||
UNICODE_STRING unicodeString;
|
||
ANSI_STRING ansiString;
|
||
PCHAR ansiBuffer;
|
||
|
||
*Buffer = NULL;
|
||
*BufferLength = 0;
|
||
|
||
if (CardData == NULL) {
|
||
return status;
|
||
}
|
||
tag = *CardData;
|
||
|
||
//
|
||
// Make sure CardData does *NOT* point to a Logical Device Id tag
|
||
//
|
||
|
||
if ((tag & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
|
||
DbgPrint("PipGetCardIdentifier: CardData is at a Logical Id tag\n");
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Find the resource descriptor which describle identifier string
|
||
//
|
||
|
||
do {
|
||
|
||
//
|
||
// Do we find the identifer resource tag?
|
||
//
|
||
|
||
if (tag == TAG_ANSI_ID) {
|
||
CardData++;
|
||
length = *(USHORT UNALIGNED *)CardData;
|
||
CardData += 2;
|
||
ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
|
||
if (ansiBuffer == NULL) {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
break;
|
||
}
|
||
RtlMoveMemory(ansiBuffer, CardData, length);
|
||
ansiBuffer[length] = 0;
|
||
RtlInitAnsiString(&ansiString, ansiBuffer);
|
||
status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
|
||
ExFreePool(ansiBuffer);
|
||
if (!NT_SUCCESS(status)) {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
break;
|
||
}
|
||
*Buffer = unicodeString.Buffer;
|
||
*BufferLength = unicodeString.Length + sizeof(WCHAR);
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Determine the size of the BIOS resource descriptor and
|
||
// advance to next resource descriptor.
|
||
//
|
||
|
||
if (!(tag & LARGE_RESOURCE_TAG)) {
|
||
size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
|
||
size += 1; // length of small tag
|
||
} else {
|
||
size = *(USHORT UNALIGNED *)(CardData + 1);
|
||
size += 3; // length of large tag
|
||
}
|
||
|
||
CardData += size;
|
||
tag = *CardData;
|
||
|
||
} while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipGetFunctionIdentifier (
|
||
PUCHAR DeviceData,
|
||
PWCHAR *Buffer,
|
||
PULONG BufferLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the desired pnp isa identifier for the specified
|
||
DeviceData/LogicalFunction. The Identifier for a logical function is
|
||
optional. If no Identifier available , Buffer is set to NULL.
|
||
|
||
Arguments:
|
||
|
||
DeviceData - supplies a pointer to the pnp isa device data.
|
||
|
||
Buffer - supplies a pointer to variable to receive a pointer to the Id.
|
||
|
||
BufferLength - supplies a pointer to a variable to receive the size of the id buffer.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS code
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
UCHAR tag;
|
||
LONG size, length;
|
||
UNICODE_STRING unicodeString;
|
||
ANSI_STRING ansiString;
|
||
PCHAR ansiBuffer;
|
||
|
||
*Buffer = NULL;
|
||
*BufferLength = 0;
|
||
|
||
if (DeviceData==NULL) {
|
||
return status;
|
||
}
|
||
tag = *DeviceData;
|
||
|
||
#if DBG
|
||
|
||
//
|
||
// Make sure device data points to Logical Device Id tag
|
||
//
|
||
|
||
if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
|
||
DbgPrint("PipGetFunctionIdentifier: DeviceData is not at a Logical Id tag\n");
|
||
}
|
||
#endif
|
||
|
||
//
|
||
// Skip all the resource descriptors to find compatible Id descriptor
|
||
//
|
||
|
||
do {
|
||
|
||
//
|
||
// Determine the size of the BIOS resource descriptor and
|
||
// advance to next resource descriptor.
|
||
//
|
||
|
||
if (!(tag & LARGE_RESOURCE_TAG)) {
|
||
size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
|
||
size += 1; // length of small tag
|
||
} else {
|
||
size = *(USHORT UNALIGNED *)(DeviceData + 1);
|
||
size += 3; // length of large tag
|
||
}
|
||
|
||
DeviceData += size;
|
||
tag = *DeviceData;
|
||
|
||
//
|
||
// Do we find the identifer resource tag?
|
||
//
|
||
|
||
if (tag == TAG_ANSI_ID) {
|
||
DeviceData++;
|
||
length = *(USHORT UNALIGNED *)DeviceData;
|
||
DeviceData += 2;
|
||
ansiBuffer = (PCHAR)ExAllocatePool(PagedPool, length+1);
|
||
if (ansiBuffer == NULL) {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
break;
|
||
}
|
||
RtlMoveMemory(ansiBuffer, DeviceData, length);
|
||
ansiBuffer[length] = 0;
|
||
RtlInitAnsiString(&ansiString, ansiBuffer);
|
||
status = RtlAnsiStringToUnicodeString(&unicodeString,
|
||
&ansiString,
|
||
TRUE);
|
||
ExFreePool(ansiBuffer);
|
||
if (!NT_SUCCESS(status)) {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
break;
|
||
}
|
||
*Buffer = unicodeString.Buffer;
|
||
*BufferLength = unicodeString.Length + sizeof(WCHAR);
|
||
break;
|
||
}
|
||
|
||
} while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipGetCompatibleDeviceId (
|
||
PUCHAR DeviceData,
|
||
ULONG IdIndex,
|
||
PWCHAR *Buffer
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the desired pnp isa id for the specified DeviceData
|
||
and Id index. If Id index = 0, the Hardware ID will be return; if id
|
||
index = n, the Nth compatible id will be returned.
|
||
|
||
Arguments:
|
||
|
||
DeviceData - supplies a pointer to the pnp isa device data.
|
||
|
||
IdIndex - supplies the index of the compatible id desired.
|
||
|
||
Buffer - supplies a pointer to variable to receive a pointer to the compatible Id.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS code
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_NO_MORE_ENTRIES;
|
||
UCHAR tag;
|
||
ULONG count = 0,length;
|
||
LONG size;
|
||
UNICODE_STRING unicodeString;
|
||
ANSI_STRING ansiString;
|
||
UCHAR eisaId[8];
|
||
ULONG id;
|
||
|
||
|
||
//
|
||
// Bail out BEFORE we touch the device data for the RDP
|
||
//
|
||
|
||
if (IdIndex == -1) {
|
||
length = 2* sizeof(WCHAR);
|
||
|
||
*Buffer = (PWCHAR) ExAllocatePool(PagedPool, length);
|
||
if (*Buffer) {
|
||
RtlZeroMemory (*Buffer,length);
|
||
}else {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
|
||
tag = *DeviceData;
|
||
|
||
#if DBG
|
||
|
||
//
|
||
// Make sure device data points to Logical Device Id tag
|
||
//
|
||
|
||
if ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID) {
|
||
DbgPrint("PipGetCompatibleDeviceId: DeviceData is not at Logical Id tag\n");
|
||
}
|
||
#endif
|
||
|
||
if (IdIndex == 0) {
|
||
|
||
//
|
||
// Caller is asking for hardware id
|
||
//
|
||
|
||
DeviceData++; // Skip tag
|
||
id = *(ULONG UNALIGNED *)DeviceData;
|
||
status = STATUS_SUCCESS;
|
||
} else {
|
||
|
||
//
|
||
// caller is asking for compatible id
|
||
//
|
||
|
||
IdIndex--;
|
||
|
||
//
|
||
// Skip all the resource descriptors to find compatible Id descriptor
|
||
//
|
||
|
||
do {
|
||
|
||
//
|
||
// Determine the size of the BIOS resource descriptor and
|
||
// advance to next resource descriptor.
|
||
//
|
||
|
||
if (!(tag & LARGE_RESOURCE_TAG)) {
|
||
size = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
|
||
size += 1; // length of small tag
|
||
} else {
|
||
size = *(USHORT UNALIGNED *)(DeviceData + 1);
|
||
size += 3; // length of large tag
|
||
}
|
||
|
||
DeviceData += size;
|
||
tag = *DeviceData;
|
||
|
||
//
|
||
// Do we reach the compatible ID descriptor?
|
||
//
|
||
|
||
if ((tag & SMALL_TAG_MASK) == TAG_COMPATIBLE_ID) {
|
||
if (count == IdIndex) {
|
||
id = *(ULONG UNALIGNED *)(DeviceData + 1);
|
||
status = STATUS_SUCCESS;
|
||
break;
|
||
} else {
|
||
count++;
|
||
}
|
||
}
|
||
|
||
} while ((tag != TAG_COMPLETE_END) && ((tag & SMALL_TAG_MASK) != TAG_LOGICAL_ID));
|
||
}
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
PipDecompressEisaId(id, eisaId);
|
||
RtlInitAnsiString(&ansiString, eisaId);
|
||
status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
|
||
if (!NT_SUCCESS(status)) {
|
||
return status;
|
||
}
|
||
*Buffer = (PWCHAR)ExAllocatePool (
|
||
PagedPool,
|
||
sizeof(L"*") + sizeof(WCHAR) + unicodeString.Length
|
||
);
|
||
if (*Buffer) {
|
||
swprintf(*Buffer, L"*%s", unicodeString.Buffer);
|
||
} else {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
RtlFreeUnicodeString(&unicodeString);
|
||
}
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipQueryDeviceUniqueId (
|
||
PDEVICE_INFORMATION DeviceInfo,
|
||
PWCHAR *DeviceId
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the unique id for the particular device.
|
||
|
||
Arguments:
|
||
|
||
DeviceData - Device data information for the specificied device.
|
||
|
||
DeviceId - supplies a pointer to a variable to receive device id.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS code.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
|
||
//
|
||
// Set up device's unique id.
|
||
// device unique id = SerialNumber of the card
|
||
//
|
||
|
||
*DeviceId = (PWCHAR)ExAllocatePool (
|
||
PagedPool,
|
||
(8 + 1) * sizeof(WCHAR) // serial number + null
|
||
);
|
||
if (*DeviceId) {
|
||
if (DeviceInfo->Flags & DF_READ_DATA_PORT) {
|
||
//
|
||
// Override the unique ID for the RDP
|
||
//
|
||
swprintf (*DeviceId,
|
||
L"0"
|
||
);
|
||
} else {
|
||
swprintf (*DeviceId,
|
||
L"%01X",
|
||
((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->SerialNumber
|
||
);
|
||
}
|
||
|
||
#if IDBG
|
||
{
|
||
ANSI_STRING ansiString;
|
||
UNICODE_STRING unicodeString;
|
||
|
||
RtlInitUnicodeString(&unicodeString, *DeviceId);
|
||
RtlUnicodeStringToAnsiString(&ansiString, &unicodeString, TRUE);
|
||
DbgPrint("PnpIsa: return Unique Id = %s\n", ansiString.Buffer);
|
||
RtlFreeAnsiString(&ansiString);
|
||
}
|
||
#endif
|
||
} else {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
|
||
}
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipQueryDeviceId (
|
||
PDEVICE_INFORMATION DeviceInfo,
|
||
PWCHAR *DeviceId,
|
||
ULONG IdIndex
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the device id for the particular device.
|
||
|
||
Arguments:
|
||
|
||
DeviceInfo - Device information for the specificied device.
|
||
|
||
DeviceId - supplies a pointer to a variable to receive the device id.
|
||
|
||
IdIndex - specifies device id or compatible id (0 - device id)
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS code.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PWSTR format;
|
||
ULONG size,length;
|
||
UCHAR eisaId[8];
|
||
UNICODE_STRING unicodeString;
|
||
ANSI_STRING ansiString;
|
||
|
||
|
||
//
|
||
// Bail out BEFORE we touch the device data for the RDP
|
||
//
|
||
|
||
if (DeviceInfo->Flags & DF_READ_DATA_PORT) {
|
||
length = (sizeof (wReadDataPort)+
|
||
+ sizeof(WCHAR) +sizeof (L"ISAPNP\\"));
|
||
*DeviceId = (PWCHAR) ExAllocatePool(PagedPool, length);
|
||
if (*DeviceId) {
|
||
_snwprintf(*DeviceId, length, L"ISAPNP\\%s",wReadDataPort);
|
||
} else {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
//
|
||
// Set up device's id.
|
||
// device id = VenderId + Logical device number
|
||
//
|
||
|
||
|
||
if (DeviceInfo->CardInformation->NumberLogicalDevices == 1) {
|
||
format = L"ISAPNP\\%s";
|
||
size = sizeof(L"ISAPNP\\*") + sizeof(WCHAR);
|
||
} else {
|
||
format = L"ISAPNP\\%s_DEV%04X";
|
||
size = sizeof(L"ISAPNP\\_DEV") + 4 * sizeof(WCHAR) + sizeof(WCHAR);
|
||
}
|
||
PipDecompressEisaId(
|
||
((PSERIAL_IDENTIFIER) (DeviceInfo->CardInformation->CardData))->VenderId,
|
||
eisaId
|
||
);
|
||
RtlInitAnsiString(&ansiString, eisaId);
|
||
status = RtlAnsiStringToUnicodeString(&unicodeString, &ansiString, TRUE);
|
||
if (!NT_SUCCESS(status)) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
size += unicodeString.Length;
|
||
*DeviceId = (PWCHAR)ExAllocatePool (PagedPool, size);
|
||
if (*DeviceId) {
|
||
swprintf (*DeviceId,
|
||
format,
|
||
unicodeString.Buffer,
|
||
DeviceInfo->LogicalDeviceNumber
|
||
);
|
||
#if IDBG
|
||
{
|
||
ANSI_STRING dbgAnsiString;
|
||
UNICODE_STRING dbgUnicodeString;
|
||
|
||
RtlInitUnicodeString(&dbgUnicodeString, *DeviceId);
|
||
RtlUnicodeStringToAnsiString(&dbgAnsiString, &dbgUnicodeString, TRUE);
|
||
DbgPrint("PnpIsa: return device Id = %s\n", dbgAnsiString.Buffer);
|
||
RtlFreeAnsiString(&dbgAnsiString);
|
||
}
|
||
#endif
|
||
} else {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
RtlFreeUnicodeString(&unicodeString);
|
||
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipQueryDeviceResources (
|
||
PDEVICE_INFORMATION DeviceInfo,
|
||
ULONG BusNumber,
|
||
PCM_RESOURCE_LIST *CmResources,
|
||
ULONG *Size
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the bus resources being used by the specified device
|
||
|
||
Arguments:
|
||
|
||
DeviceInfo - Device information for the specificied slot
|
||
|
||
BusNumber - should always be 0
|
||
|
||
CmResources - supplies a pointer to a variable to receive the device resource
|
||
data.
|
||
|
||
Size - Supplies a pointer to avariable to receive the size of device resource
|
||
data.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS code.
|
||
|
||
--*/
|
||
{
|
||
ULONG length;
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PCM_RESOURCE_LIST cmResources;
|
||
|
||
*CmResources = NULL;
|
||
*Size = 0;
|
||
|
||
if (DeviceInfo->BootResources){ // && DeviceInfo->LogConfHandle) {
|
||
|
||
*CmResources = ExAllocatePool(PagedPool, DeviceInfo->BootResourcesLength);
|
||
if (*CmResources) {
|
||
RtlMoveMemory(*CmResources, DeviceInfo->BootResources, DeviceInfo->BootResourcesLength);
|
||
*Size = DeviceInfo->BootResourcesLength;
|
||
} else {
|
||
status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
}
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipQueryDeviceResourceRequirements (
|
||
PDEVICE_INFORMATION DeviceInfo,
|
||
ULONG BusNumber,
|
||
ULONG Slot,
|
||
PCM_RESOURCE_LIST BootResources,
|
||
USHORT IrqFlags,
|
||
PIO_RESOURCE_REQUIREMENTS_LIST *IoResources,
|
||
ULONG *Size
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function returns the possible bus resources that this device may be
|
||
satisfied with.
|
||
|
||
Arguments:
|
||
|
||
DeviceData - Device data information for the specificied slot
|
||
|
||
BusNumber - Supplies the bus number
|
||
|
||
Slot - supplies the slot number of the BusNumber
|
||
|
||
IoResources - supplies a pointer to a variable to receive the IO resource
|
||
requirements list
|
||
|
||
Return Value:
|
||
|
||
The device control is completed
|
||
|
||
--*/
|
||
{
|
||
ULONG length = 0;
|
||
NTSTATUS status;
|
||
PUCHAR deviceData;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST ioResources;
|
||
|
||
deviceData = DeviceInfo->DeviceData;
|
||
status = PpBiosResourcesToNtResources (
|
||
BusNumber,
|
||
Slot,
|
||
&deviceData,
|
||
0,
|
||
&ioResources,
|
||
&length
|
||
);
|
||
|
||
//
|
||
// Return results
|
||
//
|
||
|
||
if (NT_SUCCESS(status)) {
|
||
if (length == 0) {
|
||
ioResources = NULL; // Just to make sure
|
||
} else {
|
||
|
||
// * Set the irq level/edge requirements to be consistent
|
||
// with the our determination earlier as to what is
|
||
// likely to work for this card
|
||
//
|
||
// * Make requirements reflect boot configed ROM if any.
|
||
//
|
||
// Make these changes across all alternatives.
|
||
PipTrimResourceRequirements(&ioResources,
|
||
IrqFlags,
|
||
BootResources);
|
||
|
||
//PipFilterResourceRequirementsList(&ioResources);
|
||
PipMergeBootResourcesToRequirementsList(DeviceInfo,
|
||
BootResources,
|
||
&ioResources
|
||
);
|
||
ASSERT(ioResources);
|
||
length = ioResources->ListSize;
|
||
}
|
||
*IoResources = ioResources;
|
||
*Size = length;
|
||
#if IDBG
|
||
PipDumpIoResourceList(ioResources);
|
||
#endif
|
||
}
|
||
return status;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipSetDeviceResources (
|
||
PDEVICE_INFORMATION DeviceInfo,
|
||
PCM_RESOURCE_LIST CmResources
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This function configures the device to the specified device setttings
|
||
|
||
Arguments:
|
||
|
||
DeviceInfo - Device information for the specificied slot
|
||
|
||
CmResources - pointer to the desired resource list
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS code.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
|
||
if (CmResources && (CmResources->Count != 0)) {
|
||
//
|
||
// Set resource settings for the device
|
||
//
|
||
|
||
status = PipWriteDeviceResources (
|
||
DeviceInfo->DeviceData,
|
||
(PCM_RESOURCE_LIST) CmResources
|
||
);
|
||
//
|
||
// Put all cards into wait for key state.
|
||
//
|
||
|
||
DebugPrint((DEBUG_STATE,
|
||
"SetDeviceResources CSN %d/LDN %d\n",
|
||
DeviceInfo->CardInformation->CardSelectNumber,
|
||
DeviceInfo->LogicalDeviceNumber));
|
||
|
||
//
|
||
// Delay some time for the newly set resources to be avaiable.
|
||
// This is required on some slow machines.
|
||
//
|
||
|
||
KeStallExecutionProcessor(10000); // delay 10 ms
|
||
|
||
}
|
||
|
||
return status;
|
||
}
|
||
#if 0
|
||
|
||
NTSTATUS
|
||
PipFilterResourceRequirementsList(
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResources
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine removes the length zero entries from the input Io resource
|
||
requirements list.
|
||
|
||
Parameters:
|
||
|
||
IoResources - supplies a pointer to an address to Io resource requirements List.
|
||
|
||
Return Value:
|
||
|
||
NTSTATUS code.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS status;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST oldIoResources = *IoResources, newIoResources;
|
||
PIO_RESOURCE_LIST oldIoResourceList = oldIoResources->List;
|
||
PIO_RESOURCE_LIST newIoResourceList;
|
||
PIO_RESOURCE_DESCRIPTOR oldIoResourceDescriptor, newIoResourceDescriptor;
|
||
PIO_RESOURCE_DESCRIPTOR oldIoResourceDescriptorEnd;
|
||
#if DBG
|
||
PIO_RESOURCE_DESCRIPTOR newIoResourceDescriptorEnd;
|
||
#endif
|
||
LONG IoResourceListCount = (LONG) oldIoResources->AlternativeLists;
|
||
ULONG size;
|
||
|
||
PAGED_CODE();
|
||
|
||
//
|
||
// Make sure there is some resource requirements to be fulfilled.
|
||
//
|
||
|
||
if (IoResourceListCount == 0) {
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
size = oldIoResources->ListSize;
|
||
|
||
//
|
||
// Check if there is any length zero descriptor
|
||
//
|
||
|
||
while (--IoResourceListCount >= 0) {
|
||
|
||
oldIoResourceDescriptor = oldIoResourceList->Descriptors;
|
||
oldIoResourceDescriptorEnd = oldIoResourceDescriptor + oldIoResourceList->Count;
|
||
|
||
while (oldIoResourceDescriptor < oldIoResourceDescriptorEnd) {
|
||
switch (oldIoResourceDescriptor->Type) {
|
||
case CmResourceTypePort:
|
||
case CmResourceTypeMemory:
|
||
if (oldIoResourceDescriptor->u.Generic.Length == 0) {
|
||
size -= sizeof(IO_RESOURCE_DESCRIPTOR);
|
||
}
|
||
|
||
break;
|
||
|
||
default:
|
||
|
||
break;
|
||
}
|
||
oldIoResourceDescriptor++;
|
||
}
|
||
ASSERT(oldIoResourceDescriptor == oldIoResourceDescriptorEnd);
|
||
oldIoResourceList = (PIO_RESOURCE_LIST) oldIoResourceDescriptorEnd;
|
||
}
|
||
if (size == oldIoResources->ListSize) {
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// We have length zero descriptor. Rebuild the resources requirements list
|
||
//
|
||
|
||
|
||
newIoResources = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool (
|
||
PagedPool, size);
|
||
if (newIoResources == NULL) {
|
||
return STATUS_NO_MEMORY;
|
||
} else {
|
||
RtlMoveMemory(newIoResources,
|
||
oldIoResources,
|
||
FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List)
|
||
);
|
||
newIoResources->ListSize = size;
|
||
newIoResourceList = newIoResources->List;
|
||
#if DBG
|
||
newIoResourceDescriptorEnd = (PIO_RESOURCE_DESCRIPTOR)
|
||
((PUCHAR)newIoResourceList + size);
|
||
#endif
|
||
}
|
||
|
||
//
|
||
// filter the IO ResReq list
|
||
//
|
||
|
||
oldIoResourceList = oldIoResources->List;
|
||
IoResourceListCount = (LONG) oldIoResources->AlternativeLists;
|
||
|
||
while (--IoResourceListCount >= 0) {
|
||
|
||
newIoResourceList->Version = oldIoResourceList->Version;
|
||
newIoResourceList->Revision = oldIoResourceList->Revision;
|
||
newIoResourceList->Count = oldIoResourceList->Count;
|
||
|
||
oldIoResourceDescriptor = oldIoResourceList->Descriptors;
|
||
newIoResourceDescriptor = newIoResourceList->Descriptors;
|
||
oldIoResourceDescriptorEnd = oldIoResourceDescriptor + oldIoResourceList->Count;
|
||
|
||
while (oldIoResourceDescriptor < oldIoResourceDescriptorEnd) {
|
||
switch (oldIoResourceDescriptor->Type) {
|
||
case CmResourceTypePort:
|
||
case CmResourceTypeMemory:
|
||
if (oldIoResourceDescriptor->u.Generic.Length == 0) {
|
||
newIoResourceList->Count--;
|
||
break;
|
||
}
|
||
|
||
default:
|
||
|
||
*newIoResourceDescriptor = *oldIoResourceDescriptor;
|
||
newIoResourceDescriptor++;
|
||
break;
|
||
}
|
||
oldIoResourceDescriptor++;
|
||
}
|
||
ASSERT(oldIoResourceDescriptor == oldIoResourceDescriptorEnd);
|
||
oldIoResourceList = (PIO_RESOURCE_LIST) oldIoResourceDescriptor;
|
||
newIoResourceList = (PIO_RESOURCE_LIST) newIoResourceDescriptor;
|
||
}
|
||
ASSERT(newIoResourceDescriptor <= newIoResourceDescriptorEnd);
|
||
|
||
ExFreePool(oldIoResources);
|
||
*IoResources = newIoResources;
|
||
return STATUS_SUCCESS;
|
||
}
|
||
#endif
|
||
|
||
PIO_RESOURCE_REQUIREMENTS_LIST
|
||
PipCmResourcesToIoResources (
|
||
IN PCM_RESOURCE_LIST CmResourceList
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routines converts the input CmResourceList to IO_RESOURCE_REQUIREMENTS_LIST.
|
||
|
||
Arguments:
|
||
|
||
CmResourceList - the cm resource list to convert.
|
||
|
||
Return Value:
|
||
|
||
returns a IO_RESOURCE_REQUIREMENTS_LISTST if succeeds. Otherwise a NULL value is
|
||
returned.
|
||
|
||
--*/
|
||
{
|
||
PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
|
||
ULONG count = 0, size, i, j;
|
||
PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartDesc;
|
||
PIO_RESOURCE_DESCRIPTOR ioDesc;
|
||
|
||
//
|
||
// First determine number of descriptors required.
|
||
//
|
||
|
||
cmFullDesc = &CmResourceList->List[0];
|
||
for (i = 0; i < CmResourceList->Count; i++) {
|
||
count += cmFullDesc->PartialResourceList.Count;
|
||
cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
|
||
for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
|
||
size = 0;
|
||
switch (cmPartDesc->Type) {
|
||
case CmResourceTypeDeviceSpecific:
|
||
size = cmPartDesc->u.DeviceSpecificData.DataSize;
|
||
count--;
|
||
break;
|
||
}
|
||
cmPartDesc++;
|
||
cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size);
|
||
}
|
||
cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc;
|
||
}
|
||
|
||
if (count == 0) {
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Count the extra descriptors for InterfaceType and BusNumber information.
|
||
//
|
||
|
||
count += CmResourceList->Count - 1;
|
||
|
||
//
|
||
// Allocate heap space for IO RESOURCE REQUIREMENTS LIST
|
||
//
|
||
|
||
count++; // add one for CmResourceTypeConfigData
|
||
ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePool(
|
||
PagedPool,
|
||
sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
|
||
count * sizeof(IO_RESOURCE_DESCRIPTOR)
|
||
);
|
||
if (!ioResReqList) {
|
||
return NULL;
|
||
}
|
||
|
||
//
|
||
// Parse the cm resource descriptor and build its corresponding IO resource descriptor
|
||
//
|
||
|
||
ioResReqList->InterfaceType = CmResourceList->List[0].InterfaceType;
|
||
ioResReqList->BusNumber = CmResourceList->List[0].BusNumber;
|
||
ioResReqList->SlotNumber = 0;
|
||
ioResReqList->Reserved[0] = 0;
|
||
ioResReqList->Reserved[1] = 0;
|
||
ioResReqList->Reserved[2] = 0;
|
||
ioResReqList->AlternativeLists = 1;
|
||
ioResReqList->List[0].Version = 1;
|
||
ioResReqList->List[0].Revision = 1;
|
||
ioResReqList->List[0].Count = count;
|
||
|
||
//
|
||
// Generate a CmResourceTypeConfigData descriptor
|
||
//
|
||
|
||
ioDesc = &ioResReqList->List[0].Descriptors[0];
|
||
ioDesc->Option = IO_RESOURCE_PREFERRED;
|
||
ioDesc->Type = CmResourceTypeConfigData;
|
||
ioDesc->ShareDisposition = CmResourceShareShared;
|
||
ioDesc->Flags = 0;
|
||
ioDesc->Spare1 = 0;
|
||
ioDesc->Spare2 = 0;
|
||
ioDesc->u.ConfigData.Priority = BOOT_CONFIG_PRIORITY;
|
||
ioDesc++;
|
||
|
||
cmFullDesc = &CmResourceList->List[0];
|
||
for (i = 0; i < CmResourceList->Count; i++) {
|
||
cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
|
||
for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
|
||
ioDesc->Option = IO_RESOURCE_PREFERRED;
|
||
ioDesc->Type = cmPartDesc->Type;
|
||
ioDesc->ShareDisposition = cmPartDesc->ShareDisposition;
|
||
ioDesc->Flags = cmPartDesc->Flags;
|
||
ioDesc->Spare1 = 0;
|
||
ioDesc->Spare2 = 0;
|
||
|
||
size = 0;
|
||
switch (cmPartDesc->Type) {
|
||
case CmResourceTypePort:
|
||
ioDesc->u.Port.MinimumAddress = cmPartDesc->u.Port.Start;
|
||
ioDesc->u.Port.MaximumAddress.QuadPart = cmPartDesc->u.Port.Start.QuadPart +
|
||
cmPartDesc->u.Port.Length - 1;
|
||
ioDesc->u.Port.Alignment = 1;
|
||
ioDesc->u.Port.Length = cmPartDesc->u.Port.Length;
|
||
ioDesc++;
|
||
break;
|
||
case CmResourceTypeInterrupt:
|
||
#if defined(_X86_)
|
||
ioDesc->u.Interrupt.MinimumVector = ioDesc->u.Interrupt.MaximumVector =
|
||
cmPartDesc->u.Interrupt.Level;
|
||
#else
|
||
ioDesc->u.Interrupt.MinimumVector = ioDesc->u.Interrupt.MaximumVector =
|
||
cmPartDesc->u.Interrupt.Vector;
|
||
#endif
|
||
ioDesc++;
|
||
break;
|
||
case CmResourceTypeMemory:
|
||
ioDesc->u.Memory.MinimumAddress = cmPartDesc->u.Memory.Start;
|
||
ioDesc->u.Memory.MaximumAddress.QuadPart = cmPartDesc->u.Memory.Start.QuadPart +
|
||
cmPartDesc->u.Memory.Length - 1;
|
||
ioDesc->u.Memory.Alignment = 1;
|
||
ioDesc->u.Memory.Length = cmPartDesc->u.Memory.Length;
|
||
ioDesc++;
|
||
break;
|
||
case CmResourceTypeDma:
|
||
ioDesc->u.Dma.MinimumChannel = cmPartDesc->u.Dma.Channel;
|
||
ioDesc->u.Dma.MaximumChannel = cmPartDesc->u.Dma.Channel;
|
||
ioDesc++;
|
||
break;
|
||
case CmResourceTypeDeviceSpecific:
|
||
size = cmPartDesc->u.DeviceSpecificData.DataSize;
|
||
break;
|
||
case CmResourceTypeBusNumber:
|
||
ioDesc->u.BusNumber.MinBusNumber = cmPartDesc->u.BusNumber.Start;
|
||
ioDesc->u.BusNumber.MaxBusNumber = cmPartDesc->u.BusNumber.Start +
|
||
cmPartDesc->u.BusNumber.Length - 1;
|
||
ioDesc->u.BusNumber.Length = cmPartDesc->u.BusNumber.Length;
|
||
ioDesc++;
|
||
break;
|
||
default:
|
||
ioDesc->u.DevicePrivate.Data[0] = cmPartDesc->u.DevicePrivate.Data[0];
|
||
ioDesc->u.DevicePrivate.Data[1] = cmPartDesc->u.DevicePrivate.Data[1];
|
||
ioDesc->u.DevicePrivate.Data[2] = cmPartDesc->u.DevicePrivate.Data[2];
|
||
ioDesc++;
|
||
break;
|
||
}
|
||
cmPartDesc++;
|
||
cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size);
|
||
}
|
||
cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc;
|
||
}
|
||
ioResReqList->ListSize = (ULONG)((ULONG_PTR)ioDesc - (ULONG_PTR)ioResReqList);
|
||
return ioResReqList;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipMergeResourceRequirementsLists (
|
||
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList1,
|
||
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList2,
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *MergedList
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routines merges two IoLists into one.
|
||
|
||
|
||
Arguments:
|
||
|
||
IoList1 - supplies the pointer to the first IoResourceRequirementsList
|
||
|
||
IoList2 - supplies the pointer to the second IoResourceRequirementsList
|
||
|
||
MergedList - Supplies a variable to receive the merged resource
|
||
requirements list.
|
||
|
||
Return Value:
|
||
|
||
A NTSTATUS code to indicate the result of the function.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST ioList, newList;
|
||
ULONG size;
|
||
PUCHAR p;
|
||
|
||
PAGED_CODE();
|
||
|
||
*MergedList = NULL;
|
||
|
||
//
|
||
// First handle the easy cases that both IO Lists are empty or any one of
|
||
// them is empty.
|
||
//
|
||
|
||
if ((IoList1 == NULL || IoList1->AlternativeLists == 0) &&
|
||
(IoList2 == NULL || IoList2->AlternativeLists == 0)) {
|
||
return status;
|
||
}
|
||
ioList = NULL;
|
||
if (IoList1 == NULL || IoList1->AlternativeLists == 0) {
|
||
ioList = IoList2;
|
||
} else if (IoList2 == NULL || IoList2->AlternativeLists == 0) {
|
||
ioList = IoList1;
|
||
}
|
||
if (ioList) {
|
||
newList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, ioList->ListSize);
|
||
if (newList == NULL) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
RtlMoveMemory(newList, ioList, ioList->ListSize);
|
||
*MergedList = newList;
|
||
return status;
|
||
}
|
||
|
||
//
|
||
// Do real work...
|
||
//
|
||
|
||
size = IoList1->ListSize + IoList2->ListSize - FIELD_OFFSET(IO_RESOURCE_REQUIREMENTS_LIST, List);
|
||
newList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(
|
||
PagedPool,
|
||
size
|
||
);
|
||
if (newList == NULL) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
p = (PUCHAR)newList;
|
||
RtlMoveMemory(p, IoList1, IoList1->ListSize);
|
||
p += IoList1->ListSize;
|
||
RtlMoveMemory(p,
|
||
&IoList2->List[0],
|
||
size - IoList1->ListSize
|
||
);
|
||
newList->ListSize = size;
|
||
newList->AlternativeLists += IoList2->AlternativeLists;
|
||
*MergedList = newList;
|
||
return status;
|
||
}
|
||
|
||
VOID
|
||
PipMergeBootResourcesToRequirementsList(
|
||
PDEVICE_INFORMATION DeviceInfo,
|
||
PCM_RESOURCE_LIST BootResources,
|
||
PIO_RESOURCE_REQUIREMENTS_LIST *IoResources
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routines merges two IoLists into one.
|
||
|
||
|
||
Arguments:
|
||
|
||
IoList1 - supplies the pointer to the first IoResourceRequirementsList
|
||
|
||
IoList2 - supplies the pointer to the second IoResourceRequirementsList
|
||
|
||
MergedList - Supplies a variable to receive the merged resource
|
||
requirements list.
|
||
|
||
Return Value:
|
||
|
||
A NTSTATUS code to indicate the result of the function.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status = STATUS_SUCCESS;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST ioResources = *IoResources, bootResReq = NULL, newList = NULL;
|
||
BOOLEAN exactMatch;
|
||
|
||
PAGED_CODE();
|
||
|
||
if (DeviceInfo->BootResources) {
|
||
PipBuildBootResourceRequirementsList (ioResources, BootResources, &bootResReq, &exactMatch);
|
||
if (bootResReq) {
|
||
if (exactMatch && ioResources->AlternativeLists == 1) {
|
||
ExFreePool(ioResources);
|
||
*IoResources = bootResReq;
|
||
} else {
|
||
PipMergeResourceRequirementsLists (bootResReq, ioResources, &newList);
|
||
if (newList) {
|
||
ExFreePool(ioResources);
|
||
*IoResources = newList;
|
||
}
|
||
ExFreePool(bootResReq);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
NTSTATUS
|
||
PipBuildBootResourceRequirementsList (
|
||
IN PIO_RESOURCE_REQUIREMENTS_LIST IoList,
|
||
IN PCM_RESOURCE_LIST CmList,
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *FilteredList,
|
||
OUT PBOOLEAN ExactMatch
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routines adjusts the input IoList based on input BootConfig.
|
||
|
||
|
||
Arguments:
|
||
|
||
IoList - supplies the pointer to an IoResourceRequirementsList
|
||
|
||
CmList - supplies the pointer to a BootConfig.
|
||
|
||
FilteredList - Supplies a variable to receive the filtered resource
|
||
requirements list.
|
||
|
||
Return Value:
|
||
|
||
A NTSTATUS code to indicate the result of the function.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS status;
|
||
PIO_RESOURCE_REQUIREMENTS_LIST ioList, newList;
|
||
PIO_RESOURCE_LIST ioResourceList, newIoResourceList;
|
||
PIO_RESOURCE_DESCRIPTOR ioResourceDescriptor, ioResourceDescriptorEnd;
|
||
PIO_RESOURCE_DESCRIPTOR newIoResourceDescriptor, configDataDescriptor;
|
||
LONG ioResourceDescriptorCount = 0;
|
||
USHORT version;
|
||
PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDescriptor;
|
||
ULONG cmDescriptorCount = 0;
|
||
ULONG size, i, j, oldCount, phase;
|
||
LONG k, alternativeLists;
|
||
BOOLEAN exactMatch;
|
||
|
||
PAGED_CODE();
|
||
|
||
*FilteredList = NULL;
|
||
*ExactMatch = FALSE;
|
||
|
||
//
|
||
// Make sure there is some resource requirements to be filtered.
|
||
// If no, we will convert CmList/BootConfig to an IoResourceRequirementsList
|
||
//
|
||
|
||
if (IoList == NULL || IoList->AlternativeLists == 0) {
|
||
if (CmList && CmList->Count != 0) {
|
||
*FilteredList = PipCmResourcesToIoResources (CmList);
|
||
}
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// Make a copy of the Io Resource Requirements List
|
||
//
|
||
|
||
ioList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, IoList->ListSize);
|
||
if (ioList == NULL) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
RtlMoveMemory(ioList, IoList, IoList->ListSize);
|
||
|
||
//
|
||
// If there is no BootConfig, simply return the copy of the input Io list.
|
||
//
|
||
|
||
if (CmList == NULL || CmList->Count == 0) {
|
||
*FilteredList = ioList;
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// First determine minimum number of descriptors required.
|
||
//
|
||
|
||
cmFullDesc = &CmList->List[0];
|
||
for (i = 0; i < CmList->Count; i++) {
|
||
cmDescriptorCount += cmFullDesc->PartialResourceList.Count;
|
||
cmDescriptor = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
|
||
for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
|
||
size = 0;
|
||
switch (cmDescriptor->Type) {
|
||
case CmResourceTypeConfigData:
|
||
case CmResourceTypeDevicePrivate:
|
||
cmDescriptorCount--;
|
||
break;
|
||
case CmResourceTypeDeviceSpecific:
|
||
size = cmDescriptor->u.DeviceSpecificData.DataSize;
|
||
cmDescriptorCount--;
|
||
break;
|
||
default:
|
||
|
||
//
|
||
// Invalid cmresource list. Ignore it and use io resources
|
||
//
|
||
|
||
if (cmDescriptor->Type == CmResourceTypeNull ||
|
||
cmDescriptor->Type >= CmResourceTypeMaximum) {
|
||
cmDescriptorCount--;
|
||
}
|
||
}
|
||
cmDescriptor++;
|
||
cmDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDescriptor + size);
|
||
}
|
||
cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmDescriptor;
|
||
}
|
||
|
||
if (cmDescriptorCount == 0) {
|
||
*FilteredList = ioList;
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// cmDescriptorCount is the number of BootConfig Descriptors needs.
|
||
//
|
||
// For each IO list Alternative ...
|
||
//
|
||
|
||
ioResourceList = ioList->List;
|
||
k = ioList->AlternativeLists;
|
||
while (--k >= 0) {
|
||
ioResourceDescriptor = ioResourceList->Descriptors;
|
||
ioResourceDescriptorEnd = ioResourceDescriptor + ioResourceList->Count;
|
||
while (ioResourceDescriptor < ioResourceDescriptorEnd) {
|
||
ioResourceDescriptor->Spare1 = 0;
|
||
ioResourceDescriptor++;
|
||
}
|
||
ioResourceList = (PIO_RESOURCE_LIST) ioResourceDescriptorEnd;
|
||
}
|
||
|
||
ioResourceList = ioList->List;
|
||
k = alternativeLists = ioList->AlternativeLists;
|
||
while (--k >= 0) {
|
||
version = ioResourceList->Version;
|
||
if (version == 0xffff) { // Convert bogus version to valid number
|
||
version = 1;
|
||
}
|
||
|
||
//
|
||
// We use Version field to store number of BootConfig found.
|
||
// Count field to store new number of descriptor in the alternative list.
|
||
//
|
||
|
||
ioResourceList->Version = 0;
|
||
oldCount = ioResourceList->Count;
|
||
|
||
ioResourceDescriptor = ioResourceList->Descriptors;
|
||
ioResourceDescriptorEnd = ioResourceDescriptor + ioResourceList->Count;
|
||
|
||
if (ioResourceDescriptor == ioResourceDescriptorEnd) {
|
||
|
||
//
|
||
// An alternative list with zero descriptor count
|
||
//
|
||
|
||
ioResourceList->Version = 0xffff; // Mark it as invalid
|
||
ioList->AlternativeLists--;
|
||
continue;
|
||
}
|
||
|
||
exactMatch = TRUE;
|
||
|
||
//
|
||
// For each Cm Resource descriptor ... except DevicePrivate and
|
||
// DeviceSpecific...
|
||
//
|
||
|
||
cmFullDesc = &CmList->List[0];
|
||
for (i = 0; i < CmList->Count; i++) {
|
||
cmDescriptor = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
|
||
for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
|
||
size = 0;
|
||
switch (cmDescriptor->Type) {
|
||
case CmResourceTypeDevicePrivate:
|
||
break;
|
||
case CmResourceTypeDeviceSpecific:
|
||
size = cmDescriptor->u.DeviceSpecificData.DataSize;
|
||
break;
|
||
default:
|
||
if (cmDescriptor->Type == CmResourceTypeNull ||
|
||
cmDescriptor->Type >= CmResourceTypeMaximum) {
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Check CmDescriptor against current Io Alternative list
|
||
//
|
||
|
||
for (phase = 0; phase < 2; phase++) {
|
||
ioResourceDescriptor = ioResourceList->Descriptors;
|
||
while (ioResourceDescriptor < ioResourceDescriptorEnd) {
|
||
if ((ioResourceDescriptor->Type == cmDescriptor->Type) &&
|
||
(ioResourceDescriptor->Spare1 == 0)) {
|
||
ULONGLONG min1, max1, min2, max2;
|
||
ULONG len1 = 1, len2 = 1, align1, align2;
|
||
UCHAR share1, share2;
|
||
|
||
share2 = ioResourceDescriptor->ShareDisposition;
|
||
share1 = cmDescriptor->ShareDisposition;
|
||
if ((share1 == CmResourceShareUndetermined) ||
|
||
(share1 > CmResourceShareShared)) {
|
||
share1 = share2;
|
||
}
|
||
if ((share2 == CmResourceShareUndetermined) ||
|
||
(share2 > CmResourceShareShared)) {
|
||
share2 = share1;
|
||
}
|
||
align1 = align2 = 1;
|
||
|
||
switch (cmDescriptor->Type) {
|
||
case CmResourceTypePort:
|
||
case CmResourceTypeMemory:
|
||
min1 = cmDescriptor->u.Port.Start.QuadPart;
|
||
max1 = cmDescriptor->u.Port.Start.QuadPart + cmDescriptor->u.Port.Length - 1;
|
||
len1 = cmDescriptor->u.Port.Length;
|
||
min2 = ioResourceDescriptor->u.Port.MinimumAddress.QuadPart;
|
||
max2 = ioResourceDescriptor->u.Port.MaximumAddress.QuadPart;
|
||
len2 = ioResourceDescriptor->u.Port.Length;
|
||
align2 = ioResourceDescriptor->u.Port.Alignment;
|
||
break;
|
||
case CmResourceTypeInterrupt:
|
||
max1 = min1 = cmDescriptor->u.Interrupt.Vector;
|
||
min2 = ioResourceDescriptor->u.Interrupt.MinimumVector;
|
||
max2 = ioResourceDescriptor->u.Interrupt.MaximumVector;
|
||
break;
|
||
case CmResourceTypeDma:
|
||
min1 = max1 =cmDescriptor->u.Dma.Channel;
|
||
min2 = ioResourceDescriptor->u.Dma.MinimumChannel;
|
||
max2 = ioResourceDescriptor->u.Dma.MaximumChannel;
|
||
break;
|
||
case CmResourceTypeBusNumber:
|
||
min1 = cmDescriptor->u.BusNumber.Start;
|
||
max1 = cmDescriptor->u.BusNumber.Start + cmDescriptor->u.BusNumber.Length - 1;
|
||
len1 = cmDescriptor->u.BusNumber.Length;
|
||
min2 = ioResourceDescriptor->u.BusNumber.MinBusNumber;
|
||
max2 = ioResourceDescriptor->u.BusNumber.MaxBusNumber;
|
||
len2 = ioResourceDescriptor->u.BusNumber.Length;
|
||
break;
|
||
default:
|
||
ASSERT(0);
|
||
break;
|
||
}
|
||
if (phase == 0) {
|
||
if (share1 == share2 && min2 == min1 && max2 >= max1 && len2 >= len1) {
|
||
|
||
//
|
||
// For phase 0 match, we want near exact match...
|
||
//
|
||
|
||
if (max2 != max1) {
|
||
exactMatch = FALSE;
|
||
}
|
||
|
||
ioResourceList->Version++;
|
||
ioResourceDescriptor->Spare1 = 0x80;
|
||
if (ioResourceDescriptor->Option & IO_RESOURCE_ALTERNATIVE) {
|
||
PIO_RESOURCE_DESCRIPTOR ioDesc;
|
||
|
||
ioDesc = ioResourceDescriptor;
|
||
ioDesc--;
|
||
while (ioDesc >= ioResourceList->Descriptors) {
|
||
ioDesc->Type = CmResourceTypeNull;
|
||
ioResourceList->Count--;
|
||
if (ioDesc->Option == IO_RESOURCE_ALTERNATIVE) {
|
||
ioDesc--;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
ioResourceDescriptor->Option = IO_RESOURCE_PREFERRED;
|
||
if (ioResourceDescriptor->Type == CmResourceTypePort ||
|
||
ioResourceDescriptor->Type == CmResourceTypeMemory) {
|
||
ioResourceDescriptor->u.Port.MinimumAddress.QuadPart = min1;
|
||
ioResourceDescriptor->u.Port.MaximumAddress.QuadPart = min1 + len2 - 1;
|
||
ioResourceDescriptor->u.Port.Alignment = 1;
|
||
} else if (ioResourceDescriptor->Type == CmResourceTypeBusNumber) {
|
||
ioResourceDescriptor->u.BusNumber.MinBusNumber = (ULONG)min1;
|
||
ioResourceDescriptor->u.BusNumber.MaxBusNumber = (ULONG)(min1 + len2 - 1);
|
||
}
|
||
ioResourceDescriptor++;
|
||
while (ioResourceDescriptor < ioResourceDescriptorEnd) {
|
||
if (ioResourceDescriptor->Option & IO_RESOURCE_ALTERNATIVE) {
|
||
ioResourceDescriptor->Type = CmResourceTypeNull;
|
||
ioResourceDescriptor++;
|
||
ioResourceList->Count--;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
phase = 1; // skip phase 1
|
||
break;
|
||
} else {
|
||
ioResourceDescriptor++;
|
||
}
|
||
} else {
|
||
exactMatch = FALSE;
|
||
if (share1 == share2 && min2 <= min1 && max2 >= max1 && len2 >= len1 &&
|
||
(min1 & (align2 - 1)) == 0) {
|
||
|
||
//
|
||
// Io range covers Cm range ... Change the Io range to what is specified
|
||
// in BootConfig.
|
||
//
|
||
//
|
||
|
||
switch (cmDescriptor->Type) {
|
||
case CmResourceTypePort:
|
||
case CmResourceTypeMemory:
|
||
ioResourceDescriptor->u.Port.MinimumAddress.QuadPart = min1;
|
||
ioResourceDescriptor->u.Port.MaximumAddress.QuadPart = min1 + len2 - 1;
|
||
break;
|
||
case CmResourceTypeInterrupt:
|
||
case CmResourceTypeDma:
|
||
ioResourceDescriptor->u.Interrupt.MinimumVector = (ULONG)min1;
|
||
ioResourceDescriptor->u.Interrupt.MaximumVector = (ULONG)max1;
|
||
break;
|
||
case CmResourceTypeBusNumber:
|
||
ioResourceDescriptor->u.BusNumber.MinBusNumber = (ULONG)min1;
|
||
ioResourceDescriptor->u.BusNumber.MaxBusNumber = (ULONG)(min1 + len2 - 1);
|
||
break;
|
||
}
|
||
ioResourceList->Version++;
|
||
ioResourceDescriptor->Spare1 = 0x80;
|
||
if (ioResourceDescriptor->Option & IO_RESOURCE_ALTERNATIVE) {
|
||
PIO_RESOURCE_DESCRIPTOR ioDesc;
|
||
|
||
ioDesc = ioResourceDescriptor;
|
||
ioDesc--;
|
||
while (ioDesc >= ioResourceList->Descriptors) {
|
||
ioDesc->Type = CmResourceTypeNull;
|
||
ioResourceList->Count--;
|
||
if (ioDesc->Option == IO_RESOURCE_ALTERNATIVE) {
|
||
ioDesc--;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
ioResourceDescriptor->Option = IO_RESOURCE_PREFERRED;
|
||
ioResourceDescriptor++;
|
||
while (ioResourceDescriptor < ioResourceDescriptorEnd) {
|
||
if (ioResourceDescriptor->Option & IO_RESOURCE_ALTERNATIVE) {
|
||
ioResourceDescriptor->Type = CmResourceTypeNull;
|
||
ioResourceList->Count--;
|
||
ioResourceDescriptor++;
|
||
} else {
|
||
break;
|
||
}
|
||
}
|
||
break;
|
||
} else {
|
||
ioResourceDescriptor++;
|
||
}
|
||
}
|
||
} else {
|
||
ioResourceDescriptor++;
|
||
}
|
||
} // Don't add any instruction after this ...
|
||
} // phase
|
||
} // switch
|
||
|
||
//
|
||
// Move to next Cm Descriptor
|
||
//
|
||
|
||
cmDescriptor++;
|
||
cmDescriptor = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDescriptor + size);
|
||
}
|
||
|
||
//
|
||
// Move to next Cm List
|
||
//
|
||
|
||
cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmDescriptor;
|
||
}
|
||
|
||
if (ioResourceList->Version != (USHORT)cmDescriptorCount) {
|
||
|
||
//
|
||
// If the current alternative list does not cover all the boot config
|
||
// descriptors, make it as invalid.
|
||
//
|
||
|
||
ioResourceList->Version = 0xffff;
|
||
ioList->AlternativeLists--;
|
||
} else {
|
||
ioResourceDescriptorCount += ioResourceList->Count;
|
||
ioResourceList->Version = version;
|
||
ioResourceList->Count = oldCount; // ++ single alternative list
|
||
break; // ++ single alternative list
|
||
}
|
||
ioResourceList->Count = oldCount;
|
||
|
||
//
|
||
// Move to next Io alternative list.
|
||
//
|
||
|
||
ioResourceList = (PIO_RESOURCE_LIST) ioResourceDescriptorEnd;
|
||
}
|
||
|
||
//
|
||
// If there is not any valid alternative, convert CmList to Io list.
|
||
//
|
||
|
||
if (ioList->AlternativeLists == 0) {
|
||
*FilteredList = PipCmResourcesToIoResources (CmList);
|
||
ExFreePool(ioList);
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
//
|
||
// we have finished filtering the resource requirements list. Now allocate memory
|
||
// and rebuild a new list.
|
||
//
|
||
|
||
size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
|
||
//sizeof(IO_RESOURCE_LIST) * (ioList->AlternativeLists - 1) + // ++ Single Alternative list
|
||
sizeof(IO_RESOURCE_DESCRIPTOR) * (ioResourceDescriptorCount);
|
||
newList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
|
||
if (newList == NULL) {
|
||
ExFreePool(ioList);
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Walk through the io resource requirements list and pick up any valid descriptor.
|
||
//
|
||
|
||
newList->ListSize = size;
|
||
newList->InterfaceType = CmList->List->InterfaceType;
|
||
newList->BusNumber = CmList->List->BusNumber;
|
||
newList->SlotNumber = ioList->SlotNumber;
|
||
#if 0 // ++ Single Alternative list
|
||
newList->AlternativeLists = ioList->AlternativeLists;
|
||
#else
|
||
newList->AlternativeLists = 1;
|
||
#endif
|
||
ioResourceList = ioList->List;
|
||
newIoResourceList = newList->List;
|
||
while (--alternativeLists >= 0) {
|
||
ioResourceDescriptor = ioResourceList->Descriptors;
|
||
ioResourceDescriptorEnd = ioResourceDescriptor + ioResourceList->Count;
|
||
if (ioResourceList->Version == 0xffff) {
|
||
ioResourceList = (PIO_RESOURCE_LIST)ioResourceDescriptorEnd;
|
||
continue;
|
||
}
|
||
newIoResourceList->Version = ioResourceList->Version;
|
||
newIoResourceList->Revision = ioResourceList->Revision;
|
||
|
||
newIoResourceDescriptor = newIoResourceList->Descriptors;
|
||
if (ioResourceDescriptor->Type != CmResourceTypeConfigData) {
|
||
newIoResourceDescriptor->Option = IO_RESOURCE_PREFERRED;
|
||
newIoResourceDescriptor->Type = CmResourceTypeConfigData;
|
||
newIoResourceDescriptor->ShareDisposition = CmResourceShareShared;
|
||
newIoResourceDescriptor->Flags = 0;
|
||
newIoResourceDescriptor->Spare1 = 0;
|
||
newIoResourceDescriptor->Spare2 = 0;
|
||
newIoResourceDescriptor->u.ConfigData.Priority = BOOT_CONFIG_PRIORITY;
|
||
configDataDescriptor = newIoResourceDescriptor;
|
||
newIoResourceDescriptor++;
|
||
} else {
|
||
newList->ListSize -= sizeof(IO_RESOURCE_DESCRIPTOR);
|
||
configDataDescriptor = newIoResourceDescriptor;
|
||
}
|
||
|
||
while (ioResourceDescriptor < ioResourceDescriptorEnd) {
|
||
if (ioResourceDescriptor->Type != CmResourceTypeNull) {
|
||
*newIoResourceDescriptor = *ioResourceDescriptor;
|
||
newIoResourceDescriptor++;
|
||
}
|
||
ioResourceDescriptor++;
|
||
}
|
||
newIoResourceList->Count = (ULONG)(newIoResourceDescriptor - newIoResourceList->Descriptors);
|
||
configDataDescriptor->u.ConfigData.Priority = BOOT_CONFIG_PRIORITY;
|
||
|
||
break;
|
||
}
|
||
ASSERT((PUCHAR)newIoResourceDescriptor == ((PUCHAR)newList + newList->ListSize));
|
||
|
||
*FilteredList = newList;
|
||
*ExactMatch = exactMatch;
|
||
ExFreePool(ioList);
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR
|
||
PipFindMatchingBootMemResource(
|
||
IN ULONG Index,
|
||
IN PIO_RESOURCE_DESCRIPTOR IoDesc,
|
||
IN PCM_RESOURCE_LIST BootResources
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine finds boot resources that match the i/o descriptor
|
||
|
||
|
||
Arguments:
|
||
|
||
Index - Index of memory boot config resource the caller is interested in.
|
||
|
||
IoDesc - I/O descriptor
|
||
|
||
BootResources - boot config
|
||
|
||
Return Value:
|
||
|
||
A pointer to a matching descriptor in the boot config
|
||
|
||
--*/
|
||
{
|
||
PCM_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartDesc;
|
||
ULONG count = 0, size, i, j, noMem;
|
||
|
||
if (BootResources == NULL) {
|
||
return NULL;
|
||
}
|
||
|
||
cmFullDesc = &BootResources->List[0];
|
||
for (i = 0; i < BootResources->Count; i++) {
|
||
cmPartDesc = &cmFullDesc->PartialResourceList.PartialDescriptors[0];
|
||
noMem = 0;
|
||
for (j = 0; j < cmFullDesc->PartialResourceList.Count; j++) {
|
||
size = 0;
|
||
if (cmPartDesc->Type == CmResourceTypeMemory) {
|
||
if (((cmPartDesc->u.Memory.Start.QuadPart >=
|
||
IoDesc->u.Memory.MinimumAddress.QuadPart) &&
|
||
((cmPartDesc->u.Memory.Start.QuadPart +
|
||
cmPartDesc->u.Memory.Length - 1) <=
|
||
IoDesc->u.Memory.MaximumAddress.QuadPart)) &&
|
||
noMem == Index) {
|
||
return cmPartDesc;
|
||
}
|
||
noMem++;
|
||
} else if (cmPartDesc->Type == CmResourceTypeDeviceSpecific) {
|
||
size = cmPartDesc->u.DeviceSpecificData.DataSize;
|
||
}
|
||
cmPartDesc++;
|
||
cmPartDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmPartDesc + size);
|
||
}
|
||
cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmPartDesc;
|
||
}
|
||
return NULL;
|
||
}
|
||
|
||
NTSTATUS
|
||
PipTrimResourceRequirements (
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoList,
|
||
IN USHORT IrqFlags,
|
||
IN PCM_RESOURCE_LIST BootResources
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine:
|
||
* adjusts the irq requirements level/edge to the value
|
||
decided on in PipCheckBus()
|
||
|
||
* adjusts the memory requirements to reflect the memory boot
|
||
config.
|
||
|
||
Arguments:
|
||
|
||
IoList - supplies the pointer to an IoResourceRequirementsList
|
||
|
||
IrqFlags - level/edge irq reuirements to be applied to all interrupt requirements in all alternatives.
|
||
|
||
BootResources - Used as a reference.
|
||
|
||
--*/
|
||
{
|
||
PIO_RESOURCE_REQUIREMENTS_LIST newReqList;
|
||
PIO_RESOURCE_LIST resList, newList;
|
||
PIO_RESOURCE_DESCRIPTOR resDesc, newDesc;
|
||
PCM_PARTIAL_RESOURCE_DESCRIPTOR bootDesc;
|
||
ULONG listCount, i, j, pass, size, noMem;
|
||
BOOLEAN goodAlt;
|
||
|
||
if (IoList == NULL) {
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
// The only way to create a new req list only if absolutely
|
||
// necessary and make it the perfect size is perform this
|
||
// operation in two passes.
|
||
// 1. figure out how many alternatives will be eliminated and
|
||
// compute size of new req list. if all of the alternatives
|
||
// survived, return the original list (now modified)
|
||
//
|
||
// 2. construct new reqlist minus the bad alternatives.
|
||
|
||
listCount = 0;
|
||
size = 0;
|
||
for (pass = 0; pass < 2; pass++) {
|
||
if (pass == 0) {
|
||
size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) -
|
||
sizeof(IO_RESOURCE_LIST);
|
||
} else {
|
||
newReqList = (PIO_RESOURCE_REQUIREMENTS_LIST) ExAllocatePool(PagedPool, size);
|
||
if (newReqList == NULL) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
*newReqList = **IoList;
|
||
newReqList->ListSize = size;
|
||
newReqList->AlternativeLists = listCount;
|
||
newList = &newReqList->List[0];
|
||
}
|
||
|
||
resList = &(*IoList)->List[0];
|
||
|
||
for (i = 0; i < (*IoList)->AlternativeLists; i++) {
|
||
if (pass == 1) {
|
||
|
||
*newList = *resList;
|
||
newDesc = &newList->Descriptors[0];
|
||
}
|
||
resDesc = &resList->Descriptors[0];
|
||
goodAlt = TRUE;
|
||
noMem = 0;
|
||
for (j = 0; j < resList->Count; j++) {
|
||
if (resDesc->Type == CmResourceTypeInterrupt) {
|
||
resDesc->Flags = IrqFlags;
|
||
|
||
if (resDesc->Flags & CM_RESOURCE_INTERRUPT_LATCHED) {
|
||
resDesc->ShareDisposition = CmResourceShareDeviceExclusive;
|
||
}
|
||
} else if (resDesc->Type == CmResourceTypeMemory) {
|
||
resDesc->Flags |= CM_RESOURCE_MEMORY_24;
|
||
|
||
if (BootResources) {
|
||
bootDesc = PipFindMatchingBootMemResource(noMem, resDesc, BootResources);
|
||
// have matching boot config resource, can trim requirements
|
||
if (bootDesc) {
|
||
if (bootDesc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
|
||
// exact or inclusive ROM match is
|
||
// converted into a fixed requirement.
|
||
resDesc->u.Memory.MinimumAddress.QuadPart =
|
||
bootDesc->u.Memory.Start.QuadPart;
|
||
if (bootDesc->u.Memory.Length) {
|
||
resDesc->u.Memory.MaximumAddress.QuadPart =
|
||
bootDesc->u.Memory.Start.QuadPart +
|
||
bootDesc->u.Memory.Length - 1;
|
||
} else {
|
||
resDesc->u.Memory.MaximumAddress.QuadPart =
|
||
bootDesc->u.Memory.Start.QuadPart;
|
||
}
|
||
resDesc->u.Memory.Length = bootDesc->u.Memory.Length;
|
||
resDesc->u.Memory.Alignment = 1;
|
||
resDesc->Flags |= CM_RESOURCE_MEMORY_READ_ONLY;
|
||
}
|
||
} else {
|
||
goodAlt = FALSE;
|
||
}
|
||
} else {
|
||
resDesc->Flags &= ~CM_RESOURCE_MEMORY_READ_ONLY;
|
||
}
|
||
noMem++;
|
||
}
|
||
if (pass == 1) {
|
||
*newDesc = *resDesc;
|
||
PipDumpIoResourceDescriptor(" ", newDesc);
|
||
newDesc++;
|
||
}
|
||
|
||
resDesc++;
|
||
}
|
||
|
||
if (pass == 0) {
|
||
if (goodAlt) {
|
||
size += sizeof(IO_RESOURCE_LIST) +
|
||
sizeof(IO_RESOURCE_DESCRIPTOR) * (resList->Count - 1);
|
||
listCount++;
|
||
}
|
||
} else {
|
||
if (goodAlt) {
|
||
newList = (PIO_RESOURCE_LIST) newDesc;
|
||
} else {
|
||
DebugPrint((DEBUG_RESOURCE, "An alternative trimmed off of reqlist\n"));
|
||
}
|
||
}
|
||
|
||
resList = (PIO_RESOURCE_LIST) resDesc;
|
||
}
|
||
|
||
// If we have the same number of alternatives as before use
|
||
// the use existing (modified in-place) requirements list
|
||
if (!pass && (listCount == (*IoList)->AlternativeLists)) {
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
// if all alternatives have been eliminated, then it is better
|
||
// to use the existing requirements list than to hope to build
|
||
// one out of the boot config alone.
|
||
if (!pass && (listCount == 0)) {
|
||
DebugPrint((DEBUG_RESOURCE, "All alternatives trimmed off of reqlist, going with original\n"));
|
||
return STATUS_SUCCESS;
|
||
}
|
||
}
|
||
|
||
ExFreePool(*IoList);
|
||
*IoList = newReqList;
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
#endif
|