From ba2a8ca04502bebacb4b071ef646e10104e6ed83 Mon Sep 17 00:00:00 2001 From: Casper Hornstrup Date: Sat, 5 May 2001 19:15:44 +0000 Subject: [PATCH] Added ACPI bus manager Added ACPI button driver svn path=/trunk/; revision=1890 --- reactos/drivers/bus/acpi/changed.txt | 13 +- reactos/drivers/bus/acpi/makefile | 12 + reactos/drivers/bus/acpi/ospm/acpienum.c | 211 +++- reactos/drivers/bus/acpi/ospm/acpisys.c | 177 ++- reactos/drivers/bus/acpi/ospm/bn.c | 598 ++++++++++ reactos/drivers/bus/acpi/ospm/busmgr/bm.c | 1047 +++++++++++++++++ .../drivers/bus/acpi/ospm/busmgr/bmnotify.c | 310 +++++ reactos/drivers/bus/acpi/ospm/busmgr/bmpm.c | 397 +++++++ .../drivers/bus/acpi/ospm/busmgr/bmpower.c | 669 +++++++++++ .../drivers/bus/acpi/ospm/busmgr/bmrequest.c | 164 +++ .../drivers/bus/acpi/ospm/busmgr/bmsearch.c | 191 +++ .../drivers/bus/acpi/ospm/busmgr/bmutils.c | 606 ++++++++++ .../drivers/bus/acpi/ospm/busmgr/bmxface.c | 331 ++++++ .../drivers/bus/acpi/ospm/include/acpisys.h | 34 +- reactos/drivers/bus/acpi/ospm/include/bm.h | 624 ++++++++++ .../drivers/bus/acpi/ospm/include/bmpower.h | 75 ++ reactos/drivers/bus/acpi/ospm/include/bn.h | 113 ++ reactos/drivers/bus/acpi/ospm/osl.c | 10 +- 18 files changed, 5518 insertions(+), 64 deletions(-) create mode 100644 reactos/drivers/bus/acpi/ospm/bn.c create mode 100644 reactos/drivers/bus/acpi/ospm/busmgr/bm.c create mode 100644 reactos/drivers/bus/acpi/ospm/busmgr/bmnotify.c create mode 100644 reactos/drivers/bus/acpi/ospm/busmgr/bmpm.c create mode 100644 reactos/drivers/bus/acpi/ospm/busmgr/bmpower.c create mode 100644 reactos/drivers/bus/acpi/ospm/busmgr/bmrequest.c create mode 100644 reactos/drivers/bus/acpi/ospm/busmgr/bmsearch.c create mode 100644 reactos/drivers/bus/acpi/ospm/busmgr/bmutils.c create mode 100644 reactos/drivers/bus/acpi/ospm/busmgr/bmxface.c create mode 100644 reactos/drivers/bus/acpi/ospm/include/bm.h create mode 100644 reactos/drivers/bus/acpi/ospm/include/bmpower.h create mode 100644 reactos/drivers/bus/acpi/ospm/include/bn.h diff --git a/reactos/drivers/bus/acpi/changed.txt b/reactos/drivers/bus/acpi/changed.txt index db2ffcab0aa..571775163fd 100644 --- a/reactos/drivers/bus/acpi/changed.txt +++ b/reactos/drivers/bus/acpi/changed.txt @@ -7,4 +7,15 @@ Changes to ACPI CA + include/platform/acwin.h + include/platform/types.h -- ospm/* \ No newline at end of file +- 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 diff --git a/reactos/drivers/bus/acpi/makefile b/reactos/drivers/bus/acpi/makefile index 832ce388044..dc6fc6fe0ec 100644 --- a/reactos/drivers/bus/acpi/makefile +++ b/reactos/drivers/bus/acpi/makefile @@ -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 = \ diff --git a/reactos/drivers/bus/acpi/ospm/acpienum.c b/reactos/drivers/bus/acpi/ospm/acpienum.c index 68bdfb75607..187e10dd3b8 100644 --- a/reactos/drivers/bus/acpi/ospm/acpienum.c +++ b/reactos/drivers/bus/acpi/ospm/acpienum.c @@ -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 -#include +#include #define NDEBUG #include -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; } diff --git a/reactos/drivers/bus/acpi/ospm/acpisys.c b/reactos/drivers/bus/acpi/ospm/acpisys.c index 33c911dc5be..89c30e15182 100644 --- a/reactos/drivers/bus/acpi/ospm/acpisys.c +++ b/reactos/drivers/bus/acpi/ospm/acpisys.c @@ -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 +#include +#include #define NDEBUG #include @@ -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; diff --git a/reactos/drivers/bus/acpi/ospm/bn.c b/reactos/drivers/bus/acpi/ospm/bn.c new file mode 100644 index 00000000000..c3486207b3b --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/bn.c @@ -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 +#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: + * + * RETURN: + * + * 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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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); +} diff --git a/reactos/drivers/bus/acpi/ospm/busmgr/bm.c b/reactos/drivers/bus/acpi/ospm/busmgr/bm.c new file mode 100644 index 00000000000..5dc9cb2084b --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/busmgr/bm.c @@ -0,0 +1,1047 @@ +/****************************************************************************** + * + * Module Name: bm.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 +#include "bm.h" + + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bm") + + +/**************************************************************************** + * Globals + ****************************************************************************/ + +extern FADT_DESCRIPTOR_REV2 acpi_fadt; +/* TODO: Make dynamically sizeable. */ +static BM_NODE_LIST node_list; + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_print + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print ( + BM_NODE *node, + u32 flags) +{ + ACPI_BUFFER buffer; + BM_DEVICE *device = NULL; + char *type_string = NULL; + + if (!node) { + return; + } + + device = &(node->device); + + if (flags & BM_PRINT_PRESENT) { + if (!BM_DEVICE_PRESENT(device)) { + return; + } + } + + 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)) { + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + } + + DEBUG_PRINT(ACPI_INFO, ("%s[0x%02x] hid[%s] %s\n", type_string, device->handle, device->id.hid, buffer.pointer)); + DEBUG_PRINT(ACPI_INFO, (" acpi_handle[0x%08x] flags[0x%02x] status[0x%02x]\n", device->acpi_handle, device->flags, device->status)); + + if (flags & BM_PRINT_IDENTIFICATION) { + DEBUG_PRINT(ACPI_INFO, (" identification: uid[%s] adr[0x%08x]\n", device->id.uid, device->id.adr)); + } + + if (flags & BM_PRINT_LINKAGE) { + DEBUG_PRINT(ACPI_INFO, (" linkage: this[%p] parent[%p] next[%p]\n", node, node->parent, node->next)); + DEBUG_PRINT(ACPI_INFO, (" scope.head[%p] scope.tail[%p]\n", node->scope.head, node->scope.tail)); + } + + if (flags & BM_PRINT_POWER) { + DEBUG_PRINT(ACPI_INFO, (" power: state[D%d] flags[0x%08X]\n", device->power.state, device->power.flags)); + DEBUG_PRINT(ACPI_INFO, (" 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])); + DEBUG_PRINT(ACPI_INFO, (" 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)) { + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + } + + acpi_os_free(buffer.pointer); + + return; +} + + +/**************************************************************************** + * + * FUNCTION: bm_print_hierarchy + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +void +bm_print_hierarchy (void) +{ + u32 i = 0; + + FUNCTION_TRACE("bm_print_hierarchy"); + + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + + for (i = 0; i < node_list.count; i++) { + bm_print(node_list.nodes[i], BM_PRINT_GROUP | BM_PRINT_PRESENT); + } + + DEBUG_PRINT(ACPI_INFO, ("+------------------------------------------------------------\n")); + + return_VOID; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_status + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_status ( + BM_DEVICE *device) +{ + ACPI_STATUS status = AE_OK; + + if (!device) { + return AE_BAD_PARAMETER; + } + + device->status = BM_STATUS_UNKNOWN; + + /* + * Dynamic Status? + * --------------- + * If _STA isn't present we just return the default status. + */ + if (!(device->flags & BM_FLAGS_DYNAMIC_STATUS)) { + device->status = BM_STATUS_DEFAULT; + return AE_OK; + } + + /* + * Evaluate _STA: + * -------------- + */ + status = bm_evaluate_simple_integer(device->acpi_handle, "_STA", + &(device->status)); + + return status; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_identification + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_identification ( + BM_DEVICE *device) +{ + ACPI_STATUS status = AE_OK; + ACPI_DEVICE_INFO info; + + if (!device) { + return AE_BAD_PARAMETER; + } + + if (!(device->flags & BM_FLAGS_IDENTIFIABLE)) { + return AE_OK; + } + + MEMSET(&(device->id.uid), 0, sizeof(device->id.uid)); + MEMSET(&(device->id.hid), 0, sizeof(device->id.hid)); + device->id.adr = BM_ADDRESS_UNKNOWN; + + /* + * Get Object Info: + * ---------------- + * Evalute _UID, _HID, _ADR, and _STA... + */ + status = acpi_get_object_info(device->acpi_handle, &info); + if (ACPI_FAILURE(status)) { + return status; + } + + if (info.valid & ACPI_VALID_UID) { + MEMCPY((void*)device->id.uid, (void*)info.unique_id, + sizeof(BM_DEVICE_UID)); + } + + if (info.valid & ACPI_VALID_HID) { + MEMCPY((void*)device->id.hid, (void*)info.hardware_id, + sizeof(BM_DEVICE_HID)); + } + + if (info.valid & ACPI_VALID_ADR) { + device->id.adr = info.address; + } + + return status; +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_flags + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_flags ( + BM_DEVICE *device) +{ + ACPI_HANDLE acpi_handle = NULL; + + if (!device) { + return AE_BAD_PARAMETER; + } + + device->flags = BM_FLAGS_UNKNOWN; + + switch (device->id.type) { + + case BM_TYPE_DEVICE: + + /* + * Presence of _DCK indicates a docking station. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_DCK", &acpi_handle))) { + device->flags |= BM_FLAGS_DOCKING_STATION; + } + + /* + * Presence of _EJD and/or _EJx indicates 'ejectable'. + * TODO: _EJx... + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_EJD", &acpi_handle))) { + device->flags |= BM_FLAGS_EJECTABLE; + } + + /* + * Presence of _PR0 or _PS0 indicates 'power manageable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_PR0", &acpi_handle)) || + ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_PS0", &acpi_handle))) { + device->flags |= BM_FLAGS_POWER_CONTROL; + } + + /* + * Presence of _CRS indicates 'configurable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_CRS", &acpi_handle))) { + device->flags |= BM_FLAGS_CONFIGURABLE; + } + + /* Fall through to next case statement. */ + + case BM_TYPE_PROCESSOR: + case BM_TYPE_THERMAL_ZONE: + case BM_TYPE_POWER_RESOURCE: + /* + * Presence of _HID or _ADR indicates 'identifiable'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_HID", &acpi_handle)) || + ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_ADR", &acpi_handle))) { + device->flags |= BM_FLAGS_IDENTIFIABLE; + } + + /* + * Presence of _STA indicates 'dynamic status'. + */ + if (ACPI_SUCCESS(acpi_get_handle(device->acpi_handle, + "_STA", &acpi_handle))) { + device->flags |= BM_FLAGS_DYNAMIC_STATUS; + } + + break; + } + + return AE_OK; +} + + +/**************************************************************************** + * + * FUNCTION: bm_add_namespace_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_add_namespace_device ( + ACPI_HANDLE acpi_handle, + ACPI_OBJECT_TYPE acpi_type, + BM_NODE *parent, + BM_NODE **child) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + BM_DEVICE *device = NULL; + + FUNCTION_TRACE("bm_add_namespace_device"); + + if (!parent || !child) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node_list.count > BM_HANDLES_MAX) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + (*child) = NULL; + + /* + * Create Node: + * ------------ + */ + node = acpi_os_callocate(sizeof(BM_NODE)); + if (!node) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + node->parent = parent; + node->next = NULL; + + device = &(node->device); + + device->handle = node_list.count; + device->acpi_handle = acpi_handle; + + /* + * Device Type: + * ------------ + */ + switch (acpi_type) { + case INTERNAL_TYPE_SCOPE: + device->id.type = BM_TYPE_SCOPE; + break; + case ACPI_TYPE_PROCESSOR: + device->id.type = BM_TYPE_PROCESSOR; + break; + case ACPI_TYPE_THERMAL: + device->id.type = BM_TYPE_THERMAL_ZONE; + break; + case ACPI_TYPE_POWER: + device->id.type = BM_TYPE_POWER_RESOURCE; + break; + case ACPI_TYPE_DEVICE: + device->id.type = BM_TYPE_DEVICE; + break; + } + + /* + * Get Other Device Info: + * ---------------------- + * But only if this device's parent is present (which implies + * this device MAY be present). + */ + if (BM_NODE_PRESENT(node->parent)) { + /* + * Device Flags + */ + status = bm_get_flags(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Device Identification + */ + status = bm_get_identification(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Device Status + */ + status = bm_get_status(device); + if (ACPI_FAILURE(status)) { + goto end; + } + + /* + * Power Management: + * ----------------- + * If this node doesn't provide direct power control + * then we inherit PM capabilities from its parent. + * + * TODO: Inherit! + */ + if (device->flags & BM_FLAGS_POWER_CONTROL) { + status = bm_get_pm_capabilities(node); + if (ACPI_FAILURE(status)) { + goto end; + } + } + } + +end: + if (ACPI_FAILURE(status)) { + acpi_os_free(node); + } + else { + /* + * Add to the node_list. + */ + node_list.nodes[node_list.count++] = node; + + /* + * Formulate Hierarchy: + * -------------------- + * Arrange within the namespace by assigning the parent and + * adding to the parent device's list of children (scope). + */ + if (!parent->scope.head) { + parent->scope.head = node; + } + else { + if (!parent->scope.tail) { + (parent->scope.head)->next = node; + } + else { + (parent->scope.tail)->next = node; + } + } + parent->scope.tail = node; + + (*child) = node; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_enumerate_namespace + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_enumerate_namespace (void) +{ + ACPI_STATUS status = AE_OK; + ACPI_HANDLE parent_handle = ACPI_ROOT_OBJECT; + ACPI_HANDLE child_handle = NULL; + BM_NODE *parent = NULL; + BM_NODE *child = NULL; + ACPI_OBJECT_TYPE acpi_type = 0; + u32 level = 1; + + FUNCTION_TRACE("bm_enumerate_namespace"); + + parent = node_list.nodes[0]; + + /* + * Enumerate ACPI Namespace: + * ------------------------- + * Parse through the ACPI namespace, identify all 'devices', + * and create a new entry for each in our collection. + */ + while (level > 0) { + + /* + * Get the next object at this level. + */ + status = acpi_get_next_object(ACPI_TYPE_ANY, parent_handle, child_handle, &child_handle); + if (ACPI_SUCCESS(status)) { + + /* + * TODO: This is a hack to get around the problem + * identifying scope objects. Scopes + * somehow need to be uniquely identified. + */ + status = acpi_get_type(child_handle, &acpi_type); + if (ACPI_SUCCESS(status) && (acpi_type == ACPI_TYPE_ANY)) { + status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL); + if (ACPI_SUCCESS(status)) { + acpi_type = INTERNAL_TYPE_SCOPE; + } + } + + /* + * Device? + * ------- + * If this object is a 'device', insert into the + * ACPI Bus Manager's local hierarchy and search + * the object's scope for any child devices (a + * depth-first search). + */ + switch (acpi_type) { + case INTERNAL_TYPE_SCOPE: + case ACPI_TYPE_DEVICE: + case ACPI_TYPE_PROCESSOR: + case ACPI_TYPE_THERMAL: + case ACPI_TYPE_POWER: + status = bm_add_namespace_device(child_handle, acpi_type, parent, &child); + if (ACPI_SUCCESS(status)) { + status = acpi_get_next_object(ACPI_TYPE_ANY, child_handle, 0, NULL); + if (ACPI_SUCCESS(status)) { + level++; + parent_handle = child_handle; + child_handle = 0; + parent = child; + } + } + break; + } + } + + /* + * Scope Exhausted: + * ---------------- + * No more children in this object's scope, Go back up + * in the namespace tree to the object's parent. + */ + else { + level--; + child_handle = parent_handle; + acpi_get_parent(parent_handle, + &parent_handle); + + if (parent) { + parent = parent->parent; + } + else { + return_ACPI_STATUS(AE_NULL_ENTRY); + } + } + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_add_fixed_feature_device + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_add_fixed_feature_device ( + BM_NODE *parent, + BM_DEVICE_TYPE device_type, + char *device_hid) +{ + ACPI_STATUS status = AE_OK; + BM_NODE *node = NULL; + + FUNCTION_TRACE("bm_add_fixed_feature_device"); + + if (!parent) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + if (node_list.count > BM_HANDLES_MAX) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Allocate the new device and add to the device array. + */ + node = acpi_os_callocate(sizeof(BM_NODE)); + if (!node) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Get device info. + */ + node->device.handle = node_list.count; + node->device.acpi_handle = ACPI_ROOT_OBJECT; + node->device.id.type = BM_TYPE_FIXED_BUTTON; + if (device_hid) { + MEMCPY((void*)node->device.id.hid, device_hid, + sizeof(node->device.id.hid)); + } + node->device.flags = BM_FLAGS_FIXED_FEATURE; + node->device.status = BM_STATUS_DEFAULT; + /* TODO: Device PM capabilities */ + + /* + * Add to the node_list. + */ + node_list.nodes[node_list.count++] = node; + + /* + * Formulate Hierarchy: + * -------------------- + * Arrange within the namespace by assigning the parent and + * adding to the parent device's list of children (scope). + */ + node->parent = parent; + node->next = NULL; + + if (parent) { + if (!parent->scope.head) { + parent->scope.head = node; + } + else { + if (!parent->scope.tail) { + (parent->scope.head)->next = node; + } + else { + (parent->scope.tail)->next = node; + } + } + parent->scope.tail = node; + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_enumerate_fixed_features + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_enumerate_fixed_features (void) +{ + FUNCTION_TRACE("bm_enumerate_fixed_features"); + + /* + * Root Object: + * ------------ + * Fabricate the root object, which happens to always get a + * device_handle of zero. + */ + node_list.nodes[0] = acpi_os_callocate(sizeof(BM_NODE)); + if (NULL == (node_list.nodes[0])) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + node_list.nodes[0]->device.handle = BM_HANDLE_ROOT; + node_list.nodes[0]->device.acpi_handle = ACPI_ROOT_OBJECT; + node_list.nodes[0]->device.flags = BM_FLAGS_UNKNOWN; + node_list.nodes[0]->device.status = BM_STATUS_DEFAULT; + node_list.nodes[0]->device.id.type = BM_TYPE_SYSTEM; + /* TODO: Get system PM capabilities (Sx states?) */ + + node_list.count++; + + /* + * Fixed Features: + * --------------- + * Enumerate fixed-feature devices (e.g. power and sleep buttons). + */ + if (acpi_fadt.pwr_button == 0) { + bm_add_fixed_feature_device(node_list.nodes[0], + BM_TYPE_FIXED_BUTTON, BM_HID_POWER_BUTTON); + } + + if (acpi_fadt.sleep_button == 0) { + bm_add_fixed_feature_device(node_list.nodes[0], + BM_TYPE_FIXED_BUTTON, BM_HID_SLEEP_BUTTON); + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_handle + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_handle ( + ACPI_HANDLE acpi_handle, + BM_HANDLE *device_handle) +{ + ACPI_STATUS status = AE_OK; + u32 i = 0; + + FUNCTION_TRACE("bm_get_handle"); + + if (!device_handle) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + *device_handle = BM_HANDLE_UNKNOWN; + + /* + * Search all devices for a match on the ACPI handle. + */ + for (i=0; idevice.acpi_handle == acpi_handle) { + *device_handle = node_list.nodes[i]->device.handle; + break; + } + } + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_get_node + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_get_node ( + BM_HANDLE device_handle, + ACPI_HANDLE acpi_handle, + BM_NODE **node) +{ + ACPI_STATUS status = AE_OK; + + FUNCTION_TRACE("bm_get_node"); + + if (!node) { + return_ACPI_STATUS(AE_BAD_PARAMETER); + } + + /* + * If no device handle, resolve acpi handle to device handle. + */ + if (!device_handle && acpi_handle) { + status = bm_get_handle(acpi_handle, &device_handle); + if (ACPI_FAILURE(status)) + return_ACPI_STATUS(status); + } + + /* + * Valid device handle? + */ + if (device_handle > BM_HANDLES_MAX) { + DEBUG_PRINT(ACPI_ERROR, ("Invalid node handle [0x%02x] detected.\n", device_handle)); + return_ACPI_STATUS(AE_ERROR); + } + + *node = node_list.nodes[device_handle]; + + /* + * Valid node? + */ + if (!(*node)) { + DEBUG_PRINT(ACPI_ERROR, ("Invalid (NULL) node entry [0x%02x] detected.\n", device_handle)); + return_ACPI_STATUS(AE_NULL_ENTRY); + } + + return_ACPI_STATUS(AE_OK); +} + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_initialize + * + * PARAMETERS: + * + * RETURN: Exception code. + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_initialize (void) +{ + ACPI_STATUS status = AE_OK; + u32 start = 0; + u32 stop = 0; + u32 elapsed = 0; + + FUNCTION_TRACE("bm_initialize"); + + MEMSET(&node_list, 0, sizeof(BM_HANDLE_LIST)); + + acpi_get_timer(&start); + + DEBUG_PRINT(ACPI_INFO, ("Building device hierarchy.\n")); + + /* + * Enumerate ACPI fixed-feature devices. + */ + status = bm_enumerate_fixed_features(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + /* + * Enumerate the ACPI namespace. + */ + status = bm_enumerate_namespace(); + if (ACPI_FAILURE(status)) { + return_ACPI_STATUS(status); + } + + acpi_get_timer(&stop); + acpi_get_timer_duration(start, stop, &elapsed); + + DEBUG_PRINT(ACPI_INFO, ("Device heirarchy build took [%d] microseconds.\n", elapsed)); + + /* + * Display hierarchy. + */ +#ifdef ACPI_DEBUG + bm_print_hierarchy(); +#endif /*ACPI_DEBUG*/ + + /* + * Register for all standard and device-specific notifications. + */ + DEBUG_PRINT(ACPI_INFO, ("Registering for all device notifications.\n")); + + status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, &bm_notify, NULL); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to register for standard notifications.\n")); + return_ACPI_STATUS(status); + } + + status = acpi_install_notify_handler(ACPI_ROOT_OBJECT, + ACPI_DEVICE_NOTIFY, &bm_notify, NULL); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to register for device-specific notifications.\n")); + return_ACPI_STATUS(status); + } + + /* + * Initialize /proc interface. + */ + //DEBUG_PRINT(ACPI_INFO, ("Initializing /proc interface.\n")); + //status = bm_proc_initialize(); + + DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager enabled.\n")); + + /* + * Initialize built-in power resource driver. + */ + bm_pr_initialize(); + + return_ACPI_STATUS(status); +} + + +/**************************************************************************** + * + * FUNCTION: bm_terminate + * + * PARAMETERS: + * + * RETURN: Exception code. + * + * DESCRIPTION: + * + ****************************************************************************/ + +ACPI_STATUS +bm_terminate (void) +{ + ACPI_STATUS status = AE_OK; + u32 i = 0; + + FUNCTION_TRACE("bm_terminate"); + + /* + * Terminate built-in power resource driver. + */ + bm_pr_terminate(); + + /* + * Remove the /proc interface. + */ + //DEBUG_PRINT(ACPI_INFO, ("Removing /proc interface.\n")); + //status = bm_proc_terminate(); + + + /* + * Unregister for all notifications. + */ + + DEBUG_PRINT(ACPI_INFO, ("Unregistering for device notifications.\n")); + + status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_SYSTEM_NOTIFY, &bm_notify); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for standard notifications.\n")); + } + + status = acpi_remove_notify_handler(ACPI_ROOT_OBJECT, + ACPI_DEVICE_NOTIFY, &bm_notify); + if (ACPI_FAILURE(status)) { + DEBUG_PRINT(ACPI_ERROR, ("Unable to un-register for device-specific notifications.\n")); + } + + /* + * Parse through the device array, freeing all entries. + */ + DEBUG_PRINT(ACPI_INFO, ("Removing device hierarchy.\n")); + for (i = 0; i < node_list.count; i++) { + if (node_list.nodes[i]) { + acpi_os_free(node_list.nodes[i]); + } + } + + DEBUG_PRINT(ACPI_INFO, ("ACPI Bus Manager disabled.\n")); + + return_ACPI_STATUS(AE_OK); +} diff --git a/reactos/drivers/bus/acpi/ospm/busmgr/bmnotify.c b/reactos/drivers/bus/acpi/ospm/busmgr/bmnotify.c new file mode 100644 index 00000000000..c64d5d415f1 --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/busmgr/bmnotify.c @@ -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 +#include "bm.h" + + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmnotify") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_generate_notify + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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; +} + + diff --git a/reactos/drivers/bus/acpi/ospm/busmgr/bmpm.c b/reactos/drivers/bus/acpi/ospm/busmgr/bmpm.c new file mode 100644 index 00000000000..336cb99873f --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/busmgr/bmpm.c @@ -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 +#include "bm.h" +#include "bmpower.h" + + +#define _COMPONENT ACPI_POWER_CONTROL + MODULE_NAME ("bmpm") + + +/**************************************************************************** + * Internal Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_get_inferred_power_state + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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; iacpi_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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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(¤t_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, ¤t_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(¤t_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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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); +} diff --git a/reactos/drivers/bus/acpi/ospm/busmgr/bmpower.c b/reactos/drivers/bus/acpi/ospm/busmgr/bmpower.c new file mode 100644 index 00000000000..5e76999b0af --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/busmgr/bmpower.c @@ -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 +#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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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); +} + + + diff --git a/reactos/drivers/bus/acpi/ospm/busmgr/bmrequest.c b/reactos/drivers/bus/acpi/ospm/busmgr/bmrequest.c new file mode 100644 index 00000000000..a3713811842 --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/busmgr/bmrequest.c @@ -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 +#include "bm.h" + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmrequest") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_generate_request + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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); +} diff --git a/reactos/drivers/bus/acpi/ospm/busmgr/bmsearch.c b/reactos/drivers/bus/acpi/ospm/busmgr/bmsearch.c new file mode 100644 index 00000000000..fa15bb8708c --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/busmgr/bmsearch.c @@ -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 +#include "bm.h" + + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmsearch") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_compare + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * 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: + * + ****************************************************************************/ + +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); + } +} diff --git a/reactos/drivers/bus/acpi/ospm/busmgr/bmutils.c b/reactos/drivers/bus/acpi/ospm/busmgr/bmutils.c new file mode 100644 index 00000000000..4871d9421a7 --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/busmgr/bmutils.c @@ -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 +#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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +/* + 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; ipackage.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; ipackage.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: + * + * 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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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); +} + + diff --git a/reactos/drivers/bus/acpi/ospm/busmgr/bmxface.c b/reactos/drivers/bus/acpi/ospm/busmgr/bmxface.c new file mode 100644 index 00000000000..68ec19d07e5 --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/busmgr/bmxface.c @@ -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 +#include "bm.h" + +#define _COMPONENT ACPI_BUS_MANAGER + MODULE_NAME ("bmxface") + + +/**************************************************************************** + * External Functions + ****************************************************************************/ + +/**************************************************************************** + * + * FUNCTION: bm_get_device_status + * + * PARAMETERS: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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: + * + * RETURN: + * + * DESCRIPTION: + * + ****************************************************************************/ + +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); +} diff --git a/reactos/drivers/bus/acpi/ospm/include/acpisys.h b/reactos/drivers/bus/acpi/ospm/include/acpisys.h index 619e8c6f889..eb0788011d0 100644 --- a/reactos/drivers/bus/acpi/ospm/include/acpisys.h +++ b/reactos/drivers/bus/acpi/ospm/include/acpisys.h @@ -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 #define __INCLUDE_TYPES_H #include #undef ROUND_UP #include +#include + +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 */ diff --git a/reactos/drivers/bus/acpi/ospm/include/bm.h b/reactos/drivers/bus/acpi/ospm/include/bm.h new file mode 100644 index 00000000000..1c712b229c3 --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/include/bm.h @@ -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 +#include + + +/***************************************************************************** + * 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? + * | +-------------------- + * +---------------------------- 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? + * +-------------------- + * + * 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? + * +---------------- + */ +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__ */ diff --git a/reactos/drivers/bus/acpi/ospm/include/bmpower.h b/reactos/drivers/bus/acpi/ospm/include/bmpower.h new file mode 100644 index 00000000000..2fcbedfa217 --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/include/bmpower.h @@ -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__ */ diff --git a/reactos/drivers/bus/acpi/ospm/include/bn.h b/reactos/drivers/bus/acpi/ospm/include/bn.h new file mode 100644 index 00000000000..9265196f3ed --- /dev/null +++ b/reactos/drivers/bus/acpi/ospm/include/bn.h @@ -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 +#include +#include + + +/***************************************************************************** + * 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 . 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__ */ diff --git a/reactos/drivers/bus/acpi/ospm/osl.c b/reactos/drivers/bus/acpi/ospm/osl.c index 84edff51a57..32d7870c500 100644 --- a/reactos/drivers/bus/acpi/ospm/osl.c +++ b/reactos/drivers/bus/acpi/ospm/osl.c @@ -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; }