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