429 lines
9.4 KiB
C
429 lines
9.4 KiB
C
|
/*++
|
||
|
|
||
|
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;
|
||
|
}
|