|
|
/*++
Copyright (c) 1990 Microsoft Corporation
Module Name:
eclowio.c
Abstract:
Interface module to ACPI driver functions. It encapsulates the grungy Irp details.
Author:
Bob Moore (Intel)
Environment:
Notes:
Revision History:
00-Feb-15 [vincentg] - modified to use oprghdlr.sys to register/deregister op region handler
--*/
#include "ecp.h"
#include "oprghdlr.h"
#include <initguid.h>
#include <wdmguid.h>
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, AcpiEcGetAcpiInterfaces)
#pragma alloc_text(PAGE, AcpiEcGetGpeVector)
#pragma alloc_text(PAGE, AcpiEcInstallOpRegionHandler)
#pragma alloc_text(PAGE, AcpiEcRemoveOpRegionHandler)
#endif
NTSTATUS AcpiEcGetAcpiInterfaces ( IN PECDATA EcData ) /*++
Routine Description:
Call ACPI driver to get the direct-call interfaces.
Arguments:
EcData - Pointer to the EC driver device extension
Return Value:
Status is returned.
--*/ { KEVENT event; IO_STATUS_BLOCK ioStatus; NTSTATUS status; PIRP irp; PIO_STACK_LOCATION irpSp;
PAGED_CODE();
//
// Initialize an event to block on
//
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
//
// Build an irp
//
irp = IoBuildSynchronousFsdRequest( IRP_MJ_PNP, EcData->LowerDeviceObject, NULL, 0, NULL, &event, &ioStatus );
if (!irp) { return STATUS_INSUFFICIENT_RESOURCES; }
irp->IoStatus.Status = STATUS_NOT_SUPPORTED; irp->IoStatus.Information = 0;
//
// Get the the current irp location
//
irpSp = IoGetNextIrpStackLocation( irp );
//
// Use QUERY_INTERFACE to get the address of the direct-call
// ACPI interfaces.
//
irpSp->MajorFunction = IRP_MJ_PNP; irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE; irpSp->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_ACPI_INTERFACE_STANDARD; irpSp->Parameters.QueryInterface.Version = 1; irpSp->Parameters.QueryInterface.Size = sizeof (AcpiInterfaces); irpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &AcpiInterfaces; irpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;
//
// send the request down
//
status = IoCallDriver( EcData->LowerDeviceObject, irp ); if (status == STATUS_PENDING) {
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL ); status = ioStatus.Status;
}
//
// Done
//
return status; }
NTSTATUS AcpiEcGetGpeVector ( IN PECDATA EcData ) /*++
Routine Description:
Run the _GPE method (Under the EC device in the namespace) to get the GPE vector assigned to the EC.
Note: This routine is called at PASSIVE_LEVEL
Arguments:
EcData - Pointer to the EC driver device extension
Return Value:
Status is returned.
--*/ { ACPI_EVAL_INPUT_BUFFER inputBuffer; ACPI_EVAL_OUTPUT_BUFFER outputBuffer; KEVENT event; IO_STATUS_BLOCK ioStatus; NTSTATUS status; PACPI_METHOD_ARGUMENT argument; PIRP irp;
PAGED_CODE();
//
// Initialize the event
//
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
//
// Initialize the input buffer
//
RtlZeroMemory( &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER) ); inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE; inputBuffer.MethodNameAsUlong = CM_GPE_METHOD;
//
// Initialize the output buffer
//
RtlZeroMemory( &outputBuffer, sizeof(ACPI_EVAL_OUTPUT_BUFFER ) );
//
// Initialize an IRP
//
irp = IoBuildDeviceIoControlRequest( IOCTL_ACPI_EVAL_METHOD, EcData->LowerDeviceObject, &inputBuffer, sizeof(ACPI_EVAL_INPUT_BUFFER), &outputBuffer, sizeof(ACPI_EVAL_OUTPUT_BUFFER), FALSE, &event, &ioStatus );
//
// Irp initialization failed?
//
if (!irp) {
status = STATUS_INSUFFICIENT_RESOURCES; goto AcpiEcGetGpeVectorExit;
}
//
// Send to ACPI driver
//
status = IoCallDriver (EcData->LowerDeviceObject, irp); if (status == STATUS_PENDING) {
//
// Wait for request to be completed
//
KeWaitForSingleObject( &event, Executive, KernelMode, FALSE, NULL );
//
// Get the real status
//
status = ioStatus.Status;
}
//
// Did we fail the request?
//
if (!NT_SUCCESS(status)) {
goto AcpiEcGetGpeVectorExit;
}
//
// Sanity checks
//
ASSERT( ioStatus.Information >= sizeof(ACPI_EVAL_OUTPUT_BUFFER) ); if (ioStatus.Information < sizeof(ACPI_EVAL_OUTPUT_BUFFER) || outputBuffer.Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE || outputBuffer.Count == 0) {
status = STATUS_UNSUCCESSFUL; goto AcpiEcGetGpeVectorExit;
}
//
// Crack the result
//
argument = &(outputBuffer.Argument[0]);
//
// We are expecting an integer
//
if (argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) {
status = STATUS_ACPI_INVALID_DATA; goto AcpiEcGetGpeVectorExit;
}
//
// Get the value
//
EcData->GpeVector = (UCHAR) argument->Argument;
AcpiEcGetGpeVectorExit:
//
// Done
//
return status; }
NTSTATUS AcpiEcConnectGpeVector ( IN PECDATA EcData ) /*++
Routine Description:
Call ACPI driver to connect the EC driver to a GPE vector
Arguments:
EcData - Pointer to the EC driver device extension
Return Value:
Status is returned.
--*/ {
return (AcpiInterfaces.GpeConnectVector ( AcpiInterfaces.Context, EcData->GpeVector, Latched, // Edge triggered
FALSE, // Can't be shared
AcpiEcGpeServiceRoutine, EcData, &EcData->GpeVectorObject));
}
NTSTATUS AcpiEcDisconnectGpeVector ( IN PECDATA EcData ) /*++
Routine Description:
Call ACPI driver to disconnect the EC driver from a GPE vector. Called from device unload, stop.
Arguments:
EcData - Pointer to the EC driver device extension
Return Value:
Status is returned.
--*/ { NTSTATUS status;
if (EcData->GpeVectorObject) {
status = AcpiInterfaces.GpeDisconnectVector (EcData->GpeVectorObject); EcData->GpeVectorObject = NULL;
} else {
status = STATUS_SUCCESS; }
return status;
}
NTSTATUS AcpiEcInstallOpRegionHandler( IN PECDATA EcData ) /*++
Routine Description:
Call ACPI driver to install the EC driver operation region handler
Arguments:
EcData - Pointer to the EC driver device extension
Return Value:
Status is returned.
--*/ { NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE ();
status = RegisterOpRegionHandler (EcData->LowerDeviceObject, ACPI_OPREGION_ACCESS_AS_COOKED, ACPI_OPREGION_REGION_SPACE_EC, (PACPI_OP_REGION_HANDLER) AcpiEcOpRegionHandler, EcData, 0, &EcData->OperationRegionObject); return status; }
NTSTATUS AcpiEcRemoveOpRegionHandler ( IN PECDATA EcData ) /*++
Routine Description:
Call ACPI driver to remove the EC driver operation region handler. Called from device unload, stop.
Arguments:
EcData - Pointer to the EC driver device extension
Return Value:
Status is returned.
--*/ { NTSTATUS status = STATUS_SUCCESS;
PAGED_CODE ();
status = DeRegisterOpRegionHandler (EcData->LowerDeviceObject, EcData->OperationRegionObject);
return status; }
NTSTATUS AcpiEcForwardIrpAndWait ( IN PECDATA EcData, IN PIRP Irp ) /*++
Routine Description:
Utility routine to send an irp down, and wait for the result.
Arguments:
EcData - Pointer to the EC driver device extension Irp - Irp to send and complete
Return Value:
Status is returned.
--*/ { KEVENT pdoStartedEvent; NTSTATUS status;
KeInitializeEvent (&pdoStartedEvent, SynchronizationEvent, FALSE);
IoCopyCurrentIrpStackLocationToNext (Irp); IoSetCompletionRoutine (Irp, AcpiEcIoCompletion, &pdoStartedEvent, TRUE, TRUE, TRUE);
//
// Always wait for the completion routine
//
status = IoCallDriver (EcData->LowerDeviceObject, Irp); if (status == STATUS_PENDING) {
KeWaitForSingleObject (&pdoStartedEvent, Executive, KernelMode, FALSE, NULL); status = Irp->IoStatus.Status; } return status; }
|