windows-nt/Source/XPSP1/NT/base/busdrv/acpi/ec/handlers.c
2020-09-26 16:20:57 +08:00

268 lines
6 KiB
C
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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