|
|
/*++
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 );
NTSTATUS HalpNoDeviceControl ( IN PHAL_DEVICE_CONTROL_CONTEXT Context );
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 );
//
// Prototypes for DeviceControls
//
typedef struct _SYNCHRONOUS_REQUEST { NTSTATUS Status; KEVENT Event; } SYNCHRONOUS_REQUEST, *PSYNCHRONOUS_REQUEST;
#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,HalGetInterruptVector)
#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; HalDeviceControl = HaliDeviceControl; HalCompleteDeviceControl = HaliCompleteDeviceControl; HalReferenceHandlerForBus = HaliReferenceHandlerForBus; HalReferenceBusHandler = HaliReferenceBusHandler; HalDereferenceBusHandler = HaliDereferenceBusHandler; }
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, 'HsuB' );
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; Bus->Handler.QueryBusSlots = HalpNoQueryBusSlots; Bus->Handler.ReferenceDeviceHandler = HalpNoReferenceDeviceHandler; Bus->Handler.DeviceControl = HalpNoDeviceControl; Bus->Handler.GetDeviceData = HalpNoGetDeviceData; Bus->Handler.SetDeviceData = HalpNoSetDeviceData;
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; Bus->Handler.QueryBusSlots = ParentHandler->QueryBusSlots; Bus->Handler.ReferenceDeviceHandler = ParentHandler->ReferenceDeviceHandler; Bus->Handler.DeviceControl = ParentHandler->DeviceControl; Bus->Handler.GetDeviceData = ParentHandler->GetDeviceData; Bus->Handler.SetDeviceData = ParentHandler->SetDeviceData; }
//
// 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); }
#ifdef _PNP_POWER_
//
// A bus was added to the system, notify the BusInsertionCheck callback
// of this bus
//
if (NT_SUCCESS(Status) && InterfaceType != InterfaceTypeUndefined) { ExNotifyCallback ( HalCallback.BusCheck, (PVOID) InterfaceType, (PVOID) BusNumber ); } #endif
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), 'HsuB' );
//
// 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);
// BUGBUG: 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; }
NTSTATUS HalAdjustResourceList ( IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList ) /*++
Routine Description:
Dispatcher for AdjustResourceList
--*/ { PBUS_HANDLER Handler; NTSTATUS Status;
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 ) /*++
Routine Description:
Dispatcher for AssignSlotResources
--*/ { PBUS_HANDLER Handler; NTSTATUS Status;
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;
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; }
BOOLEAN HalTranslateBusAddress( 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) { return FALSE; }
Status = Handler->TranslateBusAddress (Handler, Handler, BusAddress, AddressSpace, TranslatedAddress);
HaliDereferenceBusHandler (Handler); return Status; }
NTSTATUS HaliQueryBusSlots ( IN PBUS_HANDLER BusHandler, IN ULONG BufferSize, OUT PULONG SlotNumbers, OUT PULONG ReturnedLength ) /*++
Routine Description:
Dispatcher for QueryBusSlots
--*/ { PAGED_CODE();
return BusHandler->QueryBusSlots (BusHandler, BusHandler, BufferSize, SlotNumbers, ReturnedLength); }
NTSTATUS HaliDeviceControl ( IN PDEVICE_HANDLER_OBJECT DeviceHandler, IN PDEVICE_OBJECT DeviceObject, IN ULONG ControlCode, IN OUT PVOID Buffer OPTIONAL, IN OUT PULONG BufferLength OPTIONAL, IN PVOID CompletionContext, IN PDEVICE_CONTROL_COMPLETION CompletionRoutine ) /*++
Routine Description:
Allocates and initializes a HalDeviceControlContext and then dispatches that context to the appriopate bus handler.
--*/ { NTSTATUS Status; PHAL_DEVICE_CONTROL_CONTEXT pContext; HAL_DEVICE_CONTROL_CONTEXT Context; SYNCHRONOUS_REQUEST SyncRequest;
//
// Initialize local DeviceControl context
//
Context.DeviceControl.DeviceHandler = DeviceHandler; Context.DeviceControl.DeviceObject = DeviceObject; Context.DeviceControl.ControlCode = ControlCode; Context.DeviceControl.Buffer = Buffer; Context.DeviceControl.BufferLength = BufferLength; Context.DeviceControl.Context = CompletionContext; Context.CompletionRoutine = CompletionRoutine; Context.Handler = DeviceHandler->BusHandler; Context.RootHandler = DeviceHandler->BusHandler;
//
// Allocate HalDeviceControlContext structure
// (for now, just do it from pool)
//
pContext = ExAllocatePoolWithTag ( NonPagedPool, sizeof (HAL_DEVICE_CONTROL_CONTEXT) + Context.Handler->DeviceControlExtensionSize, 'sLAH' );
if (pContext) {
//
// Initialize HalDeviceControlContext
//
RtlCopyMemory (pContext, &Context, sizeof (HAL_DEVICE_CONTROL_CONTEXT));
pContext->BusExtensionData = NULL; if (pContext->Handler->DeviceControlExtensionSize) { pContext->BusExtensionData = pContext + 1; }
if (!Context.CompletionRoutine) {
//
// There's no completion routine, associate an event to make it a
// synchronous request
//
KeInitializeEvent (&SyncRequest.Event, SynchronizationEvent, FALSE); pContext->DeviceControl.Context = &SyncRequest; }
//
// If there's no buffer length, pass in a zero
//
if (!pContext->DeviceControl.BufferLength) { pContext->DeviceControl.BufferLength = pContext->HalReserved; pContext->HalReserved[0] = 0; }
//
// Allocated context complete, dispatch it to the appopiate bus handler
//
pContext->DeviceControl.Status = STATUS_PENDING; Status = Context.Handler->DeviceControl(pContext);
//
// If the DeviceControl is pending and this is a synchronous call
// wait for it to complete
//
if (Status == STATUS_PENDING && CompletionRoutine == NULL) {
//
// Wait for it to complete
//
KeWaitForSingleObject ( &SyncRequest.Event, WrExecutive, KernelMode, FALSE, NULL );
//
// Return results
//
Status = SyncRequest.Status; ASSERT (Status != STATUS_PENDING); }
return Status;
} else {
//
// Out of memory
//
Status = STATUS_INSUFFICIENT_RESOURCES; }
//
// Immediate error, complete request with local context
// structure with error code
//
if (CompletionRoutine) { Context.DeviceControl.Status = Status; CompletionRoutine (&Context.DeviceControl); }
return Status; }
NTSTATUS HaliCompleteDeviceControl ( IN PHAL_DEVICE_CONTROL_CONTEXT Context ) { NTSTATUS Status; PSYNCHRONOUS_REQUEST SyncRequest;
//
// Get results
//
Status = Context->DeviceControl.Status;
if (Context->CompletionRoutine) {
//
// Notify completion routine
//
Context->CompletionRoutine (&Context->DeviceControl);
} else {
//
// This is a synchronous request, return the status, and set
// the event
//
SyncRequest = (PSYNCHRONOUS_REQUEST) Context->DeviceControl.Context; SyncRequest->Status = Context->DeviceControl.Status; KeSetEvent (&SyncRequest->Event, 0, FALSE); }
//
// Free context structure
//
ExFreePool (Context); 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; }
NTSTATUS HalpNoDeviceControl ( IN PHAL_DEVICE_CONTROL_CONTEXT Context ) { Context->DeviceControl.Status = STATUS_NOT_SUPPORTED; return HaliCompleteDeviceControl (Context); }
PDEVICE_HANDLER_OBJECT HalpNoReferenceDeviceHandler ( IN PBUS_HANDLER BusHandler, IN PBUS_HANDLER RootHandler, IN ULONG SlotNumber ) { 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; }
#ifdef _PNP_POWER_
NTSTATUS HaliSuspendHibernateSystem ( IN PTIME_FIELDS ResumeTime OPTIONAL, IN PHIBERNATE_CALLBACK SystemCallback ) /*++
Routine Description:
This function is invokved by the to suspend or hibernate the system. By this point all device drivers have been turned off. All bus extenders are notified, and then a platform specific suspend function is called.
Arguments:
ResumeTime - Time to set resume alarm SystemCallback - If NULL, suspend; else call this function.
Return Value:
SUCCESS if machine was suspended/hibernated.
--*/ { KIRQL OldIrql; PHAL_BUS_HANDLER Handler; PLIST_ENTRY HibernateLink, ResumeLink; NTSTATUS Status;
LockBusDatabase (&OldIrql); ASSERT (OldIrql == HIGH_LEVEL);
//
// Notify bus handlers in reserved order for which they were installed
//
Status = STATUS_SUCCESS; for (HibernateLink = HalpAllBusHandlers.Blink; HibernateLink != &HalpAllBusHandlers && NT_SUCCESS(Status); HibernateLink = HibernateLink->Blink) {
//
// Give this handler hibernate notification
//
Handler = CONTAINING_RECORD(HibernateLink, HAL_BUS_HANDLER, AllHandlers); if (Handler->Handler.HibernateBus) { Status = Handler->Handler.HibernateBus ( &Handler->Handler, &Handler->Handler ); } }
//
// Suspend or Hibernate the system now
//
if (NT_SUCCESS (Status)) { Status = HalpSuspendHibernateSystem (ResumeTime, SystemCallback); }
//
// Notify bus handlers which were hibernated to restore state
//
for (ResumeLink = HibernateLink->Flink; ResumeLink != &HalpAllBusHandlers; ResumeLink = ResumeLink->Flink) {
//
// Give this handler resume notification
//
Handler = CONTAINING_RECORD(ResumeLink, HAL_BUS_HANDLER, AllHandlers); if (Handler->Handler.ResumeBus) { Handler->Handler.ResumeBus ( &Handler->Handler, &Handler->Handler ); } }
UnlockBusDatabase (OldIrql); return Status; } #endif
|