1756 lines
42 KiB
C
1756 lines
42 KiB
C
/*++
|
||
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
bushnd.c
|
||
|
||
Abstract:
|
||
|
||
Functions which take either BusType-BusNumber or ConfigType-BusNumberm
|
||
and route to a the appropiate registered handler.
|
||
|
||
Author:
|
||
|
||
Ken Reneris (kenr) July-28-1994
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
|
||
|
||
typedef struct _ARRAY {
|
||
ULONG ArraySize;
|
||
PVOID Element[]; // must be last field
|
||
} ARRAY, *PARRAY;
|
||
|
||
#define ARRAY_SIZE_IN_BYTES(a) ( (a + 1) * sizeof(PARRAY) + \
|
||
FIELD_OFFSET(ARRAY, Element) )
|
||
|
||
typedef struct _HAL_BUS_HANDLER {
|
||
LIST_ENTRY AllHandlers;
|
||
ULONG ReferenceCount;
|
||
BUS_HANDLER Handler;
|
||
} HAL_BUS_HANDLER, *PHAL_BUS_HANDLER;
|
||
|
||
//
|
||
// Event to serialize with adding new buses
|
||
//
|
||
|
||
KEVENT HalpBusDatabaseEvent;
|
||
|
||
//
|
||
// Lock to serialize routing functions from accessing handler arrays while
|
||
// new buses are added
|
||
//
|
||
|
||
KSPIN_LOCK HalpBusDatabaseSpinLock;
|
||
|
||
//
|
||
// HalpBusTable - pointers to BusHandlers mapped by InterfaceType,BusNumber
|
||
//
|
||
|
||
PARRAY HalpBusTable;
|
||
|
||
//
|
||
// HalpConfigTable - pointers to BusHandlers mapped by ConfigType,BusNumber
|
||
//
|
||
|
||
PARRAY HalpConfigTable;
|
||
|
||
//
|
||
// List of all installed bus handlers
|
||
//
|
||
|
||
LIST_ENTRY HalpAllBusHandlers;
|
||
|
||
//
|
||
// Lock is high_level since some routed functions can occurs at ISR time
|
||
//
|
||
|
||
#define LockBusDatabase(oldirql) \
|
||
KeRaiseIrql(HIGH_LEVEL, oldirql); \
|
||
KiAcquireSpinLock(&HalpBusDatabaseSpinLock);
|
||
|
||
#define UnlockBusDatabase(oldirql) \
|
||
KiReleaseSpinLock(&HalpBusDatabaseSpinLock); \
|
||
KeLowerIrql(oldirql);
|
||
|
||
|
||
#ifdef _PNP_POWER_
|
||
extern HAL_CALLBACKS HalCallback;
|
||
#endif
|
||
|
||
//
|
||
// Internal prototypes
|
||
//
|
||
|
||
PARRAY
|
||
HalpAllocateArray (
|
||
IN ULONG Type
|
||
);
|
||
|
||
VOID
|
||
HalpGrowArray (
|
||
IN PARRAY *CurrentArray,
|
||
IN PARRAY *NewArray
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpQueryInstalledBusInformation (
|
||
OUT PVOID Buffer,
|
||
IN ULONG BufferLength,
|
||
OUT PULONG ReturnedLength
|
||
);
|
||
|
||
ULONG
|
||
HalpNoBusData (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpNoAdjustResourceList (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpNoAssignSlotResources (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN PUNICODE_STRING RegistryPath,
|
||
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
||
IN ULONG SlotNumber,
|
||
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpNoQueryBusSlots (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG SlotNumbers,
|
||
OUT PULONG ReturnedLength
|
||
);
|
||
|
||
PDEVICE_HANDLER_OBJECT
|
||
HalpNoReferenceDeviceHandler (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG SlotNumber
|
||
);
|
||
|
||
ULONG
|
||
HalpNoGetDeviceData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN PDEVICE_HANDLER_OBJECT DeviceHandler,
|
||
IN ULONG DataType,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
ULONG
|
||
HalpNoSetDeviceData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN PDEVICE_HANDLER_OBJECT DeviceHandler,
|
||
IN ULONG DataType,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
BOOLEAN
|
||
HaliTranslateBusAddress(
|
||
IN INTERFACE_TYPE InterfaceType,
|
||
IN ULONG BusNumber,
|
||
IN PHYSICAL_ADDRESS BusAddress,
|
||
IN OUT PULONG AddressSpace,
|
||
OUT PPHYSICAL_ADDRESS TranslatedAddress
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpAssignSlotResources (
|
||
IN PUNICODE_STRING RegistryPath,
|
||
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
||
IN INTERFACE_TYPE BusType,
|
||
IN ULONG BusNumber,
|
||
IN ULONG SlotNumber,
|
||
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
||
);
|
||
|
||
BOOLEAN
|
||
HaliFindBusAddressTranslation(
|
||
IN PHYSICAL_ADDRESS BusAddress,
|
||
IN OUT PULONG AddressSpace,
|
||
OUT PPHYSICAL_ADDRESS TranslatedAddress,
|
||
IN OUT PULONG_PTR Context,
|
||
IN BOOLEAN NextBus
|
||
);
|
||
|
||
#ifdef ALLOC_PRAGMA
|
||
#pragma alloc_text(INIT,HalpInitBusHandler)
|
||
#pragma alloc_text(PAGELK,HaliRegisterBusHandler)
|
||
#pragma alloc_text(PAGELK,HalpAllocateArray)
|
||
#pragma alloc_text(PAGELK,HalpGrowArray)
|
||
#pragma alloc_text(PAGE,HalAdjustResourceList)
|
||
#pragma alloc_text(PAGE,HalAssignSlotResources)
|
||
#pragma alloc_text(PAGE,HalpAssignSlotResources)
|
||
#pragma alloc_text(PAGE,HalGetInterruptVector)
|
||
#pragma alloc_text(PAGE,HalpNoAdjustResourceList)
|
||
#pragma alloc_text(PAGE,HalpNoAssignSlotResources)
|
||
#pragma alloc_text(PAGE,HalpNoQueryBusSlots)
|
||
#pragma alloc_text(PAGE,HalpNoReferenceDeviceHandler)
|
||
//#pragma alloc_text(PAGE,HaliQueryBusSlots)
|
||
#pragma alloc_text(PAGE,HalpQueryInstalledBusInformation)
|
||
|
||
#ifdef _PNP_POWER_
|
||
#pragma alloc_text(PAGELK,HaliSuspendHibernateSystem)
|
||
#endif
|
||
|
||
#endif
|
||
|
||
VOID
|
||
HalpInitBusHandler (
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Initializes global BusHandler data
|
||
|
||
--*/
|
||
{
|
||
//
|
||
// Initialize bus handler spinlock used to synchronize against
|
||
// buses additions while array lookups are done
|
||
//
|
||
|
||
KeInitializeSpinLock (&HalpBusDatabaseSpinLock);
|
||
|
||
//
|
||
// Initialize bus handler synchronzation event used to serialize
|
||
// bus additions from < DPC_LVEL
|
||
//
|
||
|
||
KeInitializeEvent (&HalpBusDatabaseEvent, SynchronizationEvent, TRUE);
|
||
|
||
//
|
||
// Initialize global arrays
|
||
//
|
||
|
||
HalpBusTable = HalpAllocateArray (0);
|
||
HalpConfigTable = HalpAllocateArray (0);
|
||
InitializeListHead (&HalpAllBusHandlers);
|
||
|
||
//
|
||
// Fill in HAL API handlers
|
||
//
|
||
|
||
HalRegisterBusHandler = HaliRegisterBusHandler;
|
||
HalHandlerForBus = HaliHandlerForBus;
|
||
HalHandlerForConfigSpace = HaliHandlerForConfigSpace;
|
||
//HalQueryBusSlots = HaliQueryBusSlots;
|
||
HalReferenceHandlerForBus = HaliReferenceHandlerForBus;
|
||
HalReferenceBusHandler = HaliReferenceBusHandler;
|
||
HalDereferenceBusHandler = HaliDereferenceBusHandler;
|
||
|
||
HALPDISPATCH->HalPciTranslateBusAddress = HaliTranslateBusAddress;
|
||
#if !defined(NO_LEGACY_DRIVERS)
|
||
HALPDISPATCH->HalPciAssignSlotResources = HalpAssignSlotResources;
|
||
#endif // NO_LEGACY_DRIVERS
|
||
|
||
//
|
||
// Supply the "Bus Handler" version of this routine only
|
||
// if this HAL didn't already provide a different version.
|
||
//
|
||
|
||
if (!HALPDISPATCH->HalFindBusAddressTranslation) {
|
||
HALPDISPATCH->HalFindBusAddressTranslation =
|
||
HaliFindBusAddressTranslation;
|
||
}
|
||
}
|
||
|
||
NTSTATUS
|
||
HaliRegisterBusHandler (
|
||
IN INTERFACE_TYPE InterfaceType,
|
||
IN BUS_DATA_TYPE ConfigType,
|
||
IN ULONG BusNumber,
|
||
IN INTERFACE_TYPE ParentBusType,
|
||
IN ULONG ParentBusNumber,
|
||
IN ULONG SizeofBusExtensionData,
|
||
IN PINSTALL_BUS_HANDLER InstallBusHandler,
|
||
OUT PBUS_HANDLER *ReturnedBusHandler
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Adds a BusHandler for InterfaceType,BusNumber and for ConfigType,BusNumber.
|
||
|
||
Bus specific or Configuration space specific APIs are routed to the
|
||
bus or configuration specific handlers added by this routine.
|
||
|
||
Arguments:
|
||
|
||
InterfaceType - Identifies the bus type
|
||
InterfaceTypeUndefined if no interface type for this
|
||
handler.
|
||
|
||
ConfigType - Identifies the configuration space type
|
||
ConfigurationSpaceUndefined if no configuration space
|
||
type for this handler.
|
||
|
||
BusNumber - Identifies the instance of the bus & config space.
|
||
-1 if the next available bus number for this bus
|
||
should be used.
|
||
|
||
ParentBusType - If this bus is a child of a bus, then ParentBusType
|
||
ParentBusNumber and ParentBusNumber identifies that bus.
|
||
ParentBusType is -1 if no parent bus.
|
||
|
||
SizeofBusExetensionData - Sizeof bus specific exentsion data required.
|
||
|
||
InstallBusHandler - Function to call to get the bus specific handlers
|
||
added to the bus handler structure.
|
||
|
||
Return Value:
|
||
|
||
success; otherwise error code of failure.
|
||
|
||
--*/
|
||
{
|
||
PHAL_BUS_HANDLER Bus, *pBusHandler, OldHandler;
|
||
PBUS_HANDLER ParentHandler;
|
||
KIRQL OldIrql;
|
||
NTSTATUS Status;
|
||
PARRAY InterfaceArray, InterfaceBusNumberArray;
|
||
PARRAY ConfigArray, ConfigBusNumberArray;
|
||
PVOID CodeLockHandle;
|
||
|
||
//
|
||
// Must add the handler to at least one table
|
||
//
|
||
|
||
ASSERT (InterfaceType != InterfaceTypeUndefined || ConfigType != ConfigurationSpaceUndefined);
|
||
|
||
Status = STATUS_SUCCESS;
|
||
OldHandler = NULL;
|
||
|
||
//
|
||
// Allocate storage for new bus handler structure
|
||
//
|
||
|
||
Bus = (PHAL_BUS_HANDLER)
|
||
ExAllocatePoolWithTag(
|
||
NonPagedPool,
|
||
sizeof (HAL_BUS_HANDLER) + SizeofBusExtensionData,
|
||
HAL_POOL_TAG
|
||
);
|
||
|
||
if (!Bus) {
|
||
return STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
//
|
||
// Lock pagable code down
|
||
//
|
||
|
||
CodeLockHandle = MmLockPagableCodeSection (&HaliRegisterBusHandler);
|
||
|
||
//
|
||
// Synchronize adding new bus handlers
|
||
//
|
||
|
||
*ReturnedBusHandler = &Bus->Handler;
|
||
|
||
KeWaitForSingleObject (
|
||
&HalpBusDatabaseEvent,
|
||
WrExecutive,
|
||
KernelMode,
|
||
FALSE,
|
||
NULL
|
||
);
|
||
|
||
|
||
//
|
||
// If BusNumber not defined, use next available number for this BusType
|
||
//
|
||
|
||
if (BusNumber == -1) {
|
||
ASSERT (InterfaceType != InterfaceTypeUndefined);
|
||
|
||
BusNumber = 0;
|
||
while (HaliHandlerForBus (InterfaceType, BusNumber)) {
|
||
BusNumber++;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Allocate memory for each array in case any index needs to grow
|
||
//
|
||
|
||
InterfaceArray = HalpAllocateArray (InterfaceType);
|
||
InterfaceBusNumberArray = HalpAllocateArray (BusNumber);
|
||
ConfigArray = HalpAllocateArray (ConfigType);
|
||
ConfigBusNumberArray = HalpAllocateArray (BusNumber);
|
||
|
||
if (!Bus ||
|
||
!InterfaceArray ||
|
||
!InterfaceBusNumberArray ||
|
||
!ConfigArray ||
|
||
!ConfigBusNumberArray) {
|
||
|
||
Status = STATUS_INSUFFICIENT_RESOURCES;
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
//
|
||
// Lookup parent handler (if any)
|
||
//
|
||
|
||
ParentHandler = HaliReferenceHandlerForBus (ParentBusType, ParentBusNumber);
|
||
|
||
//
|
||
// Initialize new bus handlers values
|
||
//
|
||
|
||
RtlZeroMemory (Bus, sizeof (HAL_BUS_HANDLER) + SizeofBusExtensionData);
|
||
|
||
Bus->ReferenceCount = 1;
|
||
|
||
Bus->Handler.BusNumber = BusNumber;
|
||
Bus->Handler.InterfaceType = InterfaceType;
|
||
Bus->Handler.ConfigurationType = ConfigType;
|
||
Bus->Handler.ParentHandler = ParentHandler;
|
||
|
||
//
|
||
// Set to dumby handlers
|
||
//
|
||
|
||
Bus->Handler.GetBusData = HalpNoBusData;
|
||
Bus->Handler.SetBusData = HalpNoBusData;
|
||
Bus->Handler.AdjustResourceList = HalpNoAdjustResourceList;
|
||
Bus->Handler.AssignSlotResources = HalpNoAssignSlotResources;
|
||
|
||
if (SizeofBusExtensionData) {
|
||
Bus->Handler.BusData = Bus + 1;
|
||
}
|
||
|
||
//
|
||
// If bus has a parent, inherit handlers from parent as default
|
||
//
|
||
|
||
if (ParentHandler) {
|
||
Bus->Handler.GetBusData = ParentHandler->GetBusData;
|
||
Bus->Handler.SetBusData = ParentHandler->SetBusData;
|
||
Bus->Handler.AdjustResourceList = ParentHandler->AdjustResourceList;
|
||
Bus->Handler.AssignSlotResources = ParentHandler->AssignSlotResources;
|
||
Bus->Handler.TranslateBusAddress = ParentHandler->TranslateBusAddress;
|
||
Bus->Handler.GetInterruptVector = ParentHandler->GetInterruptVector;
|
||
}
|
||
|
||
//
|
||
// Install bus specific handlers
|
||
//
|
||
|
||
if (InstallBusHandler) {
|
||
Status = InstallBusHandler (&Bus->Handler);
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
//
|
||
// Might change addresses of some arrays synchronize
|
||
// with routing handlers
|
||
//
|
||
|
||
LockBusDatabase (&OldIrql);
|
||
|
||
//
|
||
// Grow HalpBusTable if needed
|
||
//
|
||
|
||
HalpGrowArray (&HalpBusTable, &InterfaceArray);
|
||
|
||
if (InterfaceType != InterfaceTypeUndefined) {
|
||
|
||
//
|
||
// Grow HalpBusTable if needed
|
||
//
|
||
|
||
HalpGrowArray (
|
||
(PARRAY *) &HalpBusTable->Element[InterfaceType],
|
||
&InterfaceBusNumberArray
|
||
);
|
||
|
||
|
||
//
|
||
// Get registered handler for InterfaceType,BusNumber
|
||
//
|
||
|
||
pBusHandler = &((PHAL_BUS_HANDLER)
|
||
((PARRAY) HalpBusTable->Element[InterfaceType])->Element[BusNumber]);
|
||
|
||
//
|
||
// If handler already defiend, remove the old one
|
||
//
|
||
|
||
if (*pBusHandler) {
|
||
OldHandler = *pBusHandler;
|
||
}
|
||
|
||
//
|
||
// Set new handler for supplied InterfaceType,BusNumber
|
||
//
|
||
|
||
*pBusHandler = Bus;
|
||
}
|
||
|
||
//
|
||
// Grow HalpConfigTable if needed
|
||
//
|
||
|
||
HalpGrowArray (&HalpConfigTable, &ConfigArray);
|
||
|
||
if (ConfigType != ConfigurationSpaceUndefined) {
|
||
|
||
//
|
||
// Grow HalpConfigTable if needed
|
||
//
|
||
|
||
HalpGrowArray (
|
||
(PARRAY *) &HalpConfigTable->Element[ConfigType],
|
||
&ConfigBusNumberArray
|
||
);
|
||
|
||
//
|
||
// Get registered handler for ConfigType,BusNumber
|
||
//
|
||
|
||
pBusHandler = &((PHAL_BUS_HANDLER)
|
||
((PARRAY) HalpConfigTable->Element[ConfigType])->Element[BusNumber]);
|
||
|
||
if (*pBusHandler) {
|
||
ASSERT (OldHandler == NULL || OldHandler == *pBusHandler);
|
||
OldHandler = *pBusHandler;
|
||
}
|
||
|
||
//
|
||
// Set new handler for supplied ConfigType,BusNumber
|
||
//
|
||
|
||
*pBusHandler = Bus;
|
||
}
|
||
|
||
//
|
||
// Add new bus handler to list of all installed handlers
|
||
//
|
||
|
||
InsertTailList (&HalpAllBusHandlers, &Bus->AllHandlers);
|
||
|
||
//
|
||
// Remove old bus handler
|
||
//
|
||
|
||
Bus = OldHandler;
|
||
if (Bus) {
|
||
RemoveEntryList (&Bus->AllHandlers);
|
||
}
|
||
|
||
//
|
||
// Lookup array modification complete, release lock
|
||
//
|
||
|
||
UnlockBusDatabase (OldIrql);
|
||
} else {
|
||
if (ParentHandler) {
|
||
HaliDereferenceBusHandler (ParentHandler);
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Bus addition modifications complete, set event
|
||
//
|
||
|
||
KeSetEvent (&HalpBusDatabaseEvent, 0, FALSE);
|
||
|
||
//
|
||
// Unlock pagable code
|
||
//
|
||
|
||
MmUnlockPagableImageSection (CodeLockHandle);
|
||
|
||
//
|
||
// Free memory which is not in use
|
||
//
|
||
|
||
if (Bus) {
|
||
ExFreePool (Bus);
|
||
}
|
||
|
||
if (InterfaceArray) {
|
||
ExFreePool (InterfaceArray);
|
||
}
|
||
|
||
if (InterfaceBusNumberArray) {
|
||
ExFreePool (InterfaceBusNumberArray);
|
||
}
|
||
|
||
if (ConfigArray) {
|
||
ExFreePool (ConfigArray);
|
||
}
|
||
|
||
if (ConfigBusNumberArray) {
|
||
ExFreePool (ConfigBusNumberArray);
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
PARRAY
|
||
HalpAllocateArray (
|
||
IN ULONG ArraySize
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Allocate an array of size ArraySize.
|
||
|
||
Arguments:
|
||
|
||
ArraySize - Size of array in elements
|
||
|
||
Return Value:
|
||
|
||
pointer to ARRAY
|
||
|
||
--*/
|
||
{
|
||
PARRAY Array;
|
||
|
||
if (ArraySize == -1) {
|
||
ArraySize = 0;
|
||
}
|
||
|
||
Array = ExAllocatePoolWithTag (
|
||
NonPagedPool,
|
||
ARRAY_SIZE_IN_BYTES(ArraySize),
|
||
HAL_POOL_TAG
|
||
);
|
||
if (!Array) {
|
||
|
||
//
|
||
// This allocation was critical.
|
||
//
|
||
|
||
KeBugCheckEx(HAL_MEMORY_ALLOCATION,
|
||
ARRAY_SIZE_IN_BYTES(ArraySize),
|
||
0,
|
||
(ULONG_PTR)__FILE__,
|
||
__LINE__
|
||
);
|
||
}
|
||
|
||
//
|
||
// Initialize array
|
||
//
|
||
|
||
Array->ArraySize = ArraySize;
|
||
RtlZeroMemory (Array->Element, sizeof(PVOID) * (ArraySize+1));
|
||
return Array;
|
||
}
|
||
|
||
VOID
|
||
HalpGrowArray (
|
||
IN PARRAY *CurrentArray,
|
||
IN PARRAY *NewArray
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
If NewArray is larger then CurrentArray, then the CurrentArray
|
||
is grown to the sizeof NewArray by swapping the pointers and
|
||
moving the arrays contents.
|
||
|
||
Arguments:
|
||
|
||
CurrentArray - Address of the current array pointer
|
||
NewArray - Address of the new array pointer
|
||
|
||
--*/
|
||
{
|
||
PVOID Tmp;
|
||
|
||
if (!*CurrentArray || (*NewArray)->ArraySize > (*CurrentArray)->ArraySize) {
|
||
|
||
//
|
||
// Copy current array ontop of new array
|
||
//
|
||
|
||
if (*CurrentArray) {
|
||
RtlCopyMemory (&(*NewArray)->Element,
|
||
&(*CurrentArray)->Element,
|
||
sizeof(PVOID) * ((*CurrentArray)->ArraySize + 1)
|
||
);
|
||
}
|
||
|
||
|
||
//
|
||
// swap current with new such that the new array is the current
|
||
// one, and the old memory will be freed back to pool
|
||
//
|
||
|
||
Tmp = *CurrentArray;
|
||
*CurrentArray = *NewArray;
|
||
*NewArray = Tmp;
|
||
}
|
||
}
|
||
|
||
PBUS_HANDLER
|
||
FASTCALL
|
||
HalpLookupHandler (
|
||
IN PARRAY Array,
|
||
IN ULONG Type,
|
||
IN ULONG Number,
|
||
IN BOOLEAN AddReference
|
||
)
|
||
{
|
||
PHAL_BUS_HANDLER Bus;
|
||
PBUS_HANDLER Handler;
|
||
KIRQL OldIrql;
|
||
|
||
LockBusDatabase (&OldIrql);
|
||
|
||
//
|
||
// Index by type
|
||
//
|
||
|
||
Handler = NULL;
|
||
if (Array->ArraySize >= Type) {
|
||
Array = (PARRAY) Array->Element[Type];
|
||
|
||
//
|
||
// Index by instance numberr
|
||
//
|
||
|
||
if (Array && Array->ArraySize >= Number) {
|
||
Bus = (PHAL_BUS_HANDLER) Array->Element[Number];
|
||
Handler = &Bus->Handler;
|
||
|
||
if (AddReference) {
|
||
Bus->ReferenceCount += 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
UnlockBusDatabase (OldIrql);
|
||
return Handler;
|
||
}
|
||
|
||
VOID
|
||
FASTCALL
|
||
HaliReferenceBusHandler (
|
||
IN PBUS_HANDLER Handler
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
--*/
|
||
{
|
||
KIRQL OldIrql;
|
||
PHAL_BUS_HANDLER Bus;
|
||
|
||
|
||
LockBusDatabase (&OldIrql);
|
||
|
||
Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
|
||
Bus->ReferenceCount += 1;
|
||
|
||
UnlockBusDatabase (OldIrql);
|
||
}
|
||
|
||
VOID
|
||
FASTCALL
|
||
HaliDereferenceBusHandler (
|
||
IN PBUS_HANDLER Handler
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
|
||
--*/
|
||
{
|
||
KIRQL OldIrql;
|
||
PHAL_BUS_HANDLER Bus;
|
||
|
||
|
||
LockBusDatabase (&OldIrql);
|
||
|
||
Bus = CONTAINING_RECORD(Handler, HAL_BUS_HANDLER, Handler);
|
||
Bus->ReferenceCount -= 1;
|
||
|
||
UnlockBusDatabase (OldIrql);
|
||
|
||
// for now totally removing a bus is not supported
|
||
ASSERT (Bus->ReferenceCount != 0);
|
||
}
|
||
|
||
|
||
PBUS_HANDLER
|
||
FASTCALL
|
||
HaliHandlerForBus (
|
||
IN INTERFACE_TYPE InterfaceType,
|
||
IN ULONG BusNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the BusHandler structure InterfaceType,BusNumber
|
||
or NULL if no such handler exists.
|
||
|
||
--*/
|
||
{
|
||
return HalpLookupHandler (HalpBusTable, (ULONG) InterfaceType, BusNumber, FALSE);
|
||
}
|
||
|
||
PBUS_HANDLER
|
||
FASTCALL
|
||
HaliHandlerForConfigSpace (
|
||
IN BUS_DATA_TYPE ConfigType,
|
||
IN ULONG BusNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the BusHandler structure ConfigType,BusNumber
|
||
or NULL if no such handler exists.
|
||
|
||
--*/
|
||
{
|
||
return HalpLookupHandler (HalpConfigTable, (ULONG) ConfigType, BusNumber, FALSE);
|
||
}
|
||
|
||
|
||
PBUS_HANDLER
|
||
FASTCALL
|
||
HaliReferenceHandlerForBus (
|
||
IN INTERFACE_TYPE InterfaceType,
|
||
IN ULONG BusNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the BusHandler structure InterfaceType,BusNumber
|
||
or NULL if no such handler exists.
|
||
|
||
--*/
|
||
{
|
||
return HalpLookupHandler (HalpBusTable, (ULONG) InterfaceType, BusNumber, TRUE);
|
||
}
|
||
|
||
PBUS_HANDLER
|
||
FASTCALL
|
||
HaliReferenceHandlerForConfigSpace (
|
||
IN BUS_DATA_TYPE ConfigType,
|
||
IN ULONG BusNumber
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns the BusHandler structure ConfigType,BusNumber
|
||
or NULL if no such handler exists.
|
||
|
||
--*/
|
||
{
|
||
return HalpLookupHandler (HalpConfigTable, (ULONG) ConfigType, BusNumber, TRUE);
|
||
}
|
||
|
||
NTSTATUS
|
||
HalpQueryInstalledBusInformation (
|
||
OUT PVOID Buffer,
|
||
IN ULONG BufferLength,
|
||
OUT PULONG ReturnedLength
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Returns an array HAL_BUS_INFORMATION, one for each
|
||
bus handler installed.
|
||
|
||
Arguments:
|
||
|
||
Buffer - output buffer
|
||
BufferLength - length of buffer on input
|
||
ReturnedLength - The length of data returned
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS
|
||
STATUS_BUFFER_TOO_SMALL - The ReturnedLength contains the buffersize
|
||
currently needed.
|
||
|
||
--*/
|
||
{
|
||
PHAL_BUS_INFORMATION Info;
|
||
PHAL_BUS_HANDLER Handler;
|
||
ULONG i, j;
|
||
ULONG Length;
|
||
NTSTATUS Status;
|
||
PARRAY Array;
|
||
|
||
PAGED_CODE ();
|
||
|
||
//
|
||
// Synchronize adding new bus handlers
|
||
//
|
||
|
||
KeWaitForSingleObject (
|
||
&HalpBusDatabaseEvent,
|
||
WrExecutive,
|
||
KernelMode,
|
||
FALSE,
|
||
NULL
|
||
);
|
||
|
||
//
|
||
// Determine sizeof return buffer
|
||
//
|
||
|
||
Length = 0;
|
||
for (i=0; i <= HalpBusTable->ArraySize; i++) {
|
||
Array = (PARRAY) HalpBusTable->Element[i];
|
||
if (Array) {
|
||
Length += sizeof (HAL_BUS_INFORMATION) *
|
||
(Array->ArraySize + 1);
|
||
}
|
||
}
|
||
|
||
//
|
||
// Return size of buffer returning, or size of buffer needed
|
||
//
|
||
|
||
*ReturnedLength = Length;
|
||
|
||
//
|
||
// Fill in the return buffer
|
||
//
|
||
|
||
if (Length <= BufferLength) {
|
||
|
||
Info = (PHAL_BUS_INFORMATION) Buffer;
|
||
|
||
for (i=0; i <= HalpBusTable->ArraySize; i++) {
|
||
Array = (PARRAY) HalpBusTable->Element[i];
|
||
if (Array) {
|
||
for (j=0; j <= Array->ArraySize; j++) {
|
||
Handler = (PHAL_BUS_HANDLER) Array->Element[j];
|
||
|
||
if (Handler) {
|
||
Info->BusType = Handler->Handler.InterfaceType;
|
||
Info->ConfigurationType = Handler->Handler.ConfigurationType;
|
||
Info->BusNumber = Handler->Handler.BusNumber;
|
||
Info->Reserved = 0;
|
||
Info += 1;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
Status = STATUS_SUCCESS;
|
||
|
||
} else {
|
||
|
||
//
|
||
// Return buffer too small
|
||
//
|
||
|
||
Status = STATUS_BUFFER_TOO_SMALL;
|
||
}
|
||
|
||
KeSetEvent (&HalpBusDatabaseEvent, 0, FALSE);
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Default dispatchers to BusHandlers
|
||
//
|
||
|
||
ULONG
|
||
HalGetBusData(
|
||
IN BUS_DATA_TYPE BusDataType,
|
||
IN ULONG BusNumber,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
return HalGetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
|
||
}
|
||
|
||
ULONG
|
||
HalGetBusDataByOffset (
|
||
IN BUS_DATA_TYPE BusDataType,
|
||
IN ULONG BusNumber,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dispatcher for GetBusData
|
||
|
||
--*/
|
||
{
|
||
PBUS_HANDLER Handler;
|
||
NTSTATUS Status;
|
||
|
||
Handler = HaliReferenceHandlerForConfigSpace (BusDataType, BusNumber);
|
||
if (!Handler) {
|
||
return 0;
|
||
}
|
||
|
||
Status = Handler->GetBusData (Handler, Handler, SlotNumber, Buffer, Offset, Length);
|
||
HaliDereferenceBusHandler (Handler);
|
||
return Status;
|
||
}
|
||
|
||
ULONG
|
||
HalSetBusData(
|
||
IN BUS_DATA_TYPE BusDataType,
|
||
IN ULONG BusNumber,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
return HalSetBusDataByOffset (BusDataType,BusNumber,SlotNumber,Buffer,0,Length);
|
||
}
|
||
|
||
ULONG
|
||
HalSetBusDataByOffset(
|
||
IN BUS_DATA_TYPE BusDataType,
|
||
IN ULONG BusNumber,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dispatcher for SetBusData
|
||
|
||
--*/
|
||
{
|
||
PBUS_HANDLER Handler;
|
||
NTSTATUS Status;
|
||
|
||
Handler = HaliReferenceHandlerForConfigSpace (BusDataType, BusNumber);
|
||
if (!Handler) {
|
||
return 0;
|
||
}
|
||
|
||
Status = Handler->SetBusData (Handler, Handler, SlotNumber, Buffer, Offset, Length);
|
||
HaliDereferenceBusHandler (Handler);
|
||
return Status;
|
||
}
|
||
|
||
#if !defined(NO_LEGACY_DRIVERS)
|
||
|
||
NTSTATUS
|
||
HalAdjustResourceList (
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dispatcher for AdjustResourceList
|
||
|
||
--*/
|
||
{
|
||
PBUS_HANDLER Handler;
|
||
NTSTATUS Status;
|
||
|
||
PAGED_CODE ();
|
||
Handler = HaliReferenceHandlerForBus (
|
||
(*pResourceList)->InterfaceType,
|
||
(*pResourceList)->BusNumber
|
||
);
|
||
if (!Handler) {
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
Status = Handler->AdjustResourceList (Handler, Handler, pResourceList);
|
||
HaliDereferenceBusHandler (Handler);
|
||
return Status;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
HalAssignSlotResources (
|
||
IN PUNICODE_STRING RegistryPath,
|
||
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
||
IN INTERFACE_TYPE BusType,
|
||
IN ULONG BusNumber,
|
||
IN ULONG SlotNumber,
|
||
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
||
)
|
||
{
|
||
PAGED_CODE ();
|
||
if (BusType == PCIBus) {
|
||
//
|
||
// Call through the HAL private dispatch table
|
||
// for PCI-related translations. This is part
|
||
// of transitioning the HAL out of the bus
|
||
// management business.
|
||
//
|
||
return HALPDISPATCH->HalPciAssignSlotResources(RegistryPath,
|
||
DriverClassName,
|
||
DriverObject,
|
||
DeviceObject,
|
||
BusType,
|
||
BusNumber,
|
||
SlotNumber,
|
||
AllocatedResources);
|
||
} else {
|
||
|
||
return HalpAssignSlotResources(RegistryPath,
|
||
DriverClassName,
|
||
DriverObject,
|
||
DeviceObject,
|
||
BusType,
|
||
BusNumber,
|
||
SlotNumber,
|
||
AllocatedResources);
|
||
}
|
||
}
|
||
|
||
NTSTATUS
|
||
HalpAssignSlotResources (
|
||
IN PUNICODE_STRING RegistryPath,
|
||
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
||
IN INTERFACE_TYPE BusType,
|
||
IN ULONG BusNumber,
|
||
IN ULONG SlotNumber,
|
||
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dispatcher for AssignSlotResources
|
||
|
||
--*/
|
||
{
|
||
PBUS_HANDLER Handler;
|
||
NTSTATUS Status;
|
||
|
||
PAGED_CODE ();
|
||
Handler = HaliReferenceHandlerForBus (BusType, BusNumber);
|
||
if (!Handler) {
|
||
return STATUS_NOT_FOUND;
|
||
}
|
||
|
||
Status = Handler->AssignSlotResources (
|
||
Handler,
|
||
Handler,
|
||
RegistryPath,
|
||
DriverClassName,
|
||
DriverObject,
|
||
DeviceObject,
|
||
SlotNumber,
|
||
AllocatedResources
|
||
);
|
||
|
||
HaliDereferenceBusHandler (Handler);
|
||
return Status;
|
||
}
|
||
|
||
|
||
ULONG
|
||
HalGetInterruptVector(
|
||
IN INTERFACE_TYPE InterfaceType,
|
||
IN ULONG BusNumber,
|
||
IN ULONG BusInterruptLevel,
|
||
IN ULONG BusInterruptVector,
|
||
OUT PKIRQL Irql,
|
||
OUT PKAFFINITY Affinity
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dispatcher for GetInterruptVector
|
||
|
||
--*/
|
||
{
|
||
PBUS_HANDLER Handler;
|
||
ULONG Vector;
|
||
|
||
PAGED_CODE ();
|
||
Handler = HaliReferenceHandlerForBus (InterfaceType, BusNumber);
|
||
*Irql = 0;
|
||
*Affinity = 0;
|
||
|
||
if (!Handler) {
|
||
return 0;
|
||
}
|
||
|
||
Vector = Handler->GetInterruptVector (Handler, Handler,
|
||
BusInterruptLevel, BusInterruptVector, Irql, Affinity);
|
||
|
||
HaliDereferenceBusHandler (Handler);
|
||
return Vector;
|
||
}
|
||
#endif // NO_LEGACY_DRIVERS
|
||
|
||
|
||
BOOLEAN
|
||
HalTranslateBusAddress(
|
||
IN INTERFACE_TYPE InterfaceType,
|
||
IN ULONG BusNumber,
|
||
IN PHYSICAL_ADDRESS BusAddress,
|
||
IN OUT PULONG AddressSpace,
|
||
OUT PPHYSICAL_ADDRESS TranslatedAddress
|
||
)
|
||
{
|
||
if (InterfaceType == PCIBus) {
|
||
//
|
||
// Call through the HAL private dispatch table
|
||
// for PCI-related translations. This is part
|
||
// of transitioning the HAL out of the bus
|
||
// management business.
|
||
//
|
||
return HALPDISPATCH->HalPciTranslateBusAddress(InterfaceType,
|
||
BusNumber,
|
||
BusAddress,
|
||
AddressSpace,
|
||
TranslatedAddress);
|
||
} else {
|
||
return HaliTranslateBusAddress(InterfaceType,
|
||
BusNumber,
|
||
BusAddress,
|
||
AddressSpace,
|
||
TranslatedAddress);
|
||
}
|
||
}
|
||
|
||
BOOLEAN
|
||
HaliTranslateBusAddress(
|
||
IN INTERFACE_TYPE InterfaceType,
|
||
IN ULONG BusNumber,
|
||
IN PHYSICAL_ADDRESS BusAddress,
|
||
IN OUT PULONG AddressSpace,
|
||
OUT PPHYSICAL_ADDRESS TranslatedAddress
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Dispatcher for TranslateBusAddress
|
||
|
||
--*/
|
||
{
|
||
PBUS_HANDLER Handler;
|
||
BOOLEAN Status;
|
||
|
||
Handler = HaliReferenceHandlerForBus (InterfaceType, BusNumber);
|
||
if (!Handler || !Handler->TranslateBusAddress) {
|
||
return FALSE;
|
||
}
|
||
|
||
Status = Handler->TranslateBusAddress (Handler, Handler,
|
||
BusAddress, AddressSpace, TranslatedAddress);
|
||
|
||
HaliDereferenceBusHandler (Handler);
|
||
return Status;
|
||
}
|
||
|
||
//
|
||
// Null handlers
|
||
//
|
||
|
||
ULONG HalpNoBusData (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Stub handler for buses which do not have a configuration space
|
||
|
||
--*/
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
NTSTATUS
|
||
HalpNoAdjustResourceList (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Stub handler for buses which do not have a configuration space
|
||
|
||
--*/
|
||
{
|
||
PAGED_CODE ();
|
||
return STATUS_UNSUCCESSFUL;
|
||
}
|
||
|
||
|
||
NTSTATUS
|
||
HalpNoAssignSlotResources (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN PUNICODE_STRING RegistryPath,
|
||
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
||
IN ULONG SlotNumber,
|
||
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Stub handler for buses which do not have a configuration space
|
||
|
||
--*/
|
||
{
|
||
PAGED_CODE ();
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
NTSTATUS
|
||
HalpNoQueryBusSlots (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG SlotNumbers,
|
||
OUT PULONG ReturnedLength
|
||
)
|
||
{
|
||
PAGED_CODE ();
|
||
return STATUS_NOT_SUPPORTED;
|
||
}
|
||
|
||
PDEVICE_HANDLER_OBJECT
|
||
HalpNoReferenceDeviceHandler (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN ULONG SlotNumber
|
||
)
|
||
{
|
||
PAGED_CODE ();
|
||
return NULL;
|
||
}
|
||
|
||
ULONG
|
||
HalpNoGetDeviceData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN PDEVICE_HANDLER_OBJECT DeviceHandler,
|
||
IN ULONG DataType,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
ULONG
|
||
HalpNoSetDeviceData (
|
||
IN PBUS_HANDLER BusHandler,
|
||
IN PBUS_HANDLER RootHandler,
|
||
IN PDEVICE_HANDLER_OBJECT DeviceHandler,
|
||
IN ULONG DataType,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
)
|
||
{
|
||
return 0;
|
||
}
|
||
|
||
PBUS_HANDLER
|
||
HalpContextToBusHandler(
|
||
IN ULONG_PTR Context
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Convert a context into a pointer to a bus handler. Not really
|
||
a big deal as the context IS a pointer to a bus handler,... or
|
||
possibly null in which case we want the first bus handler.
|
||
|
||
For the sake of paranoia, we run down the list of bus handlers
|
||
to find a match for the incoming context. This is because context
|
||
is supplied by something outside the HAL.
|
||
|
||
Arguments:
|
||
|
||
Context ULONG_PTR either NULL or a value from which
|
||
a pointer to a bus handler can be derived.
|
||
|
||
Return Value:
|
||
|
||
Pointer to a bus handler or NULL if the incoming context was not
|
||
valid.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY OldHalBusHandler;
|
||
PLIST_ENTRY NewHalBusHandler;
|
||
|
||
NewHalBusHandler = HalpAllBusHandlers.Flink;
|
||
|
||
if (Context) {
|
||
|
||
//
|
||
// Caller supplied a handler, convert to a HAL_BUS_HANDLER.
|
||
//
|
||
|
||
OldHalBusHandler = &CONTAINING_RECORD((PBUS_HANDLER)Context,
|
||
HAL_BUS_HANDLER,
|
||
Handler)->AllHandlers;
|
||
|
||
while (NewHalBusHandler != &HalpAllBusHandlers) {
|
||
|
||
if (NewHalBusHandler == OldHalBusHandler) {
|
||
|
||
//
|
||
// Match.
|
||
//
|
||
|
||
break;
|
||
}
|
||
NewHalBusHandler = NewHalBusHandler->Flink;
|
||
}
|
||
}
|
||
|
||
if (NewHalBusHandler == &HalpAllBusHandlers) {
|
||
|
||
//
|
||
// If at end of list, either the incoming value wasn't
|
||
// on the list or this list is empty.
|
||
//
|
||
|
||
#if DBG
|
||
|
||
DbgPrint("HAL: HalpContextToBusHandler, invalid context.\n");
|
||
|
||
#endif
|
||
|
||
return NULL;
|
||
}
|
||
|
||
return &CONTAINING_RECORD(NewHalBusHandler,
|
||
HAL_BUS_HANDLER,
|
||
AllHandlers)->Handler;
|
||
|
||
}
|
||
#if 0 // PLJ
|
||
PBUS_HANDLER
|
||
HalpGetNextBusHandler(
|
||
IN PBUS_HANDLER Previous
|
||
)
|
||
{
|
||
PLIST_ENTRY OldHalBusHandler;
|
||
PLIST_ENTRY NewHalBusHandler;
|
||
PBUS_HANDLER Next;
|
||
|
||
NewHalBusHandler = HalpAllBusHandlers.Flink;
|
||
|
||
if (Previous != NULL) {
|
||
|
||
//
|
||
// Caller supplied a handler, convert to a HAL_BUS_HANDLER.
|
||
//
|
||
|
||
OldHalBusHandler = &CONTAINING_RECORD(Previous,
|
||
HAL_BUS_HANDLER,
|
||
Handler)->AllHandlers;
|
||
|
||
//
|
||
// Paranoia (should probably be DBG only but there isn't
|
||
// that many handlers and we don't do this all that often.
|
||
//
|
||
|
||
{
|
||
PLIST_ENTRY ThisIteration = NULL;
|
||
|
||
while (NewHalBusHandler != &HalpAllBusHandlers) {
|
||
|
||
ThisIteration = NewHalBusHandler;
|
||
NewHalBusHandler = NewHalBusHandler->Flink;
|
||
|
||
if (ThisIteration == OldHalBusHandler) {
|
||
|
||
//
|
||
// Match.
|
||
//
|
||
|
||
break;
|
||
}
|
||
}
|
||
|
||
//
|
||
// If at end of list, either the incoming value wasn't
|
||
// on the list it was the last thing on the list, either
|
||
// way, there is no next entry.
|
||
//
|
||
|
||
#if DBG
|
||
|
||
if (ThisIteration != OldHalBusHandler) {
|
||
DbgPrint("HAL: HalpGetNextBusHandler, previous handler invalid.\n");
|
||
}
|
||
|
||
#endif
|
||
|
||
}
|
||
}
|
||
|
||
if (NewHalBusHandler == &HalpAllBusHandlers) {
|
||
return NULL;
|
||
}
|
||
|
||
return &CONTAINING_RECORD(NewHalBusHandler,
|
||
HAL_BUS_HANDLER,
|
||
AllHandlers)->Handler;
|
||
}
|
||
#endif
|
||
|
||
BOOLEAN
|
||
HaliFindBusAddressTranslation(
|
||
IN PHYSICAL_ADDRESS BusAddress,
|
||
IN OUT PULONG AddressSpace,
|
||
OUT PPHYSICAL_ADDRESS TranslatedAddress,
|
||
IN OUT PULONG_PTR Context,
|
||
IN BOOLEAN NextBus
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs a very similar function to HalTranslateBusAddress
|
||
except that InterfaceType and BusNumber are not known by the caller.
|
||
This function will walk all busses known by the HAL looking for a
|
||
valid translation for the input BusAddress of type AddressSpace.
|
||
|
||
This function is recallable using the input/output Context parameter.
|
||
On the first call to this routine for a given translation the ULONG_PTR
|
||
Context should be NULL. Note: Not the address of it but the contents.
|
||
|
||
If the caller decides the returned translation is not the desired
|
||
translation, it calls this routine again passing Context in as it
|
||
was returned on the previous call. This allows this routine to
|
||
traverse the bus structures until the correct translation is found
|
||
and is provided because on multiple bus systems, it is possible for
|
||
the same resource to exist in the independent address spaces of
|
||
multiple busses.
|
||
|
||
Note: This routine is not called directly, it is called through
|
||
the HALPDISPATCH table. If a HAL implements a simpler version of
|
||
this function (eg generic PC/AT boxes don't actually need translation,
|
||
those HALs substitute their own version of this routine. This
|
||
routine is not otherwise exported from the HAL.
|
||
|
||
Arguments:
|
||
|
||
BusAddress Address to be translated.
|
||
AddressSpace 0 = Memory
|
||
1 = IO (There are other possibilities).
|
||
N.B. This argument is a pointer, the value
|
||
will be modified if the translated address
|
||
is of a different address space type from
|
||
the untranslated bus address.
|
||
TranslatedAddress Pointer to where the translated address
|
||
should be stored.
|
||
Context Pointer to a ULONG_PTR. On the initial call,
|
||
for a given BusAddress, it should contain
|
||
0. It will be modified by this routine,
|
||
on subsequent calls for the same BusAddress
|
||
the value should be handed in again,
|
||
unmodified by the caller.
|
||
NextBus FALSE if we should attempt this translation
|
||
on the same bus as indicated by Context,
|
||
TRUE if we should be looking for another
|
||
bus.
|
||
|
||
Return Value:
|
||
|
||
TRUE if translation was successful,
|
||
FALSE otherwise.
|
||
|
||
--*/
|
||
|
||
{
|
||
PLIST_ENTRY HalBusHandler;
|
||
PBUS_HANDLER Handler;
|
||
|
||
//
|
||
// First, make sure the context parameter was supplied. (paranoia).
|
||
//
|
||
|
||
if (!Context) {
|
||
ASSERT(Context);
|
||
return FALSE;
|
||
}
|
||
|
||
ASSERT(*Context || (NextBus == TRUE));
|
||
|
||
//
|
||
// Note: The Context is really a PBUS_HANDLER, but,
|
||
// HalpContextToBusHandler is paranoid. If the incoming
|
||
// Context isn't what we expect, we won't use it as a
|
||
// pointer.
|
||
//
|
||
|
||
Handler = HalpContextToBusHandler(*Context);
|
||
|
||
if (!Handler) {
|
||
ASSERT(Handler);
|
||
return FALSE;
|
||
}
|
||
|
||
if (NextBus == FALSE) {
|
||
|
||
//
|
||
// Attempt translation on THIS bus (and ONLY this bus).
|
||
//
|
||
|
||
ASSERT(Handler == (PBUS_HANDLER)*Context);
|
||
|
||
if (HalTranslateBusAddress(
|
||
Handler->InterfaceType,
|
||
Handler->BusNumber,
|
||
BusAddress,
|
||
AddressSpace,
|
||
TranslatedAddress)) {
|
||
*Context = (ULONG_PTR)Handler;
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
HalBusHandler = &CONTAINING_RECORD(Handler,
|
||
HAL_BUS_HANDLER,
|
||
Handler)->AllHandlers;
|
||
//
|
||
// Handler is either the bus that came in in Context or the
|
||
// first bus if *Context was null. If *Context wasn't NULL,
|
||
// we want the next bus.
|
||
//
|
||
|
||
if (*Context) {
|
||
HalBusHandler = HalBusHandler->Flink;
|
||
}
|
||
|
||
//
|
||
// Examine each remaining bus looking for one that will translate
|
||
// this address.
|
||
//
|
||
|
||
while (HalBusHandler != &HalpAllBusHandlers) {
|
||
|
||
//
|
||
// This is gross, having gone to all the trouble to find
|
||
// the handler, it seems a pity to break it out into parameters
|
||
// used to search for this handler.
|
||
//
|
||
// Use HalTranslateAddress to find out if this translation
|
||
// works on this handler.
|
||
//
|
||
|
||
Handler = &CONTAINING_RECORD(HalBusHandler,
|
||
HAL_BUS_HANDLER,
|
||
AllHandlers)->Handler;
|
||
|
||
if (HalTranslateBusAddress(
|
||
Handler->InterfaceType,
|
||
Handler->BusNumber,
|
||
BusAddress,
|
||
AddressSpace,
|
||
TranslatedAddress)) {
|
||
*Context = (ULONG_PTR)Handler;
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// Try next handler.
|
||
//
|
||
|
||
HalBusHandler = HalBusHandler->Flink;
|
||
}
|
||
|
||
//
|
||
// Didn't find another handler this translation works with. Set
|
||
// the Context such that we don't do the scan again (unless the
|
||
// caller resets it) and indicate failure.
|
||
//
|
||
|
||
*Context = 1;
|
||
return FALSE;
|
||
}
|