|
|
/*++
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;
if (length > MAXULONG) { ACPIPrint( ( ACPI_PRINT_CRITICAL, "ACPI: Invalid IO/Mem Length > MAXULONG)\n" "ACPI: PCI Entry %d Min:%I64x Max:%I64x Length:%lx Align:%lx\n", j, ioList->Descriptors[j].u.Memory.MinimumAddress.QuadPart, ioList->Descriptors[j].u.Memory.MaximumAddress.QuadPart, length, ioList->Descriptors[j].u.Memory.Alignment ) ); bugCheck++; } //
// 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", j, 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++;
}
//
// 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", j, 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++;
}
//
// 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", j, 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++;
}
}
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", j, ioList->Descriptors[j].u.BusNumber.MinBusNumber, ioList->Descriptors[j].u.BusNumber.MaxBusNumber, ioList->Descriptors[j].u.BusNumber.Length ) ); bugCheck++;
}
}
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 ); }
|