Added ACPI bus manager

Added ACPI button driver

svn path=/trunk/; revision=1890
This commit is contained in:
Casper Hornstrup 2001-05-05 19:15:44 +00:00
parent efc93e5ae8
commit ba2a8ca045
18 changed files with 5518 additions and 64 deletions

View file

@ -7,4 +7,15 @@ Changes to ACPI CA
+ include/platform/acwin.h
+ include/platform/types.h
- ospm/*
- ospm/ac_adapter/*
- ospm/battery/*
- ospm/button/*
- ospm/ec/*
- ospm/include/* (except bm.h)
- ospm/processor/*
- ospm/system/*
- ospm/thermal/*
- ospm/busmgr/bm_module.c
- ospm/busmgr/bm_proc.c
- ospm/busmgr/bm_symbols.c
- ospm/busmgr/Makefile

View file

@ -9,9 +9,21 @@ LIBS = $(PATH_TO_TOP)/ntoskrnl/ntoskrnl.a
OBJECTS_PATH = objects
OBJECTS_OSPM_BUSMGR = \
ospm/busmgr/bm.o \
ospm/busmgr/bmnotify.o \
ospm/busmgr/bmpm.o \
ospm/busmgr/bmpower.o \
ospm/busmgr/bmrequest.o \
ospm/busmgr/bmsearch.o \
ospm/busmgr/bmutils.o \
ospm/busmgr/bmxface.o
OBJECTS_OSPM = \
$(OBJECTS_OSPM_BUSMGR) \
ospm/acpienum.o \
ospm/acpisys.o \
ospm/bn.o \
ospm/osl.o
OBJECTS_DISPATCHER = \

View file

@ -1,4 +1,4 @@
/* $Id: acpienum.c,v 1.1 2001/05/01 23:00:03 chorns Exp $
/* $Id: acpienum.c,v 1.2 2001/05/05 19:15:44 chorns Exp $
*
* PROJECT: ReactOS ACPI bus driver
* FILE: acpi/ospm/acpienum.c
@ -8,55 +8,200 @@
* 01-05-2001 CSH Created
*/
#include <acpisys.h>
#include <acnamesp.h>
#include <bm.h>
#define NDEBUG
#include <debug.h>
ACPI_STATUS ACPIEnumerateDevice(
ACPI_HANDLE ObjHandle,
UINT32 Level,
PVOID Context,
PVOID *ReturnValue)
void
bm_print1 (
BM_NODE *node,
u32 flags)
{
ACPI_DEVICE_INFO Info;
ACPI_STATUS Status;
ACPI_BUFFER Path;
CHAR Buffer[256];
ACPI_BUFFER buffer;
BM_DEVICE *device = NULL;
char *type_string = NULL;
Path.length = sizeof(Buffer);
Path.pointer = Buffer;
if (!node) {
return;
}
/* Get the full path of this device and print it */
Status = acpi_get_name(ObjHandle, ACPI_FULL_PATHNAME, &Path);
device = &(node->device);
if (ACPI_SUCCESS(Status)) {
DPRINT("Device: %s\n", Path.pointer);
}
if (flags & BM_PRINT_PRESENT) {
if (!BM_DEVICE_PRESENT(device)) {
return;
}
}
/* Get the device info for this device and print it */
Status = acpi_get_object_info(ObjHandle, &Info);
if (ACPI_SUCCESS(Status)) {
DPRINT(" HID: %.8X, ADR: %.8X, Status: %x\n",
Info.hardware_id, Info.address,
Info.current_status);
}
return AE_OK;
buffer.length = 256;
buffer.pointer = acpi_os_callocate(buffer.length);
if (!buffer.pointer) {
return;
}
acpi_get_name(device->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
switch(device->id.type) {
case BM_TYPE_SYSTEM:
type_string = "System";
break;
case BM_TYPE_SCOPE:
type_string = "Scope";
break;
case BM_TYPE_PROCESSOR:
type_string = "Processor";
break;
case BM_TYPE_THERMAL_ZONE:
type_string = "ThermalZone";
break;
case BM_TYPE_POWER_RESOURCE:
type_string = "PowerResource";
break;
case BM_TYPE_FIXED_BUTTON:
type_string = "Button";
break;
case BM_TYPE_DEVICE:
type_string = "Device";
break;
default:
type_string = "Unknown";
break;
}
if (!(flags & BM_PRINT_GROUP)) {
DbgPrint("+------------------------------------------------------------\n");
}
DbgPrint("%s[0x%02x] hid[%s] %s\n", type_string, device->handle, device->id.hid, buffer.pointer);
DbgPrint(" acpi_handle[0x%08x] flags[0x%02x] status[0x%02x]\n", device->acpi_handle, device->flags, device->status);
if (flags & BM_PRINT_IDENTIFICATION) {
DbgPrint(" identification: uid[%s] adr[0x%08x]\n", device->id.uid, device->id.adr);
}
if (flags & BM_PRINT_LINKAGE) {
DbgPrint(" linkage: this[%p] parent[%p] next[%p]\n", node, node->parent, node->next);
DbgPrint(" scope.head[%p] scope.tail[%p]\n", node->scope.head, node->scope.tail);
}
if (flags & BM_PRINT_POWER) {
DbgPrint(" power: state[D%d] flags[0x%08X]\n", device->power.state, device->power.flags);
DbgPrint(" S0[0x%02x] S1[0x%02x] S2[0x%02x]\n", device->power.dx_supported[0], device->power.dx_supported[1], device->power.dx_supported[2]);
DbgPrint(" S3[0x%02x] S4[0x%02x] S5[0x%02x]\n", device->power.dx_supported[3], device->power.dx_supported[4], device->power.dx_supported[5]);
}
if (!(flags & BM_PRINT_GROUP)) {
DbgPrint("+------------------------------------------------------------\n");
}
acpi_os_free(buffer.pointer);
return;
}
NTSTATUS
ACPIEnumerateSystemDevices(
ACPIEnumerateRootBusses(
PACPI_DEVICE_EXTENSION DeviceExtension)
{
ACPI_HANDLE SysBusHandle;
BM_HANDLE_LIST HandleList;
PACPI_DEVICE AcpiDevice;
ACPI_STATUS AcpiStatus;
BM_HANDLE DeviceHandle;
BM_DEVICE_ID Criteria;
KIRQL OldIrql;
ULONG i;
DPRINT("Enumerating system devices\n");
BM_NODE *Node;
ULONG j;
acpi_get_handle(0, NS_SYSTEM_BUS, &SysBusHandle);
DPRINT("Display of all devices in the namespace:\n");
acpi_walk_namespace(ACPI_TYPE_DEVICE, SysBusHandle,
~0, ACPIEnumerateDevice, NULL, NULL);
DPRINT("Called\n");
RtlZeroMemory(&Criteria, sizeof(BM_DEVICE_ID));
RtlMoveMemory(&Criteria.hid, PCI_ROOT_HID_STRING, sizeof(PCI_ROOT_HID_STRING));
AcpiStatus = bm_search(BM_HANDLE_ROOT, &Criteria, &HandleList);
if (ACPI_SUCCESS(AcpiStatus)) {
DPRINT("Got %d devices\n", HandleList.count);
for (i = 0; i < HandleList.count; i++) {
AcpiStatus = bm_get_node(HandleList.handles[i], 0, &Node);
if (ACPI_SUCCESS(AcpiStatus)) {
DPRINT("Got BM node information: (Node 0x%X)\n", Node);
bm_print1(Node, BM_PRINT_ALL - BM_PRINT_PRESENT);
#if 0
for (j=0; j < 4*1000;j++)
KeStallExecutionProcessor(1000);
#endif
} else {
DPRINT("Could not get BM node\n");
}
AcpiDevice = (PACPI_DEVICE)ExAllocatePool(
NonPagedPool, sizeof(ACPI_DEVICE));
if (!AcpiDevice) {
return STATUS_INSUFFICIENT_RESOURCES;
}
AcpiDevice->Pdo = NULL;
AcpiDevice->BmHandle = HandleList.handles[i];
KeAcquireSpinLock(&DeviceExtension->DeviceListLock, &OldIrql);
InsertHeadList(&DeviceExtension->DeviceListHead,
&AcpiDevice->DeviceListEntry);
DeviceExtension->DeviceListCount++;
KeReleaseSpinLock(&DeviceExtension->DeviceListLock, OldIrql);
}
} else {
DPRINT("Got no devices (Status 0x%X)\n", AcpiStatus);
}
return STATUS_SUCCESS;
}
NTSTATUS
ACPIEnumerateNamespace(
PACPI_DEVICE_EXTENSION DeviceExtension)
{
ACPI_STATUS AcpiStatus;
BM_DEVICE_ID Criteria;
BM_HANDLE_LIST HandleList;
ULONG i;
BM_NODE *Node;
ULONG j, q;
DPRINT("Called\n");
RtlZeroMemory(&Criteria, sizeof(BM_DEVICE_ID));
DbgPrint("Listing ACPI namespace\n");
Criteria.type = BM_TYPE_ALL;
AcpiStatus = bm_search(BM_HANDLE_ROOT, &Criteria, &HandleList);
if (ACPI_SUCCESS(AcpiStatus)) {
DPRINT("Got %d devices\n", HandleList.count);
for (i = 0; i < HandleList.count; i++) {
AcpiStatus = bm_get_node(HandleList.handles[i], 0, &Node);
if (ACPI_SUCCESS(AcpiStatus)) {
DPRINT("Got BM node information: (Node 0x%X)\n", Node);
#if 0
bm_print1(Node, BM_PRINT_ALL - BM_PRINT_PRESENT);
for (j=0; j < 4*1000;j++)
KeStallExecutionProcessor(1000);*/
#endif
} else {
DPRINT("Could not get BM node\n");
}
}
} else {
DPRINT("Got no devices (Status 0x%X)\n", AcpiStatus);
}
return STATUS_SUCCESS;
}

View file

@ -1,4 +1,4 @@
/* $Id: acpisys.c,v 1.1 2001/05/01 23:00:03 chorns Exp $
/* $Id: acpisys.c,v 1.2 2001/05/05 19:15:44 chorns Exp $
*
* PROJECT: ReactOS ACPI bus driver
* FILE: acpi/ospm/acpisys.c
@ -8,6 +8,8 @@
* 01-05-2001 CSH Created
*/
#include <acpisys.h>
#include <bm.h>
#include <bn.h>
#define NDEBUG
#include <debug.h>
@ -19,15 +21,10 @@
#pragma alloc_text(init, DriverEntry)
// Make the PASSIVE_LEVEL routines pageable, so that they don't
// waste nonpaged memory
#pragma alloc_text(page, ACPIDispatchOpenClose)
#pragma alloc_text(page, ACPIDispatchRead)
#pragma alloc_text(page, ACPIDispatchWrite)
#endif /* ALLOC_PRAGMA */
FADT_DESCRIPTOR_REV2 acpi_fadt;
NTSTATUS
STDCALL
@ -84,6 +81,57 @@ VOID ACPIPrintInfo(
}
NTSTATUS
ACPIInitializeInternalDriver(
PACPI_DEVICE_EXTENSION DeviceExtension,
ACPI_DRIVER_FUNCTION Initialize,
ACPI_DRIVER_FUNCTION Terminate)
{
ACPI_STATUS AcpiStatus;
PACPI_DEVICE AcpiDevice;
AcpiStatus = Initialize();
if (!ACPI_SUCCESS(AcpiStatus)) {
DPRINT("BN init status 0x%X\n", AcpiStatus);
return STATUS_UNSUCCESSFUL;
}
#if 0
AcpiDevice = (PACPI_DEVICE)ExAllocatePool(
NonPagedPool, sizeof(ACPI_DEVICE));
if (!AcpiDevice) {
return STATUS_INSUFFICIENT_RESOURCES;
}
AcpiDevice->Initialize = Initialize;
AcpiDevice->Terminate = Terminate;
/* FIXME: Create PDO */
AcpiDevice->Pdo = NULL;
//AcpiDevice->BmHandle = HandleList.handles[i];
ExInterlockedInsertHeadList(&DeviceExtension->DeviceListHead,
&AcpiDevice->ListEntry, &DeviceExtension->DeviceListLock);
#endif
return STATUS_SUCCESS;
}
NTSTATUS
ACPIInitializeInternalDrivers(
PACPI_DEVICE_EXTENSION DeviceExtension)
{
NTSTATUS Status;
ULONG j;
Status = ACPIInitializeInternalDriver(DeviceExtension,
bn_initialize, bn_terminate);
return STATUS_SUCCESS;
}
NTSTATUS
ACPIStartDevice(
IN PDEVICE_OBJECT DeviceObject,
@ -106,13 +154,13 @@ ACPIStartDevice(
AcpiStatus = acpi_initialize_subsystem();
if (!ACPI_SUCCESS(AcpiStatus)) {
DPRINT("acpi_initialize_subsystem() failed with status 0x%X\n", AcpiStatus);
return STATUS_NO_SUCH_DEVICE;
return STATUS_UNSUCCESSFUL;
}
AcpiStatus = acpi_find_root_pointer(&rsdp);
if (!ACPI_SUCCESS(AcpiStatus)) {
DPRINT("acpi_find_root_pointer() failed with status 0x%X\n", AcpiStatus);
return STATUS_NO_SUCH_DEVICE;
return STATUS_UNSUCCESSFUL;
}
/* From this point on, on error we must call acpi_terminate() */
@ -121,7 +169,7 @@ ACPIStartDevice(
if (!ACPI_SUCCESS(AcpiStatus)) {
DPRINT("acpi_load_tables() failed with status 0x%X\n", AcpiStatus);
acpi_terminate();
return STATUS_NO_SUCH_DEVICE;
return STATUS_UNSUCCESSFUL;
}
Buffer.length = sizeof(SysInfo);
@ -131,16 +179,22 @@ ACPIStartDevice(
if (!ACPI_SUCCESS(AcpiStatus)) {
DPRINT("acpi_get_system_info() failed with status 0x%X\n", AcpiStatus);
acpi_terminate();
return STATUS_NO_SUCH_DEVICE;
return STATUS_UNSUCCESSFUL;
}
DPRINT("ACPI CA Core Subsystem version 0x%X\n", SysInfo.acpi_ca_version);
assert(SysInfo.num_table_types > ACPI_TABLE_FADT);
RtlMoveMemory(&acpi_fadt,
&SysInfo.table_info[ACPI_TABLE_FADT],
sizeof(FADT_DESCRIPTOR_REV2));
AcpiStatus = acpi_enable_subsystem(ACPI_FULL_INITIALIZATION);
if (!ACPI_SUCCESS(AcpiStatus)) {
DPRINT("acpi_enable_subsystem() failed with status 0x%X\n", AcpiStatus);
acpi_terminate();
return STATUS_NO_SUCH_DEVICE;
return STATUS_UNSUCCESSFUL;
}
DPRINT("ACPI CA Core Subsystem enabled\n");
@ -162,11 +216,27 @@ ACPIStartDevice(
}
}
DeviceExtension->State = dsStarted;
ACPIPrintInfo(DeviceExtension);
//ACPIEnumerateSystemDevices(DeviceExtension);
/* Initialize ACPI bus manager */
AcpiStatus = bm_initialize();
if (!ACPI_SUCCESS(AcpiStatus)) {
DPRINT("bm_initialize() failed with status 0x%X\n", AcpiStatus);
acpi_terminate();
return STATUS_UNSUCCESSFUL;
}
InitializeListHead(&DeviceExtension->DeviceListHead);
KeInitializeSpinLock(&DeviceExtension->DeviceListLock);
DeviceExtension->DeviceListCount = 0;
ACPIEnumerateNamespace(DeviceExtension);
ACPIEnumerateRootBusses(DeviceExtension);
ACPIInitializeInternalDrivers(DeviceExtension);
DeviceExtension->State = dsStarted;
return STATUS_SUCCESS;
}
@ -178,26 +248,61 @@ ACPIQueryBusRelations(
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
PACPI_DEVICE_EXTENSION DeviceExtension;
PDEVICE_RELATIONS Relations;
PLIST_ENTRY CurrentEntry;
PACPI_DEVICE Device;
NTSTATUS Status;
ULONG Size;
ULONG i;
DPRINT("Called\n");
Size = sizeof(DEVICE_RELATIONS);
DeviceExtension = (PACPI_DEVICE_EXTENSION)DeviceObject->DeviceExtension;
Size = sizeof(DEVICE_RELATIONS) + sizeof(Relations->Objects) *
(DeviceExtension->DeviceListCount - 1);
Relations = (PDEVICE_RELATIONS)ExAllocatePool(PagedPool, Size);
if (!Relations)
return STATUS_INSUFFICIENT_RESOURCES;
/* FIXME: Create PDOs and return them to PnP manager */
Relations->Count = DeviceExtension->DeviceListCount;
/* FIXME: For ACPI namespace devices create filter DOs and attach them
just above */
i = 0;
CurrentEntry = DeviceExtension->DeviceListHead.Flink;
while (CurrentEntry != &DeviceExtension->DeviceListHead) {
Device = CONTAINING_RECORD(CurrentEntry, ACPI_DEVICE, DeviceListEntry);
/* FIXME: For other devices in ACPI namespace, but not on motherboard,
create PDOs */
/* FIXME: For ACPI namespace devices on the motherboard create filter DOs
and attach them just above the ACPI bus device object (PDO) */
Relations->Count = 0;
/* FIXME: For other devices in ACPI namespace, but not on motherboard,
create PDOs */
if (!Device->Pdo) {
/* Create a physical device object for the
device as it does not already have one */
Status = IoCreateDevice(DeviceObject->DriverObject, 0,
NULL, FILE_DEVICE_CONTROLLER, 0, FALSE, &Device->Pdo);
if (!NT_SUCCESS(Status)) {
DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
ExFreePool(Relations);
return Status;
}
Device->Pdo->Flags |= DO_BUS_ENUMERATED_DEVICE;
}
/* Reference the physical device object. The PnP manager
will dereference it again when it is no longer needed */
ObReferenceObject(Device->Pdo);
Relations->Objects[i] = Device->Pdo;
i++;
CurrentEntry = CurrentEntry->Flink;
}
Irp->IoStatus.Information = (ULONG)Relations;
@ -228,6 +333,25 @@ ACPIQueryDeviceRelations(
}
NTSTATUS
ACPIQueryId(
IN PDEVICE_OBJECT DeviceObject,
IN PIRP Irp,
PIO_STACK_LOCATION IrpSp)
{
NTSTATUS Status;
DPRINT("Called\n");
switch (IrpSp->Parameters.QueryId.IdType) {
default:
Status = STATUS_NOT_IMPLEMENTED;
}
return Status;
}
NTSTATUS
ACPISetPower(
IN PDEVICE_OBJECT DeviceObject,
@ -304,6 +428,10 @@ ACPIPnpControl(
Status = ACPIQueryDeviceRelations(DeviceObject, Irp, IrpSp);
break;
case IRP_MN_QUERY_ID:
Status = ACPIQueryId(DeviceObject, Irp, IrpSp);
break;
case IRP_MN_START_DEVICE:
DPRINT("IRP_MN_START_DEVICE received\n");
Status = ACPIStartDevice(DeviceObject, Irp);
@ -311,6 +439,7 @@ ACPIPnpControl(
case IRP_MN_STOP_DEVICE:
/* Currently not supported */
//bm_terminate();
Status = STATUS_UNSUCCESSFUL;
break;
@ -378,7 +507,7 @@ ACPIAddDevice(
DPRINT("Called\n");
Status = IoCreateDevice(DriverObject, sizeof(ACPI_DEVICE_EXTENSION),
NULL, FILE_DEVICE_BUS_EXTENDER, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo);
NULL, FILE_DEVICE_ACPI, FILE_DEVICE_SECURE_OPEN, TRUE, &Fdo);
if (!NT_SUCCESS(Status)) {
DPRINT("IoCreateDevice() failed with status 0x%X\n", Status);
return Status;

View file

@ -0,0 +1,598 @@
/*****************************************************************************
*
* Module Name: bn.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Plxxe, Suite 330, Boston, MA 02111-1307 USA
*/
#include <acpi.h>
#include "bn.h"
#define _COMPONENT ACPI_BUTTON
MODULE_NAME ("bn")
static struct proc_dir_entry *bn_proc_root = NULL;
/*****************************************************************************
* Internal Functions
*****************************************************************************/
/*****************************************************************************
*
* FUNCTION: bn_print
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: Prints out information on a specific button.
*
****************************************************************************/
void
bn_print (
BN_CONTEXT *button)
{
#ifdef ACPI_DEBUG
ACPI_BUFFER buffer;
#endif /*ACPI_DEBUG*/
if (!button) {
return;
}
switch (button->type) {
case BN_TYPE_POWER_BUTTON:
case BN_TYPE_POWER_BUTTON_FIXED:
acpi_os_printf("Power Button: found\n");
break;
case BN_TYPE_SLEEP_BUTTON:
case BN_TYPE_SLEEP_BUTTON_FIXED:
acpi_os_printf("Sleep Button: found\n");
break;
case BN_TYPE_LID_SWITCH:
acpi_os_printf("Lid Switch: found\n");
break;
}
#ifdef ACPI_DEBUG
buffer.length = 256;
buffer.pointer = acpi_os_callocate(buffer.length);
if (!buffer.pointer) {
return;
}
/*
* Get the full pathname for this ACPI object.
*/
acpi_get_name(button->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
/*
* Print out basic button information.
*/
DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
switch (button->type) {
case BN_TYPE_POWER_BUTTON:
case BN_TYPE_POWER_BUTTON_FIXED:
DEBUG_PRINT(ACPI_INFO, ("| PowerButton[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer));
break;
case BN_TYPE_SLEEP_BUTTON:
case BN_TYPE_SLEEP_BUTTON_FIXED:
DEBUG_PRINT(ACPI_INFO, ("| SleepButton[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer));
break;
case BN_TYPE_LID_SWITCH:
DEBUG_PRINT(ACPI_INFO, ("| LidSwitch[0x%02x]|[%p] %s\n", button->device_handle, button->acpi_handle, buffer.pointer));
break;
}
DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
acpi_os_free(buffer.pointer);
#endif /*ACPI_DEBUG*/
return;
}
/****************************************************************************
*
* FUNCTION: bn_add_device
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bn_add_device(
BM_HANDLE device_handle,
void **context)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE *device = NULL;
BN_CONTEXT *button = NULL;
FUNCTION_TRACE("bn_add_device");
DEBUG_PRINT(ACPI_INFO, ("Adding button device [0x%02x].\n", device_handle));
if (!context || *context) {
DEBUG_PRINT(ACPI_ERROR, ("Invalid context.\n"));
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Get information on this device.
*/
status = bm_get_device_info( device_handle, &device );
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Allocate a new BN_CONTEXT structure.
*/
button = acpi_os_callocate(sizeof(BN_CONTEXT));
if (!button) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
button->device_handle = device->handle;
button->acpi_handle = device->acpi_handle;
/*
* Power Button?
* -------------
* Either fixed-feature or generic (namespace) types.
*/
if (strncmp(device->id.hid, BN_HID_POWER_BUTTON,
sizeof(BM_DEVICE_HID)) == 0) {
if (device->id.type == BM_TYPE_FIXED_BUTTON) {
button->type = BN_TYPE_POWER_BUTTON_FIXED;
/* Register for fixed-feature events. */
status = acpi_install_fixed_event_handler(
ACPI_EVENT_POWER_BUTTON, bn_notify_fixed,
(void*)button);
}
else {
button->type = BN_TYPE_POWER_BUTTON;
}
//proc_mkdir(BN_PROC_POWER_BUTTON, bn_proc_root);
}
/*
* Sleep Button?
* -------------
* Either fixed-feature or generic (namespace) types.
*/
else if (strncmp( device->id.hid, BN_HID_SLEEP_BUTTON,
sizeof(BM_DEVICE_HID)) == 0) {
if (device->id.type == BM_TYPE_FIXED_BUTTON) {
button->type = BN_TYPE_SLEEP_BUTTON_FIXED;
/* Register for fixed-feature events. */
status = acpi_install_fixed_event_handler(
ACPI_EVENT_SLEEP_BUTTON, bn_notify_fixed,
(void*)button);
}
else {
button->type = BN_TYPE_SLEEP_BUTTON;
}
//proc_mkdir(BN_PROC_SLEEP_BUTTON, bn_proc_root);
}
/*
* LID Switch?
* -----------
*/
else if (strncmp( device->id.hid, BN_HID_LID_SWITCH,
sizeof(BM_DEVICE_HID)) == 0) {
button->type = BN_TYPE_LID_SWITCH;
//proc_mkdir(BN_PROC_LID_SWITCH, bn_proc_root);
}
*context = button;
bn_print(button);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bn_remove_device
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bn_remove_device(
void **context)
{
ACPI_STATUS status = AE_OK;
BN_CONTEXT *button = NULL;
FUNCTION_TRACE("bn_remove_device");
if (!context || !*context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
button = (BN_CONTEXT*)*context;
DEBUG_PRINT(ACPI_INFO, ("Removing button device [0x%02x].\n", button->device_handle));
/*
* Remove the /proc entry for this button.
*/
switch (button->type) {
case BN_TYPE_POWER_BUTTON:
case BN_TYPE_POWER_BUTTON_FIXED:
/* Unregister for fixed-feature events. */
status = acpi_remove_fixed_event_handler(
ACPI_EVENT_POWER_BUTTON, bn_notify_fixed);
//remove_proc_entry(BN_PROC_POWER_BUTTON, bn_proc_root);
break;
case BN_TYPE_SLEEP_BUTTON:
case BN_TYPE_SLEEP_BUTTON_FIXED:
/* Unregister for fixed-feature events. */
status = acpi_remove_fixed_event_handler(
ACPI_EVENT_SLEEP_BUTTON, bn_notify_fixed);
//remove_proc_entry(BN_PROC_SLEEP_BUTTON, bn_proc_root);
break;
case BN_TYPE_LID_SWITCH:
//remove_proc_entry(BN_PROC_LID_SWITCH, bn_proc_root);
break;
}
acpi_os_free(button);
*context = NULL;
return_ACPI_STATUS(status);
}
/*****************************************************************************
* External Functions
*****************************************************************************/
/*****************************************************************************
*
* FUNCTION: bn_initialize
*
* PARAMETERS: <none>
*
* RETURN:
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bn_initialize (void)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE_ID criteria;
BM_DRIVER driver;
FUNCTION_TRACE("bn_initialize");
MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
MEMSET(&driver, 0, sizeof(BM_DRIVER));
driver.notify = &bn_notify;
driver.request = &bn_request;
/*
* Create button's root /proc entry.
*/
//bn_proc_root = proc_mkdir(BN_PROC_ROOT, bm_proc_root);
//if (!bn_proc_root) {
// return_ACPI_STATUS(AE_ERROR);
// }
/*
* Register for power buttons.
*/
MEMCPY(criteria.hid, BN_HID_POWER_BUTTON, sizeof(BN_HID_POWER_BUTTON));
status = bm_register_driver(&criteria, &driver);
/*
* Register for sleep buttons.
*/
MEMCPY(criteria.hid, BN_HID_SLEEP_BUTTON, sizeof(BN_HID_SLEEP_BUTTON));
status = bm_register_driver(&criteria, &driver);
/*
* Register for LID switches.
*/
MEMCPY(criteria.hid, BN_HID_LID_SWITCH, sizeof(BN_HID_LID_SWITCH));
status = bm_register_driver(&criteria, &driver);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bn_terminate
*
* PARAMETERS: <none>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bn_terminate (void)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE_ID criteria;
BM_DRIVER driver;
FUNCTION_TRACE("bn_terminate");
MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
MEMSET(&driver, 0, sizeof(BM_DRIVER));
driver.notify = &bn_notify;
driver.request = &bn_request;
/*
* Unregister for power buttons.
*/
MEMCPY(criteria.hid, BN_HID_POWER_BUTTON, sizeof(BN_HID_POWER_BUTTON));
status = bm_unregister_driver(&criteria, &driver);
/*
* Unregister for sleep buttons.
*/
MEMCPY(criteria.hid, BN_HID_SLEEP_BUTTON, sizeof(BN_HID_SLEEP_BUTTON));
status = bm_unregister_driver(&criteria, &driver);
/*
* Unregister for LID switches.
*/
MEMCPY(criteria.hid, BN_HID_LID_SWITCH, sizeof(BN_HID_LID_SWITCH));
status = bm_unregister_driver(&criteria, &driver);
/*
* Remove button's root /proc entry.
*/
if (bn_proc_root) {
//remove_proc_entry(BN_PROC_ROOT, bm_proc_root);
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bn_notify_fixed
*
* PARAMETERS: <none>
*
* RETURN:
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bn_notify_fixed (
void *context)
{
ACPI_STATUS status = AE_OK;
BN_CONTEXT *button = NULL;
FUNCTION_TRACE("bn_notify_fixed");
if (!context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
button = (BN_CONTEXT*)context;
DbgPrint("Fixed button status change event detected.\n");
switch (button->type) {
case BN_TYPE_POWER_BUTTON_FIXED:
DEBUG_PRINT(ACPI_INFO, ("Fixed-feature button status change event detected.\n"));
/*bm_generate_event(button->device_handle, BN_PROC_ROOT,
BN_PROC_POWER_BUTTON, BN_NOTIFY_STATUS_CHANGE, 0);*/
break;
case BN_TYPE_SLEEP_BUTTON_FIXED:
DEBUG_PRINT(ACPI_INFO, ("Fixed-feature button status change event detected.\n"));
/*bm_generate_event(button->device_handle, BN_PROC_ROOT,
BN_PROC_SLEEP_BUTTON, BN_NOTIFY_STATUS_CHANGE, 0);*/
break;
default:
DEBUG_PRINT(ACPI_INFO, ("Unsupported fixed-feature event detected.\n"));
status = AE_SUPPORT;
break;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bn_notify
*
* PARAMETERS: <none>
*
* RETURN:
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bn_notify (
BM_NOTIFY notify_type,
BM_HANDLE device_handle,
void **context)
{
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE("bn_notify");
if (!context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
switch (notify_type) {
case BM_NOTIFY_DEVICE_ADDED:
status = bn_add_device(device_handle, context);
break;
case BM_NOTIFY_DEVICE_REMOVED:
status = bn_remove_device(context);
break;
case BN_NOTIFY_STATUS_CHANGE:
DEBUG_PRINT(ACPI_INFO, ("Button status change event detected.\n"));
DbgPrint("Button status change event detected.\n");
if (!context || !*context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
switch(((BN_CONTEXT*)*context)->type) {
case BN_TYPE_POWER_BUTTON:
case BN_TYPE_POWER_BUTTON_FIXED:
/*bm_generate_event(device_handle, BN_PROC_ROOT,
BN_PROC_POWER_BUTTON, notify_type, 0);*/
break;
case BN_TYPE_SLEEP_BUTTON:
case BN_TYPE_SLEEP_BUTTON_FIXED:
/*bm_generate_event(device_handle, BN_PROC_ROOT,
BN_PROC_SLEEP_BUTTON, notify_type, 0);*/
break;
case BN_TYPE_LID_SWITCH:
/*bm_generate_event(device_handle, BN_PROC_ROOT,
BN_PROC_LID_SWITCH, notify_type, 0);*/
break;
default:
status = AE_SUPPORT;
break;
}
break;
default:
status = AE_SUPPORT;
break;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bn_request
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bn_request (
BM_REQUEST *request,
void *context)
{
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE("bn_request");
/*
* Must have a valid request structure and context.
*/
if (!request || !context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Handle Request:
* ---------------
*/
switch (request->command) {
default:
status = AE_SUPPORT;
break;
}
request->status = status;
return_ACPI_STATUS(status);
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,310 @@
/*****************************************************************************
*
* Module Name: bmnotify.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <acpi.h>
#include "bm.h"
#define _COMPONENT ACPI_BUS_MANAGER
MODULE_NAME ("bmnotify")
/****************************************************************************
* Internal Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_generate_notify
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_generate_notify (
BM_NODE *node,
u32 notify_type)
{
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE("bm_generate_notify");
if (!node) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
DEBUG_PRINT(ACPI_INFO, ("Sending notify [0x%02x] to device [0x%02x].\n", notify_type, node->device.handle));
if (!(node->device.flags & BM_FLAGS_DRIVER_CONTROL) ||
!(node->driver.notify)) {
DEBUG_PRINT(ACPI_WARN, ("No driver installed for device [0x%02x].\n", node->device.handle));
return_ACPI_STATUS(AE_NOT_EXIST);
}
status = node->driver.notify(notify_type, node->device.handle,
&(node->driver.context));
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_device_check
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_device_check (
BM_NODE *node,
u32 *status_change)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE *device = NULL;
BM_DEVICE_STATUS old_status = BM_STATUS_UNKNOWN;
FUNCTION_TRACE("bm_device_check");
if (!node) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
device = &(node->device);
if (status_change) {
*status_change = FALSE;
}
old_status = device->status;
/*
* Parent Present?
* ---------------
* Only check this device if its parent is present (which implies
* this device MAY be present).
*/
if (!BM_NODE_PRESENT(node->parent)) {
return_ACPI_STATUS(AE_OK);
}
/*
* Get Status:
* -----------
* And see if the status has changed.
*/
status = bm_get_status(device);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (old_status == node->device.status) {
return_ACPI_STATUS(AE_OK);
}
if (status_change) {
*status_change = TRUE;
}
/*
* Device Insertion?
* -----------------
*/
if ((device->status & BM_STATUS_PRESENT) &&
!(old_status & BM_STATUS_PRESENT)) {
/* TODO: Make sure driver is loaded, and if not, load. */
status = bm_generate_notify(node, BM_NOTIFY_DEVICE_ADDED);
}
/*
* Device Removal?
* ---------------
*/
else if (!(device->status & BM_STATUS_PRESENT) &&
(old_status & BM_STATUS_PRESENT)) {
/* TODO: Unload driver if last device instance. */
status = bm_generate_notify(node, BM_NOTIFY_DEVICE_REMOVED);
}
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_bus_check
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_bus_check (
BM_NODE *parent_node)
{
ACPI_STATUS status = AE_OK;
u32 status_change = FALSE;
FUNCTION_TRACE("bm_bus_check");
if (!parent_node) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Status Change?
* --------------
*/
status = bm_device_check(parent_node, &status_change);
if (ACPI_FAILURE(status) || !status_change) {
return_ACPI_STATUS(status);
}
/*
* Enumerate Scope:
* ----------------
* TODO: Enumerate child devices within this device's scope and
* run bm_device_check()'s on them...
*/
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_notify
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
void
bm_notify (
ACPI_HANDLE acpi_handle,
u32 notify_value,
void *context)
{
ACPI_STATUS status = AE_OK;
BM_NODE *node = NULL;
FUNCTION_TRACE("bm_notify");
/*
* Resolve the ACPI handle.
*/
status = bm_get_node(0, acpi_handle, &node);
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_INFO, ("Recieved notify [0x%02x] for unknown device [%p].\n", notify_value, acpi_handle));
return_VOID;
}
/*
* Device-Specific or Standard?
* ----------------------------
* Device-specific notifies are forwarded to the control module's
* notify() function for processing. Standard notifies are handled
* internally.
*/
if (notify_value > 0x7F) {
status = bm_generate_notify(node, notify_value);
}
else {
switch (notify_value) {
case BM_NOTIFY_BUS_CHECK:
DEBUG_PRINT(ACPI_INFO, ("Received BUS CHECK notification.\n"));
status = bm_bus_check(node);
break;
case BM_NOTIFY_DEVICE_CHECK:
DEBUG_PRINT(ACPI_INFO, ("Received DEVICE CHECK notification.\n"));
status = bm_device_check(node, NULL);
break;
case BM_NOTIFY_DEVICE_WAKE:
DEBUG_PRINT(ACPI_INFO, ("Received DEVICE WAKE notification.\n"));
/* TODO */
break;
case BM_NOTIFY_EJECT_REQUEST:
DEBUG_PRINT(ACPI_INFO, ("Received EJECT REQUEST notification.\n"));
/* TODO */
break;
case BM_NOTIFY_DEVICE_CHECK_LIGHT:
DEBUG_PRINT(ACPI_INFO, ("Received DEVICE CHECK LIGHT notification.\n"));
/* TODO: Exactly what does the 'light' mean? */
status = bm_device_check(node, NULL);
break;
case BM_NOTIFY_FREQUENCY_MISMATCH:
DEBUG_PRINT(ACPI_INFO, ("Received FREQUENCY MISMATCH notification.\n"));
/* TODO */
break;
case BM_NOTIFY_BUS_MODE_MISMATCH:
DEBUG_PRINT(ACPI_INFO, ("Received BUS MODE MISMATCH notification.\n"));
/* TODO */
break;
case BM_NOTIFY_POWER_FAULT:
DEBUG_PRINT(ACPI_INFO, ("Received POWER FAULT notification.\n"));
/* TODO */
break;
default:
DEBUG_PRINT(ACPI_INFO, ("Received unknown/unsupported notification.\n"));
break;
}
}
return_VOID;
}

View file

@ -0,0 +1,397 @@
/*****************************************************************************
*
* Module Name: bmpm.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <acpi.h>
#include "bm.h"
#include "bmpower.h"
#define _COMPONENT ACPI_POWER_CONTROL
MODULE_NAME ("bmpm")
/****************************************************************************
* Internal Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_get_inferred_power_state
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_get_inferred_power_state (
BM_DEVICE *device)
{
ACPI_STATUS status = AE_OK;
BM_HANDLE_LIST pr_list;
BM_POWER_STATE list_state = ACPI_STATE_UNKNOWN;
char object_name[5] = {'_','P','R','0','\0'};
u32 i = 0;
FUNCTION_TRACE("bm_get_inferred_power_state");
if (!device) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
MEMSET(&pr_list, 0, sizeof(BM_HANDLE_LIST));
device->power.state = ACPI_STATE_D3;
/*
* Calculate Power State:
* ----------------------
* Try to infer the devices's power state by checking the state of
* the devices's power resources. We start by evaluating _PR0
* (resource requirements at D0) and work through _PR1 and _PR2.
* We know the current devices power state when all resources (for
* a give Dx state) are ON. If no power resources are on then the
* device is assumed to be off (D3).
*/
for (i=ACPI_STATE_D0; i<ACPI_STATE_D3; i++) {
status = bm_evaluate_reference_list(device->acpi_handle,
object_name, &pr_list);
if (ACPI_SUCCESS(status)) {
status = bm_pr_list_get_state(&pr_list,
&list_state);
if (ACPI_SUCCESS(status)) {
if (list_state == ACPI_STATE_D0) {
device->power.state = i;
break;
}
}
}
}
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_get_power_state
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_get_power_state (
BM_NODE *node)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE *device = NULL;
FUNCTION_TRACE("bm_get_power_state");
if (!node) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
device = &(node->device);
device->power.state = ACPI_STATE_UNKNOWN;
if (device->flags & BM_FLAGS_POWER_STATE) {
status = bm_evaluate_simple_integer(device->acpi_handle,
"_PSC", &(device->power.state));
}
else {
status = bm_get_inferred_power_state(device);
}
if (ACPI_SUCCESS(status)) {
DEBUG_PRINT(ACPI_INFO, ("Device [0x%02x] is at power state [D%d].\n", device->handle, device->power.state));
}
else {
DEBUG_PRINT(ACPI_INFO, ("Error getting power state for device [0x%02x]\n", device->handle));
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_set_power_state
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_set_power_state (
BM_NODE *node,
BM_POWER_STATE state)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE *device = NULL;
BM_DEVICE *parent_device = NULL;
BM_HANDLE_LIST current_list;
BM_HANDLE_LIST target_list;
char object_name[5] = {'_','P','R','0','\0'};
FUNCTION_TRACE("bm_set_power_state");
if (!node || !node->parent || (state > ACPI_STATE_D3)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
MEMSET(&current_list, 0, sizeof(BM_HANDLE_LIST));
MEMSET(&target_list, 0, sizeof(BM_HANDLE_LIST));
device = &(node->device);
parent_device = &(node->parent->device);
/*
* Check Parent's Power State:
* ---------------------------
* Can't be in a higher power state (lower Dx value) than parent.
*/
if (state < parent_device->power.state) {
DEBUG_PRINT(ACPI_WARN, ("Cannot set device [0x%02x] to a higher-powered state than parent_device.\n", device->handle));
return_ACPI_STATUS(AE_ERROR);
}
/*
* Get Resources:
* --------------
* Get the power resources associated with the device's current
* and target power states.
*/
if (device->power.state != ACPI_STATE_UNKNOWN) {
object_name[3] = '0' + device->power.state;
bm_evaluate_reference_list(device->acpi_handle,
object_name, &current_list);
}
object_name[3] = '0' + state;
bm_evaluate_reference_list(device->acpi_handle, object_name,
&target_list);
/*
* Transition Resources:
* ---------------------
* Transition all power resources referenced by this device to
* the correct power state (taking into consideration sequencing
* and dependencies to other devices).
*/
if (current_list.count || target_list.count) {
status = bm_pr_list_transition(&current_list, &target_list);
}
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Execute _PSx:
* -------------
* Execute the _PSx method corresponding to the target Dx state,
* if it exists.
*/
object_name[2] = 'S';
object_name[3] = '0' + state;
bm_evaluate_object(device->acpi_handle, object_name, NULL, NULL);
if (ACPI_SUCCESS(status)) {
DEBUG_PRINT(ACPI_INFO, ("Device [0x%02x] is now at [D%d].\n", device->handle, state));
device->power.state = state;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_get_pm_capabilities
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_get_pm_capabilities (
BM_NODE *node)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE *device = NULL;
BM_DEVICE *parent_device = NULL;
ACPI_HANDLE acpi_handle = NULL;
BM_POWER_STATE dx_supported = ACPI_STATE_UNKNOWN;
char object_name[5] = {'_','S','0','D','\0'};
u32 i = 0;
FUNCTION_TRACE("bm_get_pm_capabilities");
if (!node || !node->parent) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
device = &(node->device);
parent_device = &(node->parent->device);
/*
* Power Management Flags:
* -----------------------
*/
if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PSC",
&acpi_handle))) {
device->power.flags |= BM_FLAGS_POWER_STATE;
}
if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_IRC",
&acpi_handle))) {
device->power.flags |= BM_FLAGS_INRUSH_CURRENT;
}
if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PRW",
&acpi_handle))) {
device->power.flags |= BM_FLAGS_WAKE_CAPABLE;
}
/*
* Device Power State:
* -------------------
* Note that we can't get the device's power state until we've
* initialized all power resources, so for now we just set to
* unknown.
*/
device->power.state = ACPI_STATE_UNKNOWN;
/*
* Dx Supported in S0:
* -------------------
* Figure out which Dx states are supported by this device for the
* S0 (working) state. Note that D0 and D3 are required (assumed).
*/
device->power.dx_supported[ACPI_STATE_S0] = BM_FLAGS_D0_SUPPORT |
BM_FLAGS_D3_SUPPORT;
if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR1",
&acpi_handle))) ||
(ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS1",
&acpi_handle)))) {
device->power.dx_supported[ACPI_STATE_S0] |=
BM_FLAGS_D1_SUPPORT;
}
if ((ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PR2",
&acpi_handle))) ||
(ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, "_PS2",
&acpi_handle)))) {
device->power.dx_supported[ACPI_STATE_S0] |=
BM_FLAGS_D2_SUPPORT;
}
/*
* Dx Supported in S1-S5:
* ----------------------
* Figure out which Dx states are supported by this device for
* all other Sx states.
*/
for (i = ACPI_STATE_S1; i <= ACPI_STATE_S5; i++) {
/*
* D3 support is assumed (off is always possible!).
*/
device->power.dx_supported[i] = BM_FLAGS_D3_SUPPORT;
/*
* Evalute _SxD:
* -------------
* Which returns the highest (power) Dx state supported in
* this system (Sx) state. We convert this value to a bit
* mask of supported states (conceptually simpler).
*/
status = bm_evaluate_simple_integer(device->acpi_handle,
object_name, &dx_supported);
if (ACPI_SUCCESS(status)) {
switch (dx_supported) {
case 0:
device->power.dx_supported[i] |=
BM_FLAGS_D0_SUPPORT;
/* fall through */
case 1:
device->power.dx_supported[i] |=
BM_FLAGS_D1_SUPPORT;
/* fall through */
case 2:
device->power.dx_supported[i] |=
BM_FLAGS_D2_SUPPORT;
/* fall through */
case 3:
device->power.dx_supported[i] |=
BM_FLAGS_D3_SUPPORT;
break;
}
/*
* Validate:
* ---------
* Mask of any states that _Sx_d falsely advertises
* (e.g.claims D1 support but neither _PR2 or _PS2
* exist). In other words, S1-S5 can't offer a Dx
* state that isn't supported by S0.
*/
device->power.dx_supported[i] &=
device->power.dx_supported[ACPI_STATE_S0];
}
object_name[2]++;
}
return_ACPI_STATUS(status);
}

View file

@ -0,0 +1,669 @@
/****************************************************************************
*
* Module Name: bmpower.c - Driver for ACPI Power Resource 'devices'
* $Revision: 1.1 $
*
****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
/*
* TODO:
* -----
* 1. Sequencing of power resource list transitions.
* 2. Global serialization of power resource transtions (see ACPI
* spec section 7.1.2/7.1.3).
* 3. Better error handling.
*/
#include <acpi.h>
#include "bm.h"
#include "bmpower.h"
#define _COMPONENT ACPI_POWER_CONTROL
MODULE_NAME ("bmpower")
/****************************************************************************
* Function Prototypes
****************************************************************************/
ACPI_STATUS
bm_pr_notify (
BM_NOTIFY notify_type,
BM_HANDLE device_handle,
void **context);
ACPI_STATUS
bm_pr_request (
BM_REQUEST *request,
void *context);
/****************************************************************************
* Internal Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_pr_print
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_print (
BM_POWER_RESOURCE *pr)
{
ACPI_BUFFER buffer;
if (!pr) {
return(AE_BAD_PARAMETER);
}
buffer.length = 256;
buffer.pointer = acpi_os_callocate(buffer.length);
if (!buffer.pointer) {
return(AE_NO_MEMORY);
}
acpi_get_name(pr->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
acpi_os_printf("Power Resource: found\n");
DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
DEBUG_PRINT(ACPI_INFO, ("PowerResource[0x%02X]|[0x%08X] %s\n", pr->device_handle, pr->acpi_handle, buffer.pointer));
DEBUG_PRINT(ACPI_INFO, (" system_level[S%d] resource_order[%d]\n", pr->system_level, pr->resource_order));
DEBUG_PRINT(ACPI_INFO, (" state[D%d] reference_count[%d]\n", pr->state, pr->reference_count));
DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n"));
acpi_os_free(buffer.pointer);
return(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_pr_get_state
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_get_state (
BM_POWER_RESOURCE *pr)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE_STATUS device_status = BM_STATUS_UNKNOWN;
FUNCTION_TRACE("bm_pr_get_state");
if (!pr) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
pr->state = ACPI_STATE_UNKNOWN;
/*
* Evaluate _STA:
* --------------
* Evalute _STA to determine whether the power resource is ON or OFF.
* Note that if the power resource isn't present we'll get AE_OK but
* an unknown status.
*/
status = bm_get_device_status(pr->device_handle, &device_status);
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_ERROR, ("Error reading status for power resource [0x%02x].\n", pr->device_handle));
return_ACPI_STATUS(status);
}
if (device_status == BM_STATUS_UNKNOWN) {
DEBUG_PRINT(ACPI_ERROR, ("Error reading status for power resource [0x%02x].\n", pr->device_handle));
return_ACPI_STATUS(AE_NOT_EXIST);
}
/*
* Mask off all bits but the first as some systems return non-standard
* values (e.g. 0x51).
*/
switch (device_status & 0x01) {
case 0:
DEBUG_PRINT(ACPI_INFO, ("Power resource [0x%02x] is OFF.\n", pr->device_handle));
pr->state = ACPI_STATE_D3;
break;
case 1:
DEBUG_PRINT(ACPI_INFO, ("Power resource [0x%02x] is ON.\n", pr->device_handle));
pr->state = ACPI_STATE_D0;
break;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_pr_set_state
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_set_state (
BM_POWER_RESOURCE *pr,
BM_POWER_STATE target_state)
{
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE("bm_pr_set_state");
if (!pr) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
status = bm_pr_get_state(pr);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (target_state == pr->state) {
DEBUG_PRINT(ACPI_INFO, ("Power resource [0x%02X] already at target power state [D%d].\n", pr->device_handle, pr->state));
return_ACPI_STATUS(AE_OK);
}
switch (target_state) {
case ACPI_STATE_D0:
DEBUG_PRINT(ACPI_INFO, ("Turning power resource [0x%02X] ON.\n", pr->device_handle));
status = bm_evaluate_object(pr->acpi_handle, "_ON", NULL, NULL);
break;
case ACPI_STATE_D3:
DEBUG_PRINT(ACPI_INFO, ("Turning power resource [0x%02X] OFF.\n", pr->device_handle));
status = bm_evaluate_object(pr->acpi_handle, "_OFF", NULL, NULL);
break;
default:
status = AE_BAD_PARAMETER;
break;
}
status = bm_pr_get_state(pr);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_pr_list_get_state
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_list_get_state (
BM_HANDLE_LIST *pr_list,
BM_POWER_STATE *power_state)
{
ACPI_STATUS status = AE_OK;
BM_POWER_RESOURCE *pr = NULL;
u32 i = 0;
FUNCTION_TRACE("bm_pr_list_get_state");
if (!pr_list || !power_state) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (pr_list->count < 1) {
pr->state = ACPI_STATE_UNKNOWN;
return_ACPI_STATUS(AE_ERROR);
}
(*power_state) = ACPI_STATE_D0;
/*
* Calculate Current power_state:
* -----------------------------
* The current state of a list of power resources is ON if all
* power resources are currently in the ON state. In other words,
* if any power resource in the list is OFF then the collection
* isn't fully ON.
*/
for (i = 0; i < pr_list->count; i++) {
status = bm_get_device_context(pr_list->handles[i],
(BM_DRIVER_CONTEXT*)(&pr));
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [0x%02X].\n", pr_list->handles[i]));
(*power_state) = ACPI_STATE_UNKNOWN;
break;
}
status = bm_pr_get_state(pr);
if (ACPI_FAILURE(status)) {
(*power_state) = ACPI_STATE_UNKNOWN;
break;
}
if (pr->state != ACPI_STATE_D0) {
(*power_state) = pr->state;
break;
}
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_pr_list_transition
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_list_transition (
BM_HANDLE_LIST *current_list,
BM_HANDLE_LIST *target_list)
{
ACPI_STATUS status = AE_OK;
BM_POWER_RESOURCE *pr = NULL;
u32 i = 0;
FUNCTION_TRACE("bm_pr_list_transition");
if (!current_list || !target_list) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Reference Target:
* -----------------
* Reference all resources for the target power state first (so
* the device doesn't get turned off while transitioning). Power
* resources that aren't on (new reference count of 1) are turned on.
*/
for (i = 0; i < target_list->count; i++) {
status = bm_get_device_context(target_list->handles[i],
(BM_DRIVER_CONTEXT*)(&pr));
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [0x%02X].\n", target_list->handles[i]));
continue;
}
if (++pr->reference_count == 1) {
/* TODO: Need ordering based upon resource_order */
status = bm_pr_set_state(pr, ACPI_STATE_D0);
if (ACPI_FAILURE(status)) {
/* TODO: How do we handle this? */
DEBUG_PRINT(ACPI_WARN, ("Unable to change power state for power resource [0x%02X].\n", target_list->handles[i]));
}
}
}
/*
* Dereference Current:
* --------------------
* Dereference all resources for the current power state. Power
* resources no longer referenced (new reference count of 0) are
* turned off.
*/
for (i = 0; i < current_list->count; i++) {
status = bm_get_device_context(current_list->handles[i],
(BM_DRIVER_CONTEXT*)(&pr));
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(ACPI_WARN, ("Invalid reference to power resource [0x%02X].\n", target_list->handles[i]));
continue;
}
if (--pr->reference_count == 0) {
/* TODO: Need ordering based upon resource_order */
status = bm_pr_set_state(pr, ACPI_STATE_D3);
if (ACPI_FAILURE(status)) {
/* TODO: How do we handle this? */
DEBUG_PRINT(ACPI_ERROR, ("Unable to change power state for power resource [0x%02X].\n", current_list->handles[i]));
}
}
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_pr_add_device
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_add_device (
BM_HANDLE device_handle,
void **context)
{
ACPI_STATUS status = AE_OK;
BM_POWER_RESOURCE *pr = NULL;
BM_DEVICE *device = NULL;
ACPI_BUFFER buffer;
ACPI_OBJECT acpi_object;
FUNCTION_TRACE("bm_pr_add_device");
DEBUG_PRINT(ACPI_INFO, ("Adding power resource [0x%02X].\n", device_handle));
if (!context || *context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
buffer.length = sizeof(ACPI_OBJECT);
buffer.pointer = &acpi_object;
/*
* Get information on this device.
*/
status = bm_get_device_info(device_handle, &device);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Allocate a new BM_POWER_RESOURCE structure.
*/
pr = acpi_os_callocate(sizeof(BM_POWER_RESOURCE));
if (!pr) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
pr->device_handle = device->handle;
pr->acpi_handle = device->acpi_handle;
/*
* Get information on this power resource.
*/
status = acpi_evaluate_object(pr->acpi_handle, NULL, NULL, &buffer);
if (ACPI_FAILURE(status)) {
goto end;
}
pr->system_level = acpi_object.power_resource.system_level;
pr->resource_order = acpi_object.power_resource.resource_order;
pr->state = ACPI_STATE_UNKNOWN;
pr->reference_count = 0;
/*
* Get the power resource's current state (ON|OFF).
*/
status = bm_pr_get_state(pr);
end:
if (ACPI_FAILURE(status)) {
acpi_os_free(pr);
}
else {
*context = pr;
bm_pr_print(pr);
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_pr_remove_device
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_remove_device (
void **context)
{
ACPI_STATUS status = AE_OK;
BM_POWER_RESOURCE *pr = NULL;
FUNCTION_TRACE("bm_pr_remove_device");
if (!context || !*context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
pr = (BM_POWER_RESOURCE*)*context;
DEBUG_PRINT(ACPI_INFO, ("Removing power resource [0x%02X].\n", pr->device_handle));
acpi_os_free(pr);
return_ACPI_STATUS(status);
}
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_pr_initialize
*
* PARAMETERS: <none>
*
* RETURN:
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_initialize (void)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE_ID criteria;
BM_DRIVER driver;
FUNCTION_TRACE("bm_pr_initialize");
MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
MEMSET(&driver, 0, sizeof(BM_DRIVER));
criteria.type = BM_TYPE_POWER_RESOURCE;
driver.notify = &bm_pr_notify;
driver.request = &bm_pr_request;
status = bm_register_driver(&criteria, &driver);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_pr_terminate
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_terminate (void)
{
ACPI_STATUS status = AE_OK;
BM_DEVICE_ID criteria;
BM_DRIVER driver;
FUNCTION_TRACE("bm_pr_terminate");
MEMSET(&criteria, 0, sizeof(BM_DEVICE_ID));
MEMSET(&driver, 0, sizeof(BM_DRIVER));
criteria.type = BM_TYPE_POWER_RESOURCE;
driver.notify = &bm_pr_notify;
driver.request = &bm_pr_request;
status = bm_unregister_driver(&criteria, &driver);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_pr_notify
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_notify (
BM_NOTIFY notify_type,
BM_HANDLE device_handle,
void **context)
{
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE("bm_pr_notify");
switch (notify_type) {
case BM_NOTIFY_DEVICE_ADDED:
status = bm_pr_add_device(device_handle, context);
break;
case BM_NOTIFY_DEVICE_REMOVED:
status = bm_pr_remove_device(context);
break;
default:
status = AE_SUPPORT;
break;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_pr_request
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_pr_request (
BM_REQUEST *request,
void *context)
{
ACPI_STATUS status = AE_OK;
BM_POWER_RESOURCE *pr = NULL;
FUNCTION_TRACE("bm_pr_request");
/*
* Must have a valid request structure and context.
*/
if (!request || !context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* context contains information specific to this power resource.
*/
pr = (BM_POWER_RESOURCE*)context;
/*
* Handle request:
* ---------------
*/
switch (request->command) {
default:
status = AE_SUPPORT;
break;
}
request->status = status;
return_ACPI_STATUS(status);
}

View file

@ -0,0 +1,164 @@
/******************************************************************************
*
* Module Name: bmrequest.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <acpi.h>
#include "bm.h"
#define _COMPONENT ACPI_BUS_MANAGER
MODULE_NAME ("bmrequest")
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_generate_request
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_generate_request (
BM_NODE *node,
BM_REQUEST *request)
{
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE("bm_generate_request");
if (!node || !request) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
DEBUG_PRINT(ACPI_INFO, ("Sending request [0x%02x] to device [0x%02x].\n", request->command, node->device.handle));
if (!(node->device.flags & BM_FLAGS_DRIVER_CONTROL) ||
!(node->driver.request)) {
DEBUG_PRINT(ACPI_WARN, ("No driver installed for device [0x%02x].\n", node->device.handle));
return_ACPI_STATUS(AE_NOT_EXIST);
}
status = node->driver.request(request, node->driver.context);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_request
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_request (
BM_REQUEST *request)
{
ACPI_STATUS status = AE_OK;
BM_NODE *node = NULL;
BM_DEVICE *device = NULL;
FUNCTION_TRACE("bm_request");
/*
* Must have a valid request structure.
*/
if (!request) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
DEBUG_PRINT(ACPI_INFO, ("Received request for device [0x%02x] command [0x%08x].\n", request->handle, request->command));
/*
* Resolve the node.
*/
status = bm_get_node(request->handle, 0, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
device = &(node->device);
/*
* Device-Specific Request?
* ------------------------
* If a device-specific command (>=0x80) forward this request to
* the appropriate driver.
*/
if (request->command & BM_COMMAND_DEVICE_SPECIFIC) {
status = bm_generate_request(node, request);
return_ACPI_STATUS(status);
}
/*
* Bus-Specific Requests:
* ----------------------
*/
switch (request->command) {
case BM_COMMAND_GET_POWER_STATE:
status = bm_get_power_state(node);
if (ACPI_FAILURE(status)) {
break;
}
status = bm_copy_to_buffer(&(request->buffer),
&(device->power.state), sizeof(BM_POWER_STATE));
break;
case BM_COMMAND_SET_POWER_STATE:
{
BM_POWER_STATE *power_state = NULL;
status = bm_cast_buffer(&(request->buffer),
(void**)&power_state, sizeof(BM_POWER_STATE));
if (ACPI_FAILURE(status)) {
break;
}
status = bm_set_power_state(node, *power_state);
}
break;
default:
status = AE_SUPPORT;
request->status = AE_SUPPORT;
break;
}
return_ACPI_STATUS(status);
}

View file

@ -0,0 +1,191 @@
/******************************************************************************
*
* Module Name: bmsearch.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <acpi.h>
#include "bm.h"
#define _COMPONENT ACPI_BUS_MANAGER
MODULE_NAME ("bmsearch")
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_compare
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_compare (
BM_DEVICE *device,
BM_DEVICE_ID *criteria)
{
if (!device || !criteria) {
return AE_BAD_PARAMETER;
}
/*
* Present?
* --------
* We're only going to match on devices that are present.
* TODO: Optimize in bm_search (don't have to call here).
*/
if (!BM_DEVICE_PRESENT(device)) {
return AE_NOT_FOUND;
}
/*
* type?
*/
if (criteria->type && !(criteria->type & device->id.type)) {
return AE_NOT_FOUND;
}
/*
* hid?
*/
if ((criteria->hid[0]) && (0 != STRNCMP(criteria->hid,
device->id.hid, sizeof(BM_DEVICE_HID)))) {
return AE_NOT_FOUND;
}
/*
* adr?
*/
if ((criteria->adr) && (criteria->adr != device->id.adr)) {
return AE_NOT_FOUND;
}
return AE_OK;
}
/****************************************************************************
*
* FUNCTION: bm_search
*
* PARAMETERS: <TBD>
*
* RETURN: AE_BAD_PARAMETER- invalid input parameter
* AE_NOT_EXIST - start_device_handle doesn't exist
* AE_NOT_FOUND - no matches to Search_info.criteria found
* AE_OK - success
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_search(
BM_HANDLE device_handle,
BM_DEVICE_ID *criteria,
BM_HANDLE_LIST *results)
{
ACPI_STATUS status = AE_OK;
BM_NODE *node = NULL;
FUNCTION_TRACE("bm_search");
if (!criteria || !results) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
results->count = 0;
/*
* Locate Starting Point:
* ----------------------
* Locate the node in the hierarchy where we'll begin our search.
*/
status = bm_get_node(device_handle, 0, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Parse Hierarchy:
* ----------------
* Parse through the node hierarchy looking for matches.
*/
while (node && (results->count<=BM_HANDLES_MAX)) {
/*
* Depth-first:
* ------------
* Searches are always performed depth-first.
*/
if (node->scope.head) {
status = bm_compare(&(node->device), criteria);
if (ACPI_SUCCESS(status)) {
results->handles[results->count++] =
node->device.handle;
}
node = node->scope.head;
}
/*
* Now Breadth:
* ------------
* Search all peers until scope is exhausted.
*/
else {
status = bm_compare(&(node->device), criteria);
if (ACPI_SUCCESS(status)) {
results->handles[results->count++] =
node->device.handle;
}
/*
* Locate Next Device:
* -------------------
* The next node is either a peer at this level
* (node->next is valid), or we work are way back
* up the tree until we either find a non-parsed
* peer or hit the top (node->parent is NULL).
*/
while (!node->next && node->parent) {
node = node->parent;
}
node = node->next;
}
}
if (results->count == 0) {
return_ACPI_STATUS(AE_NOT_FOUND);
}
else {
return_ACPI_STATUS(AE_OK);
}
}

View file

@ -0,0 +1,606 @@
/*****************************************************************************
*
* Module Name: bmutils.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <acpi.h>
#include "bm.h"
#define _COMPONENT ACPI_BUS_MANAGER
MODULE_NAME ("bmutils")
#ifdef ACPI_DEBUG
#define DEBUG_EVAL_ERROR(l,h,p,s) bm_print_eval_error(l,h,p,s)
#else
#define DEBUG_EVAL_ERROR(l,h,p,s)
#endif
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_print_eval_error
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
void
bm_print_eval_error (
u32 debug_level,
ACPI_HANDLE acpi_handle,
ACPI_STRING pathname,
ACPI_STATUS status)
{
ACPI_BUFFER buffer;
ACPI_STRING status_string = NULL;
buffer.length = 256;
buffer.pointer = acpi_os_callocate(buffer.length);
if (!buffer.pointer) {
return;
}
status_string = acpi_cm_format_exception(status);
status = acpi_get_name(acpi_handle, ACPI_FULL_PATHNAME, &buffer);
if (ACPI_FAILURE(status)) {
DEBUG_PRINT(debug_level, ("Evaluate object [0x%08x], %s\n", acpi_handle, status_string));
return;
}
if (pathname) {
DEBUG_PRINT(ACPI_INFO, ("Evaluate object [%s.%s], %s\n", buffer.pointer, pathname, status_string));
}
else {
DEBUG_PRINT(ACPI_INFO, ("Evaluate object [%s], %s\n", buffer.pointer, status_string));
}
acpi_os_free(buffer.pointer);
}
/****************************************************************************
*
* FUNCTION: bm_copy_to_buffer
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_copy_to_buffer (
ACPI_BUFFER *buffer,
void *data,
u32 length)
{
FUNCTION_TRACE("bm_copy_to_buffer");
if (!buffer || (!buffer->pointer) || !data || (length == 0)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (length > buffer->length) {
buffer->length = length;
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
buffer->length = length;
MEMCPY(buffer->pointer, data, length);
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_cast_buffer
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_cast_buffer (
ACPI_BUFFER *buffer,
void **pointer,
u32 length)
{
FUNCTION_TRACE("bm_cast_buffer");
if (!buffer || !buffer->pointer || !pointer || length == 0) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
if (length > buffer->length) {
return_ACPI_STATUS(AE_BAD_DATA);
}
*pointer = buffer->pointer;
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_extract_package_data
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
/*
TODO: Don't assume numbers (in ASL) are 32-bit values!!!! (IA64)
TODO: Issue with 'assumed' types coming out of interpreter...
(e.g. toshiba _BIF)
*/
ACPI_STATUS
bm_extract_package_data (
ACPI_OBJECT *package,
ACPI_BUFFER *package_format,
ACPI_BUFFER *buffer)
{
ACPI_STATUS status = AE_OK;
u8 *head = NULL;
u8 *tail = NULL;
u8 **pointer = NULL;
u32 tail_offset = 0;
ACPI_OBJECT *element = NULL;
u32 size_required = 0;
char* format = NULL;
u32 format_count = 0;
u32 i = 0;
FUNCTION_TRACE("bm_extract_package_data");
if (!package || (package->type != ACPI_TYPE_PACKAGE) ||
(package->package.count == 0) || !package_format ||
(package_format->length < 1) ||
(!package_format->pointer) || !buffer) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
format_count = package_format->length - 1;
if (format_count > package->package.count) {
DEBUG_PRINT(ACPI_WARN, ("Format specifies more objects [%d] than exist in package [%d].", format_count, package->package.count));
return_ACPI_STATUS(AE_BAD_DATA);
}
format = (char*)package_format->pointer;
/*
* Calculate size_required.
*/
for (i=0; i<format_count; i++) {
element = &(package->package.elements[i]);
switch (element->type) {
case ACPI_TYPE_INTEGER:
switch (format[i]) {
case 'N':
size_required += sizeof(ACPI_INTEGER);
tail_offset += sizeof(ACPI_INTEGER);
break;
case 'S':
size_required += sizeof(u8*) +
sizeof(ACPI_INTEGER) + 1;
tail_offset += sizeof(ACPI_INTEGER);
break;
default:
DEBUG_PRINT(ACPI_WARN, ("Invalid package element [%d]: got number, expecing [%c].\n", i, format[i]));
return_ACPI_STATUS(AE_BAD_DATA);
break;
}
break;
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
switch (format[i]) {
case 'S':
size_required += sizeof(u8*) +
element->string.length + 1;
tail_offset += sizeof(u8*);
break;
case 'B':
size_required += sizeof(u8*) +
element->buffer.length;
tail_offset += sizeof(u8*);
break;
default:
DEBUG_PRINT(ACPI_WARN, ("Invalid package element [%d] got string/buffer, expecing [%c].\n", i, format[i]));
return_ACPI_STATUS(AE_BAD_DATA);
break;
}
break;
case ACPI_TYPE_PACKAGE:
default:
/* TODO: handle nested packages... */
return_ACPI_STATUS(AE_SUPPORT);
break;
}
}
if (size_required > buffer->length) {
buffer->length = size_required;
return_ACPI_STATUS(AE_BUFFER_OVERFLOW);
}
buffer->length = size_required;
if (!buffer->pointer) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
head = buffer->pointer;
tail = buffer->pointer + tail_offset;
/*
* Extract package data:
*/
for (i=0; i<format_count; i++) {
element = &(package->package.elements[i]);
switch (element->type) {
case ACPI_TYPE_INTEGER:
switch (format[i]) {
case 'N':
*((ACPI_INTEGER*)head) =
element->integer.value;
head += sizeof(ACPI_INTEGER);
break;
case 'S':
pointer = (u8**)head;
*pointer = tail;
*((ACPI_INTEGER*)tail) =
element->integer.value;
head += sizeof(ACPI_INTEGER*);
tail += sizeof(ACPI_INTEGER);
/* NULL terminate string */
*tail = 0;
tail++;
break;
default:
/* Should never get here */
break;
}
break;
case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER:
switch (format[i]) {
case 'S':
pointer = (u8**)head;
*pointer = tail;
memcpy(tail, element->string.pointer,
element->string.length);
head += sizeof(u8*);
tail += element->string.length;
/* NULL terminate string */
*tail = 0;
tail++;
break;
case 'B':
pointer = (u8**)head;
*pointer = tail;
memcpy(tail, element->buffer.pointer,
element->buffer.length);
head += sizeof(u8*);
tail += element->buffer.length;
break;
default:
/* Should never get here */
break;
}
break;
case ACPI_TYPE_PACKAGE:
/* TODO: handle nested packages... */
default:
/* Should never get here */
break;
}
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_evaluate_object
*
* PARAMETERS: <TBD>
*
* RETURN: AE_OK
* AE_BUFFER_OVERFLOW Evaluated object returned data, but
* caller did not provide buffer.
*
* DESCRIPTION: Helper for acpi_evaluate_object that handles buffer
* allocation. Note that the caller is responsible for
* freeing buffer->pointer!
*
****************************************************************************/
ACPI_STATUS
bm_evaluate_object (
ACPI_HANDLE acpi_handle,
ACPI_STRING pathname,
ACPI_OBJECT_LIST *arguments,
ACPI_BUFFER *buffer)
{
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE("bm_evaluate_object");
/* If caller provided a buffer it must be unallocated/zero'd. */
if ((buffer) && (buffer->length != 0 || buffer->pointer)) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Evalute Object:
* ---------------
* The first attempt is just to get the size of the object data
* (that is unless there's no return data, e.g. _INI); the second
* gets the data.
*/
status = acpi_evaluate_object(acpi_handle, pathname, arguments, buffer);
if (ACPI_SUCCESS(status)) {
return_ACPI_STATUS(status);
}
else if ((buffer) && (status == AE_BUFFER_OVERFLOW)) {
/* Gotta allocate -- CALLER MUST FREE! */
buffer->pointer = acpi_os_callocate(buffer->length);
if (!buffer->pointer) {
return_ACPI_STATUS(AE_NO_MEMORY);
}
/* Re-evaluate -- this time it should work */
status = acpi_evaluate_object(acpi_handle, pathname,
arguments, buffer);
}
if (ACPI_FAILURE(status)) {
DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status);
if (buffer && buffer->pointer) {
acpi_os_free(buffer->pointer);
buffer->pointer = NULL;
buffer->length = 0;
}
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_evaluate_simple_integer
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_evaluate_simple_integer (
ACPI_HANDLE acpi_handle,
ACPI_STRING pathname,
u32 *data)
{
ACPI_STATUS status = AE_OK;
ACPI_OBJECT *element = NULL;
ACPI_BUFFER buffer;
FUNCTION_TRACE("bm_evaluate_simple_integer");
if (!data) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
MEMSET(&buffer, 0, sizeof(ACPI_BUFFER));
/*
* Evaluate Object:
* ----------------
*/
status = bm_evaluate_object(acpi_handle, pathname, NULL, &buffer);
if (ACPI_FAILURE(status)) {
goto end;
}
/*
* Validate Data:
* --------------
*/
status = bm_cast_buffer(&buffer, (void**)&element,
sizeof(ACPI_OBJECT));
if (ACPI_FAILURE(status)) {
DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status);
goto end;
}
if (element->type != ACPI_TYPE_INTEGER) {
status = AE_BAD_DATA;
DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status);
goto end;
}
*data = element->integer.value;
end:
acpi_os_free(buffer.pointer);
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_evaluate_reference_list
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_evaluate_reference_list (
ACPI_HANDLE acpi_handle,
ACPI_STRING pathname,
BM_HANDLE_LIST *reference_list)
{
ACPI_STATUS status = AE_OK;
ACPI_OBJECT *package = NULL;
ACPI_OBJECT *element = NULL;
ACPI_HANDLE reference_handle = NULL;
ACPI_BUFFER buffer;
u32 i = 0;
FUNCTION_TRACE("bm_evaluate_reference_list");
if (!reference_list) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
MEMSET(&buffer, 0, sizeof(ACPI_BUFFER));
/*
* Evaluate Object:
* ----------------
*/
status = bm_evaluate_object(acpi_handle, pathname, NULL, &buffer);
if (ACPI_FAILURE(status)) {
goto end;
}
/*
* Validate Package:
* -----------------
*/
status = bm_cast_buffer(&buffer, (void**)&package,
sizeof(ACPI_OBJECT));
if (ACPI_FAILURE(status)) {
DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status);
goto end;
}
if (package->type != ACPI_TYPE_PACKAGE) {
status = AE_BAD_DATA;
DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status);
goto end;
}
if (package->package.count > BM_HANDLES_MAX) {
package->package.count = BM_HANDLES_MAX;
}
/*
* Parse Package Data:
* -------------------
*/
for (i = 0; i < package->package.count; i++) {
element = &(package->package.elements[i]);
if (!element || (element->type != ACPI_TYPE_STRING)) {
status = AE_BAD_DATA;
DEBUG_PRINT(ACPI_WARN, ("Invalid element in package (not a device reference).\n"));
DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status);
break;
}
/*
* Resolve reference string (e.g. "\_PR_.CPU_") to an
* ACPI_HANDLE.
*/
status = acpi_get_handle(acpi_handle,
element->string.pointer, &reference_handle);
if (ACPI_FAILURE(status)) {
status = AE_BAD_DATA;
DEBUG_PRINT(ACPI_WARN, ("Unable to resolve device reference [%s].\n", element->string.pointer));
DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status);
break;
}
/*
* Resolve ACPI_HANDLE to BM_HANDLE.
*/
status = bm_get_handle(reference_handle,
&(reference_list->handles[i]));
if (ACPI_FAILURE(status)) {
status = AE_BAD_DATA;
DEBUG_PRINT(ACPI_WARN, ("Unable to resolve device reference for [0x%08x].\n", reference_handle));
DEBUG_EVAL_ERROR(ACPI_WARN, acpi_handle, pathname, status);
break;
}
DEBUG_PRINT(ACPI_INFO, ("Resolved reference [%s]->[0x%08x]->[0x%02x]\n", element->string.pointer, reference_handle, reference_list->handles[i]));
(reference_list->count)++;
}
end:
acpi_os_free(buffer.pointer);
return_ACPI_STATUS(status);
}

View file

@ -0,0 +1,331 @@
/*****************************************************************************
*
* Module Name: bmxface.c
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <acpi.h>
#include "bm.h"
#define _COMPONENT ACPI_BUS_MANAGER
MODULE_NAME ("bmxface")
/****************************************************************************
* External Functions
****************************************************************************/
/****************************************************************************
*
* FUNCTION: bm_get_device_status
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_get_device_status (
BM_HANDLE device_handle,
BM_DEVICE_STATUS *device_status)
{
ACPI_STATUS status = AE_OK;
BM_NODE *node = NULL;
FUNCTION_TRACE("bm_get_device_status");
if (!device_status) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
*device_status = BM_STATUS_UNKNOWN;
/*
* Resolve device handle to node.
*/
status = bm_get_node(device_handle, 0, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Parent Present?
* ---------------
* If the parent isn't present we can't evalute _STA on the child.
* Return an unknown status.
*/
if (!BM_NODE_PRESENT(node->parent)) {
return_ACPI_STATUS(AE_OK);
}
/*
* Dynamic Status?
* ---------------
* If _STA isn't present we just return the default status.
*/
if (!(node->device.flags & BM_FLAGS_DYNAMIC_STATUS)) {
*device_status = BM_STATUS_DEFAULT;
return_ACPI_STATUS(AE_OK);
}
/*
* Evaluate _STA:
* --------------
*/
status = bm_evaluate_simple_integer(node->device.acpi_handle, "_STA",
&(node->device.status));
if (ACPI_SUCCESS(status)) {
*device_status = node->device.status;
}
return_ACPI_STATUS(status);
}
/****************************************************************************
*
* FUNCTION: bm_get_device_info
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_get_device_info (
BM_HANDLE device_handle,
BM_DEVICE **device)
{
ACPI_STATUS status = AE_OK;
BM_NODE *node = NULL;
FUNCTION_TRACE("bm_get_device_info");
if (!device) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
/*
* Resolve device handle to internal device.
*/
status = bm_get_node(device_handle, 0, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
*device = &(node->device);
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_get_device_context
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_get_device_context (
BM_HANDLE device_handle,
BM_DRIVER_CONTEXT *context)
{
ACPI_STATUS status = AE_OK;
BM_NODE *node = NULL;
FUNCTION_TRACE("bm_get_device_context");
if (!context) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
*context = NULL;
/*
* Resolve device handle to internal device.
*/
status = bm_get_node(device_handle, 0, &node);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
if (!node->driver.context) {
return_ACPI_STATUS(AE_NULL_ENTRY);
}
*context = node->driver.context;
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_register_driver
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_register_driver (
BM_DEVICE_ID *criteria,
BM_DRIVER *driver)
{
ACPI_STATUS status = AE_NOT_FOUND;
BM_HANDLE_LIST device_list;
BM_NODE *node = NULL;
u32 i = 0;
FUNCTION_TRACE("bm_register_driver");
if (!criteria || !driver || !driver->notify || !driver->request) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
MEMSET(&device_list, 0, sizeof(BM_HANDLE_LIST));
/*
* Find Matches:
* -------------
* Search through the entire device hierarchy for matches against
* the given device criteria.
*/
status = bm_search(BM_HANDLE_ROOT, criteria, &device_list);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Install driver:
* ----------------
* For each match, record the driver information and execute the
* driver's Notify() funciton (if present) to notify the driver
* of the device's presence.
*/
for (i = 0; i < device_list.count; i++) {
/* Resolve the device handle. */
status = bm_get_node(device_list.handles[i], 0, &node);
if (ACPI_FAILURE(status)) {
continue;
}
DEBUG_PRINT(ACPI_INFO, ("Registering driver for device [0x%02x].\n", node->device.handle));
/* Notify driver of new device. */
status = driver->notify(BM_NOTIFY_DEVICE_ADDED,
node->device.handle, &(node->driver.context));
if (ACPI_SUCCESS(status)) {
node->driver.notify = driver->notify;
node->driver.request = driver->request;
node->device.flags |= BM_FLAGS_DRIVER_CONTROL;
}
}
return_ACPI_STATUS(AE_OK);
}
/****************************************************************************
*
* FUNCTION: bm_unregister_driver
*
* PARAMETERS: <TBD>
*
* RETURN: <TBD>
*
* DESCRIPTION: <TBD>
*
****************************************************************************/
ACPI_STATUS
bm_unregister_driver (
BM_DEVICE_ID *criteria,
BM_DRIVER *driver)
{
ACPI_STATUS status = AE_NOT_FOUND;
BM_HANDLE_LIST device_list;
BM_NODE *node = NULL;
u32 i = 0;
FUNCTION_TRACE("bm_unregister_driver");
if (!criteria || !driver || !driver->notify || !driver->request) {
return_ACPI_STATUS(AE_BAD_PARAMETER);
}
MEMSET(&device_list, 0, sizeof(BM_HANDLE_LIST));
/*
* Find Matches:
* -------------
* Search through the entire device hierarchy for matches against
* the given device criteria.
*/
status = bm_search(BM_HANDLE_ROOT, criteria, &device_list);
if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status);
}
/*
* Remove driver:
* ---------------
* For each match, execute the driver's Notify() function to allow
* the driver to cleanup each device instance.
*/
for (i = 0; i < device_list.count; i++) {
/*
* Resolve the device handle.
*/
status = bm_get_node(device_list.handles[i], 0, &node);
if (ACPI_FAILURE(status)) {
continue;
}
DEBUG_PRINT(ACPI_INFO, ("Unregistering driver for device [0x%02x].\n", node->device.handle));
/* Notify driver of device removal. */
status = node->driver.notify(BM_NOTIFY_DEVICE_REMOVED,
node->device.handle, &(node->driver.context));
node->device.flags &= ~BM_FLAGS_DRIVER_CONTROL;
MEMSET(&(node->driver), 0, sizeof(BM_DRIVER));
}
return_ACPI_STATUS(AE_OK);
}

View file

@ -1,20 +1,38 @@
/*
* PROJECT: ReactOS ACPI bzus driver
* PROJECT: ReactOS ACPI bus driver
* FILE: acpi/ospm/include/acpisys.h
* PURPOSE: ACPI bus driver definitions
*/
//#define ACPI_DEBUG
#define ACPI_DEBUG
#include <acpi.h>
#define __INCLUDE_TYPES_H
#include <platform/types.h>
#undef ROUND_UP
#include <ddk/ntddk.h>
#include <bm.h>
typedef ACPI_STATUS (*ACPI_DRIVER_FUNCTION)(VOID);
typedef enum {
dsStopped,
dsStarted
} ACPI_DEVICE_STATE;
typedef struct _ACPI_DEVICE
{
// Entry on device list
LIST_ENTRY DeviceListEntry;
// Bus manager handle
BM_HANDLE BmHandle;
// Physical Device Object
PDEVICE_OBJECT Pdo;
// Initialization function
ACPI_DRIVER_FUNCTION Initialize;
// Cleanup function
ACPI_DRIVER_FUNCTION Terminate;
} ACPI_DEVICE, *PACPI_DEVICE;
typedef struct _ACPI_DEVICE_EXTENSION
{
// Physical Device Object
@ -25,10 +43,20 @@ typedef struct _ACPI_DEVICE_EXTENSION
ACPI_DEVICE_STATE State;
// Supported system states
BOOLEAN SystemStates[ACPI_S_STATE_COUNT];
// Namespace device list
LIST_ENTRY DeviceListHead;
// Number of devices in device list
ULONG DeviceListCount;
// Lock for namespace device list
KSPIN_LOCK DeviceListLock;
} ACPI_DEVICE_EXTENSION, *PACPI_DEVICE_EXTENSION;
NTSTATUS
ACPIEnumerateSystemDevices(
ACPIEnumerateRootBusses(
PACPI_DEVICE_EXTENSION DeviceExtension);
NTSTATUS
ACPIEnumerateNamespace(
PACPI_DEVICE_EXTENSION DeviceExtension);
/* EOF */

View file

@ -0,0 +1,624 @@
/*****************************************************************************
*
* Module name: bm.h
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __BM_H__
#define __BM_H__
#include <actypes.h>
#include <acexcep.h>
/*****************************************************************************
* Types & Defines
*****************************************************************************/
/*
* Output Flags (Debug):
* ---------------------
*/
#define BM_PRINT_ALL (0x00000000)
#define BM_PRINT_GROUP (0x00000001)
#define BM_PRINT_LINKAGE (0x00000002)
#define BM_PRINT_IDENTIFICATION (0x00000004)
#define BM_PRINT_POWER (0x00000008)
#define BM_PRINT_PRESENT (0x00000010)
/*
* /proc Interface:
* ----------------
*/
#define BM_PROC_ROOT "acpi"
#define BM_PROC_EVENT "event"
extern struct proc_dir_entry *bm_proc_root;
/*
* BM_COMMAND:
* -----------
*/
typedef u32 BM_COMMAND;
#define BM_COMMAND_UNKNOWN ((BM_COMMAND) 0x00)
#define BM_COMMAND_GET_POWER_STATE ((BM_COMMAND) 0x01)
#define BM_COMMAND_SET_POWER_STATE ((BM_COMMAND) 0x02)
#define BM_COMMAND_DEVICE_SPECIFIC ((BM_COMMAND) 0x80)
/*
* BM_NOTIFY:
* ----------
* Standard ACPI notification values, from section 5.6.3 of the ACPI 2.0
* specification. Note that the Bus Manager internally handles all
* standard ACPI notifications -- driver modules are never sent these
* values (see "Bus Manager Notifications", below).
*/
typedef u32 BM_NOTIFY;
#define BM_NOTIFY_BUS_CHECK ((BM_NOTIFY) 0x00)
#define BM_NOTIFY_DEVICE_CHECK ((BM_NOTIFY) 0x01)
#define BM_NOTIFY_DEVICE_WAKE ((BM_NOTIFY) 0x02)
#define BM_NOTIFY_EJECT_REQUEST ((BM_NOTIFY) 0x03)
#define BM_NOTIFY_DEVICE_CHECK_LIGHT ((BM_NOTIFY) 0x04)
#define BM_NOTIFY_FREQUENCY_MISMATCH ((BM_NOTIFY) 0x05)
#define BM_NOTIFY_BUS_MODE_MISMATCH ((BM_NOTIFY) 0x06)
#define BM_NOTIFY_POWER_FAULT ((BM_NOTIFY) 0x07)
/*
* These are a higher-level abstraction of ACPI notifications, intended
* for consumption by driver modules to facilitate PnP.
*/
#define BM_NOTIFY_UNKNOWN ((BM_NOTIFY) 0x00)
#define BM_NOTIFY_DEVICE_ADDED ((BM_NOTIFY) 0x01)
#define BM_NOTIFY_DEVICE_REMOVED ((BM_NOTIFY) 0x02)
/*
* BM_HANDLE:
* ----------
*/
typedef u32 BM_HANDLE;
#define BM_HANDLE_UNKNOWN ((BM_HANDLE) 0x00)
#define BM_HANDLE_ROOT ((BM_HANDLE) 0x00)
#define BM_HANDLES_MAX 256
/*
* BM_HANDLE_LIST:
* ---------------
*/
typedef struct
{
u32 count;
BM_HANDLE handles[BM_HANDLES_MAX];
} BM_HANDLE_LIST;
/*
* BM_DEVICE_TYPE:
* ---------------
*/
typedef u32 BM_DEVICE_TYPE;
#define BM_TYPE_UNKNOWN ((BM_DEVICE_TYPE) 0x00000000)
#define BM_TYPE_SCOPE ((BM_DEVICE_TYPE) 0x00000001)
#define BM_TYPE_PROCESSOR ((BM_DEVICE_TYPE) 0x00000002)
#define BM_TYPE_THERMAL_ZONE ((BM_DEVICE_TYPE) 0x00000004)
#define BM_TYPE_POWER_RESOURCE ((BM_DEVICE_TYPE) 0x00000008)
#define BM_TYPE_DEVICE ((BM_DEVICE_TYPE) 0x00000010)
#define BM_TYPE_FIXED_BUTTON ((BM_DEVICE_TYPE) 0x00000020)
#define BM_TYPE_SYSTEM ((BM_DEVICE_TYPE) 0x80000000)
#define BM_TYPE_ALL ((BM_DEVICE_TYPE) 0xFFFFFFFF)
/*
* BM_DEVICE_UID:
* --------------
*/
typedef char BM_DEVICE_UID[9];
#define BM_UID_UNKNOWN '0'
/*
* BM_DEVICE_HID:
* --------------
*/
typedef char BM_DEVICE_HID[9];
#define BM_HID_UNKNOWN '\0'
#define BM_HID_POWER_BUTTON "PNP0C0C"
#define BM_HID_SLEEP_BUTTON "PNP0C0E"
/*
* BM_DEVICE_CID:
* The compatibility ID can be a string with 44 characters
* The extra pad is in case there is a change. It also
* provides 8 byte alignment for the BM_DEVICE_ID structure.
* -------------------------------------------------------------
*/
typedef char BM_DEVICE_CID[46];
/*
* BM_DEVICE_ADR:
* --------------
*/
typedef u32 BM_DEVICE_ADR;
#define BM_ADDRESS_UNKNOWN 0
/*
* BM_DEVICE_FLAGS:
* ----------------
* The encoding of BM_DEVICE_FLAGS is illustrated below.
* Note that a set bit (1) indicates the property is TRUE
* (e.g. if bit 0 is set then the device has dynamic status).
* +--+------------+-+-+-+-+-+-+-+
* |31| Bits 31:11 |6|5|4|3|2|1|0|
* +--+------------+-+-+-+-+-+-+-+
* | | | | | | | | |
* | | | | | | | | +- Dynamic status?
* | | | | | | | +--- Identifiable?
* | | | | | | +----- Configurable?
* | | | | | +------- Power Manageable?
* | | | | +--------- Ejectable?
* | | | +----------- Docking Station?
* | | +------------- Fixed-Feature?
* | +-------------------- <Reserved>
* +---------------------------- Driver Control?
*
* Dynamic status: Device has a _STA object.
* Identifiable: Device has a _HID and/or _ADR and possibly other
* identification objects defined.
* Configurable: Device has a _CRS and possibly other configuration
* objects defined.
* Power Control: Device has a _PR0 and/or _PS0 and possibly other
* power management objects defined.
* Ejectable: Device has an _EJD and/or _EJx and possibly other
* dynamic insertion/removal objects defined.
* Docking Station: Device has a _DCK object defined.
* Fixed-Feature: Device does not exist in the namespace; was
* enumerated as a fixed-feature (e.g. power button).
* Power Manageable:Can change device's power consumption behavior.
* Has a HID: In the BIOS ASL this device has a hardware ID as
* defined in section 6.1.4 of ACPI Spec 2.0
* Has a CID: In the BIOS ASL this device has a compatible ID as
* defined in section 6.1.2 of ACPI Spec 2.0
* Has a ADR: In the BIOS ASL this device has an address ID as
* defined in section 6.1.1 of ACPI Spec 2.0
* Is a bridge: This device is recognized as a bridge to another bus.
* Is on PCI bus: This device is on a PCI bus or within PCI configuration
* address space.
* Is on USB bus: This device is on or within USB address space.
* Is on SCSI bus: This device is on or within SCSI address space.
* Driver Control: A driver has been installed for this device.
*/
typedef u32 BM_DEVICE_FLAGS;
#define BM_FLAGS_UNKNOWN ((BM_DEVICE_FLAGS) 0x00000000)
#define BM_FLAGS_DYNAMIC_STATUS ((BM_DEVICE_FLAGS) 0x00000001)
#define BM_FLAGS_IDENTIFIABLE ((BM_DEVICE_FLAGS) 0x00000002)
#define BM_FLAGS_CONFIGURABLE ((BM_DEVICE_FLAGS) 0x00000004)
#define BM_FLAGS_POWER_CONTROL ((BM_DEVICE_FLAGS) 0x00000008)
#define BM_FLAGS_EJECTABLE ((BM_DEVICE_FLAGS) 0x00000010)
#define BM_FLAGS_DOCKING_STATION ((BM_DEVICE_FLAGS) 0x00000020)
#define BM_FLAGS_FIXED_FEATURE ((BM_DEVICE_FLAGS) 0x00000040)
#define BM_FLAGS_IS_POWER_MANAGEABLE ((BM_DEVICE_FLAGS) 0x00000080)
#define BM_FLAGS_HAS_A_HID ((BM_DEVICE_FLAGS) 0x00000100)
#define BM_FLAGS_HAS_A_CID ((BM_DEVICE_FLAGS) 0x00000200)
#define BM_FLAGS_HAS_A_ADR ((BM_DEVICE_FLAGS) 0x00000400)
#define BM_FLAGS_IS_A_BRIDGE ((BM_DEVICE_FLAGS) 0x00000800)
#define BM_FLAGS_IS_ON_PCI_BUS ((BM_DEVICE_FLAGS) 0x00001000)
#define BM_FLAGS_IS_ON_USB_BUS ((BM_DEVICE_FLAGS) 0x00002000)
#define BM_FLAGS_IS_ON_SCSI_BUS ((BM_DEVICE_FLAGS) 0x00004000)
#define BM_FLAGS_DRIVER_CONTROL ((BM_DEVICE_FLAGS) 0x80000000)
/*
* Device PM Flags:
* ----------------
* +-----------+-+-+-+-+-+-+-+
* | Bits 31:7 |6|5|4|3|2|1|0|
* +-----------+-+-+-+-+-+-+-+
* | | | | | | | |
* | | | | | | | +- D0 Support?
* | | | | | | +--- D1 Support?
* | | | | | +----- D2 Support?
* | | | | +------- D3 Support?
* | | | +--------- Power State Queriable?
* | | +----------- Inrush Current?
* | +------------- Wake Capable?
* +-------------------- <Reserved>
*
* D0-D3 Support: Device supports corresponding Dx state.
* Power State: Device has a _PSC (current power state) object defined.
* Inrush Current: Device has an _IRC (inrush current) object defined.
* Wake Capable: Device has a _PRW (wake-capable) object defined.
*/
#define BM_FLAGS_D0_SUPPORT ((BM_DEVICE_FLAGS) 0x00000001)
#define BM_FLAGS_D1_SUPPORT ((BM_DEVICE_FLAGS) 0x00000002)
#define BM_FLAGS_D2_SUPPORT ((BM_DEVICE_FLAGS) 0x00000004)
#define BM_FLAGS_D3_SUPPORT ((BM_DEVICE_FLAGS) 0x00000008)
#define BM_FLAGS_POWER_STATE ((BM_DEVICE_FLAGS) 0x00000010)
#define BM_FLAGS_INRUSH_CURRENT ((BM_DEVICE_FLAGS) 0x00000020)
#define BM_FLAGS_WAKE_CAPABLE ((BM_DEVICE_FLAGS) 0x00000040)
/*
* BM_DEVICE_STATUS:
* -----------------
* The encoding of BM_DEVICE_STATUS is illustrated below.
* Note that a set bit (1) indicates the property is TRUE
* (e.g. if bit 0 is set then the device is present).
* +-----------+-+-+-+-+-+
* | Bits 31:4 |4|3|2|1|0|
* +-----------+-+-+-+-+-+
* | | | | | |
* | | | | | +- Present?
* | | | | +--- Enabled?
* | | | +----- Show in UI?
* | | +------- Functioning?
* | +--------- Battery Present?
* +---------------- <Reserved>
*/
typedef u32 BM_DEVICE_STATUS;
#define BM_STATUS_UNKNOWN ((BM_DEVICE_STATUS) 0x00000000)
#define BM_STATUS_PRESENT ((BM_DEVICE_STATUS) 0x00000001)
#define BM_STATUS_ENABLED ((BM_DEVICE_STATUS) 0x00000002)
#define BM_STATUS_SHOW_UI ((BM_DEVICE_STATUS) 0x00000004)
#define BM_STATUS_FUNCTIONING ((BM_DEVICE_STATUS) 0x00000008)
#define BM_STATUS_BATTERY_PRESENT ((BM_DEVICE_STATUS) 0x00000010)
#define BM_STATUS_DEFAULT ((BM_DEVICE_STATUS) 0x0000000F)
typedef u32 BM_POWER_STATE;
typedef u8 BM_PCI_BUS_NUM;
typedef u8 BM_PCI_DEVICE_NUM;
typedef u8 BM_PCI_FUNCTION_NUM;
typedef u8 BM_U8_RESERVED;
typedef u8 BM_PCI_DEVICE_CLASS_ID;
typedef u8 BM_PCI_DEVICE_SUBCLASS_ID;
typedef u8 BM_PCI_DEVICE_PROG_IF;
typedef u8 BM_PCI_DEVICE_REVISION;
typedef u16 BM_PCI_VENDOR_ID;
typedef u16 BM_PCI_DEVICE_ID;
typedef u32 BM_U32_RESERVED;
/*
* BM_DEVICE_ID:
* This structure, when filled in for a device, provides
* an "association" between hardware space and ACPI.
* -----------------------------------------------------------
*/
typedef struct
{
BM_DEVICE_CID cid;
BM_DEVICE_HID hid;
BM_DEVICE_UID uid;
BM_DEVICE_TYPE type;
BM_DEVICE_ADR adr;
BM_PCI_BUS_NUM pci_bus_num;
BM_PCI_DEVICE_NUM pci_device_num;
BM_PCI_FUNCTION_NUM pci_func_num;
BM_U8_RESERVED u8_reserved;
BM_PCI_DEVICE_CLASS_ID pci_device_class_id;
BM_PCI_DEVICE_SUBCLASS_ID pci_device_subclass_id;
BM_PCI_DEVICE_PROG_IF pci_device_prog_if;
BM_PCI_DEVICE_REVISION pci_device_rev_num;
BM_PCI_VENDOR_ID pci_vendor_id;
BM_PCI_DEVICE_ID pci_device_id;
BM_U32_RESERVED u32_reserved;
} BM_DEVICE_ID;
/*
* BM_DEVICE_POWER:
* ----------------
* Structure containing basic device power management information.
*/
typedef struct
{
BM_DEVICE_FLAGS flags;
BM_POWER_STATE state;
BM_DEVICE_FLAGS dx_supported[ACPI_S_STATE_COUNT];
} BM_DEVICE_POWER;
/*
* BM_DEVICE:
* ----------
*/
typedef struct
{
BM_HANDLE handle;
ACPI_HANDLE acpi_handle;
BM_DEVICE_FLAGS flags;
BM_DEVICE_STATUS status;
BM_DEVICE_ID id;
BM_DEVICE_POWER power;
} BM_DEVICE;
/*
* BM_SEARCH:
* ----------
* Structure used for searching the ACPI Bus Manager's device hierarchy.
*/
typedef struct
{
BM_DEVICE_ID criteria;
BM_HANDLE_LIST results;
} BM_SEARCH;
/*
* BM_REQUEST:
* -----------
* Structure used for sending requests to/through the ACPI Bus Manager.
*/
typedef struct
{
ACPI_STATUS status;
BM_COMMAND command;
BM_HANDLE handle;
ACPI_BUFFER buffer;
} BM_REQUEST;
/*
* Driver Registration:
* --------------------
*/
/* Driver Context */
typedef void * BM_DRIVER_CONTEXT;
/* Notification Callback Function */
typedef
ACPI_STATUS (*BM_DRIVER_NOTIFY) (
BM_NOTIFY notify_type,
BM_HANDLE device_handle,
BM_DRIVER_CONTEXT *context);
/* Request Callback Function */
typedef
ACPI_STATUS (*BM_DRIVER_REQUEST) (
BM_REQUEST *request,
BM_DRIVER_CONTEXT context);
/* Driver Registration */
typedef struct
{
BM_DRIVER_NOTIFY notify;
BM_DRIVER_REQUEST request;
BM_DRIVER_CONTEXT context;
} BM_DRIVER;
/*
* BM_NODE:
* --------
* Structure used to maintain the device hierarchy.
*/
typedef struct _BM_NODE
{
BM_DEVICE device;
BM_DRIVER driver;
struct _BM_NODE *parent;
struct _BM_NODE *next;
struct
{
struct _BM_NODE *head;
struct _BM_NODE *tail;
} scope;
} BM_NODE;
/*
* BM_NODE_LIST:
* -------------
* Structure used to maintain an array of node pointers.
*/
typedef struct
{
u32 count;
BM_NODE *nodes[BM_HANDLES_MAX];
} BM_NODE_LIST;
/*****************************************************************************
* Macros
*****************************************************************************/
#define BM_DEVICE_PRESENT(d) (d->status & BM_STATUS_PRESENT)
#define BM_NODE_PRESENT(n) (n->device.status & BM_STATUS_PRESENT)
/*****************************************************************************
* Function Prototypes
*****************************************************************************/
/* bm.c */
ACPI_STATUS
bm_initialize (void);
ACPI_STATUS
bm_terminate (void);
ACPI_STATUS
bm_get_status (
BM_DEVICE *device);
ACPI_STATUS
bm_get_handle (
ACPI_HANDLE acpi_handle,
BM_HANDLE *device_handle);
ACPI_STATUS
bm_get_node (
BM_HANDLE device_handle,
ACPI_HANDLE acpi_handle,
BM_NODE **node);
/* bmsearch.c */
ACPI_STATUS
bm_search(
BM_HANDLE device_handle,
BM_DEVICE_ID *criteria,
BM_HANDLE_LIST *results);
/* bmnotify.c */
void
bm_notify (
ACPI_HANDLE acpi_handle,
u32 notify_value,
void *context);
/* bm_request.c */
ACPI_STATUS
bm_request (
BM_REQUEST *request_info);
/* bmxface.c */
ACPI_STATUS
bm_get_device_status (
BM_HANDLE device_handle,
BM_DEVICE_STATUS *device_status);
ACPI_STATUS
bm_get_device_info (
BM_HANDLE device_handle,
BM_DEVICE **device_info);
ACPI_STATUS
bm_get_device_context (
BM_HANDLE device_handle,
BM_DRIVER_CONTEXT *context);
ACPI_STATUS
bm_register_driver (
BM_DEVICE_ID *criteria,
BM_DRIVER *driver);
ACPI_STATUS
bm_unregister_driver (
BM_DEVICE_ID *criteria,
BM_DRIVER *driver);
/* bmpm.c */
ACPI_STATUS
bm_get_pm_capabilities (
BM_NODE *node);
ACPI_STATUS
bm_get_power_state (
BM_NODE *node);
ACPI_STATUS
bm_set_power_state (
BM_NODE *node,
BM_POWER_STATE target_state);
/* bmpower.c */
ACPI_STATUS
bm_pr_initialize (void);
ACPI_STATUS
bm_pr_terminate (void);
/* bmutils.c */
ACPI_STATUS
bm_cast_buffer (
ACPI_BUFFER *buffer,
void **pointer,
u32 length);
ACPI_STATUS
bm_copy_to_buffer (
ACPI_BUFFER *buffer,
void *data,
u32 length);
ACPI_STATUS
bm_extract_package_data (
ACPI_OBJECT *package,
ACPI_BUFFER *format,
ACPI_BUFFER *buffer);
ACPI_STATUS
bm_evaluate_object (
ACPI_HANDLE acpi_handle,
ACPI_STRING pathname,
ACPI_OBJECT_LIST *arguments,
ACPI_BUFFER *buffer);
ACPI_STATUS
bm_evaluate_simple_integer (
ACPI_HANDLE acpi_handle,
ACPI_STRING pathname,
u32 *data);
ACPI_STATUS
bm_evaluate_reference_list (
ACPI_HANDLE acpi_handle,
ACPI_STRING pathname,
BM_HANDLE_LIST *reference_list);
/* bm_proc.c */
ACPI_STATUS
bm_proc_initialize (void);
ACPI_STATUS
bm_proc_terminate (void);
ACPI_STATUS
bm_generate_event (
BM_HANDLE device_handle,
char *device_type,
char *device_instance,
u32 event_type,
u32 event_data);
#endif /* __BM_H__ */

View file

@ -0,0 +1,75 @@
/*****************************************************************************
*
* Module name: bmpower.h
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __BMPOWER_H__
#define __BMPOWER_H__
#include "bm.h"
/*****************************************************************************
* Types & Defines
*****************************************************************************/
/*
* BM_POWER_RESOURCE:
* ------------------
*/
typedef struct
{
BM_HANDLE device_handle;
ACPI_HANDLE acpi_handle;
BM_POWER_STATE system_level;
u32 resource_order;
BM_POWER_STATE state;
u32 reference_count;
} BM_POWER_RESOURCE;
/*****************************************************************************
* Function Prototypes
*****************************************************************************/
/* bmpower.c */
ACPI_STATUS
bm_pr_initialize (void);
ACPI_STATUS
bm_pr_terminate (void);
ACPI_STATUS
bm_pr_list_get_state (
BM_HANDLE_LIST *resource_list,
BM_POWER_STATE *power_state);
ACPI_STATUS
bm_pr_list_transition (
BM_HANDLE_LIST *current_list,
BM_HANDLE_LIST *target_list);
#endif /* __BMPOWER_H__ */

View file

@ -0,0 +1,113 @@
/******************************************************************************
*
* Module Name: bn.h
* $Revision: 1.1 $
*
*****************************************************************************/
/*
* Copyright (C) 2000, 2001 Andrew Grover
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __BN_H__
#define __BN_H__
#include <actypes.h>
#include <acexcep.h>
#include <bm.h>
/*****************************************************************************
* Types & Other Defines
*****************************************************************************/
/*
* Notifications:
* ---------------------
*/
#define BN_NOTIFY_STATUS_CHANGE ((BM_NOTIFY) 0x80)
/*
* Types:
* ------
*/
#define BN_TYPE_POWER_BUTTON (0x01)
#define BN_TYPE_POWER_BUTTON_FIXED (0x02)
#define BN_TYPE_SLEEP_BUTTON (0x03)
#define BN_TYPE_SLEEP_BUTTON_FIXED (0x04)
#define BN_TYPE_LID_SWITCH (0x05)
/*
* Hardware IDs:
* -------------
* TODO: Power and Sleep button HIDs also exist in <bm.h>. Should all
* HIDs (ACPI well-known devices) exist in one place (e.g.
* acpi_hid.h)?
*/
#define BN_HID_POWER_BUTTON "PNP0C0C"
#define BN_HID_SLEEP_BUTTON "PNP0C0E"
#define BN_HID_LID_SWITCH "PNP0C0D"
/*
* /proc Entries:
* --------------
*/
#define BN_PROC_ROOT "button"
#define BN_PROC_POWER_BUTTON "power"
#define BN_PROC_SLEEP_BUTTON "sleep"
#define BN_PROC_LID_SWITCH "lid"
/*
* Device Context:
* ---------------
*/
typedef struct
{
BM_HANDLE device_handle;
ACPI_HANDLE acpi_handle;
u32 type;
} BN_CONTEXT;
/******************************************************************************
* Function Prototypes
*****************************************************************************/
ACPI_STATUS
bn_initialize (void);
ACPI_STATUS
bn_terminate (void);
ACPI_STATUS
bn_notify_fixed (
void *context);
ACPI_STATUS
bn_notify (
u32 notify_type,
u32 device,
void **context);
ACPI_STATUS
bn_request(
BM_REQUEST *request_info,
void *context);
#endif /* __BN_H__ */

View file

@ -108,7 +108,11 @@ acpi_os_callocate(u32 size)
void
acpi_os_free(void *ptr)
{
ExFreePool(ptr);
if (ptr) {
/* FIXME: There is at least one bug somewhere that
results in an attempt to release a null pointer */
ExFreePool(ptr);
}
}
ACPI_STATUS
@ -552,7 +556,7 @@ acpi_os_wait_semaphore(
DPRINT("Waiting for semaphore[%p|%d|%d]\n", handle, units, timeout);
ExAcquireFastMutex(Mutex);
//ExAcquireFastMutex(Mutex);
return AE_OK;
}
@ -571,7 +575,7 @@ acpi_os_signal_semaphore(
DPRINT("Signaling semaphore[%p|%d]\n", handle, units);
ExReleaseFastMutex(Mutex);
//ExReleaseFastMutex(Mutex);
return AE_OK;
}