755 lines
20 KiB
C
755 lines
20 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1997 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
translate.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This file implements translator interfaces for busses
|
|||
|
enumerated by ACPI.
|
|||
|
|
|||
|
The actual translation information about this bus is
|
|||
|
gotten from the _CRS associated with the bus. We put
|
|||
|
the data into an IO_RESOURCE_REQUIREMENTS_LIST as
|
|||
|
device private data of the following form:
|
|||
|
|
|||
|
DevicePrivate.Data[0]: child's CM_RESOURCE_TYPE
|
|||
|
DevicePrivate.Data[1]: child's start address [31:0]
|
|||
|
DevicePrivate.Data[2]: child's start address [63:32]
|
|||
|
|
|||
|
The descriptor that describes child-side translation
|
|||
|
immediately follows the one that describes the
|
|||
|
parent-side resources.
|
|||
|
|
|||
|
The Flags field of the IO_RESOURCE_REQUIREMENTS_LIST may have the
|
|||
|
TRANSLATION_RANGE_SPARSE bit set.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jake Oshins 7-Nov-97
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
NT Kernel Model Driver only
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "pch.h"
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FindTranslationRange(
|
|||
|
IN PHYSICAL_ADDRESS Start,
|
|||
|
IN LONGLONG Length,
|
|||
|
IN PBRIDGE_TRANSLATOR Translator,
|
|||
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|||
|
IN UCHAR ResType,
|
|||
|
OUT PBRIDGE_WINDOW *Window
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
TranslateBridgeResources(
|
|||
|
IN PVOID Context,
|
|||
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|||
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|||
|
IN ULONG AlternativesCount, OPTIONAL
|
|||
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|||
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|||
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
TranslateBridgeRequirements(
|
|||
|
IN PVOID Context,
|
|||
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|||
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|||
|
OUT PULONG TargetCount,
|
|||
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|||
|
);
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
BuildTranslatorRanges(
|
|||
|
IN PBRIDGE_TRANSLATOR Translator,
|
|||
|
OUT ULONG *BridgeWindowCount,
|
|||
|
OUT PBRIDGE_WINDOW *Window
|
|||
|
);
|
|||
|
|
|||
|
#define MAX(a, b) \
|
|||
|
((a) > (b) ? (a) : (b))
|
|||
|
|
|||
|
#define MIN(a, b) \
|
|||
|
((a) < (b) ? (a) : (b))
|
|||
|
|
|||
|
HAL_PORT_RANGE_INTERFACE HalPortRangeInterface;
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, TranslateEjectInterface)
|
|||
|
#pragma alloc_text(PAGE, TranslateBridgeResources)
|
|||
|
#pragma alloc_text(PAGE, TranslateBridgeRequirements)
|
|||
|
#pragma alloc_text(PAGE, FindTranslationRange)
|
|||
|
#pragma alloc_text(PAGE, AcpiNullReference)
|
|||
|
#pragma alloc_text(PAGE, BuildTranslatorRanges)
|
|||
|
#endif
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
TranslateEjectInterface(
|
|||
|
PDEVICE_OBJECT DeviceObject,
|
|||
|
PIRP Irp
|
|||
|
)
|
|||
|
{
|
|||
|
PIO_RESOURCE_REQUIREMENTS_LIST ioList = NULL;
|
|||
|
PIO_RESOURCE_DESCRIPTOR transDesc;
|
|||
|
PIO_RESOURCE_DESCRIPTOR parentDesc;
|
|||
|
PTRANSLATOR_INTERFACE transInterface;
|
|||
|
PBRIDGE_TRANSLATOR bridgeTrans;
|
|||
|
PIO_STACK_LOCATION irpSp;
|
|||
|
PDEVICE_EXTENSION devExtension;
|
|||
|
BOOLEAN foundTranslations = FALSE;
|
|||
|
NTSTATUS status;
|
|||
|
PUCHAR crsBuf;
|
|||
|
ULONG descCount;
|
|||
|
ULONG parentResType;
|
|||
|
ULONG childResType;
|
|||
|
ULONG crsBufSize;
|
|||
|
PHYSICAL_ADDRESS parentStart;
|
|||
|
PHYSICAL_ADDRESS childStart;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
devExtension = ACPIInternalGetDeviceExtension(DeviceObject);
|
|||
|
|
|||
|
ASSERT(devExtension);
|
|||
|
ASSERT(devExtension->AcpiObject);
|
|||
|
|
|||
|
irpSp = IoGetCurrentIrpStackLocation(Irp);
|
|||
|
ASSERT(irpSp->Parameters.QueryInterface.Size >= sizeof(TRANSLATOR_INTERFACE));
|
|||
|
|
|||
|
transInterface = (PTRANSLATOR_INTERFACE)irpSp->Parameters.QueryInterface.Interface;
|
|||
|
ASSERT(transInterface);
|
|||
|
|
|||
|
//
|
|||
|
// Get the resources for this bus.
|
|||
|
//
|
|||
|
status = ACPIGetBufferSync(
|
|||
|
devExtension,
|
|||
|
PACKED_CRS,
|
|||
|
&crsBuf,
|
|||
|
&crsBufSize
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
//
|
|||
|
// This bus has no _CRS. So it doesn't need a translator.
|
|||
|
//
|
|||
|
return Irp->IoStatus.Status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Turn it into something meaningful.
|
|||
|
//
|
|||
|
status = PnpBiosResourcesToNtResources(
|
|||
|
crsBuf,
|
|||
|
PNP_BIOS_TO_IO_NO_CONSUMED_RESOURCES,
|
|||
|
&ioList
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
goto TranslateEjectInterfaceExit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Cycle through the descriptors looking for device private data
|
|||
|
// that contains translation information.
|
|||
|
//
|
|||
|
|
|||
|
for (descCount = 0; descCount < ioList->List[0].Count; descCount++) {
|
|||
|
|
|||
|
transDesc = &ioList->List[0].Descriptors[descCount];
|
|||
|
|
|||
|
if (transDesc->Type == CmResourceTypeDevicePrivate) {
|
|||
|
|
|||
|
//
|
|||
|
// Translation information is contained in
|
|||
|
// a device private resource that has
|
|||
|
// TRANSLATION_DATA_PARENT_ADDRESS in the
|
|||
|
// flags field.
|
|||
|
//
|
|||
|
if (transDesc->Flags & TRANSLATION_DATA_PARENT_ADDRESS) {
|
|||
|
|
|||
|
// The first descriptor cannot be a translation descriptor
|
|||
|
ASSERT(descCount != 0);
|
|||
|
|
|||
|
//
|
|||
|
// The translation descriptor should follow the descriptor
|
|||
|
// that it is trying to modify. The first, normal,
|
|||
|
// descriptor is for the child-relative resources. The
|
|||
|
// second, device private, descriptor is modifies the
|
|||
|
// child-relative resources to generate the parent-relative
|
|||
|
// resources.
|
|||
|
//
|
|||
|
|
|||
|
parentResType = transDesc->u.DevicePrivate.Data[0];
|
|||
|
parentStart.LowPart = transDesc->u.DevicePrivate.Data[1];
|
|||
|
parentStart.HighPart = transDesc->u.DevicePrivate.Data[2];
|
|||
|
|
|||
|
childResType = ioList->List[0].Descriptors[descCount - 1].Type;
|
|||
|
childStart.QuadPart = (transDesc - 1)->u.Generic.MinimumAddress.QuadPart;
|
|||
|
|
|||
|
if ((parentResType != childResType) ||
|
|||
|
(parentStart.QuadPart != childStart.QuadPart)) {
|
|||
|
|
|||
|
foundTranslations = TRUE;
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (!foundTranslations) {
|
|||
|
|
|||
|
//
|
|||
|
// Didn't find any translation information for this bus.
|
|||
|
//
|
|||
|
status = Irp->IoStatus.Status;
|
|||
|
ExFreePool(ioList);
|
|||
|
goto TranslateEjectInterfaceExit;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Build a translator interface.
|
|||
|
//
|
|||
|
bridgeTrans = ExAllocatePoolWithTag(
|
|||
|
PagedPool,
|
|||
|
sizeof (BRIDGE_TRANSLATOR),
|
|||
|
ACPI_TRANSLATE_POOLTAG
|
|||
|
);
|
|||
|
if (!bridgeTrans) {
|
|||
|
|
|||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
goto TranslateEjectInterfaceExit;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
bridgeTrans->AcpiObject = devExtension->AcpiObject;
|
|||
|
bridgeTrans->IoList = ioList;
|
|||
|
|
|||
|
//
|
|||
|
// Build the array of bridge windows.
|
|||
|
//
|
|||
|
status = BuildTranslatorRanges(
|
|||
|
bridgeTrans,
|
|||
|
&bridgeTrans->RangeCount,
|
|||
|
&bridgeTrans->Ranges
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
goto TranslateEjectInterfaceExit;
|
|||
|
|
|||
|
}
|
|||
|
transInterface->Size = sizeof(TRANSLATOR_INTERFACE);
|
|||
|
transInterface->Version = 1;
|
|||
|
transInterface->Context = (PVOID)bridgeTrans;
|
|||
|
transInterface->InterfaceReference = AcpiNullReference;
|
|||
|
transInterface->InterfaceDereference = AcpiNullReference;
|
|||
|
transInterface->TranslateResources = TranslateBridgeResources;
|
|||
|
transInterface->TranslateResourceRequirements = TranslateBridgeRequirements;
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
|
|||
|
TranslateEjectInterfaceExit:
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
FindTranslationRange(
|
|||
|
IN PHYSICAL_ADDRESS Start,
|
|||
|
IN LONGLONG Length,
|
|||
|
IN PBRIDGE_TRANSLATOR Translator,
|
|||
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|||
|
IN UCHAR ResType,
|
|||
|
OUT PBRIDGE_WINDOW *Window
|
|||
|
)
|
|||
|
{
|
|||
|
LONGLONG beginning, end;
|
|||
|
ULONG i;
|
|||
|
UCHAR rangeType;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
for (i = 0; i < Translator->RangeCount; i++) {
|
|||
|
|
|||
|
if (Direction == TranslateParentToChild) {
|
|||
|
|
|||
|
beginning = Translator->Ranges[i].ParentAddress.QuadPart;
|
|||
|
rangeType = Translator->Ranges[i].ParentType;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
beginning = Translator->Ranges[i].ChildAddress.QuadPart;
|
|||
|
rangeType = Translator->Ranges[i].ChildType;
|
|||
|
}
|
|||
|
|
|||
|
end = beginning + Translator->Ranges[i].Length;
|
|||
|
|
|||
|
if ((rangeType == ResType) &&
|
|||
|
(!((Start.QuadPart < beginning) ||
|
|||
|
(Start.QuadPart + Length > end)))) {
|
|||
|
|
|||
|
//
|
|||
|
// The range lies within this bridge window
|
|||
|
// and the resource types match.
|
|||
|
//
|
|||
|
|
|||
|
*Window = &Translator->Ranges[i];
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return STATUS_NOT_FOUND;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
TranslateBridgeResources(
|
|||
|
IN PVOID Context,
|
|||
|
IN PCM_PARTIAL_RESOURCE_DESCRIPTOR Source,
|
|||
|
IN RESOURCE_TRANSLATION_DIRECTION Direction,
|
|||
|
IN ULONG AlternativesCount, OPTIONAL
|
|||
|
IN IO_RESOURCE_DESCRIPTOR Alternatives[], OPTIONAL
|
|||
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|||
|
OUT PCM_PARTIAL_RESOURCE_DESCRIPTOR Target
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function takes a set of resources that are
|
|||
|
passed through a bridge and does any translation
|
|||
|
that is necessary when changing from a parent-
|
|||
|
relative viewpoint to a child-relative one or
|
|||
|
back again.
|
|||
|
|
|||
|
In this function, we have the notion of a "window,"
|
|||
|
which is an aperature within the bridge. Bridges
|
|||
|
often have multiple windows, each with distinct
|
|||
|
translations.
|
|||
|
|
|||
|
This function should never fail, as any resource
|
|||
|
range that will fail translation should have already
|
|||
|
been stripped out by TranslateBridgeRequirements.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Context - pointer to the translation data
|
|||
|
|
|||
|
Source - resource list to be translated
|
|||
|
|
|||
|
Direction - TranslateChildToParent or
|
|||
|
TranslateParentToChild
|
|||
|
|
|||
|
AlternativesCount - not used
|
|||
|
|
|||
|
Alternatives - not used
|
|||
|
|
|||
|
PhysicalDeviceObject - not used
|
|||
|
|
|||
|
Target - translated resource list
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PBRIDGE_TRANSLATOR translator;
|
|||
|
PBRIDGE_WINDOW window;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
ASSERT(Context);
|
|||
|
ASSERT((Source->Type == CmResourceTypePort) ||
|
|||
|
(Source->Type == CmResourceTypeMemory));
|
|||
|
|
|||
|
translator = (PBRIDGE_TRANSLATOR)Context;
|
|||
|
|
|||
|
ASSERT(translator->RangeCount > 0);
|
|||
|
|
|||
|
//
|
|||
|
// Find the window that this translation occurs
|
|||
|
// within.
|
|||
|
//
|
|||
|
status = FindTranslationRange(Source->u.Generic.Start,
|
|||
|
Source->u.Generic.Length,
|
|||
|
translator,
|
|||
|
Direction,
|
|||
|
Source->Type,
|
|||
|
&window);
|
|||
|
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
//
|
|||
|
// We should never get here. This fucntion
|
|||
|
// should only be called for ranges that
|
|||
|
// are valid. TranslateBridgeRequirements should
|
|||
|
// weed out all the invalid ranges.
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy everything
|
|||
|
//
|
|||
|
*Target = *Source;
|
|||
|
|
|||
|
switch (Direction) {
|
|||
|
case TranslateChildToParent:
|
|||
|
|
|||
|
//
|
|||
|
// Target inherits the parent's resource type.
|
|||
|
//
|
|||
|
Target->Type = window->ParentType;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the target's parent-relative start
|
|||
|
// address.
|
|||
|
//
|
|||
|
Target->u.Generic.Start.QuadPart =
|
|||
|
Source->u.Generic.Start.QuadPart +
|
|||
|
window->ParentAddress.QuadPart -
|
|||
|
window->ChildAddress.QuadPart;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure the length is still in bounds.
|
|||
|
//
|
|||
|
ASSERT(Target->u.Generic.Length <= (ULONG)(window->Length -
|
|||
|
(Target->u.Generic.Start.QuadPart -
|
|||
|
window->ParentAddress.QuadPart)));
|
|||
|
|
|||
|
status = STATUS_TRANSLATION_COMPLETE;
|
|||
|
|
|||
|
break;
|
|||
|
|
|||
|
case TranslateParentToChild:
|
|||
|
|
|||
|
//
|
|||
|
// Target inherits the child's resource type.
|
|||
|
//
|
|||
|
Target->Type = window->ChildType;
|
|||
|
|
|||
|
//
|
|||
|
// Calculate the target's child-relative start
|
|||
|
// address.
|
|||
|
//
|
|||
|
Target->u.Generic.Start.QuadPart =
|
|||
|
Source->u.Generic.Start.QuadPart +
|
|||
|
window->ChildAddress.QuadPart -
|
|||
|
window->ParentAddress.QuadPart;
|
|||
|
|
|||
|
//
|
|||
|
// Make sure the length is still in bounds.
|
|||
|
//
|
|||
|
ASSERT(Target->u.Generic.Length <= (ULONG)(window->Length -
|
|||
|
(Target->u.Generic.Start.QuadPart -
|
|||
|
window->ChildAddress.QuadPart)));
|
|||
|
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
break;
|
|||
|
|
|||
|
default:
|
|||
|
status = STATUS_INVALID_PARAMETER;
|
|||
|
}
|
|||
|
|
|||
|
#if 0
|
|||
|
if (Target->Type == CmResourceTypePort) {
|
|||
|
DbgPrint("XXX: %s[%d]=0x%I64x -> %s[%d]=0x%I64x\n",
|
|||
|
(Direction == TranslateChildToParent) ? "child" : "parent",
|
|||
|
Source->Type,
|
|||
|
Source->u.Generic.Start.QuadPart,
|
|||
|
(Direction == TranslateChildToParent) ? "parent" : "child",
|
|||
|
Target->Type,
|
|||
|
Target->u.Generic.Start.QuadPart);
|
|||
|
}
|
|||
|
#endif
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
TranslateBridgeRequirements(
|
|||
|
IN PVOID Context,
|
|||
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|||
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|||
|
OUT PULONG TargetCount,
|
|||
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function takes a resource requirements list for
|
|||
|
resources on the child side of the bridge and
|
|||
|
translates them into resource requirements on the
|
|||
|
parent side of the bridge. This may involve clipping
|
|||
|
and there may be multiple target ranges.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Context - pointer to the translation data
|
|||
|
|
|||
|
Source - resource list to be translated
|
|||
|
|
|||
|
PhysicalDeviceObject - not used
|
|||
|
|
|||
|
TargetCount - number of resources in the target list
|
|||
|
|
|||
|
Target - translated resource requirements list
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
Status
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
PBRIDGE_TRANSLATOR translator;
|
|||
|
PBRIDGE_WINDOW window;
|
|||
|
NTSTATUS status;
|
|||
|
LONGLONG rangeStart, rangeEnd, windowStart, windowEnd;
|
|||
|
ULONG i;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
ASSERT(Context);
|
|||
|
ASSERT((Source->Type == CmResourceTypePort) ||
|
|||
|
(Source->Type == CmResourceTypeMemory));
|
|||
|
|
|||
|
translator = (PBRIDGE_TRANSLATOR)Context;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate memory for the target range.
|
|||
|
//
|
|||
|
|
|||
|
*Target = ExAllocatePoolWithTag(PagedPool,
|
|||
|
sizeof(IO_RESOURCE_DESCRIPTOR),
|
|||
|
ACPI_RESOURCE_POOLTAG);
|
|||
|
|
|||
|
if (!*Target) {
|
|||
|
status = STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
goto cleanup;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Look at all the aperatures in the bridge to see which
|
|||
|
// ones of them could possibly provide translations for
|
|||
|
// this resource.
|
|||
|
//
|
|||
|
|
|||
|
rangeStart = Source->u.Generic.MinimumAddress.QuadPart;
|
|||
|
rangeEnd = Source->u.Generic.MaximumAddress.QuadPart;
|
|||
|
|
|||
|
for (i = 0; i < translator->RangeCount; i++) {
|
|||
|
|
|||
|
window = &translator->Ranges[i];
|
|||
|
|
|||
|
if (window->ChildType != Source->Type) {
|
|||
|
|
|||
|
//
|
|||
|
// This window describes the wrong
|
|||
|
// type of resource.
|
|||
|
//
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
if (Source->u.Generic.Length > window->Length) {
|
|||
|
|
|||
|
//
|
|||
|
// This resource won't fit in this aperature.
|
|||
|
//
|
|||
|
continue;
|
|||
|
}
|
|||
|
|
|||
|
windowStart = window->ChildAddress.QuadPart;
|
|||
|
windowEnd = window->ChildAddress.QuadPart + (LONGLONG)window->Length;
|
|||
|
|
|||
|
if (!(((rangeStart < windowStart) && (rangeEnd < windowStart)) ||
|
|||
|
((rangeStart > windowEnd) && (rangeEnd > windowEnd)))) {
|
|||
|
|
|||
|
//
|
|||
|
// The range and the window do intersect. So create
|
|||
|
// a resource that clips the range to the window.
|
|||
|
//
|
|||
|
|
|||
|
**Target = *Source;
|
|||
|
*TargetCount = 1;
|
|||
|
|
|||
|
(*Target)->Type = window->ParentType;
|
|||
|
|
|||
|
(*Target)->u.Generic.MinimumAddress.QuadPart =
|
|||
|
rangeStart + (window->ParentAddress.QuadPart - windowStart);
|
|||
|
|
|||
|
(*Target)->u.Generic.MaximumAddress.QuadPart =
|
|||
|
rangeEnd + (window->ParentAddress.QuadPart - windowStart);
|
|||
|
|
|||
|
break;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (i < translator->RangeCount) {
|
|||
|
|
|||
|
return STATUS_TRANSLATION_COMPLETE;
|
|||
|
|
|||
|
} else {
|
|||
|
|
|||
|
*TargetCount = 0;
|
|||
|
status = STATUS_PNP_TRANSLATION_FAILED;
|
|||
|
}
|
|||
|
|
|||
|
cleanup:
|
|||
|
|
|||
|
if (*Target) {
|
|||
|
ExFreePool(*Target);
|
|||
|
}
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
BuildTranslatorRanges(
|
|||
|
IN PBRIDGE_TRANSLATOR Translator,
|
|||
|
OUT ULONG *BridgeWindowCount,
|
|||
|
OUT PBRIDGE_WINDOW *Window
|
|||
|
)
|
|||
|
{
|
|||
|
PIO_RESOURCE_REQUIREMENTS_LIST ioList;
|
|||
|
PIO_RESOURCE_DESCRIPTOR transDesc, resDesc;
|
|||
|
ULONG descCount, windowCount, maxWindows;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
ioList = Translator->IoList;
|
|||
|
|
|||
|
//
|
|||
|
// Make an array of windows for holding the translation information.
|
|||
|
//
|
|||
|
|
|||
|
maxWindows = ioList->List[0].Count / 2;
|
|||
|
|
|||
|
*Window = ExAllocatePoolWithTag(PagedPool,
|
|||
|
maxWindows * sizeof(BRIDGE_WINDOW),
|
|||
|
ACPI_TRANSLATE_POOLTAG);
|
|||
|
|
|||
|
if (!*Window) {
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the array with translations.
|
|||
|
//
|
|||
|
|
|||
|
windowCount = 0;
|
|||
|
|
|||
|
for (descCount = 0; descCount < ioList->List[0].Count; descCount++) {
|
|||
|
|
|||
|
transDesc = &ioList->List[0].Descriptors[descCount];
|
|||
|
|
|||
|
if (transDesc->Type == CmResourceTypeDevicePrivate) {
|
|||
|
|
|||
|
//
|
|||
|
// Translation information is contained in
|
|||
|
// a device private resource that has
|
|||
|
// TRANSLATION_DATA_PARENT_ADDRESS in the
|
|||
|
// flags field.
|
|||
|
//
|
|||
|
if (transDesc->Flags & TRANSLATION_DATA_PARENT_ADDRESS) {
|
|||
|
|
|||
|
ASSERT(windowCount <= maxWindows);
|
|||
|
|
|||
|
|
|||
|
|
|||
|
//
|
|||
|
// The translation descriptor is supposed to follow
|
|||
|
// the resource that it is providing information about.
|
|||
|
//
|
|||
|
|
|||
|
resDesc = &ioList->List[0].Descriptors[descCount - 1];
|
|||
|
|
|||
|
|
|||
|
|
|||
|
(*Window)[windowCount].ParentType =
|
|||
|
(UCHAR)transDesc->u.DevicePrivate.Data[0];
|
|||
|
|
|||
|
(*Window)[windowCount].ChildType = resDesc->Type;
|
|||
|
|
|||
|
(*Window)[windowCount].ParentAddress.LowPart =
|
|||
|
transDesc->u.DevicePrivate.Data[1];
|
|||
|
|
|||
|
(*Window)[windowCount].ParentAddress.HighPart =
|
|||
|
transDesc->u.DevicePrivate.Data[2];
|
|||
|
|
|||
|
(*Window)[windowCount].ChildAddress.QuadPart =
|
|||
|
resDesc->u.Generic.MinimumAddress.QuadPart;
|
|||
|
|
|||
|
(*Window)[windowCount].Length =
|
|||
|
resDesc->u.Generic.Length;
|
|||
|
|
|||
|
//
|
|||
|
// If the HAL has provided underlying sparse port translation
|
|||
|
// services, allow for that.
|
|||
|
//
|
|||
|
|
|||
|
if ((HalPortRangeInterface.QueryAllocateRange != NULL) &&
|
|||
|
(resDesc->Type == CmResourceTypePort)) {
|
|||
|
|
|||
|
USHORT rangeId;
|
|||
|
UCHAR parentType = (UCHAR)transDesc->u.DevicePrivate.Data[0];
|
|||
|
|
|||
|
BOOLEAN isSparse = transDesc->Flags & TRANSLATION_RANGE_SPARSE;
|
|||
|
ULONG parentLength = resDesc->u.Generic.Length;
|
|||
|
PHYSICAL_ADDRESS parentAddress;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
PHYSICAL_ADDRESS rangeZeroBase;
|
|||
|
|
|||
|
parentAddress.LowPart = transDesc->u.DevicePrivate.Data[1];
|
|||
|
parentAddress.HighPart = transDesc->u.DevicePrivate.Data[2];
|
|||
|
|
|||
|
rangeZeroBase.QuadPart = parentAddress.QuadPart - resDesc->u.Generic.MinimumAddress.QuadPart;
|
|||
|
|
|||
|
if (isSparse) {
|
|||
|
parentLength = (parentLength + resDesc->u.Generic.MinimumAddress.LowPart) << 10;
|
|||
|
}
|
|||
|
|
|||
|
status = HalPortRangeInterface.QueryAllocateRange(
|
|||
|
isSparse,
|
|||
|
parentType == CmResourceTypeMemory,
|
|||
|
NULL,
|
|||
|
rangeZeroBase,
|
|||
|
parentLength,
|
|||
|
&rangeId
|
|||
|
);
|
|||
|
|
|||
|
if (NT_SUCCESS(status)) {
|
|||
|
(*Window)[windowCount].ParentType = CmResourceTypePort;
|
|||
|
|
|||
|
(*Window)[windowCount].ParentAddress.QuadPart =
|
|||
|
(rangeId << 16) |
|
|||
|
((*Window)[windowCount].ChildAddress.QuadPart & 0xffff);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
windowCount++;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
*BridgeWindowCount = windowCount;
|
|||
|
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
|