|
|
/*++
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
|