Something went wrong. Try again.
Reactos
Something went wrong. Try again.
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538/* * PROJECT: ReactOS ACPI-Compliant Control Method Battery * LICENSE: BSD - See COPYING.ARM in the top level directory * FILE: boot/drivers/bus/acpi/cmbatt/cmexec.c * PURPOSE: ACPI Method Execution/Evaluation Glue * PROGRAMMERS: ReactOS Portable Systems Group */
/* INCLUDES *******************************************************************/
#include "cmbatt.h"
#include <acpiioct.h>
typedef struct _ACPI_PACKAGE_FIELD{ PSTR Name; BOOLEAN IsString; PVOID Data;} ACPI_PACKAGE_FIELD, *PACPI_PACKAGE_FIELD;
/* FUNCTIONS ******************************************************************/
NTSTATUSNTAPIGetDwordElement(IN PACPI_METHOD_ARGUMENT Argument, OUT PULONG Value){ NTSTATUS Status;
/* Must have an integer */ if (Argument->Type != ACPI_METHOD_ARGUMENT_INTEGER) { /* Not an integer, fail */ Status = STATUS_ACPI_INVALID_DATA; if (CmBattDebug & 0x4C) DbgPrint("GetDwordElement: Object contained wrong data type - %d\n", Argument->Type); } else { /* Read the integer value */ *Value = Argument->Argument; Status = STATUS_SUCCESS; }
/* Return status */ return Status;}
NTSTATUSNTAPIGetStringElement(IN PACPI_METHOD_ARGUMENT Argument, OUT PCHAR Value){ NTSTATUS Status;
/* Must have a string of buffer */ if ((Argument->Type == ACPI_METHOD_ARGUMENT_STRING) || (Argument->Type == ACPI_METHOD_ARGUMENT_BUFFER)) { /* String must be less than 256 characters */ if (Argument->DataLength < 256) { /* Copy the buffer */ RtlCopyMemory(Value, Argument->Data, Argument->DataLength); Status = STATUS_SUCCESS; } else { /* The buffer is too small (the string is too large) */ Status = STATUS_BUFFER_TOO_SMALL; if (CmBattDebug & 0x4C) DbgPrint("GetStringElement: return buffer not big enough - %d\n", Argument->DataLength); } } else { /* Not valid string data */ Status = STATUS_ACPI_INVALID_DATA; if (CmBattDebug & 0x4C) DbgPrint("GetStringElement: Object contained wrong data type - %d\n", Argument->Type); }
/* Return the status */ return Status;}
NTSTATUSNTAPICmBattSendDownStreamIrp(IN PDEVICE_OBJECT DeviceObject, IN ULONG IoControlCode, IN PVOID InputBuffer, IN ULONG InputBufferLength, IN PACPI_EVAL_OUTPUT_BUFFER OutputBuffer, IN ULONG OutputBufferLength){ PIRP Irp; NTSTATUS Status; KEVENT Event; IO_STATUS_BLOCK IoStatusBlock; PAGED_CODE();
/* Initialize our wait event */ KeInitializeEvent(&Event, SynchronizationEvent, 0);
/* Allocate the IRP */ Irp = IoBuildDeviceIoControlRequest(IoControlCode, DeviceObject, InputBuffer, InputBufferLength, OutputBuffer, OutputBufferLength, 0, &Event, &IoStatusBlock); if (!Irp) { /* No IRP, fail */ if (CmBattDebug & 0x4C) DbgPrint("CmBattSendDownStreamIrp: Failed to allocate Irp\n"); return STATUS_INSUFFICIENT_RESOURCES; }
/* Call ACPI */ if (CmBattDebug & 0x40) DbgPrint("CmBattSendDownStreamIrp: Irp %x [Tid] %x\n", Irp, KeGetCurrentThread()); Status = IoCallDriver(DeviceObject, Irp); if (Status == STATUS_PENDING) { /* Wait for completion */ KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL); Status = Irp->IoStatus.Status; }
/* Check if caller wanted output */ if (OutputBuffer) { /* Make sure it's valid ACPI output buffer */ if ((OutputBuffer->Signature != ACPI_EVAL_OUTPUT_BUFFER_SIGNATURE) || !(OutputBuffer->Count)) { /* It isn't, so set failure code */ Status = STATUS_ACPI_INVALID_DATA; } }
/* Return status */ if (CmBattDebug & 0x40) DbgPrint("CmBattSendDownStreamIrp: Irp %x completed %x! [Tid] %x\n", Irp, Status, KeGetCurrentThread()); return Status;}
staticNTSTATUSCmBattCallAcpiPackage( _In_ LPCSTR FunctionName, _In_ PCMBATT_DEVICE_EXTENSION DeviceExtension, _In_ ULONG PackageName, _In_ ULONG OutputBufferSize, _In_ PACPI_PACKAGE_FIELD PackageFields, _In_ ULONG PackageFieldCount){ NTSTATUS Status; PACPI_EVAL_OUTPUT_BUFFER OutputBuffer; ACPI_EVAL_INPUT_BUFFER InputBuffer; PACPI_METHOD_ARGUMENT Argument; ULONG i; PAGED_CODE();
OutputBuffer = ExAllocatePoolWithTag(PagedPool, OutputBufferSize, 'MtaB'); if (!OutputBuffer) { if (CmBattDebug & (CMBATT_ACPI_ENTRY_EXIT | CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)) DbgPrint("%s: Failed to allocate Buffer\n", FunctionName); return STATUS_INSUFFICIENT_RESOURCES; }
/* Initialize to zero */ RtlZeroMemory(OutputBuffer, OutputBufferSize);
/* Request the ACPI method */ *(PULONG)InputBuffer.MethodName = PackageName; InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
/* Send it to ACPI */ Status = CmBattSendDownStreamIrp(DeviceExtension->AttachedDevice, IOCTL_ACPI_EVAL_METHOD, &InputBuffer, sizeof(InputBuffer), OutputBuffer, OutputBufferSize); if (!NT_SUCCESS(Status)) { if (CmBattDebug & (CMBATT_ACPI_ASSERT | CMBATT_ACPI_ENTRY_EXIT | CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)) DbgPrint("%s: Failed 0x%08x method on device %x - Status (0x%x)\n", FunctionName, PackageName, DeviceExtension->DeviceId, Status); ExFreePoolWithTag(OutputBuffer, 'MtaB'); return Status; }
/* Check if we got the right number of elements */ if (OutputBuffer->Count != PackageFieldCount) { if (CmBattDebug & (CMBATT_ACPI_ASSERT | CMBATT_ACPI_ENTRY_EXIT | CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)) DbgPrint("%s: 0x%08x method returned %d elements (requires %d)\n", FunctionName, PackageName, OutputBuffer->Count, PackageFieldCount); ExFreePoolWithTag(OutputBuffer, 'MtaB'); return STATUS_ACPI_INVALID_DATA; }
Argument = OutputBuffer->Argument; for (i = 0; i < PackageFieldCount && NT_SUCCESS(Status); i++) { if (PackageFields[i].IsString) Status = GetStringElement(Argument, PackageFields[i].Data); else Status = GetDwordElement(Argument, PackageFields[i].Data); if (!NT_SUCCESS(Status)) { if (CmBattDebug & (CMBATT_ACPI_ASSERT | CMBATT_ACPI_ENTRY_EXIT | CMBATT_ACPI_WARNING | CMBATT_GENERIC_WARNING)) DbgPrint("%s: Failed to get %s\n", FunctionName, PackageFields[i].Name); break; } Argument = ACPI_METHOD_NEXT_ARGUMENT(Argument); }
ExFreePoolWithTag(OutputBuffer, 'MtaB'); return Status;}
NTSTATUSNTAPICmBattGetPsrData(IN PDEVICE_OBJECT DeviceObject, OUT PULONG PsrData){ NTSTATUS Status; ACPI_EVAL_OUTPUT_BUFFER OutputBuffer; ACPI_EVAL_INPUT_BUFFER InputBuffer; PAGED_CODE(); if (CmBattDebug & 0x40) DbgPrint("CmBattGetPsrData: Entered with Pdo %x Tid %x\n", DeviceObject, KeGetCurrentThread());
/* Initialize to zero */ ASSERT(PsrData != NULL); *PsrData = 0;
/* Request the _PSR method */ *(PULONG)InputBuffer.MethodName = 'RSP_'; InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
/* Send it to ACPI */ Status = CmBattSendDownStreamIrp(DeviceObject, IOCTL_ACPI_EVAL_METHOD, &InputBuffer, sizeof(InputBuffer), &OutputBuffer, sizeof(OutputBuffer)); if (NT_SUCCESS(Status)) { /* Read the result */ Status = GetDwordElement(OutputBuffer.Argument, PsrData); if (CmBattDebug & 0x440) DbgPrint("CmBattGetPsrData: _PSR method returned %x \n", *PsrData); } else if (CmBattDebug & 0x44C) { /* Failure */ DbgPrint("CmBattGetPsrData: Failed _PSR method - Status (0x%x)\n", Status); }
/* Return status */ return Status;}
NTSTATUSNTAPICmBattGetStaData(IN PDEVICE_OBJECT DeviceObject, OUT PULONG StaData){ NTSTATUS Status; ACPI_EVAL_OUTPUT_BUFFER OutputBuffer; ACPI_EVAL_INPUT_BUFFER InputBuffer; PAGED_CODE(); if (CmBattDebug & 0x40) DbgPrint("CmBattGetStaData: Entered with Pdo %x Tid %x\n", DeviceObject, KeGetCurrentThread());
/* Initialize to zero */ ASSERT(StaData != NULL); *StaData = 0;
/* Request the _STA method */ *(PULONG)InputBuffer.MethodName = 'ATS_'; InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
/* Send it to ACPI */ Status = CmBattSendDownStreamIrp(DeviceObject, IOCTL_ACPI_EVAL_METHOD, &InputBuffer, sizeof(InputBuffer), &OutputBuffer, sizeof(OutputBuffer)); if (NT_SUCCESS(Status)) { /* Read the result */ Status = GetDwordElement(OutputBuffer.Argument, StaData); if (CmBattDebug & 0x440) DbgPrint("CmBattGetStaData: _STA method returned %x \n", *StaData); } else if (CmBattDebug & 0x44C) { /* Failure */ DbgPrint("CmBattGetStaData: Failed _STA method - Status (0x%x)\n", Status); Status = STATUS_NO_SUCH_DEVICE; }
/* Return status */ return Status;}
NTSTATUSNTAPICmBattGetUniqueId(IN PDEVICE_OBJECT DeviceObject, OUT PULONG UniqueId){ NTSTATUS Status; ACPI_EVAL_OUTPUT_BUFFER OutputBuffer; ACPI_EVAL_INPUT_BUFFER InputBuffer; PAGED_CODE(); if (CmBattDebug & 0x40) DbgPrint("CmBattGetUniqueId: Entered with Pdo %x Tid %x\n", DeviceObject, KeGetCurrentThread());
/* Initialize to zero */ ASSERT(UniqueId != NULL); *UniqueId = 0;
/* Request the _UID method */ *(PULONG)InputBuffer.MethodName = 'DIU_'; InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIGNATURE;
/* Send it to ACPI */ Status = CmBattSendDownStreamIrp(DeviceObject, IOCTL_ACPI_EVAL_METHOD, &InputBuffer, sizeof(InputBuffer), &OutputBuffer, sizeof(OutputBuffer)); if (NT_SUCCESS(Status)) { /* Read the result */ Status = GetDwordElement(OutputBuffer.Argument, UniqueId); if (CmBattDebug & 0x440) DbgPrint("CmBattGetUniqueId: _UID method returned %x \n", *UniqueId); } else if (CmBattDebug & 0x44C) { /* Failure */ DbgPrint("CmBattGetUniqueId: Failed _UID method - Status (0x%x)\n", Status); Status = STATUS_NO_SUCH_DEVICE; }
/* Return status */ return Status;}
NTSTATUSNTAPICmBattSetTripPoint(IN PCMBATT_DEVICE_EXTENSION DeviceExtension, IN ULONG AlarmValue){ NTSTATUS Status; ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER InputBuffer; PAGED_CODE(); if (CmBattDebug & 0x440) DbgPrint("CmBattSetTripPoint: _BTP Alarm Value %x Device %x Tid %x\n", AlarmValue, DeviceExtension->DeviceId, KeGetCurrentThread());
/* Request the _BTP method */ *(PULONG)InputBuffer.MethodName = 'PTB_'; InputBuffer.Signature = ACPI_EVAL_INPUT_BUFFER_SIMPLE_INTEGER_SIGNATURE; InputBuffer.IntegerArgument = AlarmValue;
/* Send it to ACPI */ Status = CmBattSendDownStreamIrp(DeviceExtension->AttachedDevice, IOCTL_ACPI_EVAL_METHOD, &InputBuffer, sizeof(InputBuffer), NULL, 0); if (!(NT_SUCCESS(Status)) && (CmBattDebug & 0x440)) DbgPrint("CmBattSetTripPoint: Failed _BTP method on device %x - Status (0x%x)\n", DeviceExtension->DeviceId, Status);
/* Return status */ return Status;}
NTSTATUSNTAPICmBattGetBifData(PCMBATT_DEVICE_EXTENSION DeviceExtension, PACPI_BIF_DATA BifData){ ACPI_PACKAGE_FIELD BifFields[] = { { "PowerUnit", FALSE, &BifData->PowerUnit }, { "DesignCapacity", FALSE, &BifData->DesignCapacity }, { "LastFullCapacity", FALSE, &BifData->LastFullCapacity }, { "BatteryTechnology", FALSE, &BifData->BatteryTechnology }, { "DesignVoltage", FALSE, &BifData->DesignVoltage }, { "DesignCapacityWarning", FALSE, &BifData->DesignCapacityWarning }, { "DesignCapacityLow", FALSE, &BifData->DesignCapacityLow }, { "BatteryCapacityGranularity1", FALSE, &BifData->BatteryCapacityGranularity1 }, { "BatteryCapacityGranularity2", FALSE, &BifData->BatteryCapacityGranularity2 }, { "ModelNumber", TRUE, &BifData->ModelNumber }, { "SerialNumber", TRUE, &BifData->SerialNumber }, { "BatteryType", TRUE, &BifData->BatteryType }, { "OemInfo", TRUE, &BifData->OemInfo }, }; PAGED_CODE();
if (CmBattDebug & CMBATT_ACPI_ENTRY_EXIT) DbgPrint("CmBattGetBifData: Buffer (0x%x) Device %x Tid %x\n", BifData, DeviceExtension->DeviceId, KeGetCurrentThread());
/* Request the _BIF method */ /* Note that _BIF method is deprecated since ACPI 4.0, and replaced by _BIX method. * However, VirtualBox 7.0 only support _BIF method. */ return CmBattCallAcpiPackage("CmBattGetBifData", DeviceExtension, 'FIB_', 512, BifFields, RTL_NUMBER_OF(BifFields));}
/** * @brief * Retrieves the eXtended static battery information from the * ACPI _BIX method. * * @param[in] DeviceExtension * A pointer to a Control Method (CM) battery device extension. * It is used to send the ACPI method evaluation operation * to the ACPI driver of which it is attached to this CM battery. * * @param[out] BixData * A pointer to a structure that contains the _BIX data fields, * returned to caller. * * @return * Returns STATUS_SUCCESS if the operation has succeeded successfully, * otherwise a failure NTSTATUS code is returned. */NTSTATUSNTAPICmBattGetBixData( _In_ PCMBATT_DEVICE_EXTENSION DeviceExtension, _Out_ PACPI_BIX_DATA BixData){ ACPI_PACKAGE_FIELD BixFields[] = { { "Revision", FALSE, &BixData->Revision }, { "PowerUnit", FALSE, &BixData->PowerUnit }, { "DesignCapacity", FALSE, &BixData->DesignCapacity }, { "LastFullCapacity", FALSE, &BixData->LastFullCapacity }, { "BatteryTechnology", FALSE, &BixData->BatteryTechnology }, { "DesignVoltage", FALSE, &BixData->DesignVoltage }, { "DesignCapacityWarning", FALSE, &BixData->DesignCapacityWarning }, { "DesignCapacityLow", FALSE, &BixData->DesignCapacityLow }, { "CycleCount", FALSE, &BixData->CycleCount }, { "Accuracy", FALSE, &BixData->Accuracy }, { "MaxSampleTime", FALSE, &BixData->MaxSampleTime }, { "MinSampleTime", FALSE, &BixData->MinSampleTime }, { "MaxAverageInterval", FALSE, &BixData->MaxAverageInterval }, { "MinAverageInterval", FALSE, &BixData->MinAverageInterval }, { "BatteryCapacityGranularity1", FALSE, &BixData->BatteryCapacityGranularity1 }, { "BatteryCapacityGranularity2", FALSE, &BixData->BatteryCapacityGranularity2 }, { "ModelNumber", TRUE, &BixData->ModelNumber }, { "SerialNumber", TRUE, &BixData->SerialNumber }, { "BatteryType", TRUE, &BixData->BatteryType }, { "OemInfo", TRUE, &BixData->OemInfo }, { "SwapCapability", FALSE, &BixData->SwapCapability }, }; PAGED_CODE();
if (CmBattDebug & CMBATT_ACPI_ENTRY_EXIT) { DbgPrint("CmBattGetBixData: Buffer (0x%x) Device %x Tid %x\n", BixData, DeviceExtension->DeviceId, KeGetCurrentThread()); }
/* Request the ACPI driver to get the _BIX data for us */ return CmBattCallAcpiPackage("CmBattGetBifData", DeviceExtension, 'XIB_', 512, BixFields, RTL_NUMBER_OF(BixFields));}
NTSTATUSNTAPICmBattGetBstData(PCMBATT_DEVICE_EXTENSION DeviceExtension, PACPI_BST_DATA BstData){ ACPI_PACKAGE_FIELD BstFields[] = { { "State", FALSE, &BstData->State }, { "PresentRate", FALSE, &BstData->PresentRate }, { "RemainingCapacity", FALSE, &BstData->RemainingCapacity }, { "PresentVoltage", FALSE, &BstData->PresentVoltage }, }; PAGED_CODE();
if (CmBattDebug & CMBATT_ACPI_ENTRY_EXIT) DbgPrint("CmBattGetBstData: Buffer (0x%x) Device %x Tid %x\n", BstData, DeviceExtension->DeviceId, KeGetCurrentThread());
return CmBattCallAcpiPackage("CmBattGetBstData", DeviceExtension, 'TSB_', 512, BstFields, RTL_NUMBER_OF(BstFields));}
/* EOF */