windows-nt/Source/XPSP1/NT/base/busdrv/acpi/oprghdlr/oprghdlr.c

429 lines
9.4 KiB
C
Raw Permalink Normal View History

2020-09-26 03:20:57 -05:00
/*++
Copyright (c) 2000 Microsoft Corporation
Module Name:
oprghdlr.c
Abstract:
This module contains the code that implements ACPI op region
registration DLL
Author:
Vincent Geglia (vincentg) 09-Feb-2000
Environment:
Kernel mode
Notes:
Revision History:
--*/
//
// Standard includes
//
#include "stdarg.h"
#include "stdio.h"
#include "wdm.h"
//
// Oprghdlr dll specific includes
//
#include "oprghdlr.h"
//
// Definitions / static definitions
//
#define DEBUG_INFO 1
#define DEBUG_WARN 2
#define DEBUG_ERROR 4
static const UCHAR DebugPrepend[] = {'O', 'P', 'R', 'G', 'H', 'D', 'L', 'R', ':'};
//
// IRP_MJ_INTERNAL_DEVICE_CONTROL CODES
//
#define IOCTL_ACPI_REGISTER_OPREGION_HANDLER CTL_CODE(FILE_DEVICE_ACPI, 0x2, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
#define IOCTL_ACPI_UNREGISTER_OPREGION_HANDLER CTL_CODE(FILE_DEVICE_ACPI, 0x3, METHOD_BUFFERED, FILE_READ_ACCESS | FILE_WRITE_ACCESS)
//
// Signatures for Register, Unregister of OpRegions
//
#define ACPI_REGISTER_OPREGION_HANDLER_BUFFER_SIGNATURE 'HorA'
#define ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER_SIGNATURE 'HouA'
//
// Globals / Externals
//
extern ULONG OprghdlrDebugLevel = 0;
//
// Structures / type definitions
//
typedef struct _ACPI_REGISTER_OPREGION_HANDLER_BUFFER {
ULONG Signature;
ULONG AccessType;
ULONG RegionSpace;
PACPI_OP_REGION_HANDLER Handler;
PVOID Context;
} ACPI_REGISTER_OPREGION_HANDLER_BUFFER, *PACPI_REGISTER_OPREGION_HANDLER_BUFFER;
typedef struct _ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER {
ULONG Signature;
PVOID OperationRegionObject;
} ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER,*PACPI_UNREGISTER_OPREGION_HANDLER_BUFFER;
//
// Define the local routines used by this driver module.
//
VOID
DebugPrint (
IN ULONG DebugLevel,
IN PUCHAR DebugMessage,
...
);
NTSTATUS
DriverEntry (
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
);
//
// Function code
//
NTSTATUS
RegisterOpRegionHandler (
IN PDEVICE_OBJECT DeviceObject,
IN ULONG AccessType,
IN ULONG RegionSpace,
IN PACPI_OP_REGION_HANDLER Handler,
IN PVOID Context,
IN ULONG Flags,
IN OUT PVOID *OperationRegionObject
)
/*++
Routine Description:
This is the operation region registration routine. It builds the appropriate
IOCTL, and sends it to ACPI to register the op region handler.
Arguments:
DeviceObject - Pointer to device object for ACPI PDO
AccessType - Specifies accesstype for which to register the op region handler
(see oprghdlr.h)
RegionSpace - Specifies the region space type for which the op region handler should
be called for
Handler - Pointer to a function that will handle the op region accesses
Context - Context passed to handler when op region access occurs
OperationRegionObject - Contains a pointer to the op region object returned by ACPI
Return Value:
STATUS_SUCCESS if sucessful, otherwise error status.
--*/
{
ACPI_REGISTER_OPREGION_HANDLER_BUFFER inputData;
ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER outputData;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
NTSTATUS status = STATUS_SUCCESS;
PIRP irp;
DebugPrint (DEBUG_INFO,
"Entering RegisterOpRegionHandler\n");
//
// Zero out IOCTL buffers
//
RtlZeroMemory (&inputData, sizeof (inputData));
RtlZeroMemory (&outputData, sizeof (outputData));
//
// Init our synchronization event
//
KeInitializeEvent (&event, SynchronizationEvent, FALSE);
//
// Set up the IOCTL buffer
//
inputData.Signature = ACPI_REGISTER_OPREGION_HANDLER_BUFFER_SIGNATURE;
inputData.AccessType = AccessType;
inputData.RegionSpace = RegionSpace;
inputData.Handler = Handler;
inputData.Context = Context;
//
// Build the IOCTL
//
irp = IoBuildDeviceIoControlRequest (IOCTL_ACPI_REGISTER_OPREGION_HANDLER,
DeviceObject,
&inputData,
sizeof(ACPI_REGISTER_OPREGION_HANDLER_BUFFER),
&outputData,
sizeof(ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER),
FALSE,
&event,
&ioStatus);
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Send to ACPI driver
//
status = IoCallDriver (DeviceObject, irp);
if (status == STATUS_PENDING) {
//
// Wait for request to be completed
//
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
//
// Get the real status
//
status = ioStatus.Status;
}
//
// Check the status code
//
if (!NT_SUCCESS(status)) {
DebugPrint (DEBUG_ERROR,
"Registration IRP was failed by ACPI (%lx)\n",
status);
return status;
}
//
// Check the signature
//
if (outputData.Signature != ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER_SIGNATURE) {
status = STATUS_ACPI_INVALID_DATA;
DebugPrint (DEBUG_ERROR,
"Signature returned from ACPI is invalid. Registration failed.\n");
return status;
}
*OperationRegionObject = outputData.OperationRegionObject;
return status;
}
NTSTATUS
DeRegisterOpRegionHandler (
IN PDEVICE_OBJECT DeviceObject,
IN PVOID OperationRegionObject
)
/*++
Routine Description:
This is the operation region deregistration routine. It builds the appropriate
IOCTL, and sends it to ACPI to deregister the op region handler.
Arguments:
DeviceObject - Pointer to device object for ACPI PDO
OperationRegionObject - Contains a pointer to the op region object returned
during registration
Return Value:
STATUS_SUCCESS if sucessful, otherwise error status.
--*/
{
ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER inputData;
IO_STATUS_BLOCK ioStatus;
KEVENT event;
NTSTATUS status;
PIRP irp;
DebugPrint (DEBUG_INFO,
"Entering DeRegisterOpRegionHandler\n");
//
// Zero out IOCTL buffer
//
RtlZeroMemory (&inputData, sizeof (inputData));
//
// Init our synchronization event
//
KeInitializeEvent (&event, SynchronizationEvent, FALSE);
//
// Set up the IOCTL buffer
//
inputData.Signature = ACPI_UNREGISTER_OPREGION_HANDLER_BUFFER_SIGNATURE;
inputData.OperationRegionObject = OperationRegionObject;
//
// Build the IOCTL
//
irp = IoBuildDeviceIoControlRequest (IOCTL_ACPI_UNREGISTER_OPREGION_HANDLER,
DeviceObject,
&inputData,
sizeof(ACPI_REGISTER_OPREGION_HANDLER_BUFFER),
NULL,
0,
FALSE,
&event,
&ioStatus);
if (!irp) {
return STATUS_INSUFFICIENT_RESOURCES;
}
//
// Send to ACPI driver
//
status = IoCallDriver (DeviceObject, irp);
if (status == STATUS_PENDING) {
//
// Wait for request to be completed
//
KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
//
// Get the real status
//
status = ioStatus.Status;
}
//
// Check the status code
//
if (!NT_SUCCESS(status)) {
DebugPrint (DEBUG_ERROR,
"Deregistration IRP was failed by ACPI (%lx)\n",
status);
}
return status;
}
VOID
DebugPrint (
IN ULONG DebugLevel,
IN PUCHAR DebugMessage,
...
)
/*++
Routine Description:
This is the general debug printing routine.
Arguments:
DebugLevel - Debug level for which this message should be printed
DebugMessage - Pointer to a buffer for the message to be printed
... - Variable length argument list
Return Value:
None
--*/
{
UCHAR Text[200];
va_list va;
RtlCopyMemory (&Text, DebugPrepend, sizeof (DebugPrepend));
va_start (va, DebugMessage);
vsprintf ((PVOID) ((ULONG_PTR) &Text + sizeof (DebugPrepend)), DebugMessage, va);
va_end (va);
if (OprghdlrDebugLevel & DebugLevel) {
DbgPrint (Text);
}
}
/*++
Routine Description:
Required DriverEntry routine. Not used as this is an EXPORT_DRIVER type.
Arguments:
DriverObject - Address of DriverObject
RegistryPath - Address of the registry path
Return Value:
STATUS_SUCCESS, always
--*/
NTSTATUS
DriverEntry (
PDRIVER_OBJECT DriverObject,
PUNICODE_STRING RegistryPath
)
{
return STATUS_SUCCESS;
}