mirror of https://github.com/tongzx/nt5src
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.
1755 lines
42 KiB
1755 lines
42 KiB
/*++
|
|
|
|
|
|
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;
|
|
}
|