mirror of https://github.com/lianthony/NT4.0
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.
1562 lines
45 KiB
1562 lines
45 KiB
/*++
|
|
|
|
Copyright (c) 1991 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
xlate.c
|
|
|
|
Abstract:
|
|
|
|
This file contains routines to translate resources between PnP ISA/BIOS
|
|
format and Windows NT formats.
|
|
|
|
Author:
|
|
|
|
Shie-Lin Tzong (shielint) 12-Apr-1995
|
|
|
|
Environment:
|
|
|
|
Kernel mode only.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
|
|
#include "pbapi.h"
|
|
|
|
VOID
|
|
PbIoDescriptorToCmDescriptor (
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
|
|
);
|
|
|
|
PPB_DEPENDENT_RESOURCES
|
|
PbAddDependentResourcesToList (
|
|
IN OUT PUCHAR *ResourceDescriptor,
|
|
IN ULONG ListNo,
|
|
IN PPB_ALTERNATIVE_INFORMATION AlternativeList
|
|
);
|
|
|
|
NTSTATUS
|
|
PbBiosIrqToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
PbBiosDmaToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
PbBiosPortFixedToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
PbBiosPortToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
PbBiosMemoryToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
PbCmIrqToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PUCHAR *BiosDescriptor,
|
|
OUT PULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
PbCmDmaToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PUCHAR *BiosDescriptor,
|
|
OUT PULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
PbCmPortToBiosDescriptor (
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PUCHAR *BiosDescriptor,
|
|
OUT PULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
PbCmMemoryToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PUCHAR *BiosDescriptor,
|
|
OUT PULONG Length
|
|
);
|
|
#ifdef ALLOC_PRAGMA
|
|
|
|
#pragma alloc_text(PAGE,PbBiosResourcesToNtResources)
|
|
#pragma alloc_text(PAGE,PbIoDescriptorToCmDescriptor)
|
|
#pragma alloc_text(PAGE,PbAddDependentResourcesToList)
|
|
#pragma alloc_text(PAGE,PbBiosIrqToIoDescriptor)
|
|
#pragma alloc_text(PAGE,PbBiosDmaToIoDescriptor)
|
|
#pragma alloc_text(PAGE,PbBiosPortFixedToIoDescriptor)
|
|
#pragma alloc_text(PAGE,PbBiosPortToIoDescriptor)
|
|
#pragma alloc_text(PAGE,PbBiosMemoryToIoDescriptor)
|
|
#pragma alloc_text(PAGE,PbCmIrqToBiosDescriptor)
|
|
#pragma alloc_text(PAGE,PbCmDmaToBiosDescriptor)
|
|
#pragma alloc_text(PAGE,PbCmPortToBiosDescriptor)
|
|
#pragma alloc_text(PAGE,PbCmMemoryToBiosDescriptor)
|
|
#endif
|
|
|
|
NTSTATUS
|
|
PbBiosResourcesToNtResources (
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
IN OUT PUCHAR *BiosData,
|
|
IN UCHAR Format,
|
|
OUT PUCHAR *ReturnedList,
|
|
OUT PULONG ReturnedLength
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine parses the Bios resource list and generates
|
|
a NT resource list. The returned Nt resource list could be either IO
|
|
format or CM format. It is caller's responsibility to release the
|
|
returned data buffer.
|
|
|
|
Arguments:
|
|
|
|
SlotNumber - specifies the slot number of the BIOS resource.
|
|
|
|
BiosData - Supplies a pointer to a variable which specifies the bios resource
|
|
data buffer and which to receive the pointer to next bios resource data.
|
|
|
|
Format - PB_CM_FORMAT (0) if convert bios resources to Cm format;
|
|
PB_IO_FORMAT (1) if convert bios resources to Io format.
|
|
|
|
ReturnedList - supplies a variable to receive the desired resource list.
|
|
|
|
ReturnedLength - Supplies a variable to receive the length of the resource list.
|
|
|
|
Return Value:
|
|
|
|
NTSTATUS code
|
|
|
|
--*/
|
|
{
|
|
PUCHAR buffer;
|
|
USHORT mask16, increment;
|
|
UCHAR tagName, mask8;
|
|
NTSTATUS status;
|
|
PPB_ALTERNATIVE_INFORMATION alternativeList = NULL;
|
|
ULONG commonResCount = 0, dependDescCount = 0, i, j;
|
|
ULONG alternativeListCount = 0, dependFunctionCount = 0;
|
|
PIO_RESOURCE_DESCRIPTOR commonResources = NULL, commonIoDesc, dependIoDesc, ioDesc;
|
|
PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
|
|
BOOLEAN dependent = FALSE;
|
|
PCM_RESOURCE_LIST cmResourceList;
|
|
ULONG listSize, noResLists;
|
|
PUCHAR resourceList = NULL;
|
|
|
|
//
|
|
// First, scan the bios data to determine the memory requirement and
|
|
// the information to build internal data structures.
|
|
//
|
|
|
|
*ReturnedLength = 0;
|
|
alternativeListCount = 0;
|
|
buffer = *BiosData;
|
|
tagName = *buffer;
|
|
while (tagName != TAG_COMPLETE_END) {
|
|
|
|
//
|
|
// Determine the size of the BIOS resource descriptor
|
|
//
|
|
|
|
if (!(tagName & LARGE_RESOURCE_TAG)) {
|
|
increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
|
|
increment += 1; // length of small tag
|
|
tagName &= SMALL_TAG_MASK;
|
|
} else {
|
|
increment = *(PUSHORT)(buffer+1);
|
|
increment += 3; // length of large tag
|
|
}
|
|
|
|
//
|
|
// Based on the type of the BIOS resource, determine the count of
|
|
// the IO descriptors.
|
|
//
|
|
|
|
switch (tagName) {
|
|
case TAG_IRQ:
|
|
mask16 = ((PPNP_IRQ_DESCRIPTOR)buffer)->IrqMask;
|
|
i = 0;
|
|
while (mask16) {
|
|
if (mask16 & 1) {
|
|
i++;
|
|
}
|
|
mask16 >>= 1;
|
|
}
|
|
if (!dependent) {
|
|
commonResCount += i;
|
|
} else {
|
|
dependDescCount += i;
|
|
}
|
|
break;
|
|
case TAG_DMA:
|
|
mask8 = ((PPNP_DMA_DESCRIPTOR)buffer)->ChannelMask;
|
|
i = 0;
|
|
while (mask8) {
|
|
if (mask8 & 1) {
|
|
i++;
|
|
}
|
|
mask8 >>= 1;
|
|
}
|
|
if (!dependent) {
|
|
commonResCount += i;
|
|
} else {
|
|
dependDescCount += i;
|
|
}
|
|
break;
|
|
case TAG_START_DEPEND:
|
|
dependent = TRUE;
|
|
dependFunctionCount++;
|
|
break;
|
|
case TAG_END_DEPEND:
|
|
dependent = FALSE;
|
|
alternativeListCount++;
|
|
break;
|
|
case TAG_IO_FIXED:
|
|
case TAG_IO:
|
|
case TAG_MEMORY:
|
|
case TAG_MEMORY32:
|
|
case TAG_MEMORY32_FIXED:
|
|
if (!dependent) {
|
|
commonResCount++;
|
|
} else {
|
|
dependDescCount++;
|
|
}
|
|
break;
|
|
default:
|
|
|
|
//
|
|
// Unknown tag. Skip it.
|
|
//
|
|
|
|
DebugPrint((DEBUG_BREAK, "BiosToNtResources: unknown tag.\n"));
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Move to next bios resource descriptor.
|
|
//
|
|
|
|
buffer += increment;
|
|
tagName = *buffer;
|
|
}
|
|
|
|
//
|
|
// if empty bios resources, simply return.
|
|
//
|
|
|
|
if (commonResCount == 0 && dependFunctionCount == 0) {
|
|
*ReturnedList = NULL;
|
|
*ReturnedLength = 0;
|
|
*BiosData = buffer + 2;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for our internal data structures
|
|
//
|
|
|
|
if (dependFunctionCount) {
|
|
dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
|
|
dependDescCount * sizeof(IO_RESOURCE_DESCRIPTOR),
|
|
'bPnP'
|
|
);
|
|
if (!dependResources) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
dependResList = dependResources; // remember it so we can free it.
|
|
}
|
|
|
|
if (alternativeListCount) {
|
|
ASSERT(dependFunctionCount != 0);
|
|
alternativeList = (PPB_ALTERNATIVE_INFORMATION)ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
sizeof(PB_ALTERNATIVE_INFORMATION) * (alternativeListCount + 1),
|
|
'bPnP'
|
|
);
|
|
if (!alternativeList) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto exit0;
|
|
}
|
|
RtlZeroMemory(alternativeList,
|
|
sizeof(PB_ALTERNATIVE_INFORMATION) * alternativeListCount
|
|
);
|
|
alternativeList[0].Resources = dependResources;
|
|
}
|
|
if (commonResCount) {
|
|
commonResources = (PIO_RESOURCE_DESCRIPTOR)ExAllocatePoolWithTag (
|
|
PagedPool,
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount,
|
|
'bPnP'
|
|
);
|
|
if (!commonResources) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto exit1;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Now start over again to process the bios data and initialize our internal
|
|
// resource representation.
|
|
//
|
|
|
|
commonIoDesc = commonResources;
|
|
dependDescCount = 0;
|
|
alternativeListCount = 0;
|
|
buffer = *BiosData;
|
|
tagName = *buffer;
|
|
dependent = FALSE;
|
|
while (tagName != TAG_COMPLETE_END) {
|
|
if (!(tagName & LARGE_RESOURCE_TAG)) {
|
|
tagName &= SMALL_TAG_MASK;
|
|
}
|
|
switch (tagName) {
|
|
case TAG_IRQ:
|
|
if (dependent) {
|
|
ioDesc = dependIoDesc;
|
|
} else {
|
|
ioDesc = commonIoDesc;
|
|
}
|
|
status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
|
|
if (NT_SUCCESS(status)) {
|
|
if (dependent) {
|
|
dependIoDesc++;
|
|
dependDescCount++;
|
|
} else {
|
|
commonIoDesc++;
|
|
}
|
|
}
|
|
break;
|
|
case TAG_DMA:
|
|
if (dependent) {
|
|
ioDesc = dependIoDesc;
|
|
} else {
|
|
ioDesc = commonIoDesc;
|
|
}
|
|
status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
|
|
if (NT_SUCCESS(status)) {
|
|
if (dependent) {
|
|
dependIoDesc++;
|
|
dependDescCount++;
|
|
} else {
|
|
commonIoDesc++;
|
|
}
|
|
}
|
|
break;
|
|
case TAG_START_DEPEND:
|
|
dependent = TRUE;
|
|
alternativeList[alternativeListCount].NoDependentFunctions++;
|
|
if (dependDescCount != 0) {
|
|
|
|
//
|
|
// End of current dependent function
|
|
//
|
|
|
|
dependResources->Count = dependDescCount;
|
|
dependResources->Flags = 0;
|
|
dependResources->Next = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
|
|
dependResources = dependResources->Next;
|
|
alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
|
|
}
|
|
if (*buffer & SMALL_TAG_SIZE_MASK) {
|
|
dependResources->Priority = *(buffer + 1);
|
|
}
|
|
dependDescCount = 0;
|
|
dependIoDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
|
|
buffer += 1 + (*buffer & SMALL_TAG_SIZE_MASK);
|
|
break;
|
|
case TAG_END_DEPEND:
|
|
alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
|
|
dependResources->Count = dependDescCount;
|
|
dependResources->Flags = DEPENDENT_FLAGS_END;
|
|
dependResources->Next = alternativeList[alternativeListCount].Resources;
|
|
dependent = FALSE;
|
|
dependDescCount = 0;
|
|
alternativeListCount++;
|
|
alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)dependIoDesc;
|
|
dependResources = alternativeList[alternativeListCount].Resources;
|
|
buffer++;
|
|
break;
|
|
case TAG_IO:
|
|
if (dependent) {
|
|
ioDesc = dependIoDesc;
|
|
} else {
|
|
ioDesc = commonIoDesc;
|
|
}
|
|
status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
|
|
if (NT_SUCCESS(status)) {
|
|
if (dependent) {
|
|
dependIoDesc++;
|
|
dependDescCount++;
|
|
} else {
|
|
commonIoDesc++;
|
|
}
|
|
}
|
|
break;
|
|
case TAG_IO_FIXED:
|
|
if (dependent) {
|
|
ioDesc = dependIoDesc;
|
|
} else {
|
|
ioDesc = commonIoDesc;
|
|
}
|
|
status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc);
|
|
if (NT_SUCCESS(status)) {
|
|
if (dependent) {
|
|
dependIoDesc++;
|
|
dependDescCount++;
|
|
} else {
|
|
commonIoDesc++;
|
|
}
|
|
}
|
|
break;
|
|
case TAG_MEMORY:
|
|
case TAG_MEMORY32:
|
|
case TAG_MEMORY32_FIXED:
|
|
if (dependent) {
|
|
ioDesc = dependIoDesc;
|
|
dependDescCount;
|
|
} else {
|
|
ioDesc = commonIoDesc;
|
|
}
|
|
status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
|
|
if (NT_SUCCESS(status)) {
|
|
if (dependent) {
|
|
dependIoDesc++;
|
|
dependDescCount++;
|
|
} else {
|
|
commonIoDesc++;
|
|
}
|
|
}
|
|
break;
|
|
default:
|
|
|
|
//
|
|
// Don't-care tag simpley advance the buffer pointer to next tag.
|
|
//
|
|
|
|
if (*buffer & LARGE_RESOURCE_TAG) {
|
|
increment = *(buffer+1);
|
|
increment += 3; // length of large tag
|
|
} else {
|
|
increment = (UCHAR)(*buffer) & SMALL_TAG_SIZE_MASK;
|
|
increment += 1; // length of small tag
|
|
}
|
|
buffer += increment;
|
|
}
|
|
tagName = *buffer;
|
|
}
|
|
|
|
if (alternativeListCount != 0) {
|
|
alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
|
|
}
|
|
*BiosData = buffer + 2; // Skip END_TAG
|
|
|
|
//
|
|
// prepare Cm/IoResourceList
|
|
//
|
|
|
|
if (Format == PB_CM_FORMAT) {
|
|
listSize = sizeof(CM_RESOURCE_LIST) + sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR) *
|
|
(commonResCount - 1);
|
|
} else {
|
|
ULONG totalDescCount, descCount;
|
|
|
|
noResLists = 1;
|
|
for (i = 0; i < alternativeListCount; i++) {
|
|
noResLists *= alternativeList[i].NoDependentFunctions;
|
|
}
|
|
totalDescCount = 0;
|
|
for (i = 0; i < alternativeListCount; i++) {
|
|
descCount = 1;
|
|
for (j = 0; j < alternativeListCount; j++) {
|
|
if (j == i) {
|
|
descCount *= alternativeList[j].TotalResourceCount;
|
|
} else {
|
|
descCount *= alternativeList[j].NoDependentFunctions;
|
|
}
|
|
}
|
|
totalDescCount += descCount;
|
|
}
|
|
listSize = sizeof(IO_RESOURCE_REQUIREMENTS_LIST) +
|
|
sizeof(IO_RESOURCE_LIST) * (noResLists - 1) +
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * totalDescCount -
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * noResLists +
|
|
sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount * noResLists;
|
|
}
|
|
resourceList = ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
|
|
if (!resourceList) {
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto exit2;
|
|
}
|
|
if (Format == PB_CM_FORMAT) {
|
|
PCM_PARTIAL_RESOURCE_LIST partialResList;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR partialDesc;
|
|
|
|
cmResourceList = (PCM_RESOURCE_LIST)resourceList;
|
|
cmResourceList->Count = 1;
|
|
cmResourceList->List[0].InterfaceType = Internal;
|
|
cmResourceList->List[0].BusNumber = BusNumber;
|
|
partialResList = (PCM_PARTIAL_RESOURCE_LIST)&cmResourceList->List[0].PartialResourceList;
|
|
partialResList->Version = 0;
|
|
partialResList->Revision = 0;
|
|
partialResList->Count = commonResCount;
|
|
commonIoDesc = commonResources;
|
|
partialDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR)&partialResList->PartialDescriptors[0];
|
|
for (i = 0; i < commonResCount; i++) {
|
|
PbIoDescriptorToCmDescriptor(commonIoDesc, partialDesc);
|
|
partialDesc++;
|
|
commonIoDesc++;
|
|
}
|
|
} else {
|
|
PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
|
|
PIO_RESOURCE_LIST ioResList;
|
|
|
|
ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)resourceList;
|
|
ioResReqList->ListSize = listSize;
|
|
ioResReqList->InterfaceType = Internal;
|
|
ioResReqList->BusNumber = BusNumber;
|
|
ioResReqList->SlotNumber = SlotNumber;
|
|
ioResReqList->Reserved[0] = 0;
|
|
ioResReqList->Reserved[1] = 0;
|
|
ioResReqList->Reserved[2] = 0;
|
|
ioResReqList->AlternativeLists = noResLists;
|
|
ioResList = &ioResReqList->List[0];
|
|
|
|
//
|
|
// Build resource lists
|
|
//
|
|
|
|
for (i = 0; i < noResLists; i++) {
|
|
ULONG size;
|
|
|
|
ioResList->Version = 1;
|
|
ioResList->Revision = 1;
|
|
buffer = (PUCHAR)&ioResList->Descriptors[0];
|
|
|
|
//
|
|
// Copy common resources to the list
|
|
//
|
|
|
|
if (commonResources) {
|
|
size = sizeof(IO_RESOURCE_DESCRIPTOR) * commonResCount;
|
|
RtlMoveMemory(buffer, commonResources, size);
|
|
buffer += size;
|
|
}
|
|
|
|
//
|
|
// Copy dependent functions if any.
|
|
//
|
|
|
|
if (alternativeList) {
|
|
PbAddDependentResourcesToList(&buffer, 0, alternativeList);
|
|
}
|
|
|
|
//
|
|
// Update io resource list ptr
|
|
//
|
|
|
|
ioResList->Count = ((ULONG)buffer - (ULONG)&ioResList->Descriptors[0]) /
|
|
sizeof(IO_RESOURCE_DESCRIPTOR);
|
|
ioResList = (PIO_RESOURCE_LIST)buffer;
|
|
}
|
|
}
|
|
*ReturnedLength = listSize;
|
|
status = STATUS_SUCCESS;
|
|
*ReturnedList = resourceList;
|
|
exit2:
|
|
if (commonResources) {
|
|
ExFreePool(commonResources);
|
|
}
|
|
exit1:
|
|
if (alternativeList) {
|
|
ExFreePool(alternativeList);
|
|
}
|
|
exit0:
|
|
if (dependResList) {
|
|
ExFreePool(dependResList);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
PPB_DEPENDENT_RESOURCES
|
|
PbAddDependentResourcesToList (
|
|
IN OUT PUCHAR *ResourceDescriptor,
|
|
IN ULONG ListNo,
|
|
IN PPB_ALTERNATIVE_INFORMATION AlternativeList
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine adds dependent functions to caller specified list.
|
|
|
|
Arguments:
|
|
|
|
ResourceDescriptor - supplies a pointer to the descriptor buffer.
|
|
|
|
ListNo - supplies an index to the AlternativeList.
|
|
|
|
AlternativeList - supplies a pointer to the alternativelist array.
|
|
|
|
Return Value:
|
|
|
|
return NTSTATUS code to indicate the result of the operation.
|
|
|
|
--*/
|
|
{
|
|
PPB_DEPENDENT_RESOURCES dependentResources, ptr;
|
|
ULONG size;
|
|
|
|
//
|
|
// Copy dependent resources to caller supplied list buffer and
|
|
// update the list buffer pointer.
|
|
//
|
|
|
|
dependentResources = AlternativeList[ListNo].Resources;
|
|
size = sizeof(IO_RESOURCE_DESCRIPTOR) * dependentResources->Count;
|
|
RtlMoveMemory(*ResourceDescriptor, dependentResources + 1, size);
|
|
*ResourceDescriptor = *ResourceDescriptor + size;
|
|
|
|
//
|
|
// Add dependent resource of next list to caller's buffer
|
|
//
|
|
|
|
if (AlternativeList[ListNo + 1].Resources) {
|
|
ptr = PbAddDependentResourcesToList(ResourceDescriptor, ListNo + 1, AlternativeList);
|
|
} else {
|
|
ptr = NULL;
|
|
}
|
|
if (ptr == NULL) {
|
|
AlternativeList[ListNo].Resources = dependentResources->Next;
|
|
if (!(dependentResources->Flags & DEPENDENT_FLAGS_END)) {
|
|
ptr = dependentResources->Next;
|
|
}
|
|
}
|
|
return ptr;
|
|
}
|
|
|
|
VOID
|
|
PbIoDescriptorToCmDescriptor (
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates IO_RESOURCE_DESCRIPTOR to CM_PARTIAL_RESOURCE_DESCRIPTOR.
|
|
|
|
Arguments:
|
|
|
|
IoDescriptor - Supplies a pointer to the IO_RESOURCE_DESCRIPTOR to be converted.
|
|
|
|
CmDescriptor - Supplies a pointer to the receiving CM_PARTIAL_RESOURCE_DESCRIPTOR.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
CmDescriptor->Type = IoDescriptor->Type;
|
|
CmDescriptor->ShareDisposition = IoDescriptor->ShareDisposition;
|
|
CmDescriptor->Flags = IoDescriptor->Flags;
|
|
switch (CmDescriptor->Type) {
|
|
case CmResourceTypePort:
|
|
CmDescriptor->u.Port.Length = IoDescriptor->u.Port.Length;
|
|
CmDescriptor->u.Port.Start = IoDescriptor->u.Port.MinimumAddress;
|
|
break;
|
|
case CmResourceTypeInterrupt:
|
|
CmDescriptor->u.Interrupt.Level =
|
|
CmDescriptor->u.Interrupt.Vector = IoDescriptor->u.Interrupt.MinimumVector;
|
|
CmDescriptor->u.Interrupt.Affinity = (ULONG)-1;
|
|
break;
|
|
case CmResourceTypeMemory:
|
|
CmDescriptor->u.Memory.Length = IoDescriptor->u.Memory.Length;
|
|
CmDescriptor->u.Memory.Start = IoDescriptor->u.Memory.MinimumAddress;
|
|
break;
|
|
case CmResourceTypeDma:
|
|
CmDescriptor->u.Dma.Channel = IoDescriptor->u.Dma.MinimumChannel;
|
|
CmDescriptor->u.Dma.Port = 0;
|
|
CmDescriptor->u.Dma.Reserved1 = 0;
|
|
break;
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
PbBiosIrqToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates BIOS IRQ information to NT usable format.
|
|
This routine stops when an irq io resource is generated. if there are
|
|
more irq io resource descriptors available, the BiosData pointer will
|
|
not advance. So caller will pass us the same resource tag again.
|
|
|
|
Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
|
|
for each seperated channel required.
|
|
|
|
Arguments:
|
|
|
|
BiosData - Supplies a pointer to the bios resource data buffer.
|
|
|
|
IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
|
|
Converted resource will be stored here.
|
|
|
|
Return Value:
|
|
|
|
return NTSTATUS code to indicate the result of the operation.
|
|
|
|
--*/
|
|
{
|
|
static ULONG bitPosition = 0;
|
|
USHORT mask;
|
|
ULONG irq;
|
|
PPNP_IRQ_DESCRIPTOR buffer;
|
|
UCHAR size, option;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
buffer = (PPNP_IRQ_DESCRIPTOR)*BiosData;
|
|
|
|
//
|
|
// if this is not the first descriptor for the tag, set
|
|
// its option to alternative.
|
|
//
|
|
|
|
if (bitPosition == 0) {
|
|
option = 0;
|
|
} else {
|
|
option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
size = buffer->Tag & SMALL_TAG_SIZE_MASK;
|
|
mask = buffer->IrqMask;
|
|
mask >>= bitPosition;
|
|
irq = (ULONG) -1;
|
|
|
|
while (mask) {
|
|
if (mask & 1) {
|
|
irq = bitPosition;
|
|
break;
|
|
}
|
|
mask >>= 1;
|
|
bitPosition++;
|
|
}
|
|
|
|
//
|
|
// Fill in Io resource descriptor
|
|
//
|
|
|
|
if (irq != (ULONG)-1) {
|
|
IoDescriptor->Option = option;
|
|
IoDescriptor->Type = CmResourceTypeInterrupt;
|
|
IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LATCHED;
|
|
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
if (size == 3 && buffer->Information & 0x0C) {
|
|
IoDescriptor->Flags = CM_RESOURCE_INTERRUPT_LEVEL_SENSITIVE;
|
|
IoDescriptor->ShareDisposition = CmResourceShareShared;
|
|
}
|
|
IoDescriptor->Spare1 = 0;
|
|
IoDescriptor->Spare2 = 0;
|
|
IoDescriptor->u.Interrupt.MinimumVector = irq;
|
|
IoDescriptor->u.Interrupt.MaximumVector = irq;
|
|
} else {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// try to move bitPosition to next 1 bit.
|
|
//
|
|
|
|
while (mask) {
|
|
mask >>= 1;
|
|
bitPosition++;
|
|
if (mask & 1) {
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Done with current irq tag, advance pointer to next tag
|
|
//
|
|
|
|
bitPosition = 0;
|
|
*BiosData = (PUCHAR)buffer + size + 1;
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbBiosDmaToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates BIOS DMA information to NT usable format.
|
|
This routine stops when an dma io resource is generated. if there are
|
|
more dma io resource descriptors available, the BiosData pointer will
|
|
not advance. So caller will pass us the same resource tag again.
|
|
|
|
Note, BIOS DMA info alway uses SMALL TAG. A tag structure is repeated
|
|
for each seperated channel required.
|
|
|
|
Arguments:
|
|
|
|
BiosData - Supplies a pointer to the bios resource data buffer.
|
|
|
|
IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
|
|
Converted resource will be stored here.
|
|
|
|
Return Value:
|
|
|
|
return NTSTATUS code to indicate the result of the operation.
|
|
|
|
--*/
|
|
{
|
|
static ULONG bitPosition = 0;
|
|
ULONG dma;
|
|
PPNP_DMA_DESCRIPTOR buffer;
|
|
UCHAR mask, option;
|
|
NTSTATUS status = STATUS_SUCCESS;
|
|
|
|
buffer = (PPNP_DMA_DESCRIPTOR)*BiosData;
|
|
|
|
//
|
|
// if this is not the first descriptor for the tag, set
|
|
// its option to alternative.
|
|
//
|
|
|
|
if (bitPosition == 0) {
|
|
option = 0;
|
|
} else {
|
|
option = IO_RESOURCE_ALTERNATIVE;
|
|
}
|
|
mask = buffer->ChannelMask;
|
|
mask >>= bitPosition;
|
|
dma = (ULONG) -1;
|
|
|
|
while (mask) {
|
|
if (mask & 1) {
|
|
dma = bitPosition;
|
|
break;
|
|
}
|
|
mask >>= 1;
|
|
bitPosition++;
|
|
}
|
|
|
|
//
|
|
// Fill in Io resource descriptor
|
|
//
|
|
|
|
if (dma != (ULONG)-1) {
|
|
IoDescriptor->Option = option;
|
|
IoDescriptor->Type = CmResourceTypeDma;
|
|
IoDescriptor->Flags = 0;
|
|
IoDescriptor->ShareDisposition = CmResourceShareUndetermined;
|
|
IoDescriptor->Spare1 = 0;
|
|
IoDescriptor->Spare2 = 0;
|
|
IoDescriptor->u.Dma.MinimumChannel = dma;
|
|
IoDescriptor->u.Dma.MaximumChannel = dma;
|
|
} else {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
|
|
//
|
|
// try to move bitPosition to next 1 bit.
|
|
//
|
|
|
|
while (mask) {
|
|
mask >>= 1;
|
|
bitPosition++;
|
|
if (mask & 1) {
|
|
return status;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Done with current dma tag, advance pointer to next tag
|
|
//
|
|
|
|
bitPosition = 0;
|
|
buffer += 1;
|
|
*BiosData = (PUCHAR)buffer;
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbBiosPortFixedToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates BIOS FIXED IO information to NT usable format.
|
|
|
|
Arguments:
|
|
|
|
BiosData - Supplies a pointer to the bios resource data buffer.
|
|
|
|
IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
|
|
Converted resource will be stored here.
|
|
|
|
Return Value:
|
|
|
|
return NTSTATUS code to indicate the result of the operation.
|
|
|
|
--*/
|
|
{
|
|
PPNP_FIXED_PORT_DESCRIPTOR buffer;
|
|
|
|
buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
|
|
|
|
//
|
|
// Fill in Io resource descriptor
|
|
//
|
|
|
|
IoDescriptor->Option = 0;
|
|
IoDescriptor->Type = CmResourceTypePort;
|
|
IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
|
|
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
IoDescriptor->Spare1 = 0;
|
|
IoDescriptor->Spare2 = 0;
|
|
IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
|
|
IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)(buffer->MinimumAddress & 0x3ff);
|
|
IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
|
|
IoDescriptor->u.Port.MaximumAddress.LowPart = IoDescriptor->u.Port.MinimumAddress.LowPart +
|
|
IoDescriptor->u.Port.Length - 1;
|
|
IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
|
|
IoDescriptor->u.Port.Alignment = 1;
|
|
|
|
//
|
|
// Done with current fixed port tag, advance pointer to next tag
|
|
//
|
|
|
|
buffer += 1;
|
|
*BiosData = (PUCHAR)buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbBiosPortToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates BIOS IO information to NT usable format.
|
|
|
|
Arguments:
|
|
|
|
BiosData - Supplies a pointer to the bios resource data buffer.
|
|
|
|
IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
|
|
Converted resource will be stored here.
|
|
|
|
Return Value:
|
|
|
|
return NTSTATUS code to indicate the result of the operation.
|
|
|
|
--*/
|
|
{
|
|
PPNP_PORT_DESCRIPTOR buffer;
|
|
|
|
buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
|
|
|
|
//
|
|
// Fill in Io resource descriptor
|
|
//
|
|
|
|
IoDescriptor->Option = 0;
|
|
IoDescriptor->Type = CmResourceTypePort;
|
|
IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
|
|
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
IoDescriptor->Spare1 = 0;
|
|
IoDescriptor->Spare2 = 0;
|
|
IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
|
|
IoDescriptor->u.Port.MinimumAddress.LowPart = (ULONG)buffer->MinimumAddress;
|
|
IoDescriptor->u.Port.MinimumAddress.HighPart = 0;
|
|
IoDescriptor->u.Port.MaximumAddress.LowPart = (ULONG)buffer->MaximumAddress +
|
|
IoDescriptor->u.Port.Length - 1;
|
|
IoDescriptor->u.Port.MaximumAddress.HighPart = 0;
|
|
IoDescriptor->u.Port.Alignment = (ULONG)buffer->Alignment;
|
|
|
|
//
|
|
// Done with current fixed port tag, advance pointer to next tag
|
|
//
|
|
|
|
buffer += 1;
|
|
*BiosData = (PUCHAR)buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbBiosMemoryToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates BIOS MEMORY information to NT usable format.
|
|
|
|
Arguments:
|
|
|
|
BiosData - Supplies a pointer to the bios resource data buffer.
|
|
|
|
IoDescriptor - supplies a pointer to an IO_RESOURCE_DESCRIPTOR buffer.
|
|
Converted resource will be stored here.
|
|
|
|
Return Value:
|
|
|
|
return NTSTATUS code to indicate the result of the operation.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR buffer;
|
|
UCHAR tag;
|
|
PHYSICAL_ADDRESS minAddr, maxAddr;
|
|
ULONG alignment, length;
|
|
USHORT increment;
|
|
|
|
buffer = *BiosData;
|
|
tag = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Tag;
|
|
increment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Length + 3; // larg tag size = 3
|
|
|
|
minAddr.HighPart = 0;
|
|
maxAddr.HighPart = 0;
|
|
switch (tag) {
|
|
case TAG_MEMORY:
|
|
minAddr.LowPart = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MinimumAddress)) << 8;
|
|
if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)buffer)->Alignment) == 0) {
|
|
alignment = 0x10000;
|
|
}
|
|
length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MemorySize)) << 8;
|
|
maxAddr.LowPart = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)buffer)->MaximumAddress)) << 8) + length - 1;
|
|
break;
|
|
case TAG_MEMORY32:
|
|
length = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
|
|
minAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MinimumAddress;
|
|
maxAddr.LowPart = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->MaximumAddress + length - 1;
|
|
alignment = ((PPNP_MEMORY32_DESCRIPTOR)buffer)->Alignment;
|
|
break;
|
|
case TAG_MEMORY32_FIXED:
|
|
length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->MemorySize;
|
|
minAddr.LowPart = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)buffer)->BaseAddress;
|
|
maxAddr.LowPart = minAddr.LowPart + length - 1;
|
|
alignment = 1;
|
|
break;
|
|
}
|
|
//
|
|
// Fill in Io resource descriptor
|
|
//
|
|
|
|
IoDescriptor->Option = 0;
|
|
IoDescriptor->Type = CmResourceTypeMemory;
|
|
IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY;
|
|
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
IoDescriptor->Spare1 = 0;
|
|
IoDescriptor->Spare2 = 0;
|
|
IoDescriptor->u.Memory.MinimumAddress = minAddr;
|
|
IoDescriptor->u.Memory.MaximumAddress = maxAddr;
|
|
IoDescriptor->u.Memory.Alignment = alignment;
|
|
IoDescriptor->u.Memory.Length = length;
|
|
|
|
//
|
|
// Done with current tag, advance pointer to next tag
|
|
//
|
|
|
|
buffer += increment;
|
|
*BiosData = (PUCHAR)buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmResourcesToBiosResources (
|
|
IN PCM_RESOURCE_LIST CmResources,
|
|
IN PUCHAR BiosRequirements,
|
|
IN PUCHAR *BiosResources,
|
|
IN PULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine parses the Cm resource list and generates
|
|
a Pnp BIOS resource list. It is caller's responsibility to release the
|
|
returned data buffer.
|
|
|
|
Arguments:
|
|
|
|
CmResources - Supplies a pointer to a Cm resource list buffer.
|
|
|
|
BiosRequirements - supplies a pointer to the PnP BIOS possible resources.
|
|
|
|
BiosResources - Supplies a variable to receive the pointer to the
|
|
converted bios resource buffer.
|
|
|
|
Length - supplies a pointer to a variable to receive the length
|
|
of the Pnp Bios resources.
|
|
|
|
Return Value:
|
|
|
|
a pointer to a Pnp Bios resource list if succeeded. Else,
|
|
a NULL pointer will be returned.
|
|
|
|
--*/
|
|
{
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
|
|
ULONG i, count, length, totalSize = 0;
|
|
PUCHAR p, biosDesc;
|
|
NTSTATUS status;
|
|
|
|
count = CmResources->List[0].PartialResourceList.Count;
|
|
if (count == 0 || CmResources->Count != 1) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Allocate max amount of memory
|
|
//
|
|
|
|
p= ExAllocatePoolWithTag(PagedPool,
|
|
count * sizeof(PNP_MEMORY_DESCRIPTOR),
|
|
'bPnP');
|
|
if (!p) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
cmDesc = CmResources->List[0].PartialResourceList.PartialDescriptors;
|
|
for (i = 0; i < count; i++) {
|
|
switch (cmDesc->Type) {
|
|
case CmResourceTypePort:
|
|
status = PbCmPortToBiosDescriptor (
|
|
cmDesc,
|
|
&biosDesc,
|
|
&length
|
|
);
|
|
break;
|
|
case CmResourceTypeInterrupt:
|
|
status = PbCmIrqToBiosDescriptor(
|
|
BiosRequirements,
|
|
cmDesc,
|
|
&biosDesc,
|
|
&length
|
|
);
|
|
break;
|
|
case CmResourceTypeMemory:
|
|
status = PbCmMemoryToBiosDescriptor (
|
|
BiosRequirements,
|
|
cmDesc,
|
|
&biosDesc,
|
|
&length
|
|
);
|
|
break;
|
|
case CmResourceTypeDma:
|
|
status = PbCmDmaToBiosDescriptor (
|
|
BiosRequirements,
|
|
cmDesc,
|
|
&biosDesc,
|
|
&length
|
|
);
|
|
break;
|
|
case CmResourceTypeDeviceSpecific:
|
|
length = cmDesc->u.DeviceSpecificData.DataSize;
|
|
cmDesc++;
|
|
cmDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDesc + length);
|
|
continue;
|
|
}
|
|
if (NT_SUCCESS(status)) {
|
|
cmDesc++;
|
|
RtlMoveMemory(p, biosDesc, length);
|
|
ExFreePool(biosDesc);
|
|
p += length;
|
|
totalSize += length;
|
|
} else {
|
|
ExFreePool(p);
|
|
break;
|
|
}
|
|
}
|
|
if (NT_SUCCESS(status)) {
|
|
*p = TAG_COMPLETE_END;
|
|
p++;
|
|
*p = 0; // checksum ignored
|
|
totalSize += 2;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmIrqToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PUCHAR *BiosDescriptor,
|
|
OUT PULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates CM IRQ information to Pnp BIOS format.
|
|
Since there is not enough information in the CM int descriptor to
|
|
convert it to Pnp BIOS descriptor. We will search the Bios
|
|
possible resource lists for the corresponding resource information.
|
|
|
|
Arguments:
|
|
|
|
BiosRequirements - Supplies a pointer to the bios possible resource lists.
|
|
|
|
CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
|
|
|
|
Return Value:
|
|
|
|
return a pointer to the desired dma descriptor in the BiosRequirements. Null
|
|
if not found.
|
|
|
|
--*/
|
|
{
|
|
USHORT irqMask;
|
|
UCHAR tag;
|
|
PPNP_IRQ_DESCRIPTOR biosDesc;
|
|
PUCHAR returnDesc;
|
|
NTSTATUS status;
|
|
ULONG increment;
|
|
|
|
if (!BiosRequirements) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
status = STATUS_UNSUCCESSFUL;
|
|
if (!(CmDescriptor->u.Interrupt.Level & 0xfffffff0)) {
|
|
irqMask = 1 << CmDescriptor->u.Interrupt.Level;
|
|
tag = *BiosRequirements;
|
|
while (tag != TAG_COMPLETE_END) {
|
|
if ((tag & SMALL_TAG_MASK) == TAG_IRQ) {
|
|
biosDesc = (PPNP_IRQ_DESCRIPTOR)BiosRequirements;
|
|
if (biosDesc->IrqMask & irqMask) {
|
|
*Length = (biosDesc->Tag & SMALL_TAG_SIZE_MASK) + 1;
|
|
returnDesc = ExAllocatePoolWithTag(PagedPool,
|
|
*Length,
|
|
'bPnP' );
|
|
if (!returnDesc) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
} else {
|
|
RtlMoveMemory(returnDesc, BiosRequirements, *Length);
|
|
*BiosDescriptor = returnDesc;
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
|
|
break;
|
|
}
|
|
}
|
|
increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
|
|
BiosRequirements += increment;
|
|
tag = *BiosRequirements;
|
|
}
|
|
} else {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmDmaToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PUCHAR *BiosDescriptor,
|
|
OUT PULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates CM DMA information to Pnp BIOS format.
|
|
Since there is not enough information in the CM descriptor to
|
|
convert it to Pnp BIOS descriptor. We will search the Bios
|
|
possible resource lists for the corresponding resource information.
|
|
|
|
Arguments:
|
|
|
|
BiosRequirements - Supplies a pointer to the bios possible resource lists.
|
|
|
|
CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
|
|
|
|
Return Value:
|
|
|
|
return a pointer to the desired dma descriptor in the BiosRequirements. Null
|
|
if not found.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
UCHAR dmaMask, tag;
|
|
PPNP_DMA_DESCRIPTOR biosDesc;
|
|
PUCHAR returnDesc;
|
|
ULONG increment;
|
|
|
|
if (!BiosRequirements) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
status = STATUS_UNSUCCESSFUL;
|
|
if (!(CmDescriptor->u.Dma.Channel & 0xfffffff0)) {
|
|
dmaMask = 1 << CmDescriptor->u.Dma.Channel;
|
|
tag = *BiosRequirements;
|
|
while (tag != TAG_COMPLETE_END) {
|
|
if ((tag & SMALL_TAG_MASK) == TAG_DMA) {
|
|
biosDesc = (PPNP_DMA_DESCRIPTOR)BiosRequirements;
|
|
if (biosDesc->ChannelMask & dmaMask) {
|
|
*Length = (biosDesc->Tag & SMALL_TAG_SIZE_MASK) + 1;
|
|
returnDesc = ExAllocatePoolWithTag(PagedPool,
|
|
*Length,
|
|
'bPnP' );
|
|
if (!returnDesc) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
} else {
|
|
RtlMoveMemory(returnDesc, BiosRequirements, *Length);
|
|
*BiosDescriptor = returnDesc;
|
|
status = STATUS_SUCCESS;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
increment = (tag & SMALL_TAG_SIZE_MASK) + 1;
|
|
BiosRequirements += increment;
|
|
tag = *BiosRequirements;
|
|
}
|
|
} else {
|
|
status = STATUS_INVALID_PARAMETER;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmPortToBiosDescriptor (
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PUCHAR *BiosDescriptor,
|
|
OUT PULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates CM PORT information to Pnp BIOS format.
|
|
Since there is not enough information in the CM descriptor to
|
|
convert it to Pnp BIOS full function port descriptor. We will
|
|
convert it to Pnp Bios fixed PORT descriptor. It is caller's
|
|
responsibility to release the returned data buffer.
|
|
|
|
Arguments:
|
|
|
|
CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
|
|
|
|
BiosDescriptor - supplies a variable to receive the buffer which contains
|
|
the desired Bios Port descriptor.
|
|
|
|
Length - supplies a variable to receive the size the returned bios port
|
|
descriptor.
|
|
|
|
Return Value:
|
|
|
|
A NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status;
|
|
PPNP_PORT_DESCRIPTOR portDesc;
|
|
|
|
if (CmDescriptor->u.Port.Start.HighPart != 0 ||
|
|
CmDescriptor->u.Port.Start.LowPart & 0xffff0000 ||
|
|
CmDescriptor->u.Port.Length & 0xffffff00) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
portDesc = (PPNP_PORT_DESCRIPTOR) ExAllocatePoolWithTag(
|
|
PagedPool, sizeof(PNP_PORT_DESCRIPTOR), 'bPnP' );
|
|
if (!portDesc) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
//
|
|
// Set the return port descriptor
|
|
//
|
|
|
|
portDesc->Tag = TAG_IO | (sizeof(PNP_PORT_DESCRIPTOR) - 1);
|
|
portDesc->Information = 1; // 16 bit decoding
|
|
portDesc->Length = (UCHAR)CmDescriptor->u.Port.Length;
|
|
portDesc->Alignment = 0; // 1?
|
|
portDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
|
|
portDesc->MaximumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
|
|
*BiosDescriptor = (PUCHAR)portDesc;
|
|
*Length = sizeof(PNP_PORT_DESCRIPTOR);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmMemoryToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PUCHAR *BiosDescriptor,
|
|
OUT PULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine translates CM Memory information to Pnp BIOS format.
|
|
Since there is not enough information in the CM descriptor to
|
|
convert it to Pnp BIOS descriptor. We will search the Bios
|
|
possible resource lists for the corresponding resource information and
|
|
build a Pnp BIOS memory descriptor from there. It is caller's responsibility
|
|
to release the returned buffer.
|
|
|
|
Arguments:
|
|
|
|
BiosRequirements - Supplies a pointer to the bios possible resource lists.
|
|
|
|
CmDescriptor - supplies a pointer to an CM_PARTIAL_RESOURCE_DESCRIPTOR buffer.
|
|
|
|
BiosDescriptor - supplies a variable to receive the buffer which contains
|
|
the desired Bios Port descriptor.
|
|
|
|
Length - supplies a variable to receive the size the returned bios port
|
|
descriptor.
|
|
|
|
Return Value:
|
|
|
|
A NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
UCHAR tag, information;
|
|
PPNP_FIXED_MEMORY32_DESCRIPTOR memoryDesc;
|
|
ULONG address, size, length, minAddr, maxAddr, alignment;
|
|
USHORT increment;
|
|
|
|
//
|
|
// Search the possible resource list to get the information
|
|
// for the memory range described by CmDescriptor.
|
|
//
|
|
|
|
address = CmDescriptor->u.Memory.Start.LowPart;
|
|
size = CmDescriptor->u.Memory.Length;
|
|
|
|
tag = *BiosRequirements;
|
|
while (tag != TAG_COMPLETE_END) {
|
|
switch (tag) {
|
|
case TAG_MEMORY:
|
|
minAddr = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MinimumAddress)) << 8;
|
|
if ((alignment = ((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->Alignment) == 0) {
|
|
alignment = 0x10000;
|
|
}
|
|
length = ((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MemorySize)) << 8;
|
|
maxAddr = (((ULONG)(((PPNP_MEMORY_DESCRIPTOR)BiosRequirements)->MaximumAddress)) << 8)
|
|
+ length - 1;
|
|
break;
|
|
case TAG_MEMORY32:
|
|
length = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
|
|
minAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MinimumAddress;
|
|
maxAddr = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->MaximumAddress
|
|
+ length - 1;
|
|
alignment = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Alignment;
|
|
break;
|
|
case TAG_MEMORY32_FIXED:
|
|
length = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->MemorySize;
|
|
minAddr = ((PPNP_FIXED_MEMORY32_DESCRIPTOR)BiosRequirements)->BaseAddress;
|
|
maxAddr = minAddr + length - 1;
|
|
alignment = 1;
|
|
break;
|
|
}
|
|
|
|
if (minAddr <= address && maxAddr >= (address + size - 1)) {
|
|
information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Advance to next tag
|
|
//
|
|
|
|
if (tag & LARGE_RESOURCE_TAG) {
|
|
increment = *(PUSHORT)(BiosRequirements + 1);
|
|
increment += 3; // length of large tag
|
|
} else {
|
|
increment = tag & SMALL_TAG_SIZE_MASK;
|
|
increment += 1; // length of small tag
|
|
}
|
|
BiosRequirements += increment;
|
|
tag = *BiosRequirements;
|
|
}
|
|
if (tag == TAG_COMPLETE_END) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Set up Pnp BIOS memory descriptor
|
|
//
|
|
|
|
memoryDesc = (PPNP_FIXED_MEMORY32_DESCRIPTOR) ExAllocatePoolWithTag(
|
|
PagedPool, sizeof(PNP_FIXED_MEMORY32_DESCRIPTOR), 'bPnP' );
|
|
if (!memoryDesc) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
} else {
|
|
memoryDesc->Tag = TAG_MEMORY32_FIXED;
|
|
memoryDesc->Length = sizeof (PNP_FIXED_MEMORY32_DESCRIPTOR);
|
|
memoryDesc->Information = information;
|
|
memoryDesc->BaseAddress = address;
|
|
memoryDesc->MemorySize = size;
|
|
*BiosDescriptor = (PUCHAR)memoryDesc;
|
|
*Length = sizeof(PNP_FIXED_MEMORY32_DESCRIPTOR);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
}
|
|
|