NT4/private/ntos/nthals/bushnd.c
2020-09-30 17:12:29 +02:00

1642 lines
37 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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