1642 lines
37 KiB
C
1642 lines
37 KiB
C
/*++
|
||
|
||
|
||
Copyright (c) 1989 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
bushnd.c
|
||
|
||
Abstract:
|
||
|
||
Functions which take either BusType-BusNumber or ConfigType-BusNumberm
|
||
and route to a the appropiate registered handler.
|
||
|
||
Author:
|
||
|
||
Ken Reneris (kenr) July-28-1994
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History:
|
||
|
||
|
||
--*/
|
||
|
||
#include "halp.h"
|
||
|
||
|
||
typedef struct _ARRAY {
|
||
ULONG ArraySize;
|
||
PVOID Element[]; // must be last field
|
||
} ARRAY, *PARRAY;
|
||
|
||
#define ARRAY_SIZE_IN_BYTES(a) ( (a + 1) * sizeof(PARRAY) + \
|
||
FIELD_OFFSET(ARRAY, Element) )
|
||
|
||
typedef struct _HAL_BUS_HANDLER {
|
||
LIST_ENTRY AllHandlers;
|
||
ULONG ReferenceCount;
|
||
BUS_HANDLER Handler;
|
||
} HAL_BUS_HANDLER, *PHAL_BUS_HANDLER;
|
||
|
||
//
|
||
// Event to serialize with adding new buses
|
||
//
|
||
|
||
KEVENT HalpBusDatabaseEvent;
|
||
|
||
//
|
||
// Lock to serialize routing functions from accessing handler arrays while
|
||
// new buses are added
|
||
//
|
||
|
||
KSPIN_LOCK HalpBusDatabaseSpinLock;
|
||
|
||
//
|
||
// HalpBusTable - pointers to BusHandlers mapped by InterfaceType,BusNumber
|
||
//
|
||
|
||
PARRAY HalpBusTable;
|
||
|
||
//
|
||
// HalpConfigTable - pointers to BusHandlers mapped by ConfigType,BusNumber
|
||
//
|
||
|
||
PARRAY HalpConfigTable;
|
||
|
||
//
|
||
// List of all installed bus handlers
|
||
//
|
||
|
||
LIST_ENTRY HalpAllBusHandlers;
|
||
|
||
//
|
||
// Lock is high_level since some routed functions can occurs at ISR time
|
||
//
|
||
|
||
#define LockBusDatabase(oldirql) \
|
||
KeRaiseIrql(HIGH_LEVEL, oldirql); \
|
||
KiAcquireSpinLock(&HalpBusDatabaseSpinLock);
|
||
|
||
#define UnlockBusDatabase(oldirql) \
|
||
KiReleaseSpinLock(&HalpBusDatabaseSpinLock); \
|
||
KeLowerIrql(oldirql);
|
||
|
||
|
||
#ifdef _PNP_POWER_
|
||
extern HAL_CALLBACKS HalCallback;
|
||
#endif
|
||
|
||
//
|
||
// Internal prototypes
|
||
//
|
||
|
||
PARRAY
|
||
HalpAllocateArray (
|
||
IN ULONG Type
|
||
);
|
||
|
||
VOID
|
||
HalpGrowArray (
|
||
IN PARRAY *CurrentArray,
|
||
IN PARRAY *NewArray
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpQueryInstalledBusInformation (
|
||
OUT PVOID Buffer,
|
||
IN ULONG BufferLength,
|
||
OUT PULONG ReturnedLength
|
||
);
|
||
|
||
ULONG
|
||
HalpNoBusData (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN ULONG SlotNumber,
|
||
IN PVOID Buffer,
|
||
IN ULONG Offset,
|
||
IN ULONG Length
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpNoAdjustResourceList (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN OUT PIO_RESOURCE_REQUIREMENTS_LIST *pResourceList
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpNoAssignSlotResources (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN PUNICODE_STRING RegistryPath,
|
||
IN PUNICODE_STRING DriverClassName OPTIONAL,
|
||
IN PDRIVER_OBJECT DriverObject,
|
||
IN PDEVICE_OBJECT DeviceObject OPTIONAL,
|
||
IN ULONG SlotNumber,
|
||
IN OUT PCM_RESOURCE_LIST *AllocatedResources
|
||
);
|
||
|
||
NTSTATUS
|
||
HalpNoQueryBusSlots (
|
||
IN PVOID BusHandler,
|
||
IN PVOID RootHandler,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG SlotNumbers,
|
||
OUT PULONG ReturnedLength
|
||
);
|
||
|
||
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
|