windows-nt/Source/XPSP1/NT/base/busdrv/acpi/driver/nt/rangesup.c
2020-09-26 16:20:57 +08:00

2342 lines
60 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
rangesup.c
Abstract:
This handles the subtraction of a set of CmResList from an IoResList
IoResList
Author:
Stephane Plante (splante)
Environment:
Kernel mode only.
Revision History:
Aug-05-97 - Initial Revision
--*/
#include "pch.h"
NTSTATUS
ACPIRangeAdd(
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *GlobalList,
IN PIO_RESOURCE_REQUIREMENTS_LIST AddList
)
/*++
Routine Description:
This routine is called to add an Io List to another. This is not a
straightforward operation
Arguments:
IoList - The list that contains both lists
AddList - The list what will be added to the other. We are desctructive
to this list
Return Value:
NTSTATUS:
--*/
{
BOOLEAN proceed;
NTSTATUS status;
PIO_RESOURCE_DESCRIPTOR addDesc;
PIO_RESOURCE_DESCRIPTOR newDesc;
PIO_RESOURCE_LIST addList;
PIO_RESOURCE_LIST globalList;
PIO_RESOURCE_LIST newList;
PIO_RESOURCE_REQUIREMENTS_LIST globalResList;
PIO_RESOURCE_REQUIREMENTS_LIST newResList;
ULONG addCount = 0;
ULONG addIndex = 0;
ULONG ioCount = 0;
ULONG ioIndex = 0;
ULONG maxSize = 0;
ULONG size = 0;
if (GlobalList == NULL) {
return STATUS_INVALID_PARAMETER_1;
}
globalResList = *GlobalList;
//
// Make sure that we have a list to add
//
if (AddList == NULL || AddList->AlternativeLists == 0) {
return STATUS_SUCCESS;
}
//
// Figure out how much space we need in the
//
addList = &(AddList->List[0]);
maxSize = addCount = addList->Count;
ACPIRangeSortIoList( addList );
//
// Worst case is that the new list is as big as both lists combined
//
size = AddList->ListSize;
//
// Do we have a global list to add to?
//
if (globalResList == NULL || globalResList->AlternativeLists == 0) {
//
// No? Then just copy the old list
//
newResList = ExAllocatePoolWithTag(
NonPagedPool,
size,
ACPI_RESOURCE_POOLTAG
);
if (newResList == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(
newResList,
AddList,
size
);
} else {
//
// Yes, so calculate how much space the first one will take
//
globalList = &(globalResList->List[0]);
ioCount = globalList->Count;
maxSize += ioCount;
size += (ioCount * sizeof(IO_RESOURCE_DESCRIPTOR) );
//
// Allocate the list
//
newResList = ExAllocatePoolWithTag(
NonPagedPool,
size,
ACPI_RESOURCE_POOLTAG
);
if (newResList == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Copy both lists into the new one
//
RtlZeroMemory( newResList, size );
RtlCopyMemory(
newResList,
AddList,
AddList->ListSize
);
RtlCopyMemory(
&(newResList->List[0].Descriptors[addCount]),
globalList->Descriptors,
(ioCount * sizeof(IO_RESOURCE_DESCRIPTOR) )
);
//
// We no longer need this list
//
ExFreePool( *GlobalList );
}
//
// Make sure that we update the list count
//
newResList->ListSize = size;
newList = &(newResList->List[0]);
newList->Count = ioCount = addCount = maxSize;
//
// Sort the new list
//
status = ACPIRangeSortIoList( newList );
if (!NT_SUCCESS(status)) {
//
// We failed, so exit now
//
ExFreePool( newResList );
return status;
}
//
// Add all the resource we can together
//
for (ioIndex = 0; ioIndex < maxSize; ioIndex++) {
//
// First step is to copy the current desc from the master list to
// the new list
//
newDesc = &(newList->Descriptors[ioIndex]);
//
// Is it interesting?
//
if (newDesc->Type == CmResourceTypeNull) {
//
// No
//
continue;
}
//
// Do we care about it?
//
if (newDesc->Type != CmResourceTypeMemory &&
newDesc->Type != CmResourceTypePort &&
newDesc->Type != CmResourceTypeDma &&
newDesc->Type != CmResourceTypeInterrupt) {
//
// We do not care
//
newDesc->Type = CmResourceTypeNull;
ioCount--;
continue;
}
//
// Try to get as far as possible
//
proceed = TRUE;
//
// Now we try to find any lists that we can merge in that location
//
for (addIndex = ioIndex + 1; addIndex < maxSize; addIndex++) {
addDesc = &(newList->Descriptors[addIndex]);
//
// If they are not the same type, then next
//
if (newDesc->Type != addDesc->Type) {
continue;
}
//
// What we do next is dependent on the type
//
switch (newDesc->Type) {
case CmResourceTypePort:
case CmResourceTypeMemory:
//
// Does the new descriptor lie entirely before the add
// descriptor?
//
if (addDesc->u.Port.MinimumAddress.QuadPart >
newDesc->u.Port.MaximumAddress.QuadPart + 1) {
//
// Then we are done with this newDesc
//
proceed = FALSE;
break;
}
//
// does part of the current new descriptor lie in part
// of the add one?
//
if (newDesc->u.Port.MaximumAddress.QuadPart <=
addDesc->u.Port.MaximumAddress.QuadPart) {
//
// Update the current new descriptor to refect the
// correct range and length
//
newDesc->u.Port.MaximumAddress.QuadPart =
addDesc->u.Port.MaximumAddress.QuadPart;
newDesc->u.Port.Length = (ULONG)
(newDesc->u.Port.MaximumAddress.QuadPart -
newDesc->u.Port.MinimumAddress.QuadPart + 1);
newDesc->u.Port.Alignment = 1;
}
//
// Nuke the add descriptor since it has been swallowed up
//
ioCount--;
addDesc->Type = CmResourceTypeNull;
break;
case CmResourceTypeDma:
case CmResourceTypeInterrupt:
//
// Does the current new descriptor lie entirely before the
// one we are looking at now?
//
if (addDesc->u.Dma.MinimumChannel >
newDesc->u.Dma.MaximumChannel + 1) {
proceed = FALSE;
break;
}
//
// does part of the current new descriptor lie in part
// of the add one?
//
if (newDesc->u.Dma.MaximumChannel <=
addDesc->u.Dma.MaximumChannel ) {
//
// Update the current new descriptor to reflect the
// correct range
//
newDesc->u.Dma.MaximumChannel =
addDesc->u.Dma.MaximumChannel;
}
//
// Nuke the add descriptor since it has been swallowed up
//
ioCount--;
addDesc->Type = CmResourceTypeNull;
break;
} // switch
//
// Do we need to stop?
//
if (proceed == FALSE) {
break;
}
}
} // for
//
// Do we have any items left that we care about?
//
if (ioCount == 0) {
//
// No then free everything and return an empty list
//
ExFreePool( newResList );
return STATUS_SUCCESS;
}
//
// Now we can build the proper list. See how many items we must allocate
//
size = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) + (ioCount - 1) *
sizeof(IO_RESOURCE_DESCRIPTOR);
globalResList = ExAllocatePoolWithTag(
NonPagedPool,
size,
ACPI_RESOURCE_POOLTAG
);
if (globalResList == NULL) {
ExFreePool( newResList );
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Initialize the new list by copying the header from the working list
//
RtlZeroMemory( globalResList, size );
RtlCopyMemory(
globalResList,
newResList,
sizeof(IO_RESOURCE_REQUIREMENTS_LIST)
);
globalResList->ListSize = size;
globalList = &(globalResList->List[0]);
globalList->Count = ioCount;
//
// Copy all of the valid items into this new list
//
for (addIndex = 0, ioIndex = 0;
ioIndex < ioCount && addIndex < maxSize;
addIndex++) {
addDesc = &(newList->Descriptors[addIndex]);
//
// If the type is null, skip it
//
if (addDesc->Type == CmResourceTypeNull) {
continue;
}
//
// Copy the new list
//
RtlCopyMemory(
&(globalList->Descriptors[ioIndex]),
addDesc,
sizeof(IO_RESOURCE_DESCRIPTOR)
);
ioIndex++;
}
//
// Free the old list
//
ExFreePool( newResList );
//
// Point the global to the new list
//
*GlobalList = globalResList;
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
ACPIRangeAddCmList(
IN OUT PCM_RESOURCE_LIST *GlobalList,
IN PCM_RESOURCE_LIST AddList
)
/*++
Routine Description:
This routine is called to add an Cm List to another. This is not a
straightforward operation
Arguments:
CmList - The list that contains both lists
AddList - The list what will be added to the other. We are desctructive
to this list
Return Value:
NTSTATUS:
--*/
{
BOOLEAN proceed;
NTSTATUS status;
PCM_PARTIAL_RESOURCE_DESCRIPTOR addDesc;
PCM_PARTIAL_RESOURCE_DESCRIPTOR newDesc;
PCM_PARTIAL_RESOURCE_LIST addPartialList;
PCM_PARTIAL_RESOURCE_LIST cmPartialList;
PCM_PARTIAL_RESOURCE_LIST newPartialList;
PCM_RESOURCE_LIST globalList;
PCM_RESOURCE_LIST newList;
ULONG addCount = 0;
ULONG addIndex = 0;
ULONG cmCount = 0;
ULONG cmIndex = 0;
ULONG maxSize = 0;
ULONG size = 0;
ULONGLONG maxAddr1;
ULONGLONG maxAddr2;
if (GlobalList == NULL) {
return STATUS_INVALID_PARAMETER_1;
}
globalList = *GlobalList;
//
// Make sure that we have a list to add
//
if (AddList == NULL || AddList->Count == 0) {
return STATUS_SUCCESS;
}
addPartialList = &(AddList->List[0].PartialResourceList);
addCount = addPartialList->Count;
//
// If we have no global list, then we just copy over the other one
//
if (globalList == NULL || globalList->Count == 0) {
//
// Just copy over the original list
//
size = sizeof(CM_RESOURCE_LIST) + (addCount - 1) *
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
maxSize = addCount;
newList = ExAllocatePoolWithTag(
NonPagedPool,
size,
ACPI_RESOURCE_POOLTAG
);
if (newList == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlCopyMemory(
newList,
AddList,
size
);
} else {
cmPartialList = &( globalList->List[0].PartialResourceList);
cmCount = cmPartialList->Count;
maxSize = addCount + cmCount;
//
// Allocate space for both lists
//
size = sizeof(CM_RESOURCE_LIST) + (maxSize - 1) *
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
newList = ExAllocatePoolWithTag(
NonPagedPool,
size,
ACPI_RESOURCE_POOLTAG
);
if (newList == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Merge both sets of descriptors into one list
//
RtlZeroMemory( newList, size );
RtlCopyMemory(
newList,
AddList,
size - (cmCount * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR))
);
RtlCopyMemory(
( (PUCHAR) newList) +
(size - (cmCount * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR ) ) ),
&(cmPartialList->PartialDescriptors[0]),
cmCount * sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
);
//
// Make sure to preserver the version id from the global list
//
newList->List->PartialResourceList.Version =
globalList->List->PartialResourceList.Version;
newList->List->PartialResourceList.Revision =
globalList->List->PartialResourceList.Revision;
ExFreePool( globalList );
}
//
// Obtain a pointer to the descriptors of the new list, and update the
// number of descriptors in the list
//
newPartialList = &(newList->List[0].PartialResourceList);
newPartialList->Count = cmCount = addCount = maxSize;
//
// Make sure to sort the combined list
//
status = ACPIRangeSortCmList( newList );
if (!NT_SUCCESS(status)) {
ExFreePool( newList );
return status;
}
//
// Add all the resource we can together
//
for (cmIndex = 0; cmIndex < maxSize; cmIndex++) {
//
// Grab a pointer to the current descriptor
//
newDesc = &(newPartialList->PartialDescriptors[cmIndex]);
//
// Is it interesting?
//
if (newDesc->Type == CmResourceTypeNull) {
//
// No
//
continue;
}
//
// Do we care about it?
//
if (newDesc->Type != CmResourceTypeMemory &&
newDesc->Type != CmResourceTypePort &&
newDesc->Type != CmResourceTypeDma &&
newDesc->Type != CmResourceTypeInterrupt) {
//
// We do not care
//
newDesc->Type = CmResourceTypeNull;
cmCount--;
continue;
}
//
// Try to get as far as possible
//
proceed = TRUE;
//
// Try to merge the following items
//
for (addIndex = cmIndex + 1; addIndex < maxSize; addIndex++) {
addDesc = &(newPartialList->PartialDescriptors[addIndex]);
//
// If they are not the same type, then we are done here
//
if (newDesc->Type != addDesc->Type) {
continue;
}
switch (newDesc->Type) {
case CmResourceTypePort:
case CmResourceTypeMemory:
//
// Obtain the max addresses
//
maxAddr1 = newDesc->u.Port.Start.QuadPart +
newDesc->u.Port.Length;
maxAddr2 = addDesc->u.Port.Start.QuadPart +
addDesc->u.Port.Length;
//
// does the current new descriptor lie entirely before the
// add one?
//
if (maxAddr1 < (ULONGLONG) addDesc->u.Port.Start.QuadPart ) {
//
// Yes, so we are done with this newDesc;
//
proceed = FALSE;
break;
}
//
// does part of the current new descriptor lie in part of the
// add one?
//
if (maxAddr1 <= maxAddr2) {
//
// Update the current new descriptor to reflect the
// correct length
//
newDesc->u.Port.Length = (ULONG) (maxAddr2 -
newDesc->u.Port.Start.QuadPart);
}
//
// Nuke the add descriptor since it has been swallowed up
//
cmCount--;
addDesc->Type = CmResourceTypeNull;
break;
case CmResourceTypeDma:
//
// Do the resource match?
//
if (addDesc->u.Dma.Channel != newDesc->u.Dma.Channel) {
//
// No, then stop
//
proceed = FALSE;
break;
}
//
// We can ignore the duplicate copy
//
addDesc->Type = CmResourceTypeNull;
cmCount--;
break;
case CmResourceTypeInterrupt:
//
// Do the resource match?
//
if (addDesc->u.Interrupt.Vector !=
newDesc->u.Interrupt.Vector) {
//
// No, then stop
//
proceed = FALSE;
break;
}
//
// We can ignore the duplicate copy
//
addDesc->Type = CmResourceTypeNull;
cmCount--;
break;
} // switch
//
// Do we have to stop?
//
if (proceed == FALSE) {
break;
}
} // for
} // for
//
// Do we have any items that we care about left?
//
if (cmCount == 0) {
//
// No, then free everything and return an empty list
//
ExFreePool( newList );
return STATUS_SUCCESS;
}
//
// Now we can build the proper list. See how many items we must
// allocate
//
size = sizeof(CM_RESOURCE_LIST) + (cmCount - 1) *
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
globalList = ExAllocatePoolWithTag(
NonPagedPool,
size,
ACPI_RESOURCE_POOLTAG
);
if (globalList == NULL) {
ExFreePool( newList );
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Initialize the list by copying the header from the AddList
//
RtlZeroMemory( globalList, size );
RtlCopyMemory(
globalList,
AddList,
sizeof(CM_RESOURCE_LIST)
);
cmPartialList = &(globalList->List[0].PartialResourceList);
cmPartialList->Count = cmCount;
//
// Copy all of the valid resources into this new list
//
for (cmIndex = 0, addIndex = 0;
cmIndex < maxSize && addIndex < cmCount;
cmIndex++) {
newDesc = &(newPartialList->PartialDescriptors[cmIndex]);
//
// If the type is null, skip it
//
if (newDesc->Type == CmResourceTypeNull) {
continue;
}
//
// Copy the new list
//
RtlCopyMemory(
&(cmPartialList->PartialDescriptors[addIndex]),
newDesc,
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
);
addIndex++;
}
//
// Free the old lists
//
ExFreePool( newList );
//
// Point the global to the new list
//
*GlobalList = globalList;
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
ACPIRangeFilterPICInterrupt(
IN PIO_RESOURCE_REQUIREMENTS_LIST IoResList
)
/*++
Routine Description:
This routine is called to remove Interrupt #2 from the list of
resources that are returned by the PIC
Arguments:
IoResList - The IO Resource List to smash
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
PIO_RESOURCE_LIST ioList;
ULONG i;
ULONG j;
ULONG size;
//
// Sanity checks
//
if (IoResList == NULL) {
//
// No work to do
//
return STATUS_SUCCESS;
}
//
// Walk the resource requirements list
//
ioList = &(IoResList->List[0]);
for (i = 0; i < IoResList->AlternativeLists; i++) {
//
// Walk the IO list
//
for (j = 0; j < ioList->Count; j++) {
if (ioList->Descriptors[j].Type != CmResourceTypeInterrupt) {
continue;
}
//
// Do we have the case where the minimum starts on int 2?
//
if (ioList->Descriptors[j].u.Interrupt.MinimumVector == 2) {
//
// If the maximum is on 2, then we snuff out this
// descriptors, otherwise, we change the minimum
//
if (ioList->Descriptors[j].u.Interrupt.MaximumVector == 2) {
ioList->Descriptors[j].Type = CmResourceTypeNull;
} else {
ioList->Descriptors[j].u.Interrupt.MinimumVector++;
}
continue;
}
//
// Do we have the case where the maximum ends on int 2?
// Note that the minimum cannot be on 2...
//
if (ioList->Descriptors[j].u.Interrupt.MaximumVector == 2) {
ioList->Descriptors[j].u.Interrupt.MaximumVector--;
continue;
}
//
// If INT2 is in the middle of the ranges, then prune them
// one way or the other...
//
if (ioList->Descriptors[j].u.Interrupt.MinimumVector < 2 &&
ioList->Descriptors[j].u.Interrupt.MaximumVector > 2) {
ioList->Descriptors[j].u.Interrupt.MinimumVector = 3;
}
}
//
// Next list
//
size = sizeof(IO_RESOURCE_LIST) +
( (ioList->Count - 1) * sizeof(IO_RESOURCE_DESCRIPTOR) );
ioList = (PIO_RESOURCE_LIST) ( ( (PUCHAR) ioList ) + size );
}
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
ACPIRangeSortCmList(
IN PCM_RESOURCE_LIST CmResList
)
/*++
Routine Description:
This routine ensures that the elements of a CmResList are sorted in
assending order (by type)
Arguments:
CmResList - The list to sort
Return Value:
NTSTATUS
--*/
{
CM_PARTIAL_RESOURCE_DESCRIPTOR tempDesc;
PCM_PARTIAL_RESOURCE_DESCRIPTOR curDesc;
PCM_PARTIAL_RESOURCE_DESCRIPTOR subDesc;
PCM_PARTIAL_RESOURCE_LIST cmList;
ULONG cmIndex;
ULONG cmSize;
ULONG cmSubLoop;
//
// Setup the pointer to the cmList
//
cmList = &(CmResList->List[0].PartialResourceList);
cmSize = cmList->Count;
for (cmIndex = 0; cmIndex < cmSize; cmIndex++) {
curDesc = &(cmList->PartialDescriptors[cmIndex]);
for (cmSubLoop = cmIndex + 1; cmSubLoop < cmSize; cmSubLoop++) {
subDesc = &(cmList->PartialDescriptors[cmSubLoop]);
//
// Is this a compatible descriptor?
//
if (curDesc->Type != subDesc->Type) {
continue;
}
//
// Test by type
//
if (curDesc->Type == CmResourceTypePort ||
curDesc->Type == CmResourceTypeMemory) {
if (subDesc->u.Port.Start.QuadPart <
curDesc->u.Port.Start.QuadPart) {
curDesc = subDesc;
}
} else if (curDesc->Type == CmResourceTypeInterrupt) {
if (subDesc->u.Interrupt.Vector < curDesc->u.Interrupt.Vector) {
curDesc = subDesc;
}
} else if (curDesc->Type == CmResourceTypeDma) {
if (subDesc->u.Dma.Channel < curDesc->u.Dma.Channel) {
curDesc = subDesc;
}
}
}
//
// Did we find a smaller element?
//
if (curDesc == &(cmList->PartialDescriptors[cmIndex])) {
continue;
}
//
// We have found the smallest element. Swap them
//
RtlCopyMemory(
&tempDesc,
&(cmList->PartialDescriptors[cmIndex]),
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
);
RtlCopyMemory(
&(cmList->PartialDescriptors[cmIndex]),
curDesc,
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
);
RtlCopyMemory(
curDesc,
&tempDesc,
sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR)
);
}
//
// Success
//
return STATUS_SUCCESS;
}
NTSTATUS
ACPIRangeSortIoList(
IN PIO_RESOURCE_LIST IoList
)
/*++
Routine Description:
This routine ensures that the elements of a CmResList are sorted in
assending order (by type)
Arguments:
CmResList - The list to sort
Return Value:
NTSTATUS
--*/
{
IO_RESOURCE_DESCRIPTOR tempDesc;
PIO_RESOURCE_DESCRIPTOR curDesc;
PIO_RESOURCE_DESCRIPTOR subDesc;
ULONG ioIndex;
ULONG ioSize;
ULONG ioSubLoop;
//
// Count the number of element ioList
//
ioSize = IoList->Count;
for (ioIndex = 0; ioIndex < ioSize; ioIndex++) {
curDesc = &(IoList->Descriptors[ioIndex]);
for (ioSubLoop = ioIndex + 1; ioSubLoop < ioSize; ioSubLoop++) {
subDesc = &(IoList->Descriptors[ioSubLoop]);
//
// Is this a compatible descriptor?
//
if (curDesc->Type != subDesc->Type) {
continue;
}
//
// Test by type
//
if (curDesc->Type == CmResourceTypePort ||
curDesc->Type == CmResourceTypeMemory) {
if (subDesc->u.Port.MinimumAddress.QuadPart <
curDesc->u.Port.MinimumAddress.QuadPart) {
curDesc = subDesc;
}
} else if (curDesc->Type == CmResourceTypeInterrupt ||
curDesc->Type == CmResourceTypeDma) {
if (subDesc->u.Interrupt.MinimumVector <
curDesc->u.Interrupt.MinimumVector) {
curDesc = subDesc;
}
}
}
//
// Did we find a smaller element?
//
if (curDesc == &(IoList->Descriptors[ioIndex])) {
continue;
}
//
// We have found the smallest element. Swap them
//
RtlCopyMemory(
&tempDesc,
&(IoList->Descriptors[ioIndex]),
sizeof(IO_RESOURCE_DESCRIPTOR)
);
RtlCopyMemory(
&(IoList->Descriptors[ioIndex]),
curDesc,
sizeof(IO_RESOURCE_DESCRIPTOR)
);
RtlCopyMemory(
curDesc,
&tempDesc,
sizeof(IO_RESOURCE_DESCRIPTOR)
);
}
//
// Success
//
return STATUS_SUCCESS;
}
NTSTATUS
ACPIRangeSubtract(
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *IoResReqList,
IN PCM_RESOURCE_LIST CmResList
)
/*++
Routine Description:
This routine takes a IoResReqList, and subtracts the CmResList
from each one of the IoResList, and returns the new list
Arguments:
IoResReqList The original list and where to store the new one
CmResList What to subtract
Return Value:
NTSTATUS
--*/
{
NTSTATUS status;
PIO_RESOURCE_LIST curList;
PIO_RESOURCE_LIST *resourceArray;
PIO_RESOURCE_REQUIREMENTS_LIST newList;
PUCHAR buffer;
ULONG listIndex;
ULONG listSize = (*IoResReqList)->AlternativeLists;
ULONG newSize;
ULONG size;
//
// Sort the CmResList
//
status = ACPIRangeSortCmList( CmResList );
if (!NT_SUCCESS(status)) {
ACPIPrint( (
ACPI_PRINT_FAILURE,
"ACPIRangeSubtract: AcpiRangeSortCmList 0x%08lx Failed 0x%08lx\n",
CmResList,
status
) );
return status;
}
//
// Allocate an array to hold all the alternatives
//
resourceArray = ExAllocatePoolWithTag(
NonPagedPool,
sizeof(PIO_RESOURCE_LIST) * listSize,
ACPI_RESOURCE_POOLTAG
);
if (resourceArray == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( resourceArray, sizeof(PIO_RESOURCE_LIST) * listSize );
//
// Get the first list to work on
//
curList = &( (*IoResReqList)->List[0]);
buffer = (PUCHAR) curList;
newSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) - sizeof(IO_RESOURCE_LIST);
//
// Sort the IoResList
//
status = ACPIRangeSortIoList( curList );
if (!NT_SUCCESS(status)) {
ACPIPrint( (
ACPI_PRINT_FAILURE,
"ACPIRangeSubtract: AcpiRangeSortIoList 0x%08lx Failed 0x%08lx\n",
*curList,
status
) );
return status;
}
//
// Process all the elements in the list
//
for (listIndex = 0; listIndex < listSize; listIndex++) {
//
// Process that list
//
status = ACPIRangeSubtractIoList(
curList,
CmResList,
&(resourceArray[listIndex])
);
if (!NT_SUCCESS(status)) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPIRangeSubtract: Failed - 0x%08lx\n",
status
) );
while (listIndex) {
ExFreePool( resourceArray[listIndex] );
listIndex--;
}
ExFreePool( resourceArray );
return status;
}
//
// Help calculate the size of the new res req descriptor
//
newSize += sizeof(IO_RESOURCE_LIST) +
( ( (resourceArray[listIndex])->Count - 1) *
sizeof(IO_RESOURCE_DESCRIPTOR) );
//
// Find the next list
//
size = sizeof(IO_RESOURCE_LIST) + (curList->Count - 1) *
sizeof(IO_RESOURCE_DESCRIPTOR);
buffer += size;
curList = (PIO_RESOURCE_LIST) buffer;
}
//
// Allocate the new list
//
newList = ExAllocatePoolWithTag(
NonPagedPool,
newSize,
ACPI_RESOURCE_POOLTAG
);
if (newList == NULL) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPIRangeSubtract: Failed to allocate 0x%08lx bytes\n",
size
) );
do {
listSize--;
ExFreePool( resourceArray[listSize] );
} while (listSize);
ExFreePool( resourceArray );
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Copy the head of the res req list
//
RtlZeroMemory( newList, newSize );
RtlCopyMemory(
newList,
*IoResReqList,
sizeof(IO_RESOURCE_REQUIREMENTS_LIST) -
sizeof(IO_RESOURCE_LIST)
);
newList->ListSize = newSize;
curList = &(newList->List[0]);
buffer = (PUCHAR) curList;
for (listIndex = 0; listIndex < listSize; listIndex++) {
//
// Determine the size to copy
//
size = sizeof(IO_RESOURCE_LIST) +
( ( ( (resourceArray[listIndex])->Count) - 1) *
sizeof(IO_RESOURCE_DESCRIPTOR) );
//
// Copy the new resource to the correct place
//
RtlCopyMemory(
curList,
resourceArray[ listIndex ],
size
);
//
// Find the next list
//
buffer += size;
curList = (PIO_RESOURCE_LIST) buffer;
//
// Done with this list
//
ExFreePool( resourceArray[listIndex] );
}
//
// Done with this area of memory
//
ExFreePool( resourceArray );
//
// Free Old list
//
ExFreePool( *IoResReqList );
//
// Return the new list
//
*IoResReqList = newList;
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
ACPIRangeSubtractIoList(
IN PIO_RESOURCE_LIST IoResList,
IN PCM_RESOURCE_LIST CmResList,
OUT PIO_RESOURCE_LIST *Result
)
/*++
Routine Description:
This routine is responsible for subtracting the elements of the
CmResList from the IoResList
Arguments:
IoResList - The list to subtract from
CmResList - The list to subtract
Result - The answer
Return Value:
NTSTATUS
--*/
{
//
// The current CM descriptor
//
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
//
// The current CM resource list that we are processing
//
PCM_PARTIAL_RESOURCE_LIST cmList;
//
// The current IO descriptor
//
PIO_RESOURCE_DESCRIPTOR ioDesc;
//
// The working copy of the result list
//
PIO_RESOURCE_LIST workList;
//
// The current index into the cm res list
//
ULONG cmIndex;
//
// The number of elements there are in the cm res list
//
ULONG cmSize;
//
// The current index into the io res list
//
ULONG ioIndex;
//
// The number of elements there are in the io res list
//
ULONG ioSize;
//
// The current index into the result. This is where the 'next' resource
// descriptor goes into.
//
ULONG resultIndex = 0;
//
// How many elements there are in the result
//
ULONG resultSize;
//
// These are the max and min of the cm desc
//
ULONGLONG cmMax, cmMin;
//
// These are the max and min of the io desc
//
ULONGLONG ioMax, ioMin;
//
// The length of the resource
//
ULONGLONG length;
//
// Step one: Obtain the pointers we need to the start of the cm list
// and the size of the supplied lists
//
cmList = &(CmResList->List[0].PartialResourceList);
cmSize = cmList->Count;
ioSize = IoResList->Count;
//
// Step two: Calculate the number of Io descriptors needed in the
// worst case. That is 2x the number of cm descriptors plut the number
// of original io descriptors.
//
resultSize = cmSize * 2 + ioSize * 2;
//
// Step three: Allocate enough memory for those descriptors
//
workList = ExAllocatePoolWithTag(
NonPagedPool,
sizeof(IO_RESOURCE_LIST) +
(sizeof(IO_RESOURCE_DESCRIPTOR) * (resultSize - 1) ),
ACPI_RESOURCE_POOLTAG
);
if (workList == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
RtlZeroMemory( workList, sizeof(IO_RESOURCE_LIST) +
(sizeof(IO_RESOURCE_DESCRIPTOR) * (resultSize - 1) ) );
RtlCopyMemory(
workList,
IoResList,
sizeof(IO_RESOURCE_LIST) - sizeof(IO_RESOURCE_DESCRIPTOR)
);
//
// Step four: walk through the entire io res list
//
for (ioIndex = 0; ioIndex < ioSize; ioIndex++) {
//
// Step five: copy the current descriptor to the result, and
// keep a pointer to it. Remember where to store the next io
// descriptor.
//
RtlCopyMemory(
&(workList->Descriptors[resultIndex]),
&(IoResList->Descriptors[ioIndex]),
sizeof(IO_RESOURCE_DESCRIPTOR)
);
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"Copied Desc %d (0x%08lx) to Index %d (0x%08lx)\n",
ioIndex,
&(IoResList->Descriptors[ioIndex]),
resultIndex,
&(workList->Descriptors[resultIndex])
) );
ioDesc = &(workList->Descriptors[resultIndex]);
resultIndex += 1;
//
// Step six: Walk the Cm Res list, looking for resources to
// subtract from this descriptor
//
for (cmIndex = 0; cmIndex < cmSize; cmIndex++) {
//
// If we don't have a resource descriptor any more, then
// we stop looping
//
if (ioDesc == NULL) {
break;
}
//
// Step seven: determine the current cm descriptor
//
cmDesc = &(cmList->PartialDescriptors[cmIndex]);
//
// Step eight: is the current cm descriptor of the same type
// as the io descriptor?
//
if (cmDesc->Type != ioDesc->Type) {
//
// No
//
continue;
}
//
// Step nine: we must handle each resource type indepently.
//
switch (ioDesc->Type) {
case CmResourceTypeMemory:
case CmResourceTypePort:
ioMin = ioDesc->u.Port.MinimumAddress.QuadPart;
ioMax = ioDesc->u.Port.MaximumAddress.QuadPart;
cmMin = cmDesc->u.Port.Start.QuadPart;
cmMax = cmDesc->u.Port.Start.QuadPart +
cmDesc->u.Port.Length - 1;
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"ACPIRangeSubtractIoRange: ioMin 0x%lx ioMax 0x%lx "
"cmMin 0x%lx cmMax 0x%lx resultIndex 0x%lx\n",
(ULONG) ioMin,
(ULONG) ioMax,
(ULONG) cmMin,
(ULONG) cmMax,
resultIndex
) );
//
// Does the descriptors overlap?
//
if (ioMin > cmMax || ioMax < cmMin) {
break;
}
//
// Do we need to remove the descriptor from the list?
//
if (ioMin >= cmMin && ioMax <= cmMax) {
resultIndex -= 1;
ioDesc = NULL;
break;
}
//
// Do we need to truncate the lowpart of the io desc?
//
if (ioMin >= cmMin && ioMax > cmMax) {
ioDesc->u.Port.MinimumAddress.QuadPart = (cmMax + 1);
length = ioMax - cmMax;
}
//
// Do we need to truncate the highpart of the io desc?
//
if (ioMin < cmMin && ioMax <= cmMax) {
ioDesc->u.Port.MaximumAddress.QuadPart = (cmMin - 1);
length = cmMin - ioMin;
}
//
// Do we need to split the descriptor into two parts
//
if (ioMin < cmMin && ioMax > cmMax) {
//
// Create a new descriptors
//
RtlCopyMemory(
&(workList->Descriptors[resultIndex]),
ioDesc,
sizeof(IO_RESOURCE_DESCRIPTOR)
);
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"Copied Desc (0x%08lx) to Index %d (0x%08lx)\n",
&(IoResList->Descriptors[ioIndex]),
resultIndex,
&(workList->Descriptors[resultIndex])
) );
ioDesc->u.Port.MaximumAddress.QuadPart = (cmMin - 1);
ioDesc->u.Port.Alignment = 1;
length = cmMin - ioMin;
if ( (ULONG) length < ioDesc->u.Port.Length) {
ioDesc->u.Port.Length = (ULONG) length;
}
//
// Next descriptor
//
ioDesc = &(workList->Descriptors[resultIndex]);
ioDesc->u.Port.MinimumAddress.QuadPart = (cmMax + 1);
ioDesc->u.Port.Alignment = 1;
length = ioMax - cmMax;
resultIndex += 1;
}
//
// Do we need to update the length?
//
if ( (ULONG) length < ioDesc->u.Port.Length) {
ioDesc->u.Port.Length = (ULONG) length;
}
break;
case CmResourceTypeInterrupt:
//
// Do the descriptors overlap?
//
if (ioDesc->u.Interrupt.MinimumVector >
cmDesc->u.Interrupt.Vector ||
ioDesc->u.Interrupt.MaximumVector <
cmDesc->u.Interrupt.Vector) {
break;
}
//
// Do we have to remove the descriptor
//
if (ioDesc->u.Interrupt.MinimumVector ==
cmDesc->u.Interrupt.Vector &&
ioDesc->u.Interrupt.MaximumVector ==
cmDesc->u.Interrupt.Vector) {
resultIndex =- 1;
ioDesc = NULL;
break;
}
//
// Do we clip the low part?
//
if (ioDesc->u.Interrupt.MinimumVector ==
cmDesc->u.Interrupt.Vector) {
ioDesc->u.Interrupt.MinimumVector++;
break;
}
//
// Do we clip the high part
//
if (ioDesc->u.Interrupt.MaximumVector ==
cmDesc->u.Interrupt.Vector) {
ioDesc->u.Interrupt.MaximumVector--;
break;
}
//
// Split the record
//
RtlCopyMemory(
&(workList->Descriptors[resultIndex]),
ioDesc,
sizeof(IO_RESOURCE_DESCRIPTOR)
);
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"Copied Desc (0x%08lx) to Index %d (0x%08lx)\n",
&(IoResList->Descriptors[ioIndex]),
resultIndex,
&(workList->Descriptors[resultIndex])
) );
ioDesc->u.Interrupt.MaximumVector =
cmDesc->u.Interrupt.Vector - 1;
ioDesc = &(workList->Descriptors[resultIndex]);
ioDesc->u.Interrupt.MinimumVector =
cmDesc->u.Interrupt.Vector + 1;
resultIndex += 1;
break;
case CmResourceTypeDma:
//
// Do the descriptors overlap?
//
if (ioDesc->u.Dma.MinimumChannel >
cmDesc->u.Dma.Channel ||
ioDesc->u.Dma.MaximumChannel <
cmDesc->u.Dma.Channel) {
break;
}
//
// Do we have to remove the descriptor
//
if (ioDesc->u.Dma.MinimumChannel ==
cmDesc->u.Dma.Channel &&
ioDesc->u.Dma.MaximumChannel ==
cmDesc->u.Dma.Channel) {
resultIndex -= 1;
ioDesc = NULL;
break;
}
//
// Do we clip the low part?
//
if (ioDesc->u.Dma.MinimumChannel ==
cmDesc->u.Dma.Channel) {
ioDesc->u.Dma.MinimumChannel++;
break;
}
//
// Do we clip the high part
//
if (ioDesc->u.Dma.MaximumChannel ==
cmDesc->u.Dma.Channel) {
ioDesc->u.Dma.MaximumChannel--;
break;
}
//
// Split the record
//
RtlCopyMemory(
&(workList->Descriptors[resultIndex]),
ioDesc,
sizeof(IO_RESOURCE_DESCRIPTOR)
);
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"Copied Desc (0x%08lx) to Index %d (0x%08lx)\n",
&(IoResList->Descriptors[ioIndex]),
resultIndex,
&(workList->Descriptors[resultIndex])
) );
ioDesc->u.Dma.MaximumChannel =
cmDesc->u.Dma.Channel - 1;
ioDesc = &(workList->Descriptors[resultIndex]);
ioDesc->u.Dma.MinimumChannel =
cmDesc->u.Dma.Channel + 1;
resultIndex += 1;
break;
} // switch
} // for
//
// Step ten, make a backup copy of the original descriptor, and
// mark it as a DeviceSpecific resource
//
RtlCopyMemory(
&(workList->Descriptors[resultIndex]),
&(IoResList->Descriptors[ioIndex]),
sizeof(IO_RESOURCE_DESCRIPTOR)
);
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"Copied Desc %d (0x%08lx) to Index %d (0x%08lx) for backup\n",
ioIndex,
&(IoResList->Descriptors[ioIndex]),
resultIndex,
&(workList->Descriptors[resultIndex])
) );
ioDesc = &(workList->Descriptors[resultIndex]);
ioDesc->Type = CmResourceTypeDevicePrivate;
resultIndex += 1;
} // for
//
// Step 11: Calculate the number of resources in the new list
//
workList->Count = resultIndex;
//
// Step 12: Allocate the block for the return value. Don't waste
// any memory here
//
*Result = ExAllocatePoolWithTag(
NonPagedPool,
sizeof(IO_RESOURCE_LIST) +
(sizeof(IO_RESOURCE_DESCRIPTOR) * (resultIndex - 1) ),
ACPI_RESOURCE_POOLTAG
);
if (*Result == NULL) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Step 13: Copy the result over and free the work buffer
//
RtlCopyMemory(
*Result,
workList,
sizeof(IO_RESOURCE_LIST) +
(sizeof(IO_RESOURCE_DESCRIPTOR) * (resultIndex - 1) )
);
//
// Step 14: Done
//
return STATUS_SUCCESS;
}
VOID
ACPIRangeValidatePciMemoryResource(
IN PIO_RESOURCE_LIST IoList,
IN ULONG Index,
IN PACPI_BIOS_MULTI_NODE E820Info,
OUT ULONG *BugCheck
)
/*++
Routine Description:
This routine checks the specified descriptor in the resource list does
not in any way overlap or conflict with any of the descriptors in the
E820 information structure
Arguments:
IoResList - The IoResourceList to check
Index - The descript we are currently looking at
E820Info - The BIOS's memory description table (Chapter 14 of ACPI Spec)
BugCheck - The number of bugcheckable offences commited
Return Value:
None
--*/
{
ULONG i;
ULONGLONG absMin;
ULONGLONG absMax;
ASSERT( IoList != NULL );
//
// Make sure that there is an E820 table before we look at it
//
if (E820Info == NULL) {
return;
}
//
// Calculate the absolute maximum and minimum size of the memory window
//
absMin = IoList->Descriptors[Index].u.Memory.MinimumAddress.QuadPart;
absMax = IoList->Descriptors[Index].u.Memory.MaximumAddress.QuadPart;
//
// Look at all the entries in the E820Info and see if there is an
// overlap
//
for (i = 0; i < E820Info->Count; i++) {
//
// Hackhack --- if this is a "Reserved" address, then don't consider
// those a bugcheck
//
if (E820Info->E820Entry[i].Type == AcpiAddressRangeReserved) {
continue;
}
//
// Do some fixups firsts
//
if (E820Info->E820Entry[i].Type == AcpiAddressRangeNVS ||
E820Info->E820Entry[i].Type == AcpiAddressRangeACPI) {
ASSERT( E820Info->E820Entry[i].Length.HighPart == 0);
if (E820Info->E820Entry[i].Length.HighPart != 0) {
ACPIPrint( (
ACPI_PRINT_WARNING,
"ACPI: E820 Entry #%d (type %d) Length = %016I64x > 32bit\n",
i,
E820Info->E820Entry[i].Type,
E820Info->E820Entry[i].Length.QuadPart
) );
E820Info->E820Entry[i].Length.HighPart = 0;
}
}
//
// Is the descriptor beyond what we are looking for?
//
if (absMax < (ULONGLONG) E820Info->E820Entry[i].Base.QuadPart) {
continue;
}
//
// Is it before what we are looking for?
//
if (absMin >= (ULONGLONG) (E820Info->E820Entry[i].Base.QuadPart + E820Info->E820Entry[i].Length.QuadPart) ) {
continue;
}
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPI: E820 Entry %d (type %I64d) (%I64x-%I64x) overlaps\n"
"ACPI: PCI Entry %d Min:%I64x Max:%I64x Length:%lx Align:%lx\n",
i, E820Info->E820Entry[i].Type,
E820Info->E820Entry[i].Base.QuadPart,
(E820Info->E820Entry[i].Base.QuadPart + E820Info->E820Entry[i].Length.QuadPart),
Index,
IoList->Descriptors[Index].u.Memory.MinimumAddress.QuadPart,
IoList->Descriptors[Index].u.Memory.MaximumAddress.QuadPart,
IoList->Descriptors[Index].u.Memory.Length,
IoList->Descriptors[Index].u.Memory.Alignment
) );
//
// Is this an NVS area? Are we doing an override of this?
//
if ( (AcpiOverrideAttributes & ACPI_OVERRIDE_NVS_CHECK) &&
(E820Info->E820Entry[i].Type == AcpiAddressRangeNVS) ) {
if (absMax >= (ULONGLONG) E820Info->E820Entry[i].Base.QuadPart &&
absMin < (ULONGLONG) E820Info->E820Entry[i].Base.QuadPart) {
//
// We can attempt to do a helpfull fixup here
//
IoList->Descriptors[Index].u.Memory.MaximumAddress.QuadPart =
(ULONGLONG) E820Info->E820Entry[i].Base.QuadPart - 1;
IoList->Descriptors[Index].u.Memory.Length = (ULONG)
(IoList->Descriptors[Index].u.Memory.MaximumAddress.QuadPart -
IoList->Descriptors[Index].u.Memory.MinimumAddress.QuadPart + 1);
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPI: PCI Entry %d Changed to\n"
"ACPI: PCI Entry %d Min:%I64x Max:%I64x Length:%lx Align:%lx\n",
Index,
Index,
IoList->Descriptors[Index].u.Memory.MinimumAddress.QuadPart,
IoList->Descriptors[Index].u.Memory.MaximumAddress.QuadPart,
IoList->Descriptors[Index].u.Memory.Length,
IoList->Descriptors[Index].u.Memory.Alignment
) );
}
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPI: E820 Entry %d Overrides PCI Entry\n",
i
) );
continue;
}
//
// If we got here, then there is an overlap, and we need to bugcheck
//
(*BugCheck)++;
}
}
VOID
ACPIRangeValidatePciResources(
IN PDEVICE_EXTENSION DeviceExtension,
IN PIO_RESOURCE_REQUIREMENTS_LIST IoResList
)
/*++
Routine Description:
This routine is called to make sure that the resource that we will
hand of to PCI have a chance of making the system boot.
This is what the list will allow
MEM - A0000 - DFFFF,
<Physical Base> - 4GB
IO - Any
BUS - Any
The code checks to make sure that the Length = Max - Min + 1, and that
the Alignment value is correct
Arguments:
IoResList - The list to check
Return Value:
Nothing
--*/
{
NTSTATUS status;
PACPI_BIOS_MULTI_NODE e820Info;
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmPartialDesc;
PCM_PARTIAL_RESOURCE_LIST cmPartialList;
PIO_RESOURCE_LIST ioList;
PKEY_VALUE_PARTIAL_INFORMATION_ALIGN64 keyInfo;
ULONG bugCheck = 0;
ULONG i;
ULONG j;
ULONGLONG length;
ULONG size;
if (IoResList == NULL) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPIRangeValidPciResources: No IoResList\n"
) );
KeBugCheckEx(
ACPI_BIOS_ERROR,
ACPI_ROOT_PCI_RESOURCE_FAILURE,
(ULONG_PTR) DeviceExtension,
2,
0
);
}
//
// Read the key for the AcpiConfigurationData
//
status = OSReadAcpiConfigurationData( &keyInfo );
if (!NT_SUCCESS(status)) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPIRangeValidatePciResources: Cannot get Information %08lx\n",
status
) );
return;
}
//
// Crack the structure to get the E820Table entry
//
cmPartialList = (PCM_PARTIAL_RESOURCE_LIST) (keyInfo->Data);
cmPartialDesc = &(cmPartialList->PartialDescriptors[0]);
e820Info = (PACPI_BIOS_MULTI_NODE) ( (PUCHAR) cmPartialDesc +
sizeof(CM_PARTIAL_RESOURCE_LIST) );
//
// Walk the resource requirements list
//
ioList = &(IoResList->List[0]);
for (i = 0; i < IoResList->AlternativeLists; i++) {
//
// Walk the IO list
//
for (j = 0; j < ioList->Count; j++) {
if (ioList->Descriptors[j].Type == CmResourceTypePort ||
ioList->Descriptors[j].Type == CmResourceTypeMemory) {
length = ioList->Descriptors[j].u.Port.MaximumAddress.QuadPart -
ioList->Descriptors[j].u.Port.MinimumAddress.QuadPart + 1;
//
// Does the length match?
//
if (length != ioList->Descriptors[j].u.Port.Length) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPI: Invalid IO/Mem Length - ( (Max - Min + 1) != Length)\n"
"ACPI: PCI Entry %d Min:%I64x Max:%I64x Length:%lx Align:%lx\n",
ioList->Descriptors[j].u.Memory.MinimumAddress.QuadPart,
ioList->Descriptors[j].u.Memory.MaximumAddress.QuadPart,
ioList->Descriptors[j].u.Memory.Length,
ioList->Descriptors[j].u.Memory.Alignment
) );
bugCheck++;
ioList->Descriptors[j].u.Port.Length = (ULONG) length;
}
//
// Is the alignment non-zero?
//
if (ioList->Descriptors[j].u.Port.Alignment == 0) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPI: Invalid IO/Mem Alignment"
"ACPI: PCI Entry %d Min:%I64x Max:%I64x Length:%lx Align:%lx\n",
ioList->Descriptors[j].u.Memory.MinimumAddress.QuadPart,
ioList->Descriptors[j].u.Memory.MaximumAddress.QuadPart,
ioList->Descriptors[j].u.Memory.Length,
ioList->Descriptors[j].u.Memory.Alignment
) );
bugCheck++;
ioList->Descriptors[j].u.Port.Alignment = 1;
}
//
// The alignment cannot intersect with the min value
//
if (ioList->Descriptors[j].u.Port.MinimumAddress.LowPart &
(ioList->Descriptors[j].u.Port.Alignment - 1) ) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPI: Invalid IO/Mem Alignment - (Min & (Align - 1) )\n"
"ACPI: PCI Entry %d Min:%I64x Max:%I64x Length:%lx Align:%lx\n",
ioList->Descriptors[j].u.Memory.MinimumAddress.QuadPart,
ioList->Descriptors[j].u.Memory.MaximumAddress.QuadPart,
ioList->Descriptors[j].u.Memory.Length,
ioList->Descriptors[j].u.Memory.Alignment
) );
bugCheck++;
ioList->Descriptors[j].u.Port.Alignment = 1;
}
}
if (ioList->Descriptors[j].Type == CmResourceTypeBusNumber) {
length = ioList->Descriptors[j].u.BusNumber.MaxBusNumber -
ioList->Descriptors[j].u.BusNumber.MinBusNumber + 1;
//
// Does the length match?
//
if (length != ioList->Descriptors[j].u.BusNumber.Length) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPI: Invalid BusNumber Length - ( (Max - Min + 1) != Length)\n"
"ACPI: PCI Entry %d Min:%x Max:%x Length:%lx\n",
ioList->Descriptors[j].u.BusNumber.MinBusNumber,
ioList->Descriptors[j].u.BusNumber.MaxBusNumber,
ioList->Descriptors[j].u.BusNumber.Length
) );
bugCheck++;
ioList->Descriptors[j].u.BusNumber.Length = (ULONG) length;
}
}
if (ioList->Descriptors[j].Type == CmResourceTypeMemory) {
ACPIRangeValidatePciMemoryResource(
ioList,
j,
e820Info,
&bugCheck
);
}
}
//
// Next list
//
size = sizeof(IO_RESOURCE_LIST) +
( (ioList->Count - 1) * sizeof(IO_RESOURCE_DESCRIPTOR) );
ioList = (PIO_RESOURCE_LIST) ( ( (PUCHAR) ioList ) + size );
}
//
// Do we errors?
//
if (bugCheck) {
ACPIPrint( (
ACPI_PRINT_CRITICAL,
"ACPI:\n"
"ACPI: FATAL BIOS ERROR - Need new BIOS to fix PCI problems\n"
"ACPI:\n"
"ACPI: This machine will not boot after 8/26/98!!!!\n"
) );
//
// No, well, bugcheck
//
KeBugCheckEx(
ACPI_BIOS_ERROR,
ACPI_ROOT_PCI_RESOURCE_FAILURE,
(ULONG_PTR) DeviceExtension,
(ULONG_PTR) IoResList,
(ULONG_PTR) e820Info
);
}
//
// Free the E820 info
//
ExFreePool( keyInfo );
}