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