1000 lines
24 KiB
C
1000 lines
24 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
CmBatt.c
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Control Method Battery Miniport Driver
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Ron Mosgrove (Intel)
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
Kernel mode
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
#include "CmBattp.h"
|
|||
|
|
|||
|
#ifdef ALLOC_PRAGMA
|
|||
|
#pragma alloc_text(PAGE, CmBattSendDownStreamIrp)
|
|||
|
#pragma alloc_text(PAGE, CmBattGetUniqueId)
|
|||
|
#pragma alloc_text(PAGE, CmBattGetStaData)
|
|||
|
#pragma alloc_text(PAGE, CmBattSetTripPpoint)
|
|||
|
#endif
|
|||
|
|
|||
|
#define EXPECTED_DATA_SIZE 512
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmBattSendDownStreamIrp(
|
|||
|
IN PDEVICE_OBJECT Pdo,
|
|||
|
IN ULONG Ioctl,
|
|||
|
IN PVOID InputBuffer,
|
|||
|
IN ULONG InputSize,
|
|||
|
IN PVOID OutputBuffer,
|
|||
|
IN ULONG OutputSize
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Called to send a request to the Pdo
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pdo - The request is sent to this device object
|
|||
|
Ioctl - the request
|
|||
|
InputBuffer - The incoming request
|
|||
|
InputSize - The size of the incoming request
|
|||
|
OutputBuffer - The answer
|
|||
|
OutputSize - The size of the answer buffer
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
IO_STATUS_BLOCK ioBlock;
|
|||
|
KEVENT event;
|
|||
|
NTSTATUS status;
|
|||
|
PIRP irp;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
//
|
|||
|
// Initialize an event to wait on
|
|||
|
//
|
|||
|
KeInitializeEvent( &event, SynchronizationEvent, FALSE );
|
|||
|
|
|||
|
//
|
|||
|
// Build the request
|
|||
|
//
|
|||
|
irp = IoBuildDeviceIoControlRequest(
|
|||
|
Ioctl,
|
|||
|
Pdo,
|
|||
|
InputBuffer,
|
|||
|
InputSize,
|
|||
|
OutputBuffer,
|
|||
|
OutputSize,
|
|||
|
FALSE,
|
|||
|
&event,
|
|||
|
&ioBlock
|
|||
|
);
|
|||
|
if (!irp) {
|
|||
|
|
|||
|
CmBattPrint((CMBATT_ERROR | CMBATT_CM_EXE),
|
|||
|
("CmBattSendDownStreamIrp: Failed to allocate Irp\n"));
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
CMBATT_CM_EXE,
|
|||
|
("CmBattSendDownStreamIrp: Irp %x [Tid] %x\n", irp, GetTid() )
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Pass request to Pdo, always wait for completion routine
|
|||
|
//
|
|||
|
status = IoCallDriver(Pdo, irp);
|
|||
|
if (status == STATUS_PENDING) {
|
|||
|
|
|||
|
//
|
|||
|
// Wait for the irp to be completed, then grab the real status code
|
|||
|
//
|
|||
|
KeWaitForSingleObject(
|
|||
|
&event,
|
|||
|
Executive,
|
|||
|
KernelMode,
|
|||
|
FALSE,
|
|||
|
NULL
|
|||
|
);
|
|||
|
status = ioBlock.Status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Sanity check the data
|
|||
|
//
|
|||
|
if (OutputBuffer != NULL) {
|
|||
|
|
|||
|
if ( ( (PACPI_EVAL_OUTPUT_BUFFER) OutputBuffer)->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
|
|||
|
( (PACPI_EVAL_OUTPUT_BUFFER) OutputBuffer)->Count == 0) {
|
|||
|
|
|||
|
status = STATUS_ACPI_INVALID_DATA;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
CMBATT_CM_EXE,
|
|||
|
("CmBattSendDownStreamIrp: Irp %x completed %x! [Tid] %x\n",
|
|||
|
irp, status, GetTid() )
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Done
|
|||
|
//
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmBattGetUniqueId(
|
|||
|
IN PDEVICE_OBJECT Pdo,
|
|||
|
OUT PULONG UniqueId
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Obtain the UID (unique ID) for a battery.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CmBatt - The extension for this device.
|
|||
|
UniqueId - Pointer to where the ID is stored.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ACPI_EVAL_INPUT_BUFFER inputBuffer;
|
|||
|
ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
|
|||
|
NTSTATUS status;
|
|||
|
PACPI_METHOD_ARGUMENT argument;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
CMBATT_CM_EXE,
|
|||
|
("CmBattGetUniqueId: Entered with Pdo %x Tid %x\n", Pdo, GetTid() )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( UniqueId != NULL );
|
|||
|
*UniqueId = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the input data
|
|||
|
//
|
|||
|
inputBuffer.MethodNameAsUlong = CM_UID_METHOD;
|
|||
|
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
|
|||
|
|
|||
|
//
|
|||
|
// Send the request along
|
|||
|
//
|
|||
|
status = CmBattSendDownStreamIrp(
|
|||
|
Pdo,
|
|||
|
IOCTL_ACPI_EVAL_METHOD,
|
|||
|
&inputBuffer,
|
|||
|
sizeof(ACPI_EVAL_INPUT_BUFFER),
|
|||
|
&outputBuffer,
|
|||
|
sizeof(ACPI_EVAL_OUTPUT_BUFFER)
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetUniqueId: Failed _UID method - Status (0x%x)\n", status)
|
|||
|
);
|
|||
|
return status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Grab the argument
|
|||
|
//
|
|||
|
argument = outputBuffer.Argument;
|
|||
|
status = GetDwordElement( argument, UniqueId );
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetUniqueId: _UID method returned 0x%x\n", *UniqueId)
|
|||
|
);
|
|||
|
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmBattGetStaData(
|
|||
|
IN PDEVICE_OBJECT Pdo,
|
|||
|
OUT PULONG ReturnStatus
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Called to get a device status via the _STA method. Generic, works for
|
|||
|
any device with the _STA method (assuming caller has a Pdo).
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pdo - For the device.
|
|||
|
ReturnStatus - Pointer to where the status data is placed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ACPI_EVAL_INPUT_BUFFER inputBuffer;
|
|||
|
ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
|
|||
|
NTSTATUS status;
|
|||
|
PACPI_METHOD_ARGUMENT argument;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
CMBATT_CM_EXE,
|
|||
|
("CmBattGetStaData: Entered with Pdo %x Tid %x\n", Pdo, GetTid() )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( ReturnStatus != NULL );
|
|||
|
*ReturnStatus = 0x0;
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the input data
|
|||
|
//
|
|||
|
inputBuffer.MethodNameAsUlong = CM_STA_METHOD;
|
|||
|
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
|
|||
|
|
|||
|
//
|
|||
|
// Send the request along
|
|||
|
//
|
|||
|
status = CmBattSendDownStreamIrp(
|
|||
|
Pdo,
|
|||
|
IOCTL_ACPI_EVAL_METHOD,
|
|||
|
&inputBuffer,
|
|||
|
sizeof(ACPI_EVAL_INPUT_BUFFER),
|
|||
|
&outputBuffer,
|
|||
|
sizeof(ACPI_EVAL_OUTPUT_BUFFER)
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetStaData: Failed _STA method - Status (0x%x)\n", status)
|
|||
|
);
|
|||
|
return STATUS_NO_SUCH_DEVICE;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Grab the argument
|
|||
|
//
|
|||
|
argument = outputBuffer.Argument;
|
|||
|
status = GetDwordElement( argument, ReturnStatus );
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetStaData: _STA method returned %x \n", *ReturnStatus )
|
|||
|
);
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmBattGetPsrData(
|
|||
|
IN PDEVICE_OBJECT Pdo,
|
|||
|
OUT PULONG ReturnStatus
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Called to get the AC adapter device status via the _PSR method.
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Pdo - For the device.
|
|||
|
ReturnStatus - Pointer to where the status data is placed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ACPI_EVAL_INPUT_BUFFER inputBuffer;
|
|||
|
ACPI_EVAL_OUTPUT_BUFFER outputBuffer;
|
|||
|
NTSTATUS status;
|
|||
|
PACPI_METHOD_ARGUMENT argument;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
CMBATT_CM_EXE,
|
|||
|
("CmBattGetPsrData: Entered with Pdo %x Tid %x\n", Pdo, GetTid() )
|
|||
|
);
|
|||
|
|
|||
|
ASSERT( ReturnStatus != NULL );
|
|||
|
*ReturnStatus = 0x0;
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the input data
|
|||
|
//
|
|||
|
inputBuffer.MethodNameAsUlong = CM_PSR_METHOD;
|
|||
|
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
|
|||
|
|
|||
|
//
|
|||
|
// Send the request along
|
|||
|
//
|
|||
|
status = CmBattSendDownStreamIrp(
|
|||
|
Pdo,
|
|||
|
IOCTL_ACPI_EVAL_METHOD,
|
|||
|
&inputBuffer,
|
|||
|
sizeof(ACPI_EVAL_INPUT_BUFFER),
|
|||
|
&outputBuffer,
|
|||
|
sizeof(ACPI_EVAL_OUTPUT_BUFFER)
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetPsrData: Failed _PSR method - Status (0x%x)\n", status)
|
|||
|
);
|
|||
|
return status;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Get the value
|
|||
|
//
|
|||
|
argument = outputBuffer.Argument;
|
|||
|
status = GetDwordElement( argument, ReturnStatus );
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetPsrData: _PSR method returned %x \n", *ReturnStatus )
|
|||
|
);
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmBattSetTripPpoint(
|
|||
|
IN PCM_BATT CmBatt,
|
|||
|
IN ULONG TripPoint
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Called to set the tripPoint via the BTP control method.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CmBatt - The extension for this device.
|
|||
|
TripPoint - The desired alarm value
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER inputBuffer;
|
|||
|
NTSTATUS status;
|
|||
|
|
|||
|
PAGED_CODE();
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattSetTripPpoint: _BTP Alarm Value %x Device %x Tid %x\n",
|
|||
|
TripPoint, CmBatt->DeviceNumber, GetTid() )
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the input data
|
|||
|
//
|
|||
|
inputBuffer.MethodNameAsUlong = CM_BTP_METHOD;
|
|||
|
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE;
|
|||
|
inputBuffer.IntegerArgument = TripPoint;
|
|||
|
|
|||
|
//
|
|||
|
// Send the request along
|
|||
|
//
|
|||
|
status = CmBattSendDownStreamIrp(
|
|||
|
CmBatt->LowerDeviceObject,
|
|||
|
IOCTL_ACPI_EVAL_METHOD,
|
|||
|
&inputBuffer,
|
|||
|
sizeof(ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER),
|
|||
|
NULL,
|
|||
|
0
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattSetTripPpoint: Failed _BTP method on device %x - Status (0x%x)\n",
|
|||
|
CmBatt->DeviceNumber, status)
|
|||
|
);
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Done
|
|||
|
//
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmBattGetBifData(
|
|||
|
IN PCM_BATT CmBatt,
|
|||
|
OUT PCM_BIF_BAT_INFO BifBuf
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Called to read the BIF package from ACPI
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CmBatt - The extension for this device.
|
|||
|
BifBuf - Output buffer for the BIF data
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ACPI_EVAL_INPUT_BUFFER inputBuffer;
|
|||
|
NTSTATUS status;
|
|||
|
PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
|
|||
|
PACPI_METHOD_ARGUMENT argument;
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
CMBATT_CM_EXE,
|
|||
|
("CmBattGetBifData: Buffer (0x%x) Device %x Tid %x\n",
|
|||
|
BifBuf, CmBatt->DeviceNumber, GetTid() )
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a buffer for this
|
|||
|
//
|
|||
|
outputBuffer = ExAllocatePoolWithTag(
|
|||
|
PagedPool,
|
|||
|
EXPECTED_DATA_SIZE,
|
|||
|
'MtaB'
|
|||
|
);
|
|||
|
if (!outputBuffer) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE),
|
|||
|
("CmBattGetBifData: Failed to allocate Buffer\n")
|
|||
|
);
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Clear the buffers
|
|||
|
//
|
|||
|
RtlZeroMemory(outputBuffer, EXPECTED_DATA_SIZE);
|
|||
|
RtlZeroMemory(BifBuf, sizeof(CM_BIF_BAT_INFO));
|
|||
|
|
|||
|
//
|
|||
|
// Set the request data
|
|||
|
//
|
|||
|
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
|
|||
|
inputBuffer.MethodNameAsUlong = CM_BIF_METHOD;
|
|||
|
|
|||
|
//
|
|||
|
// Send the request along
|
|||
|
//
|
|||
|
status = CmBattSendDownStreamIrp(
|
|||
|
CmBatt->LowerDeviceObject,
|
|||
|
IOCTL_ACPI_EVAL_METHOD,
|
|||
|
&inputBuffer,
|
|||
|
sizeof(ACPI_EVAL_INPUT_BUFFER),
|
|||
|
outputBuffer,
|
|||
|
EXPECTED_DATA_SIZE
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed _BIF method on device %x - Status (0x%x)\n",
|
|||
|
CmBatt->DeviceNumber, status)
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Sanity check the return count
|
|||
|
//
|
|||
|
if (outputBuffer->Count != NUMBER_OF_BIF_ELEMENTS) {
|
|||
|
|
|||
|
//
|
|||
|
// Package did not contain the correct number of elements to be a BIF
|
|||
|
//
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: _BIF returned %d elements. BIF requires %d\n",
|
|||
|
outputBuffer->Count,
|
|||
|
NUMBER_OF_BIF_ELEMENTS)
|
|||
|
);
|
|||
|
status = STATUS_ACPI_INVALID_DATA;
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Look at the return arguments
|
|||
|
//
|
|||
|
argument = outputBuffer->Argument;
|
|||
|
|
|||
|
//
|
|||
|
// Parse the package data that is returned. This should look like:
|
|||
|
//
|
|||
|
status = GetDwordElement (argument, &BifBuf->PowerUnit);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get PowerUnit\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BifBuf->DesignCapacity);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get DesignCapacity\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BifBuf->LastFullChargeCapacity);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get LastFullChargeCapacity\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BifBuf->BatteryTechnology);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get BatteryTechnology\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BifBuf->DesignVoltage);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get DesignVoltage\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BifBuf->DesignCapacityOfWarning);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get DesignCapacityOfWarning\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BifBuf->DesignCapacityOfLow);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get DesignCapacityOfLow\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BifBuf->BatteryCapacityGran_1);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get BatteryCapacityGran_1\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BifBuf->BatteryCapacityGran_2);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get BatteryCapacityGran_2\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory (&BifBuf->ModelNumber[0], CM_MAX_STRING_LENGTH);
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetStringElement (argument, &BifBuf->ModelNumber[0]);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get ModelNumber\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory (&BifBuf->SerialNumber[0], CM_MAX_STRING_LENGTH);
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetStringElement (argument, &BifBuf->SerialNumber[0]);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get SerialNumber\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory (&BifBuf->BatteryType[0], CM_MAX_STRING_LENGTH);
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetStringElement (argument, &BifBuf->BatteryType[0]);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get BatteryType\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
|
|||
|
RtlZeroMemory (&BifBuf->OEMInformation[0], CM_MAX_STRING_LENGTH);
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
|
|||
|
//
|
|||
|
// This returns an ASCIIZ string normally,
|
|||
|
// but returns integer 0x00 if OEMInformation isn't supported.
|
|||
|
//
|
|||
|
if (argument->Type == ACPI_METHOD_ARGUMENT_INTEGER) {
|
|||
|
if (argument->Argument != 0) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: Failed to get OEMInformation\n")
|
|||
|
);
|
|||
|
goto CmBattGetBifDataExit;
|
|||
|
}
|
|||
|
BifBuf->OEMInformation[0] = 0;
|
|||
|
status = STATUS_SUCCESS;
|
|||
|
} else {
|
|||
|
status = GetStringElement (argument, &BifBuf->OEMInformation[0]);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBifData: OEMInformation not supported\n")
|
|||
|
);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
CmBattGetBifDataExit:
|
|||
|
//
|
|||
|
// Done
|
|||
|
//
|
|||
|
ExFreePool (outputBuffer);
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
CmBattGetBstData(
|
|||
|
IN PCM_BATT CmBatt,
|
|||
|
OUT PCM_BST_BAT_INFO BstBuf
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Called to read the BST package from ACPI
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
CmBatt - The extension for this device.
|
|||
|
BstBuf - Output buffer for the BST data
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
ACPI_EVAL_INPUT_BUFFER inputBuffer;
|
|||
|
NTSTATUS status;
|
|||
|
PACPI_EVAL_OUTPUT_BUFFER outputBuffer;
|
|||
|
PACPI_METHOD_ARGUMENT argument;
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
CMBATT_CM_EXE,
|
|||
|
("CmBattGetBstData: Buffer (0x%x) Device %x Tid %x\n",
|
|||
|
BstBuf, CmBatt->DeviceNumber, GetTid() )
|
|||
|
);
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a buffer for this
|
|||
|
//
|
|||
|
outputBuffer = ExAllocatePoolWithTag(
|
|||
|
PagedPool,
|
|||
|
EXPECTED_DATA_SIZE,
|
|||
|
'MtaB'
|
|||
|
);
|
|||
|
if (!outputBuffer) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE),
|
|||
|
("CmBattGetBstData: Failed to allocate Buffer\n")
|
|||
|
);
|
|||
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Clear the buffers
|
|||
|
//
|
|||
|
RtlZeroMemory(outputBuffer, EXPECTED_DATA_SIZE);
|
|||
|
RtlZeroMemory(BstBuf, sizeof(CM_BST_BAT_INFO));
|
|||
|
|
|||
|
//
|
|||
|
// Set the request data
|
|||
|
//
|
|||
|
inputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
|
|||
|
inputBuffer.MethodNameAsUlong = CM_BST_METHOD;
|
|||
|
|
|||
|
//
|
|||
|
// Send the request along
|
|||
|
//
|
|||
|
status = CmBattSendDownStreamIrp(
|
|||
|
CmBatt->LowerDeviceObject,
|
|||
|
IOCTL_ACPI_EVAL_METHOD,
|
|||
|
&inputBuffer,
|
|||
|
sizeof(ACPI_EVAL_INPUT_BUFFER),
|
|||
|
outputBuffer,
|
|||
|
EXPECTED_DATA_SIZE
|
|||
|
);
|
|||
|
if (!NT_SUCCESS(status)) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBstData: Failed _BST method on device %x - Status (0x%x)\n",
|
|||
|
CmBatt->DeviceNumber, status)
|
|||
|
);
|
|||
|
goto CmBattGetBstDataExit;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Sanity check the return value
|
|||
|
//
|
|||
|
if (outputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE ||
|
|||
|
outputBuffer->Count != NUMBER_OF_BST_ELEMENTS) {
|
|||
|
|
|||
|
//
|
|||
|
// Package did not contain the correct number of elements to be a BIF
|
|||
|
//
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBstData: _BST returned %d elements. BIF requires %d\n",
|
|||
|
outputBuffer->Count,
|
|||
|
NUMBER_OF_BST_ELEMENTS)
|
|||
|
);
|
|||
|
status = STATUS_ACPI_INVALID_DATA;
|
|||
|
goto CmBattGetBstDataExit;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Look at the return arguments
|
|||
|
//
|
|||
|
argument = outputBuffer->Argument;
|
|||
|
|
|||
|
//
|
|||
|
// Parse the package data that is returned. This should look like:
|
|||
|
//
|
|||
|
status = GetDwordElement (argument, &BstBuf->BatteryState);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBstData: Failed to get BatteryState\n")
|
|||
|
);
|
|||
|
goto CmBattGetBstDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BstBuf->PresentRate);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBstData: Failed to get PresentRate\n")
|
|||
|
);
|
|||
|
goto CmBattGetBstDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BstBuf->RemainingCapacity);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBstData: Failed to get RemainingCapacity\n")
|
|||
|
);
|
|||
|
goto CmBattGetBstDataExit;
|
|||
|
}
|
|||
|
|
|||
|
argument = ACPI_METHOD_NEXT_ARGUMENT( argument );
|
|||
|
status = GetDwordElement (argument, &BstBuf->PresentVoltage);
|
|||
|
if (!NT_SUCCESS (status)) {
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE | CMBATT_BIOS),
|
|||
|
("CmBattGetBstData: Failed to get PresentVoltage\n")
|
|||
|
);
|
|||
|
goto CmBattGetBstDataExit;
|
|||
|
}
|
|||
|
|
|||
|
CmBattPrint ((CMBATT_TRACE | CMBATT_DATA | CMBATT_BIOS),
|
|||
|
("CmBattGetBstData: (BST) State=%x Rate=%x Capacity=%x Volts=%x\n",
|
|||
|
BstBuf->BatteryState, BstBuf->PresentRate,
|
|||
|
BstBuf->RemainingCapacity, BstBuf->PresentVoltage));
|
|||
|
|
|||
|
//
|
|||
|
// Done --- cleanup
|
|||
|
//
|
|||
|
|
|||
|
CmBattGetBstDataExit:
|
|||
|
ExFreePool( outputBuffer );
|
|||
|
return status;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
GetDwordElement (
|
|||
|
IN PACPI_METHOD_ARGUMENT Argument,
|
|||
|
OUT PULONG PDword
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine cracks the integer value from the argument and stores it
|
|||
|
in the supplied pointer to a ULONG
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Argument - Points to the argument to parse
|
|||
|
PDword - Where to store the argument
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Check to see if we have the right type of data
|
|||
|
//
|
|||
|
if (Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE),
|
|||
|
("GetDwordElement: Object contained wrong data type - %d\n",
|
|||
|
Argument->Type)
|
|||
|
);
|
|||
|
return STATUS_ACPI_INVALID_DATA;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy the DWORD
|
|||
|
//
|
|||
|
*PDword = Argument->Argument;
|
|||
|
|
|||
|
//
|
|||
|
// Success!
|
|||
|
//
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|
|||
|
|
|||
|
NTSTATUS
|
|||
|
GetStringElement (
|
|||
|
IN PACPI_METHOD_ARGUMENT Argument,
|
|||
|
OUT PUCHAR PBuffer
|
|||
|
)
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This routine cracks the string from the argument and stroes it in the
|
|||
|
supplied pointer to a PUCHAR
|
|||
|
|
|||
|
Note: A buffer is allowed as well.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
Argument - Points to the argument to parse
|
|||
|
PBuffer - Pointer to storage for the string
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
NT Status of the operation
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
//
|
|||
|
// Check to see if we have the right type of data
|
|||
|
//
|
|||
|
if (Argument->Type != ACPI_METHOD_ARGUMENT_STRING &&
|
|||
|
Argument->Type != ACPI_METHOD_ARGUMENT_BUFFER) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE),
|
|||
|
("GetStringElement: Object contained wrong data type - %d\n",
|
|||
|
Argument->Type)
|
|||
|
);
|
|||
|
return STATUS_ACPI_INVALID_DATA;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Check to see if the return buffer is long enough
|
|||
|
//
|
|||
|
if (Argument->DataLength >= CM_MAX_STRING_LENGTH) {
|
|||
|
|
|||
|
CmBattPrint(
|
|||
|
(CMBATT_ERROR | CMBATT_CM_EXE),
|
|||
|
("GetStringElement: return buffer not big enough - %d\n",
|
|||
|
Argument->DataLength)
|
|||
|
);
|
|||
|
return STATUS_BUFFER_TOO_SMALL;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Copy the string
|
|||
|
//
|
|||
|
RtlCopyMemory (PBuffer, Argument->Data, Argument->DataLength);
|
|||
|
|
|||
|
//
|
|||
|
// Success
|
|||
|
//
|
|||
|
return STATUS_SUCCESS;
|
|||
|
}
|