You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
264 lines
6.1 KiB
264 lines
6.1 KiB
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
acpintfy.c
|
|
|
|
Abstract:
|
|
|
|
This modules contains code to deal with notifying interested parties
|
|
of events
|
|
|
|
Author:
|
|
|
|
Jason Clark
|
|
Ken Reneris
|
|
|
|
Environment:
|
|
|
|
NT Kernel Model Driver only
|
|
Some changes are required to work in win9x model
|
|
|
|
--*/
|
|
#include "pch.h"
|
|
|
|
//
|
|
// For handler installation
|
|
//
|
|
KSPIN_LOCK NotifyHandlerLock;
|
|
|
|
NTSTATUS
|
|
ACPIRegisterForDeviceNotifications (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PDEVICE_NOTIFY_CALLBACK DeviceNotify,
|
|
IN PVOID Context
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Registers the DeviceNotify function as the function to receive device notify
|
|
callbacks
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - The device object to register a notification handler for
|
|
DeviceNotify - The handle for device specific notifications
|
|
|
|
Return Value
|
|
|
|
Returns status
|
|
|
|
--*/
|
|
{
|
|
PACPI_POWER_INFO node;
|
|
PVOID previous;
|
|
KIRQL oldIrql;
|
|
NTSTATUS status;
|
|
|
|
|
|
//
|
|
// Find the Node associated with this device object (or DevNode)
|
|
// Note: that for NT, the context field is the DeviceExtension of the
|
|
// DeviceObject, since this is what is stored within the ACPI Name Space
|
|
// object
|
|
//
|
|
node = OSPowerFindPowerInfoByContext( DeviceObject );
|
|
if (node == NULL) {
|
|
|
|
return STATUS_NO_SUCH_DEVICE;
|
|
|
|
}
|
|
|
|
//
|
|
// Apply the handler
|
|
//
|
|
KeAcquireSpinLock (&NotifyHandlerLock, &oldIrql);
|
|
|
|
if (node->DeviceNotifyHandler != NULL) {
|
|
|
|
//
|
|
// A handler already present
|
|
//
|
|
status = STATUS_UNSUCCESSFUL;
|
|
|
|
} else {
|
|
|
|
node->DeviceNotifyHandler = DeviceNotify;
|
|
node->HandlerContext = Context;
|
|
status = STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock (&NotifyHandlerLock, oldIrql);
|
|
|
|
return status;
|
|
}
|
|
|
|
|
|
VOID
|
|
ACPIUnregisterForDeviceNotifications (
|
|
IN PDEVICE_OBJECT DeviceObject,
|
|
IN PDEVICE_NOTIFY_CALLBACK DeviceNotify
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Disconnects a handler from device notify event.
|
|
|
|
Arguments:
|
|
|
|
DeviceObject - The device object to register a notification handler for
|
|
|
|
DeviceNotify - The handle for device specific notifications
|
|
|
|
Return Value
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
PACPI_POWER_INFO node;
|
|
PVOID previous;
|
|
KIRQL oldIrql;
|
|
NTSTATUS status;
|
|
|
|
|
|
//
|
|
// Find the Node associated with this device object (or DevNode)
|
|
// Note: that for NT, the context field is the DeviceExtension of the
|
|
// DeviceObject, since this is what is stored within the ACPI Name Space
|
|
// object
|
|
//
|
|
node = OSPowerFindPowerInfoByContext( DeviceObject );
|
|
if (node == NULL) {
|
|
ASSERTMSG("ACPIUnregisterForDeviceNotifications failed. "\
|
|
"Can't find ACPI_POWER_INFO for DeviceObject", FALSE);
|
|
return;
|
|
}
|
|
|
|
//
|
|
// Attempt to remove the handler/context from the node
|
|
//
|
|
KeAcquireSpinLock (&NotifyHandlerLock, &oldIrql);
|
|
|
|
if (node->DeviceNotifyHandler != DeviceNotify) {
|
|
|
|
//
|
|
// Handler does not match
|
|
//
|
|
ASSERTMSG("ACPIUnregisterForDeviceNotifications failed. "\
|
|
"Handler doesn't match.", FALSE);
|
|
|
|
} else {
|
|
|
|
node->DeviceNotifyHandler = NULL;
|
|
node->HandlerContext = NULL;
|
|
|
|
}
|
|
|
|
KeReleaseSpinLock (&NotifyHandlerLock, oldIrql);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
NTSTATUS EXPORT
|
|
NotifyHandler (
|
|
ULONG dwEventType,
|
|
ULONG dwEventData,
|
|
PNSOBJ pnsObj,
|
|
ULONG dwParam,
|
|
PFNAA CompletionCallback,
|
|
PVOID CallbackContext
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
The master ACPI notify handler.
|
|
|
|
The design philosophy here is that ACPI should process all notify requests
|
|
that *ONLY* it can handle, namely, DeviceCheck, DeviceEject, and DeviceWake,
|
|
and let *all* other notifies get handled by the driver associated with the
|
|
object. The other driver will also get told about the ACPI handled events,
|
|
but that is only as an FYI, the driver shouldn't do anything...
|
|
|
|
Arguments:
|
|
|
|
dwEventType - The type of event that occured (this is EVTYPE_NOTIFY)
|
|
dwEventData - The event code
|
|
pnsObj - The name space object that was notified
|
|
dwParam - The event code
|
|
|
|
Return Value
|
|
|
|
NTSTATUS
|
|
|
|
--*/
|
|
{
|
|
PACPI_POWER_INFO node;
|
|
KIRQL oldIrql;
|
|
PDEVICE_NOTIFY_CALLBACK notifyHandler;
|
|
PVOID notifyHandlerContext;
|
|
|
|
ASSERT (dwEventType == EVTYPE_NOTIFY);
|
|
|
|
ACPIPrint( (
|
|
ACPI_PRINT_DPC,
|
|
"ACPINotifyHandler: Notify on %x value %x, object type %x\n",
|
|
pnsObj,
|
|
dwEventData,
|
|
NSGETOBJTYPE(pnsObj)
|
|
) );
|
|
|
|
//
|
|
// Any events which must be handled by ACPI and is common to all device
|
|
// object types is handled here
|
|
//
|
|
switch (dwEventData) {
|
|
case OPEVENT_DEVICE_ENUM:
|
|
OSNotifyDeviceEnum( pnsObj );
|
|
break;
|
|
case OPEVENT_DEVICE_CHECK:
|
|
OSNotifyDeviceCheck( pnsObj );
|
|
break;
|
|
case OPEVENT_DEVICE_WAKE:
|
|
OSNotifyDeviceWake( pnsObj );
|
|
break;
|
|
case OPEVENT_DEVICE_EJECT:
|
|
OSNotifyDeviceEject( pnsObj );
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Look for handle for this node and dispatch it
|
|
//
|
|
node = OSPowerFindPowerInfo(pnsObj);
|
|
if (node) {
|
|
|
|
//
|
|
// Get handler address/context with mutex
|
|
//
|
|
KeAcquireSpinLock (&NotifyHandlerLock, &oldIrql);
|
|
|
|
notifyHandler = node->DeviceNotifyHandler;
|
|
notifyHandlerContext = node->HandlerContext;
|
|
|
|
KeReleaseSpinLock (&NotifyHandlerLock, oldIrql);
|
|
|
|
//
|
|
// If we got something, dispatch it
|
|
//
|
|
if (notifyHandler) {
|
|
|
|
notifyHandler (notifyHandlerContext, dwEventData);
|
|
|
|
}
|
|
|
|
}
|
|
return (STATUS_SUCCESS);
|
|
}
|