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.
1899 lines
56 KiB
1899 lines
56 KiB
/*++
|
|
|
|
Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
Module Name:
|
|
|
|
convert.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:
|
|
|
|
Note:
|
|
|
|
This file is shared between the io subsystem and the ISAPNP bus driver.
|
|
|
|
It is not compiled directly but is included by:
|
|
base\ntos\io\pnpmgr\pnpcvrt.c
|
|
base\busdrv\isapnp\convert.c
|
|
|
|
***** If you change this file make sure you build in *BOTH* places *****
|
|
|
|
--*/
|
|
|
|
#include "pbios.h"
|
|
#include "pnpcvrt.h"
|
|
|
|
#if UMODETEST
|
|
#undef IsNEC_98
|
|
#define IsNEC_98 0
|
|
#endif
|
|
|
|
//
|
|
// internal structures for resource translation
|
|
//
|
|
|
|
typedef struct _PB_DEPENDENT_RESOURCES {
|
|
ULONG Count;
|
|
UCHAR Flags;
|
|
UCHAR Priority;
|
|
struct _PB_DEPENDENT_RESOURCES *Next;
|
|
} PB_DEPENDENT_RESOURCES, *PPB_DEPENDENT_RESOURCES;
|
|
|
|
#define DEPENDENT_FLAGS_END 1
|
|
|
|
typedef struct _PB_ATERNATIVE_INFORMATION {
|
|
PPB_DEPENDENT_RESOURCES Resources;
|
|
ULONG NoDependentFunctions;
|
|
ULONG TotalResourceCount;
|
|
} PB_ALTERNATIVE_INFORMATION, *PPB_ALTERNATIVE_INFORMATION;
|
|
|
|
//
|
|
// Internal function references
|
|
//
|
|
|
|
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,
|
|
IN BOOLEAN ForceFixedIoTo16bit
|
|
);
|
|
|
|
NTSTATUS
|
|
PbBiosPortToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
PbBiosMemoryToIoDescriptor (
|
|
IN OUT PUCHAR *BiosData,
|
|
IN PIO_RESOURCE_DESCRIPTOR IoDescriptor
|
|
);
|
|
|
|
NTSTATUS
|
|
PpCmResourcesToBiosResources (
|
|
IN PCM_RESOURCE_LIST CmResources,
|
|
IN PUCHAR BiosRequirements,
|
|
IN PUCHAR *BiosResources,
|
|
IN PULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
PbCmIrqToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PVOID ReturnDescriptor,
|
|
OUT PULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
PbCmDmaToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PVOID ReturnDescriptor,
|
|
OUT PULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
PbCmPortToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PVOID ReturnDescriptor,
|
|
OUT PULONG Length
|
|
);
|
|
|
|
NTSTATUS
|
|
PbCmMemoryToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PVOID ReturnDescriptor,
|
|
OUT PULONG Length
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
|
|
#pragma alloc_text(PAGE, PpBiosResourcesToNtResources)
|
|
#pragma alloc_text(PAGE, PpBiosResourcesSetToDisabled)
|
|
#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, PpCmResourcesToBiosResources)
|
|
#pragma alloc_text(PAGE, PbCmIrqToBiosDescriptor)
|
|
#pragma alloc_text(PAGE, PbCmDmaToBiosDescriptor)
|
|
#pragma alloc_text(PAGE, PbCmPortToBiosDescriptor)
|
|
#pragma alloc_text(PAGE, PbCmMemoryToBiosDescriptor)
|
|
#endif
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma data_seg("PAGEDATA")
|
|
#endif
|
|
|
|
NTSTATUS
|
|
PpBiosResourcesToNtResources (
|
|
IN ULONG BusNumber,
|
|
IN ULONG SlotNumber,
|
|
IN OUT PUCHAR *BiosData,
|
|
IN ULONG ConvertFlags,
|
|
OUT PIO_RESOURCE_REQUIREMENTS_LIST *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.
|
|
|
|
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 ioDesc;
|
|
PPB_DEPENDENT_RESOURCES dependResList = NULL, dependResources;
|
|
BOOLEAN dependent = FALSE;
|
|
BOOLEAN forceFixedIoTo16bit;
|
|
ULONG listSize, noResLists;
|
|
ULONG totalDescCount, descCount;
|
|
PIO_RESOURCE_REQUIREMENTS_LIST ioResReqList;
|
|
PIO_RESOURCE_LIST ioResList;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// 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;
|
|
|
|
forceFixedIoTo16bit =
|
|
(BOOLEAN)((ConvertFlags & PPCONVERTFLAG_FORCE_FIXED_IO_16BIT_DECODE) != 0);
|
|
|
|
for ( ; ; ) {
|
|
|
|
//
|
|
// 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 = *(USHORT UNALIGNED *)(buffer+1);
|
|
increment += 3; // length of large tag
|
|
}
|
|
|
|
if (tagName == TAG_END) {
|
|
buffer += increment;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// 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.
|
|
//
|
|
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Move to next bios resource descriptor.
|
|
//
|
|
|
|
buffer += increment;
|
|
tagName = *buffer;
|
|
if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dependent) {
|
|
//
|
|
// TAG_END_DEPEND was not found before we hit TAG_COMPLETE_END, so
|
|
// simulate it.
|
|
//
|
|
dependent = FALSE;
|
|
alternativeListCount++;
|
|
}
|
|
|
|
//
|
|
// if empty bios resources, simply return.
|
|
//
|
|
|
|
if (commonResCount == 0 && dependFunctionCount == 0) {
|
|
*ReturnedList = NULL;
|
|
*ReturnedLength = 0;
|
|
*BiosData = buffer;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Allocate memory for our internal data structures
|
|
//
|
|
|
|
dependFunctionCount += commonResCount;
|
|
dependResources = (PPB_DEPENDENT_RESOURCES)ExAllocatePoolWithTag(
|
|
PagedPool,
|
|
dependFunctionCount * sizeof(PB_DEPENDENT_RESOURCES) +
|
|
(commonResCount + dependDescCount) * sizeof(IO_RESOURCE_DESCRIPTOR),
|
|
'bPnP'
|
|
);
|
|
if (!dependResources) {
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
dependResList = dependResources; // remember it so we can free it.
|
|
|
|
alternativeListCount += commonResCount;
|
|
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;
|
|
ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
|
|
|
|
//
|
|
// Now start over again to process the bios data and initialize our internal
|
|
// resource representation.
|
|
//
|
|
|
|
dependDescCount = 0;
|
|
alternativeListCount = 0;
|
|
buffer = *BiosData;
|
|
tagName = *buffer;
|
|
dependent = FALSE;
|
|
|
|
for ( ; ; ) {
|
|
if (!(tagName & LARGE_RESOURCE_TAG)) {
|
|
tagName &= SMALL_TAG_MASK;
|
|
}
|
|
|
|
if (tagName == TAG_END) {
|
|
buffer += (*buffer & SMALL_TAG_SIZE_MASK) + 1;
|
|
break;
|
|
}
|
|
|
|
switch (tagName) {
|
|
case TAG_DMA:
|
|
case TAG_IRQ:
|
|
case TAG_IO:
|
|
case TAG_IO_FIXED:
|
|
case TAG_MEMORY:
|
|
case TAG_MEMORY32:
|
|
case TAG_MEMORY32_FIXED:
|
|
|
|
if (tagName == TAG_DMA) {
|
|
status = PbBiosDmaToIoDescriptor(&buffer, ioDesc);
|
|
} else if (tagName == TAG_IRQ) {
|
|
status = PbBiosIrqToIoDescriptor(&buffer, ioDesc);
|
|
} else if (tagName == TAG_IO) {
|
|
status = PbBiosPortToIoDescriptor(&buffer, ioDesc);
|
|
} else if (tagName == TAG_IO_FIXED) {
|
|
status = PbBiosPortFixedToIoDescriptor(&buffer, ioDesc, forceFixedIoTo16bit);
|
|
} else {
|
|
status = PbBiosMemoryToIoDescriptor(&buffer, ioDesc);
|
|
}
|
|
|
|
if (NT_SUCCESS(status)) {
|
|
ioDesc++;
|
|
if (dependent) {
|
|
dependDescCount++;
|
|
} else {
|
|
alternativeList[alternativeListCount].NoDependentFunctions = 1;
|
|
alternativeList[alternativeListCount].TotalResourceCount = 1;
|
|
dependResources->Count = 1;
|
|
dependResources->Flags = DEPENDENT_FLAGS_END;
|
|
dependResources->Next = alternativeList[alternativeListCount].Resources;
|
|
alternativeListCount++;
|
|
alternativeList[alternativeListCount].Resources = (PPB_DEPENDENT_RESOURCES)ioDesc;
|
|
dependResources = alternativeList[alternativeListCount].Resources;
|
|
ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
|
|
}
|
|
}
|
|
break;
|
|
case TAG_START_DEPEND:
|
|
//
|
|
// Some card (OPTI) put empty START_DEPENDENT functions
|
|
//
|
|
|
|
dependent = TRUE;
|
|
if (alternativeList[alternativeListCount].NoDependentFunctions != 0) {
|
|
|
|
//
|
|
// End of current dependent function
|
|
//
|
|
|
|
dependResources->Count = dependDescCount;
|
|
dependResources->Flags = 0;
|
|
dependResources->Next = (PPB_DEPENDENT_RESOURCES)ioDesc;
|
|
dependResources = dependResources->Next;
|
|
ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
|
|
alternativeList[alternativeListCount].TotalResourceCount += dependDescCount;
|
|
}
|
|
alternativeList[alternativeListCount].NoDependentFunctions++;
|
|
if (*buffer & SMALL_TAG_SIZE_MASK) {
|
|
dependResources->Priority = *(buffer + 1);
|
|
}
|
|
dependDescCount = 0;
|
|
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)ioDesc;
|
|
dependResources = alternativeList[alternativeListCount].Resources;
|
|
ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
|
|
buffer++;
|
|
break;
|
|
default:
|
|
|
|
//
|
|
// Don't-care tag simply advance the buffer pointer to next tag.
|
|
//
|
|
|
|
if (*buffer & LARGE_RESOURCE_TAG) {
|
|
increment = *(USHORT UNALIGNED *)(buffer+1);
|
|
increment += 3; // length of large tag
|
|
} else {
|
|
increment = (USHORT)(*buffer & SMALL_TAG_SIZE_MASK);
|
|
increment += 1; // length of small tag
|
|
}
|
|
buffer += increment;
|
|
}
|
|
tagName = *buffer;
|
|
if ((tagName & SMALL_TAG_MASK) == TAG_LOGICAL_ID) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (dependent) {
|
|
//
|
|
// TAG_END_DEPEND was not found before we hit TAG_COMPLETE_END, so
|
|
// simulate it.
|
|
//
|
|
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)ioDesc;
|
|
dependResources = alternativeList[alternativeListCount].Resources;
|
|
ioDesc = (PIO_RESOURCE_DESCRIPTOR)(dependResources + 1);
|
|
}
|
|
|
|
if (alternativeListCount != 0) {
|
|
alternativeList[alternativeListCount].Resources = NULL; // dummy alternativeList record
|
|
}
|
|
*BiosData = buffer;
|
|
|
|
//
|
|
// prepare IoResourceList
|
|
//
|
|
|
|
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;
|
|
|
|
if (ConvertFlags & PPCONVERTFLAG_SET_RESTART_LCPRI) {
|
|
listSize += noResLists * sizeof(IO_RESOURCE_DESCRIPTOR);
|
|
}
|
|
|
|
ioResReqList = (PIO_RESOURCE_REQUIREMENTS_LIST)ExAllocatePoolWithTag(PagedPool, listSize, 'bPnP');
|
|
if (!ioResReqList) {
|
|
|
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|
goto exit1;
|
|
}
|
|
|
|
ioResReqList->ListSize = listSize;
|
|
ioResReqList->InterfaceType = Isa;
|
|
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++) {
|
|
|
|
ioResList->Version = 1;
|
|
ioResList->Revision = 0x30 | (USHORT)i;
|
|
|
|
if (ConvertFlags & PPCONVERTFLAG_SET_RESTART_LCPRI) {
|
|
|
|
RtlZeroMemory(&ioResList->Descriptors[0], sizeof(IO_RESOURCE_DESCRIPTOR));
|
|
|
|
ioResList->Descriptors[0].Option = IO_RESOURCE_PREFERRED;
|
|
ioResList->Descriptors[0].Type = CmResourceTypeConfigData;
|
|
ioResList->Descriptors[0].u.ConfigData.Priority = LCPRI_RESTART;
|
|
|
|
buffer = (PUCHAR)&ioResList->Descriptors[1];
|
|
|
|
} else {
|
|
|
|
buffer = (PUCHAR)&ioResList->Descriptors[0];
|
|
}
|
|
|
|
//
|
|
// Copy dependent functions if any.
|
|
//
|
|
|
|
if (alternativeList) {
|
|
PbAddDependentResourcesToList(&buffer, 0, alternativeList);
|
|
}
|
|
|
|
//
|
|
// Update io resource list ptr
|
|
//
|
|
|
|
ioResList->Count = ((ULONG)((ULONG_PTR)buffer - (ULONG_PTR)&ioResList->Descriptors[0])) /
|
|
sizeof(IO_RESOURCE_DESCRIPTOR);
|
|
|
|
//
|
|
// Hack for user mode pnp mgr
|
|
//
|
|
|
|
for (j = 0; j < ioResList->Count; j++) {
|
|
ioResList->Descriptors[j].Spare2 = (USHORT)j;
|
|
}
|
|
ioResList = (PIO_RESOURCE_LIST)buffer;
|
|
}
|
|
|
|
*ReturnedLength = listSize;
|
|
status = STATUS_SUCCESS;
|
|
*ReturnedList = ioResReqList;
|
|
exit1:
|
|
if (alternativeList) {
|
|
ExFreePool(alternativeList);
|
|
}
|
|
exit0:
|
|
if (dependResList) {
|
|
ExFreePool(dependResList);
|
|
}
|
|
return status;
|
|
}
|
|
|
|
VOID
|
|
PpBiosResourcesSetToDisabled (
|
|
IN OUT PUCHAR BiosData,
|
|
OUT PULONG Length
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine modifies the passed in Bios resource list so that it reflects
|
|
what PnPBIOS expects to see if a device is disabled.
|
|
|
|
Arguments:
|
|
|
|
BiosData - Supplies a pointer to the bios resource data buffer
|
|
|
|
Length - This points to a ULONG that will contain the length of the single
|
|
resource list that has been programmed to look disabled.
|
|
|
|
Return Value:
|
|
|
|
None.
|
|
|
|
--*/
|
|
{
|
|
PUCHAR buffer;
|
|
USHORT increment;
|
|
UCHAR tagName;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// First, scan the bios data to determine the memory requirement and
|
|
// the information to build internal data structures.
|
|
//
|
|
|
|
buffer = BiosData;
|
|
|
|
do {
|
|
|
|
tagName = *buffer;
|
|
|
|
//
|
|
// Determine the size of the BIOS resource descriptor
|
|
//
|
|
if (!(tagName & LARGE_RESOURCE_TAG)) {
|
|
increment = (USHORT)(tagName & SMALL_TAG_SIZE_MASK);
|
|
tagName &= SMALL_TAG_MASK;
|
|
|
|
//
|
|
// Be careful not to wipe out the version field. That's very bad.
|
|
//
|
|
if (tagName != TAG_VERSION) {
|
|
RtlZeroMemory(buffer+1, increment);
|
|
}
|
|
increment += 1; // length of small tag
|
|
} else {
|
|
increment = *(USHORT UNALIGNED *)(buffer+1);
|
|
RtlZeroMemory(buffer+3, increment);
|
|
increment += 3; // length of large tag
|
|
}
|
|
|
|
buffer += increment;
|
|
} while (tagName != TAG_END) ;
|
|
|
|
*Length = (ULONG)(buffer - BiosData) ;
|
|
}
|
|
|
|
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;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// 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;
|
|
}
|
|
|
|
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;
|
|
|
|
PAGED_CODE();
|
|
|
|
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;
|
|
|
|
PAGED_CODE();
|
|
|
|
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,
|
|
IN BOOLEAN ForceFixedIoTo16bit
|
|
)
|
|
|
|
/*++
|
|
|
|
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.
|
|
|
|
ForceFixedIoTo16bit - hack option to force fixed I/O resources to 16bit
|
|
for far too pessimistic BIOS's.
|
|
|
|
Return Value:
|
|
|
|
return NTSTATUS code to indicate the result of the operation.
|
|
|
|
--*/
|
|
{
|
|
PPNP_FIXED_PORT_DESCRIPTOR buffer;
|
|
|
|
PAGED_CODE();
|
|
|
|
buffer = (PPNP_FIXED_PORT_DESCRIPTOR)*BiosData;
|
|
|
|
//
|
|
// Fill in Io resource descriptor
|
|
//
|
|
|
|
IoDescriptor->Option = 0;
|
|
IoDescriptor->Type = CmResourceTypePort;
|
|
|
|
if (ForceFixedIoTo16bit) {
|
|
|
|
IoDescriptor->Flags = CM_RESOURCE_PORT_IO + CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
|
|
} else {
|
|
|
|
IoDescriptor->Flags = CM_RESOURCE_PORT_IO + CM_RESOURCE_PORT_10_BIT_DECODE;
|
|
}
|
|
|
|
#if defined(_X86_)
|
|
|
|
//
|
|
// Workaround:
|
|
// NEC PC9800 series's PnPBIOS report I/O resources between 0x00 and 0xFF as FIXED IO.
|
|
// But These resources are 16bit DECODE resource, not 10bit DECODE one. We need to check
|
|
// the range of I/O resources .
|
|
//
|
|
|
|
if (IsNEC_98) {
|
|
if ( (ULONG)buffer->MinimumAddress < 0x100 ) {
|
|
IoDescriptor->Flags = CM_RESOURCE_PORT_IO + CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
}
|
|
}
|
|
#endif // <--end changing code
|
|
|
|
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;
|
|
|
|
PAGED_CODE();
|
|
|
|
buffer = (PPNP_PORT_DESCRIPTOR)*BiosData;
|
|
|
|
//
|
|
// Fill in Io resource descriptor
|
|
//
|
|
|
|
IoDescriptor->Option = 0;
|
|
IoDescriptor->Type = CmResourceTypePort;
|
|
IoDescriptor->Flags = CM_RESOURCE_PORT_IO;
|
|
if (buffer->Information & 1) {
|
|
IoDescriptor->Flags |= CM_RESOURCE_PORT_16_BIT_DECODE;
|
|
} else {
|
|
IoDescriptor->Flags |= CM_RESOURCE_PORT_10_BIT_DECODE;
|
|
}
|
|
IoDescriptor->ShareDisposition = CmResourceShareDeviceExclusive;
|
|
IoDescriptor->Spare1 = 0;
|
|
IoDescriptor->Spare2 = 0;
|
|
IoDescriptor->u.Port.Length = (ULONG)buffer->Length;
|
|
|
|
#if defined(_X86_)
|
|
if (IsNEC_98) {
|
|
if (buffer->Information & 0x80) {
|
|
IoDescriptor->u.Port.Length *= 2;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
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;
|
|
USHORT flags = 0;
|
|
|
|
PAGED_CODE();
|
|
|
|
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;
|
|
flags = CM_RESOURCE_MEMORY_24;
|
|
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;
|
|
default:
|
|
alignment = 0;
|
|
length = 0;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Fill in Io resource descriptor
|
|
//
|
|
|
|
IoDescriptor->Option = 0;
|
|
IoDescriptor->Type = CmResourceTypeMemory;
|
|
IoDescriptor->Flags = CM_RESOURCE_PORT_MEMORY + flags;
|
|
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
|
|
PpCmResourcesToBiosResources (
|
|
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_FULL_RESOURCE_DESCRIPTOR cmFullDesc;
|
|
PCM_PARTIAL_RESOURCE_DESCRIPTOR cmDesc;
|
|
ULONG i, l, count, length, totalSize = 0;
|
|
PUCHAR p, px;
|
|
PNP_MEMORY_DESCRIPTOR biosDesc;
|
|
NTSTATUS status;
|
|
|
|
PAGED_CODE();
|
|
|
|
*BiosResources = NULL;
|
|
*Length = 0;
|
|
CmResources->Count;
|
|
if (CmResources->Count == 0) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Determine pool size needed
|
|
//
|
|
|
|
count = 0;
|
|
cmFullDesc = &CmResources->List[0];
|
|
for (l = 0; l < CmResources->Count; l++) {
|
|
cmDesc = cmFullDesc->PartialResourceList.PartialDescriptors;
|
|
for (i = 0; i < cmFullDesc->PartialResourceList.Count; i++) {
|
|
switch (cmDesc->Type) {
|
|
case CmResourceTypePort:
|
|
case CmResourceTypeInterrupt:
|
|
case CmResourceTypeMemory:
|
|
case CmResourceTypeDma:
|
|
count++;
|
|
cmDesc++;
|
|
break;
|
|
case CmResourceTypeDeviceSpecific:
|
|
length = cmDesc->u.DeviceSpecificData.DataSize;
|
|
cmDesc++;
|
|
cmDesc = (PCM_PARTIAL_RESOURCE_DESCRIPTOR) ((PUCHAR)cmDesc + length);
|
|
break;
|
|
default:
|
|
count++;
|
|
cmDesc++;
|
|
break;
|
|
}
|
|
}
|
|
cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmDesc;
|
|
}
|
|
|
|
if (count == 0) {
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
//
|
|
// Allocate max amount of memory
|
|
//
|
|
|
|
px = p= ExAllocatePoolWithTag(PagedPool,
|
|
count * sizeof(PNP_MEMORY_DESCRIPTOR),
|
|
'bPnP');
|
|
if (!p) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
status = STATUS_RESOURCE_TYPE_NOT_FOUND;
|
|
cmFullDesc = &CmResources->List[0];
|
|
for (l = 0; l < CmResources->Count; l++) {
|
|
cmDesc = cmFullDesc->PartialResourceList.PartialDescriptors;
|
|
for (i = 0; i < cmFullDesc->PartialResourceList.Count; i++) {
|
|
switch (cmDesc->Type) {
|
|
case CmResourceTypePort:
|
|
status = PbCmPortToBiosDescriptor (
|
|
BiosRequirements,
|
|
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;
|
|
default:
|
|
cmDesc++;
|
|
continue;
|
|
}
|
|
if (NT_SUCCESS(status)) {
|
|
cmDesc++;
|
|
RtlCopyMemory(p, &biosDesc, length);
|
|
p += length;
|
|
totalSize += length;
|
|
} else {
|
|
ExFreePool(px);
|
|
goto exit;
|
|
}
|
|
}
|
|
cmFullDesc = (PCM_FULL_RESOURCE_DESCRIPTOR)cmDesc;
|
|
}
|
|
|
|
exit:
|
|
if (NT_SUCCESS(status)) {
|
|
*p = TAG_COMPLETE_END;
|
|
p++;
|
|
*p = 0; // checksum ignored
|
|
totalSize += 2;
|
|
*BiosResources = px;
|
|
*Length = totalSize;
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmIrqToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PVOID ReturnDescriptor,
|
|
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.
|
|
|
|
ReturnDescriptor - Supplies a buffer to receive the returned BIOS descriptor.
|
|
|
|
Length - Supplies a variable to receive the length of the returned bios descriptor.
|
|
|
|
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;
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
ULONG increment;
|
|
PPNP_IRQ_DESCRIPTOR irqDesc = (PPNP_IRQ_DESCRIPTOR)ReturnDescriptor;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (!(CmDescriptor->u.Interrupt.Level & 0xfffffff0)) {
|
|
irqMask = (USHORT)(1 << CmDescriptor->u.Interrupt.Level);
|
|
} else {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
if (!BiosRequirements) {
|
|
irqDesc->Tag = TAG_IRQ | (sizeof(PNP_IRQ_DESCRIPTOR) - 2); // No Information
|
|
irqDesc->IrqMask = irqMask;
|
|
*Length = sizeof(PNP_IRQ_DESCRIPTOR) - 1;
|
|
status = STATUS_SUCCESS;
|
|
} else {
|
|
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;
|
|
RtlCopyMemory(ReturnDescriptor, BiosRequirements, *Length);
|
|
((PPNP_IRQ_DESCRIPTOR)ReturnDescriptor)->IrqMask = irqMask;
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Don't-care tag simply advance the buffer pointer to next tag.
|
|
//
|
|
|
|
if (tag & LARGE_RESOURCE_TAG) {
|
|
increment = *(USHORT UNALIGNED *)(BiosRequirements + 1);
|
|
increment += 3; // length of large tag
|
|
} else {
|
|
increment = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
|
|
increment += 1; // length of small tag
|
|
}
|
|
BiosRequirements += increment;
|
|
tag = *BiosRequirements;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmDmaToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PVOID ReturnDescriptor,
|
|
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.
|
|
|
|
BiosDescriptor - Supplies a variable to receive the returned BIOS descriptor.
|
|
|
|
Length - Supplies a variable to receive the length of the returned bios descriptor.
|
|
|
|
Return Value:
|
|
|
|
return a pointer to the desired dma descriptor in the BiosRequirements. Null
|
|
if not found.
|
|
|
|
--*/
|
|
{
|
|
NTSTATUS status = STATUS_UNSUCCESSFUL;
|
|
UCHAR dmaMask, tag;
|
|
PPNP_DMA_DESCRIPTOR biosDesc;
|
|
ULONG increment;
|
|
PPNP_DMA_DESCRIPTOR dmaDesc = (PPNP_DMA_DESCRIPTOR)ReturnDescriptor;
|
|
USHORT flags = CmDescriptor->Flags;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (!(CmDescriptor->u.Dma.Channel & 0xfffffff0)) {
|
|
dmaMask = (UCHAR)(1 << CmDescriptor->u.Dma.Channel);
|
|
} else {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
if (!BiosRequirements) {
|
|
dmaDesc->Tag = TAG_DMA | (sizeof(PNP_DMA_DESCRIPTOR) - 1);
|
|
dmaDesc->ChannelMask = dmaMask;
|
|
dmaDesc->Flags = 0;
|
|
if (flags & CM_RESOURCE_DMA_8_AND_16) {
|
|
dmaDesc->Flags += 1;
|
|
} else if (flags & CM_RESOURCE_DMA_16) {
|
|
dmaDesc->Flags += 2;
|
|
}
|
|
if (flags & CM_RESOURCE_DMA_BUS_MASTER) {
|
|
dmaDesc->Flags += 4;
|
|
}
|
|
if (flags & CM_RESOURCE_DMA_TYPE_A) {
|
|
dmaDesc->Flags += 32;
|
|
}
|
|
if (flags & CM_RESOURCE_DMA_TYPE_B) {
|
|
dmaDesc->Flags += 64;
|
|
}
|
|
if (flags & CM_RESOURCE_DMA_TYPE_F) {
|
|
dmaDesc->Flags += 96;
|
|
}
|
|
*Length = sizeof(PNP_DMA_DESCRIPTOR);
|
|
status = STATUS_SUCCESS;
|
|
} else {
|
|
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;
|
|
RtlMoveMemory(ReturnDescriptor, BiosRequirements, *Length);
|
|
((PPNP_DMA_DESCRIPTOR)ReturnDescriptor)->ChannelMask = dmaMask;
|
|
status = STATUS_SUCCESS;
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// Don't-care tag simply advance the buffer pointer to next tag.
|
|
//
|
|
|
|
if (tag & LARGE_RESOURCE_TAG) {
|
|
increment = *(USHORT UNALIGNED *)(BiosRequirements + 1);
|
|
increment += 3; // length of large tag
|
|
} else {
|
|
increment = (USHORT)(tag & SMALL_TAG_SIZE_MASK);
|
|
increment += 1; // length of small tag
|
|
}
|
|
BiosRequirements += increment;
|
|
tag = *BiosRequirements;
|
|
}
|
|
}
|
|
return status;
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmPortToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PVOID ReturnDescriptor,
|
|
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.
|
|
|
|
ReturnDescriptor - supplies a buffer to receive the desired Bios Port descriptor.
|
|
|
|
Length - Supplies a variable to receive the length of the returned bios descriptor.
|
|
|
|
Return Value:
|
|
|
|
A NTSTATUS code.
|
|
|
|
--*/
|
|
{
|
|
PPNP_PORT_DESCRIPTOR portDesc = (PPNP_PORT_DESCRIPTOR)ReturnDescriptor;
|
|
USHORT minAddr, maxAddr, address;
|
|
UCHAR alignment, length, size, information = 0, tag, returnTag;
|
|
USHORT increment;
|
|
BOOLEAN test = FALSE;
|
|
|
|
PAGED_CODE();
|
|
|
|
if (CmDescriptor->u.Port.Start.HighPart != 0 ||
|
|
CmDescriptor->u.Port.Start.LowPart & 0xffff0000 ||
|
|
CmDescriptor->u.Port.Length & 0xffffff00) {
|
|
return STATUS_INVALID_PARAMETER;
|
|
}
|
|
|
|
//
|
|
// Search the possible resource list to get the information
|
|
// for the port range described by CmDescriptor.
|
|
//
|
|
|
|
address = (USHORT) CmDescriptor->u.Port.Start.LowPart;
|
|
size = (UCHAR) CmDescriptor->u.Port.Length;
|
|
if (!BiosRequirements) {
|
|
|
|
//
|
|
// No BiosRequirement. Use TAG_IO as default.
|
|
//
|
|
|
|
portDesc->Tag = TAG_IO | (sizeof(PNP_PORT_DESCRIPTOR) - 1);
|
|
if (CmDescriptor->Flags & CM_RESOURCE_PORT_16_BIT_DECODE) {
|
|
portDesc->Information = 1;
|
|
} else {
|
|
portDesc->Information = 0;
|
|
}
|
|
portDesc->Length = size;
|
|
portDesc->Alignment = 1;
|
|
portDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
|
|
portDesc->MaximumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
|
|
*Length = sizeof(PNP_PORT_DESCRIPTOR);
|
|
} else {
|
|
returnTag = TAG_END;
|
|
tag = *BiosRequirements;
|
|
minAddr = 0;
|
|
maxAddr = 0;
|
|
alignment = 0;
|
|
while (tag != TAG_COMPLETE_END) {
|
|
test = FALSE;
|
|
switch (tag & SMALL_TAG_MASK) {
|
|
case TAG_IO:
|
|
minAddr = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->MinimumAddress;
|
|
alignment = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->Alignment;
|
|
length = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->Length;
|
|
maxAddr = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->MaximumAddress;
|
|
information = ((PPNP_PORT_DESCRIPTOR)BiosRequirements)->Information;
|
|
test = TRUE;
|
|
returnTag = TAG_IO;
|
|
if (!alignment) {
|
|
if (minAddr == maxAddr) {
|
|
|
|
//
|
|
// If the max is equal to the min, the alignment is
|
|
// meaningless. As we told OEMs 0 is appropriate here,
|
|
// let us handle it.
|
|
//
|
|
alignment = 1;
|
|
}
|
|
}
|
|
maxAddr += length - 1;
|
|
break;
|
|
case TAG_IO_FIXED:
|
|
length = ((PPNP_FIXED_PORT_DESCRIPTOR)BiosRequirements)->Length;
|
|
minAddr = ((PPNP_FIXED_PORT_DESCRIPTOR)BiosRequirements)->MinimumAddress;
|
|
maxAddr = minAddr + length - 1;
|
|
alignment = 1;
|
|
information = 0; // 10 bit decode
|
|
returnTag = TAG_IO_FIXED;
|
|
test = TRUE;
|
|
break;
|
|
}
|
|
if (test) {
|
|
if (minAddr <= address && maxAddr >= (address + size - 1) && !(address & (alignment - 1 ))) {
|
|
break;
|
|
}
|
|
test = FALSE;
|
|
}
|
|
|
|
//
|
|
// Advance to next tag
|
|
//
|
|
|
|
if (tag & LARGE_RESOURCE_TAG) {
|
|
increment = *(USHORT UNALIGNED *)(BiosRequirements + 1);
|
|
increment += 3; // length of large tag
|
|
} else {
|
|
increment = (USHORT) tag & SMALL_TAG_SIZE_MASK;
|
|
increment += 1; // length of small tag
|
|
}
|
|
BiosRequirements += increment;
|
|
tag = *BiosRequirements;
|
|
}
|
|
if (tag == TAG_COMPLETE_END) {
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
//
|
|
// Set the return port descriptor
|
|
//
|
|
|
|
if (returnTag == TAG_IO) {
|
|
portDesc->Tag = TAG_IO + (sizeof(PNP_PORT_DESCRIPTOR) - 1);
|
|
portDesc->Information = information;
|
|
portDesc->Length = size;
|
|
portDesc->Alignment = alignment;
|
|
portDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
|
|
portDesc->MaximumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
|
|
*Length = sizeof(PNP_PORT_DESCRIPTOR);
|
|
} else {
|
|
PPNP_FIXED_PORT_DESCRIPTOR fixedPortDesc = (PPNP_FIXED_PORT_DESCRIPTOR)ReturnDescriptor;
|
|
|
|
fixedPortDesc->Tag = TAG_IO_FIXED + (sizeof(PPNP_FIXED_PORT_DESCRIPTOR) - 1);
|
|
fixedPortDesc->MinimumAddress = (USHORT)CmDescriptor->u.Port.Start.LowPart;
|
|
fixedPortDesc->Length = size;
|
|
*Length = sizeof(PNP_FIXED_PORT_DESCRIPTOR);
|
|
}
|
|
}
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
PbCmMemoryToBiosDescriptor (
|
|
IN PUCHAR BiosRequirements,
|
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR CmDescriptor,
|
|
OUT PVOID ReturnDescriptor,
|
|
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.
|
|
|
|
ReturnDescriptor - supplies a buffer to receive the desired Bios Memory 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 = (PPNP_FIXED_MEMORY32_DESCRIPTOR)ReturnDescriptor;
|
|
ULONG address, size, length, minAddr, maxAddr, alignment;
|
|
USHORT increment;
|
|
BOOLEAN test = FALSE;
|
|
|
|
PAGED_CODE();
|
|
|
|
//
|
|
// 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;
|
|
if (!BiosRequirements) {
|
|
|
|
//
|
|
// We don't support reserving legacy device's memory ranges from PNP
|
|
// BIOS. There isn't really any reason why not it just wasn't
|
|
// implemented for Windows 2000. It isn't near as necessary as it is
|
|
// for I/O ports since ROM memory has a signature and is self
|
|
// describing.
|
|
//
|
|
|
|
*Length = 0;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
information = 0;
|
|
tag = *BiosRequirements;
|
|
while (tag != TAG_COMPLETE_END) {
|
|
switch (tag & SMALL_TAG_MASK) {
|
|
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;
|
|
test = TRUE;
|
|
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;
|
|
test = TRUE;
|
|
break;
|
|
|
|
default:
|
|
|
|
//
|
|
// Any tag we don't understand is treated as a corrupt list.
|
|
//
|
|
|
|
ASSERT (FALSE);
|
|
return STATUS_UNSUCCESSFUL;
|
|
}
|
|
|
|
if (test) {
|
|
if (minAddr <= address && maxAddr >= (address + size - 1) && !(address & (alignment - 1 ))) {
|
|
information = ((PPNP_MEMORY32_DESCRIPTOR)BiosRequirements)->Information;
|
|
break;
|
|
}
|
|
test = FALSE;
|
|
}
|
|
|
|
//
|
|
// Advance to next tag
|
|
//
|
|
|
|
if (tag & LARGE_RESOURCE_TAG) {
|
|
increment = *(USHORT UNALIGNED *)(BiosRequirements + 1);
|
|
increment += 3; // length of large tag
|
|
} else {
|
|
increment = (USHORT) 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->Tag = TAG_MEMORY32_FIXED;
|
|
memoryDesc->Length = sizeof (PNP_FIXED_MEMORY32_DESCRIPTOR);
|
|
memoryDesc->Information = information;
|
|
memoryDesc->BaseAddress = address;
|
|
memoryDesc->MemorySize = size;
|
|
*Length = sizeof(PNP_FIXED_MEMORY32_DESCRIPTOR);
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
#ifdef ALLOC_DATA_PRAGMA
|
|
#pragma data_seg()
|
|
#endif
|