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.
382 lines
10 KiB
382 lines
10 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
translate.c
|
|
|
|
Abstract:
|
|
|
|
This is the default pnp IRQ translator.
|
|
|
|
Author:
|
|
|
|
Andy Thornton (andrewth) 7-June-97
|
|
|
|
Environment:
|
|
|
|
Kernel Mode Driver.
|
|
|
|
Notes:
|
|
|
|
This should only be temporary and will be replaced by a call into the HAL
|
|
to retrieve its translators.
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#pragma warning(disable:4214) // bit field types other than int
|
|
#pragma warning(disable:4201) // nameless struct/union
|
|
#pragma warning(disable:4115) // named type definition in parentheses
|
|
#pragma warning(disable:4127) // condition expression is constant
|
|
|
|
#include "ntos.h"
|
|
#include "haldisp.h"
|
|
#include <wdmguid.h>
|
|
|
|
//
|
|
// Iteration macros
|
|
//
|
|
|
|
//
|
|
// Control macro (used like a for loop) which iterates over all entries in
|
|
// a standard doubly linked list. Head is the list head and the entries are of
|
|
// type Type. A member called ListEntry is assumed to be the LIST_ENTRY
|
|
// structure linking the entries together. Current contains a pointer to each
|
|
// entry in turn.
|
|
//
|
|
#define FOR_ALL_IN_LIST(Type, Head, Current) \
|
|
for((Current) = CONTAINING_RECORD((Head)->Flink, Type, ListEntry); \
|
|
(Head) != &(Current)->ListEntry; \
|
|
(Current) = CONTAINING_RECORD((Current)->ListEntry.Flink, \
|
|
Type, \
|
|
ListEntry) \
|
|
)
|
|
//
|
|
// Similar to the above only iteration is over an array of length _Size.
|
|
//
|
|
#define FOR_ALL_IN_ARRAY(_Array, _Size, _Current) \
|
|
for ( (_Current) = (_Array); \
|
|
(_Current) < (_Array) + (_Size); \
|
|
(_Current)++ )
|
|
|
|
//
|
|
// As above only iteration begins with the entry _Current
|
|
//
|
|
#define FOR_REST_IN_ARRAY(_Array, _Size, _Current) \
|
|
for ( ; \
|
|
(_Current) < (_Array) + (_Size); \
|
|
(_Current)++ )
|
|
|
|
#define HAL_IRQ_TRANSLATOR_VERSION 0
|
|
|
|
NTSTATUS
|
|
FstubTranslateResource(
|
|
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
|
|
FstubTranslateRequirement (
|
|
IN PVOID Context,
|
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PULONG TargetCount,
|
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|
);
|
|
|
|
VOID
|
|
FstubTranslatorNull(
|
|
IN PVOID Context
|
|
);
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(PAGE,xHalGetInterruptTranslator)
|
|
#pragma alloc_text(PAGE,FstubTranslateResource)
|
|
#pragma alloc_text(PAGE,FstubTranslateRequirement)
|
|
#pragma alloc_text(PAGE,FstubTranslatorNull)
|
|
#endif
|
|
|
|
|
|
NTSTATUS
|
|
xHalGetInterruptTranslator(
|
|
IN INTERFACE_TYPE ParentInterfaceType,
|
|
IN ULONG ParentBusNumber,
|
|
IN INTERFACE_TYPE BridgeInterfaceType,
|
|
IN USHORT Size,
|
|
IN USHORT Version,
|
|
OUT PTRANSLATOR_INTERFACE Translator,
|
|
OUT PULONG BridgeBusNumber
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
|
|
Arguments:
|
|
|
|
ParentInterfaceType - The type of the bus the bridge lives on (normally PCI).
|
|
|
|
ParentBusNumber - The number of the bus the bridge lives on.
|
|
|
|
ParentSlotNumber - The slot number the bridge lives in (where valid).
|
|
|
|
BridgeInterfaceType - The bus type the bridge provides (ie ISA for a PCI-ISA bridge).
|
|
|
|
ResourceType - The resource type we want to translate.
|
|
|
|
Size - The size of the translator buffer.
|
|
|
|
Version - The version of the translator interface requested.
|
|
|
|
Translator - Pointer to the buffer where the translator should be returned
|
|
|
|
BridgeBusNumber - Pointer to where the bus number of the bridge bus should be returned
|
|
|
|
Return Value:
|
|
|
|
Returns the status of this operation.
|
|
|
|
--*/
|
|
{
|
|
PAGED_CODE();
|
|
|
|
UNREFERENCED_PARAMETER (BridgeBusNumber);
|
|
|
|
#if defined(NO_LEGACY_DRIVERS)
|
|
UNREFERENCED_PARAMETER(ParentInterfaceType);
|
|
UNREFERENCED_PARAMETER(ParentBusNumber);
|
|
UNREFERENCED_PARAMETER(BridgeInterfaceType);
|
|
UNREFERENCED_PARAMETER(Size);
|
|
UNREFERENCED_PARAMETER(Version);
|
|
UNREFERENCED_PARAMETER(Translator);
|
|
|
|
return STATUS_SUCCESS;
|
|
}
|
|
#else
|
|
|
|
UNREFERENCED_PARAMETER(ParentInterfaceType);
|
|
UNREFERENCED_PARAMETER(ParentBusNumber);
|
|
|
|
#if !DBG
|
|
UNREFERENCED_PARAMETER(Version);
|
|
UNREFERENCED_PARAMETER(Size);
|
|
#endif
|
|
|
|
ASSERT(Version == HAL_IRQ_TRANSLATOR_VERSION);
|
|
ASSERT(Size >= sizeof (TRANSLATOR_INTERFACE));
|
|
|
|
switch (BridgeInterfaceType) {
|
|
case Eisa:
|
|
case Isa:
|
|
case MicroChannel:
|
|
case InterfaceTypeUndefined: // special "IDE" cookie
|
|
|
|
//
|
|
// Pass back an interface for an IRQ translator.
|
|
//
|
|
RtlZeroMemory(Translator, sizeof (TRANSLATOR_INTERFACE));
|
|
|
|
Translator->Size = sizeof (TRANSLATOR_INTERFACE);
|
|
Translator->Version = HAL_IRQ_TRANSLATOR_VERSION;
|
|
Translator->InterfaceReference = &FstubTranslatorNull;
|
|
Translator->InterfaceDereference = &FstubTranslatorNull;
|
|
Translator->TranslateResources = &FstubTranslateResource;
|
|
Translator->TranslateResourceRequirements = &FstubTranslateRequirement;
|
|
|
|
if (BridgeInterfaceType == InterfaceTypeUndefined) {
|
|
Translator->Context = (PVOID)Isa;
|
|
} else {
|
|
Translator->Context = (PVOID)BridgeInterfaceType;
|
|
}
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
default:
|
|
return STATUS_NOT_IMPLEMENTED;
|
|
}
|
|
}
|
|
|
|
NTSTATUS
|
|
FstubTranslateResource(
|
|
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 status;
|
|
ULONG affinity, currentVector, translatedVector;
|
|
KIRQL irql;
|
|
PIO_RESOURCE_DESCRIPTOR currentAlternative;
|
|
|
|
PAGED_CODE();
|
|
|
|
UNREFERENCED_PARAMETER (PhysicalDeviceObject);
|
|
|
|
ASSERT(Source->Type == CmResourceTypeInterrupt);
|
|
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
//
|
|
// Copy unchanged fields
|
|
//
|
|
|
|
*Target = *Source;
|
|
|
|
switch (Direction) {
|
|
case TranslateChildToParent:
|
|
|
|
//
|
|
// Perform the translation - The interrupt source is
|
|
// ISA.
|
|
//
|
|
|
|
Target->u.Interrupt.Vector = HalGetInterruptVector(
|
|
(INTERFACE_TYPE)(ULONG_PTR)Context,
|
|
0, // assume bus 0
|
|
Source->u.Interrupt.Vector,
|
|
Source->u.Interrupt.Vector,
|
|
&irql,
|
|
&affinity
|
|
);
|
|
|
|
Target->u.Interrupt.Level = irql;
|
|
Target->u.Interrupt.Affinity = affinity;
|
|
|
|
status = STATUS_TRANSLATION_COMPLETE;
|
|
|
|
break;
|
|
|
|
case TranslateParentToChild:
|
|
|
|
//
|
|
// Translate each alternative and when we match then use the value we
|
|
// just translated
|
|
//
|
|
|
|
FOR_ALL_IN_ARRAY(Alternatives, AlternativesCount, currentAlternative) {
|
|
|
|
ASSERT(currentAlternative->Type == CmResourceTypeInterrupt);
|
|
|
|
currentVector = currentAlternative->u.Interrupt.MinimumVector;
|
|
|
|
while (currentVector <=
|
|
currentAlternative->u.Interrupt.MaximumVector) {
|
|
|
|
translatedVector = HalGetInterruptVector((INTERFACE_TYPE)(ULONG_PTR)Context,
|
|
0, // assume bus 0
|
|
currentVector,
|
|
currentVector,
|
|
&irql,
|
|
&affinity
|
|
);
|
|
|
|
|
|
|
|
if (translatedVector == Source->u.Interrupt.Vector) {
|
|
|
|
//
|
|
// We found our vector - fill in the target and return
|
|
//
|
|
|
|
Target->u.Interrupt.Vector = currentVector;
|
|
Target->u.Interrupt.Level = Target->u.Interrupt.Vector;
|
|
Target->u.Interrupt.Affinity = 0xFFFFFFFF;
|
|
return STATUS_SUCCESS;
|
|
}
|
|
|
|
currentVector++;
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
return status;
|
|
}
|
|
NTSTATUS
|
|
FstubTranslateRequirement (
|
|
IN PVOID Context,
|
|
IN PIO_RESOURCE_DESCRIPTOR Source,
|
|
IN PDEVICE_OBJECT PhysicalDeviceObject,
|
|
OUT PULONG TargetCount,
|
|
OUT PIO_RESOURCE_DESCRIPTOR *Target
|
|
)
|
|
{
|
|
ULONG affinity;
|
|
KIRQL irql;
|
|
|
|
PAGED_CODE();
|
|
|
|
UNREFERENCED_PARAMETER (PhysicalDeviceObject);
|
|
|
|
ASSERT(Source->Type == CmResourceTypeInterrupt);
|
|
|
|
*Target = ExAllocatePoolWithTag(PagedPool,
|
|
sizeof(IO_RESOURCE_DESCRIPTOR),
|
|
'btsF'
|
|
);
|
|
|
|
if (!*Target) {
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
}
|
|
|
|
*TargetCount = 1;
|
|
|
|
//
|
|
// Copy unchanged fields
|
|
//
|
|
|
|
**Target = *Source;
|
|
|
|
(*Target)->u.Interrupt.MinimumVector =
|
|
HalGetInterruptVector(
|
|
(INTERFACE_TYPE)(ULONG_PTR)Context,
|
|
0, // assume bus 0
|
|
Source->u.Interrupt.MinimumVector,
|
|
Source->u.Interrupt.MinimumVector,
|
|
&irql,
|
|
&affinity
|
|
);
|
|
|
|
|
|
(*Target)->u.Interrupt.MaximumVector =
|
|
HalGetInterruptVector(
|
|
(INTERFACE_TYPE)(ULONG_PTR)Context,
|
|
0, // assume bus 0
|
|
Source->u.Interrupt.MaximumVector,
|
|
Source->u.Interrupt.MaximumVector,
|
|
&irql,
|
|
&affinity
|
|
);
|
|
|
|
|
|
return STATUS_TRANSLATION_COMPLETE;
|
|
}
|
|
|
|
VOID
|
|
FstubTranslatorNull(
|
|
IN PVOID Context
|
|
)
|
|
{
|
|
PAGED_CODE();
|
|
|
|
UNREFERENCED_PARAMETER (Context);
|
|
|
|
return;
|
|
}
|
|
#endif // NO_LEGACY_DRIVERS
|
|
|
|
|