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