Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1571 lines
35 KiB

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
cmres.c
Abstract:
This file contains routines to translate resources between PnP ISA/BIOS
format and Windows NT formats.
Author:
Stephane Plante (splante) 20-Nov-1996
Environment:
Kernel mode only.
Revision History:
13-Feb-1997:
Initial Revision
--*/
#include "pch.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,PnpiCmResourceToBiosAddress)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosAddressDouble)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosDma)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosExtendedIrq)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosIoFixedPort)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosIoPort)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosIrq)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory32)
#pragma alloc_text(PAGE,PnpiCmResourceToBiosMemory32Fixed)
#pragma alloc_text(PAGE,PnpiCmResourceValidEmptyList)
#pragma alloc_text(PAGE,PnpCmResourcesToBiosResources)
#endif
NTSTATUS
PnpiCmResourceToBiosAddress(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine converts the proper Cm resource descriptor back into a
word address descriptor
Arguments:
Buffer - Pointer to the Bios Resource list
List - Pointer to the CM resource List
Return:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_WORD_ADDRESS_DESCRIPTOR buffer;
UCHAR type;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_WORD_ADDRESS_DESCRIPTOR) Buffer;
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1 );
ASSERT( aList->PartialResourceList.Count );
//
// Determine which type of descriptor we are looking for
//
switch (buffer->RFlag) {
case PNP_ADDRESS_MEMORY_TYPE:
type = CmResourceTypeMemory;
break;
case PNP_ADDRESS_IO_TYPE:
type = CmResourceTypePort;
break;
case PNP_ADDRESS_BUS_NUMBER_TYPE:
type = CmResourceTypeBusNumber;
break;
default:
return STATUS_UNSUCCESSFUL;
}
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != type) {
//
// No
//
continue;
}
switch (desc->Type) {
case PNP_ADDRESS_MEMORY_TYPE:
//
// Set the flags
//
buffer->TFlag = 0;
if (desc->Flags & CM_RESOURCE_MEMORY_READ_WRITE) {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_WRITE;
} else {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_ONLY;
}
if (desc->Flags & CM_RESOURCE_MEMORY_CACHEABLE) {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_CACHEABLE;
} else if (desc->Flags & CM_RESOURCE_MEMORY_COMBINEDWRITE) {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE;
} else if (desc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE;
} else {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE;
}
//
// Set the rest of the information
//
buffer->MinimumAddress = (USHORT)
(desc->u.Memory.Start.LowPart & 0xFFFF);
buffer->MaximumAddress = buffer->MinimumAddress +
(USHORT) (desc->u.Memory.Length - 1);
buffer->AddressLength = (USHORT) desc->u.Memory.Length;
break;
case PNP_ADDRESS_IO_TYPE:
//
// We must extract the flags here from the
// devicePrivate resource
//
//
// Set the rest of the information
//
buffer->MinimumAddress = (USHORT)
(desc->u.Port.Start.LowPart & 0xFFFF);
buffer->MaximumAddress = buffer->MinimumAddress +
(USHORT) (desc->u.Port.Length - 1);
buffer->AddressLength = (USHORT) desc->u.Port.Length;
break;
case PNP_ADDRESS_BUS_NUMBER_TYPE:
buffer->MinimumAddress = (USHORT)
(desc->u.BusNumber.Start & 0xFFFF);
buffer->MaximumAddress = buffer->MinimumAddress +
(USHORT) (desc->u.BusNumber.Length - 1);
buffer->AddressLength = (USHORT) desc->u.BusNumber.Length;
break;
} // switch
//
// Handling for the GFlags goes here, if we ever decide to
// support it
//
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
} // for
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
PnpiCmResourceToBiosAddressDouble(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine converts the proper Cm resource descriptor back into a
word address descriptor
Arguments:
Buffer - Pointer to the Bios Resource list
List - Pointer to the CM resource List
Return:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_DWORD_ADDRESS_DESCRIPTOR buffer;
UCHAR type;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_DWORD_ADDRESS_DESCRIPTOR) Buffer;
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1 );
ASSERT( aList->PartialResourceList.Count );
//
// Determine which type of descriptor we are looking for
//
switch (buffer->RFlag) {
case PNP_ADDRESS_MEMORY_TYPE:
type = CmResourceTypeMemory;
break;
case PNP_ADDRESS_IO_TYPE:
type = CmResourceTypePort;
break;
case PNP_ADDRESS_BUS_NUMBER_TYPE:
type = CmResourceTypeBusNumber;
break;
default:
return STATUS_UNSUCCESSFUL;
}
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != type) {
//
// No
//
continue;
}
switch (desc->Type) {
case PNP_ADDRESS_MEMORY_TYPE:
//
// Set the flags
//
buffer->TFlag = 0;
if (desc->Flags & CM_RESOURCE_MEMORY_READ_WRITE) {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_WRITE;
} else {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_READ_ONLY;
}
if (desc->Flags & CM_RESOURCE_MEMORY_CACHEABLE) {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_CACHEABLE;
} else if (desc->Flags & CM_RESOURCE_MEMORY_COMBINEDWRITE) {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_WRITE_COMBINE;
} else if (desc->Flags & CM_RESOURCE_MEMORY_PREFETCHABLE) {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_PREFETCHABLE;
} else {
buffer->TFlag |= PNP_ADDRESS_TYPE_MEMORY_NONCACHEABLE;
}
//
// Set the rest of the information
//
buffer->MinimumAddress = (ULONG) desc->u.Memory.Start.LowPart;
buffer->MaximumAddress = buffer->MinimumAddress +
(ULONG) (desc->u.Memory.Length - 1);
buffer->AddressLength = desc->u.Memory.Length;
break;
case PNP_ADDRESS_IO_TYPE:
//
// We must extract the flags here from the
// devicePrivate resource
//
//
// Set the rest of the information
//
buffer->MinimumAddress = (ULONG) desc->u.Port.Start.LowPart;
buffer->MaximumAddress = buffer->MinimumAddress +
(ULONG) (desc->u.Port.Length - 1);
buffer->AddressLength = desc->u.Port.Length;
break;
case PNP_ADDRESS_BUS_NUMBER_TYPE:
buffer->MinimumAddress = (ULONG) desc->u.BusNumber.Start;
buffer->MaximumAddress = buffer->MinimumAddress +
(ULONG) (desc->u.BusNumber.Length - 1);
buffer->AddressLength = desc->u.BusNumber.Length;
break;
} // switch
//
// Handling for the GFlags goes here if we ever decide to support it
//
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
} // for
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
PnpiCmResourceToBiosDma(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine stores all of the DMAs in the resource list into the Bios resource
list
Arguments:
Buffer - Pointer to the Bios resource List
List - Pointer to the CM resource List
Return:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_DMA_DESCRIPTOR buffer;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_DMA_DESCRIPTOR) Buffer;
ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 2);
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// We can have a descriptor with no DMA channels
//
buffer->ChannelMask = 0;
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypeDma) {
//
// No
//
continue;
}
//
// Here we *have* a match...
//
buffer->ChannelMask = (1 << desc->u.Dma.Channel);
//
// Set the correct flags
//
buffer->Flags = 0;
if (desc->Flags & CM_RESOURCE_DMA_8) {
buffer->Flags |= PNP_DMA_SIZE_8;
} else if (desc->Flags & CM_RESOURCE_DMA_8_AND_16) {
buffer->Flags |= PNP_DMA_SIZE_8_AND_16;
} else if (desc->Flags & CM_RESOURCE_DMA_16) {
buffer->Flags |= PNP_DMA_SIZE_16;
} else if (desc->Flags & CM_RESOURCE_DMA_32) {
buffer->Flags |= PNP_DMA_SIZE_RESERVED;
}
if (desc->Flags & CM_RESOURCE_DMA_BUS_MASTER) {
buffer->Flags |= PNP_DMA_BUS_MASTER;
}
if (desc->Flags & CM_RESOURCE_DMA_TYPE_A) {
buffer->Flags |= PNP_DMA_TYPE_A;
} else if (desc->Flags & CM_RESOURCE_DMA_TYPE_B) {
buffer->Flags |= PNP_DMA_TYPE_B;
} else if (desc->Flags & CM_RESOURCE_DMA_TYPE_F) {
buffer->Flags |= PNP_DMA_TYPE_F;
}
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
}
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
PnpiCmResourceToBiosExtendedIrq(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine stores all of the Irqs in the resource list into the Bios resource
list
Arguments:
Buffer - Pointer to the Bios resource List
List - Pointer to the CM resource List
Return Value:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_EXTENDED_IRQ_DESCRIPTOR buffer;
ULONG i;
ULONG matches = 0;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_EXTENDED_IRQ_DESCRIPTOR) Buffer;
ASSERT( buffer->TableSize == 1);
ASSERT( buffer->Length >= 6);
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypeInterrupt) {
//
// No
//
continue;
}
//
// Here we *have* a match...
//
buffer->Table[0] = (ULONG) desc->u.Interrupt.Level;
//
// Set the Flags
//
buffer->Flags = 0;
if ( (desc->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ) {
buffer->Flags |= $EDG | $HGH;
} else {
buffer->Flags |= $LVL | $LOW;
}
if (desc->ShareDisposition == CmResourceShareShared) {
buffer->Flags |= PNP_EXTENDED_IRQ_SHARED;
}
//
// We need to use DevicePrivate information to store this
// bit. For now, assume that it is set to true
//
buffer->Flags |= PNP_EXTENDED_IRQ_RESOURCE_CONSUMER_ONLY;
//
// Done with the record
//
desc->Type = CmResourceTypeNull;
matches++;
break;
}
//
// Done with matches
//
return (matches == 0 ? STATUS_UNSUCCESSFUL : STATUS_SUCCESS );
}
NTSTATUS
PnpiCmResourceToBiosIoFixedPort(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine stores all of the IoPort in the resource list into the Bios resource
list
Arguments:
Buffer - Pointer to the Bios resource List
List - Pointer to the CM resource List
Return:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_FIXED_PORT_DESCRIPTOR buffer;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_FIXED_PORT_DESCRIPTOR) Buffer;
ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 3);
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// Our fixed port can be nothing
//
buffer->MinimumAddress = buffer->Length = 0;
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypePort) {
//
// No
//
continue;
}
//
// This port type is always set to a 10 bit decode
//
if ( !(desc->Flags & CM_RESOURCE_PORT_10_BIT_DECODE) ) {
//
// No
//
continue;
}
//
// Here we *have* a match...
//
buffer->MinimumAddress = (USHORT) desc->u.Port.Start.LowPart;
buffer->Length = (UCHAR) desc->u.Port.Length;
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
}
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
PnpiCmResourceToBiosIoPort(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine stores all of the IoPort in the resource list into the Bios resource
list
Arguments:
Buffer - Pointer to the Bios resource List
List - Pointer to the CM resource List
Return:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_PORT_DESCRIPTOR buffer;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_PORT_DESCRIPTOR) Buffer;
ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 7);
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// We can use no ports
//
buffer->Information = 0;
buffer->MinimumAddress = 0;
buffer->MaximumAddress = 0;
buffer->Alignment = 0;
buffer->Length = 0;
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypePort) {
//
// No
//
continue;
}
//
// Here we *have* a match...
//
buffer->MinimumAddress = (USHORT) desc->u.Port.Start.LowPart;
buffer->MaximumAddress = buffer->MinimumAddress;
buffer->Alignment = 1;
buffer->Length = (UCHAR) desc->u.Port.Length;
//
// Set the flags
//
buffer->Information = 0;
if (desc->Flags & CM_RESOURCE_PORT_10_BIT_DECODE) {
buffer->Information |= PNP_PORT_10_BIT_DECODE;
}
if (desc->Flags & CM_RESOURCE_PORT_16_BIT_DECODE) {
buffer->Information |= PNP_PORT_16_BIT_DECODE;
}
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
}
//
// Done with matches
//
return STATUS_SUCCESS;
}
NTSTATUS
PnpiCmResourceToBiosIrq(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine stores all of the Irqs in the resource list into the Bios resource
list
Arguments:
Buffer - Pointer to the Bios resource List
List - Pointer to the CM resource List
Return Value:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_IRQ_DESCRIPTOR buffer;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_IRQ_DESCRIPTOR) Buffer;
ASSERT( (buffer->Tag & SMALL_TAG_SIZE_MASK) >= 2);
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// We can use no interrupts
//
buffer->IrqMask = 0;
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypeInterrupt) {
//
// No
//
continue;
}
//
// Okay, we have a possible match...
//
if (desc->u.Interrupt.Level >= sizeof(USHORT) * 8) {
//
// Interrupts > 15 are Extended Irqs
//
continue;
}
//
// Here we *have* a match...
//
buffer->IrqMask = ( 1 << desc->u.Interrupt.Level );
if ( (buffer->Tag & SMALL_TAG_SIZE_MASK) == 3) {
//
// Wipe out the previous flags
//
buffer->Information = 0;
if ( (desc->Flags & CM_RESOURCE_INTERRUPT_LATCHED) ) {
buffer->Information |= PNP_IRQ_LATCHED;
} else {
buffer->Information |= PNP_IRQ_LEVEL;
}
if (desc->ShareDisposition == CmResourceShareShared) {
buffer->Information |= PNP_IRQ_SHARED;
}
}
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
}
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
PnpiCmResourceToBiosMemory(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine stores all of the Memory elements in the resource list into the Bios resource
list
Arguments:
Buffer - Pointer to the Bios resource List
List - Pointer to the CM resource List
Return:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_MEMORY_DESCRIPTOR buffer;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_MEMORY_DESCRIPTOR) Buffer;
ASSERT( buffer->Length == 9);
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// We can use no memory
//
buffer->Information = 0;
buffer->MinimumAddress = 0;
buffer->MaximumAddress = 0;
buffer->Alignment = 0;
buffer->MemorySize = 0;
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypeMemory) {
//
// No
//
continue;
}
//
// Is this a 24 bit memory descriptor?
//
if ( !(desc->Flags & CM_RESOURCE_MEMORY_24)) {
//
// No
//
continue;
}
//
// Here we *have* a match...
//
buffer->MinimumAddress = buffer->MaximumAddress =
(USHORT) (desc->u.Memory.Start.LowPart >> 8);
buffer->MemorySize = (USHORT) (desc->u.Memory.Length >> 8);
if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
buffer->Information |= PNP_MEMORY_READ_ONLY;
} else {
buffer->Information |= PNP_MEMORY_READ_WRITE;
}
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
}
//
// Done
//
return STATUS_SUCCESS;
}
NTSTATUS
PnpiCmResourceToBiosMemory32(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine stores all of the Memory elements in the resource list into the Bios resource
list
Arguments:
Buffer - Pointer to the Bios resource List
List - Pointer to the CM resource List
Return:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_MEMORY32_DESCRIPTOR buffer;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_MEMORY32_DESCRIPTOR) Buffer;
ASSERT( buffer->Length == 17);
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// We can use no memory
//
buffer->Information = 0;
buffer->MinimumAddress = 0;
buffer->MaximumAddress = 0;
buffer->Alignment = 0;
buffer->MemorySize = 0;
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypeMemory) {
//
// No
//
continue;
}
//
// Here we *have* a match...
//
buffer->MemorySize = desc->u.Memory.Length;
buffer->MinimumAddress = buffer->MaximumAddress = desc->u.Memory.Start.LowPart;
if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
buffer->Information |= PNP_MEMORY_READ_ONLY;
} else {
buffer->Information |= PNP_MEMORY_READ_WRITE;
}
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
}
//
// Done with matches
//
return STATUS_SUCCESS;
}
NTSTATUS
PnpiCmResourceToBiosMemory32Fixed(
IN PUCHAR Buffer,
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine stores all of the Memory elements in the resource list into the Bios resource
list
Arguments:
Buffer - Pointer to the Bios resource List
List - Pointer to the CM resource List
Return:
NTSTATUS
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PPNP_FIXED_MEMORY32_DESCRIPTOR buffer;
ULONG i;
PAGED_CODE();
//
// Setup the initial buffer
//
buffer = (PPNP_FIXED_MEMORY32_DESCRIPTOR) Buffer;
ASSERT( buffer->Length == 9);
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// We can use no memory
//
buffer->Information = 0;
buffer->BaseAddress = 0;
buffer->MemorySize = 0;
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypeMemory) {
//
// No
//
continue;
}
//
// Here we *have* a match...
//
buffer->BaseAddress = desc->u.Memory.Start.LowPart;
buffer->MemorySize = desc->u.Memory.Length >> 8;
if (desc->Flags & CM_RESOURCE_MEMORY_READ_ONLY) {
buffer->Information |= PNP_MEMORY_READ_ONLY;
} else {
buffer->Information |= PNP_MEMORY_READ_WRITE;
}
//
// Done with descriptor and match
//
desc->Type = CmResourceTypeNull;
break;
}
//
// Done
//
return STATUS_SUCCESS;
}
BOOLEAN
PnpiCmResourceValidEmptyList(
IN PCM_RESOURCE_LIST List
)
/*++
Routine Description:
This routine takes a CM_RESOURCE_LIST and makes sure that no unallocated elements
remain...
Arguments:
List - List to check
Return Value:
TRUE - Empty
FALSE - Nonempty
--*/
{
PCM_FULL_RESOURCE_DESCRIPTOR aList;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
ULONG i;
PAGED_CODE();
//
// We can only have one list...
//
aList = &(List->List[0]);
ASSERT( List->Count == 1);
ASSERT( aList->PartialResourceList.Count );
//
// Loop for each of the partial resource descriptors
//
for (i = 0; i < aList->PartialResourceList.Count; i++) {
//
// Current descriptor
//
desc = &(aList->PartialResourceList.PartialDescriptors[i]);
//
// Is this an interesting descriptor?
//
if (desc->Type != CmResourceTypeNull) {
//
// No
//
continue;
}
//
// This element wasn't consumed...<sigh>
//
break;
}
//
// Done
//
return ( i == aList->PartialResourceList.Count ? TRUE : FALSE );
}
NTSTATUS
PnpCmResourcesToBiosResources(
IN PCM_RESOURCE_LIST List,
IN PUCHAR Data
)
/*++
Routine Description:
This routine takes a CM_RESOURCE_LIST and a _CRS buffer. The routine sets the
resources in the _CRS buffer to equal to those reported in the CM_RESOURCE_LIST.
That is: the buffer is used as a template for the new resources that are in
the system.
Arguments:
List - Pointer to the CM_RESOURCE_LIST that we wish to assign
Data - Where we wish to store the data, and the template for it
Return Value:
NTSTATUS
--*/
{
NTSTATUS status = STATUS_SUCCESS;
PCM_PARTIAL_RESOURCE_DESCRIPTOR desc;
PUCHAR buffer;
UCHAR tagName;
USHORT increment;
PAGED_CODE();
ASSERT( Data != NULL );
//
// Setup initial variables.
//
buffer = Data;
tagName = *buffer;
//
// The algorithm we use is that we examine each tag in the buffer, and try to
// match it with an entry in the resource list. So we take the convertion routine
// for the previous problem and turn it upside down.
//
while (1) {
//
// Determine the size of the PNP resource descriptor
//
if ( !(tagName & LARGE_RESOURCE_TAG) ) {
//
// Small Tag
//
increment = (USHORT) (tagName & SMALL_TAG_SIZE_MASK) + 1;
tagName &= SMALL_TAG_MASK;
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"PnpCmResourcesToBiosResources: small tag = %#02lx increment = %#02lx\n",
tagName, increment
) );
} else {
//
// Large Tag
//
increment = ( *(USHORT UNALIGNED *)(buffer+1) ) + 3;
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"PnpCmResourcesToBiosResources: large tag = %#02lx increment = %#02lx\n",
tagName, increment
) );
}
//
// We are done if the current tag is the end tag
//
if (tagName == TAG_END) {
ACPIPrint( (
ACPI_PRINT_RESOURCES_2,
"PnpCmResourcesToBiosResources: TAG_END\n"
) );
break;
}
switch(tagName) {
case TAG_IRQ:
status = PnpiCmResourceToBiosIrq( buffer, List );
break;
case TAG_EXTENDED_IRQ:
status = PnpiCmResourceToBiosExtendedIrq( buffer, List );
break;
case TAG_DMA:
status = PnpiCmResourceToBiosDma( buffer, List );
break;
case TAG_START_DEPEND:
ASSERT( tagName != TAG_START_DEPEND );
break;
case TAG_END_DEPEND:
ASSERT( tagName != TAG_END_DEPEND );
break;
case TAG_IO:
status = PnpiCmResourceToBiosIoPort( buffer, List );
break;
case TAG_IO_FIXED:
status = PnpiCmResourceToBiosIoFixedPort( buffer, List );
break;
case TAG_MEMORY:
status = PnpiCmResourceToBiosMemory( buffer, List );
break;
case TAG_MEMORY32:
status = PnpiCmResourceToBiosMemory32( buffer, List );
break;
case TAG_MEMORY32_FIXED:
status = PnpiCmResourceToBiosMemory32Fixed( buffer, List );
break;
case TAG_WORD_ADDRESS:
status = PnpiCmResourceToBiosAddress( buffer, List );
break;
case TAG_DOUBLE_ADDRESS:
status = PnpiCmResourceToBiosAddressDouble( buffer, List );
break;
case TAG_VENDOR:
//
// Ignore this tag
//
break;
default: {
//
// Unknown tag. Skip it
//
ACPIPrint( (
ACPI_PRINT_WARNING,
"PnpBiosResourceToNtResources: TAG_UNKNOWN [tagName = %#02lx]\n",
tagName
) );
break;
}
} // switch
//
// Did we fail?
//
if (!NT_SUCCESS(status)) {
break;
}
//
// Move to the next descriptor
//
buffer += increment;
tagName = *buffer;
}
if (!( NT_SUCCESS(status) )) {
return status;
}
//
// Check to see if we have consumed all of the appropriate resources...
//
if (PnpiCmResourceValidEmptyList( List ) ) {
//
// We failed to empty the list... <sigh>
//
return STATUS_UNSUCCESSFUL;
}
return STATUS_SUCCESS;
}