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);
|
|||
|
}
|