268 lines
6 KiB
C
268 lines
6 KiB
C
/*++
|
||
|
||
Copyright (c) 1990 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
handlers.c
|
||
|
||
Abstract:
|
||
|
||
GPE and Operation Region handlers for the ACPI Embedded Controller Driver
|
||
|
||
Author:
|
||
|
||
Bob Moore (Intel)
|
||
|
||
Environment:
|
||
|
||
Notes:
|
||
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
#include "ecp.h"
|
||
|
||
NTSTATUS
|
||
AcpiEcOpRegionCompletion (
|
||
IN PDEVICE_OBJECT DeviceObject,
|
||
IN PIRP Irp,
|
||
IN PVOID Context
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine starts or continues servicing the device's work queue
|
||
|
||
Arguments:
|
||
|
||
DeviceObject - EC device object
|
||
Irp - Completing Irp
|
||
Context - Not Used
|
||
|
||
Return Value:
|
||
|
||
Status
|
||
|
||
--*/
|
||
{
|
||
PACPI_OPREGION_CALLBACK completionHandler;
|
||
PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation( Irp );
|
||
PVOID completionContext;
|
||
|
||
//
|
||
// Grab the arguments from the irp
|
||
//
|
||
completionHandler = (PACPI_OPREGION_CALLBACK) irpSp->Parameters.Others.Argument1;
|
||
completionContext = (PVOID) irpSp->Parameters.Others.Argument2;
|
||
|
||
EcPrint(
|
||
EC_HANDLER,
|
||
("AcpiEcOpRegionCompletion: Callback: %08lx Context: %08lx\n",
|
||
completionHandler, completionContext )
|
||
);
|
||
|
||
//
|
||
// What happened?
|
||
//
|
||
if (!NT_SUCCESS(Irp->IoStatus.Status)) {
|
||
|
||
EcPrint(
|
||
EC_ERROR,
|
||
("AcpiEcOpRegionCompletion: region IO failed: %x\n",
|
||
Irp->IoStatus.Status)
|
||
);
|
||
|
||
}
|
||
|
||
//
|
||
// Invoke the AML interpreter's callback
|
||
//
|
||
(completionHandler)( completionContext );
|
||
|
||
//
|
||
// We are done with this irp and the irp
|
||
//
|
||
IoFreeIrp( Irp );
|
||
|
||
//
|
||
// Return always return this --- because had to free the irp
|
||
//
|
||
return STATUS_MORE_PROCESSING_REQUIRED;
|
||
}
|
||
|
||
|
||
|
||
NTSTATUS
|
||
EXPORT
|
||
AcpiEcOpRegionHandler (
|
||
ULONG AccessType,
|
||
PVOID OpRegion,
|
||
ULONG Address,
|
||
ULONG Size,
|
||
PULONG Data,
|
||
ULONG_PTR Context,
|
||
PACPI_OPREGION_CALLBACK CompletionHandler,
|
||
PVOID CompletionContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine handles requests to service the EC operation region
|
||
|
||
Arguments:
|
||
|
||
AccessType - Read or Write data
|
||
OpRegion - Operation region object
|
||
Address - Address within the EC address space
|
||
Size - Number of bytes to transfer
|
||
Data - Data buffer to transfer to/from
|
||
Context - EcData
|
||
CompletionHandler - AMLI handler to call when operation is complete
|
||
CompletionContext - Context to pass to the AMLI handler
|
||
|
||
Return Value:
|
||
|
||
Status
|
||
|
||
Notes:
|
||
|
||
Optimization 1: Queue the IRP directly.
|
||
Optimization 2: Queue the context, modify service loop handle it
|
||
|
||
--*/
|
||
{
|
||
LARGE_INTEGER startingOffset;
|
||
NTSTATUS status;
|
||
PECDATA ecData = (PECDATA) Context;
|
||
PIO_STACK_LOCATION irpSp;
|
||
PIRP irp;
|
||
|
||
EcPrint(
|
||
(EC_HANDLER | EC_OPREGION),
|
||
("AcpiEcOpRegionHandler: %s Addr=%x Data = %x EcData=%x, Irql=%x\n",
|
||
(AccessType == ACPI_OPREGION_READ ? "read" : "write"),
|
||
Address, *Data, ecData, KeGetCurrentIrql() )
|
||
);
|
||
|
||
//
|
||
// Parameter validation will be done in AcpiEcReadWrite
|
||
//
|
||
|
||
//
|
||
// Determine where the read will occur
|
||
//
|
||
startingOffset.LowPart = Address;
|
||
startingOffset.HighPart = 0;
|
||
|
||
//
|
||
// Allocate an IRP for ourselves. Since we are going to send this
|
||
// irp to ourselves, we know that we only need 1 stack location for it
|
||
// However, to make life easier for ourselves, we will allocate a
|
||
// second one as well and store some data on it.
|
||
//
|
||
irp = IoAllocateIrp( 2, FALSE );
|
||
if (!irp) {
|
||
|
||
EcPrint(EC_ERROR, ("AcpiEcOpRegionHandler: Couldn't allocate Irp\n"));
|
||
|
||
//
|
||
// Retun -1 for data
|
||
//
|
||
RtlFillMemory (Data, Size, 0xff);
|
||
CompletionHandler( CompletionContext );
|
||
|
||
//
|
||
// Always return STATUS_PENDING because ACPI interpreter doesn't handle errors.
|
||
//
|
||
return STATUS_PENDING;
|
||
|
||
}
|
||
|
||
//
|
||
// Fill in the top location so that we can use it ourselves
|
||
//
|
||
irpSp = IoGetNextIrpStackLocation( irp );
|
||
irpSp->Parameters.Others.Argument1 = (PVOID) CompletionHandler;
|
||
irpSp->Parameters.Others.Argument2 = (PVOID) CompletionContext;
|
||
IoSetNextIrpStackLocation( irp );
|
||
|
||
//
|
||
// Fill out the irp with the request info
|
||
//
|
||
irpSp = IoGetNextIrpStackLocation( irp );
|
||
irpSp->MajorFunction = (AccessType == ACPI_OPREGION_READ ? IRP_MJ_READ : IRP_MJ_WRITE);
|
||
irpSp->Parameters.Read.ByteOffset.HighPart = 0;
|
||
irpSp->Parameters.Read.ByteOffset.LowPart = Address;
|
||
irpSp->Parameters.Read.Length = Size;
|
||
irp->AssociatedIrp.SystemBuffer = Data;
|
||
|
||
//
|
||
// Set a completion routine
|
||
//
|
||
IoSetCompletionRoutine(
|
||
irp,
|
||
AcpiEcOpRegionCompletion,
|
||
NULL,
|
||
TRUE,
|
||
TRUE,
|
||
TRUE
|
||
);
|
||
|
||
//
|
||
// Send to the front-end of the EC driver as a normal I/O request
|
||
//
|
||
status = IoCallDriver( ecData->DeviceObject, irp);
|
||
EcPrint(
|
||
EC_HANDLER,
|
||
("AcpiEcOpRegionHandler: Exiting - Data=%08lx Status=%08lx\n",
|
||
(UCHAR) *Data, status)
|
||
);
|
||
|
||
return STATUS_PENDING;
|
||
//
|
||
// Always return STATUS_PENDING since actual status has been returned
|
||
// by the calback function.
|
||
//
|
||
}
|
||
|
||
|
||
|
||
BOOLEAN
|
||
AcpiEcGpeServiceRoutine (
|
||
IN PVOID GpeVectorObject,
|
||
IN PVOID ServiceContext
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Routine to service the EC based on a General Purpose Event
|
||
|
||
Arguments:
|
||
|
||
GpeVectorObject - Object associated with this GPE
|
||
ServiceContext - EcData
|
||
|
||
Return Value:
|
||
|
||
TRUE, since we always handle this GPE
|
||
|
||
--*/
|
||
{
|
||
|
||
PECDATA EcData = (PECDATA) ServiceContext;
|
||
|
||
EcPrint (EC_HANDLER, ("AcpiEcGpeServiceRoutine: Vobj=%Lx, EcData=%Lx\n",
|
||
GpeVectorObject, EcData));
|
||
|
||
AcpiEcLogAction (EcData, EC_ACTION_INTERRUPT, 0);
|
||
AcpiEcServiceDevice (EcData);
|
||
|
||
return (TRUE);
|
||
}
|