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
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;
|
|
}
|