1572 lines
35 KiB
C
1572 lines
35 KiB
C
/*++
|
||
|
||
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;
|
||
}
|