/*
* Modified for ReactOS and latest ACPICA
- * Copyright (C)2009 Samuel Serapion
+ * Copyright (C)2009 Samuel Serapion
*/
-#include <ntddk.h>
-
-#include <acpi.h>
-#include <acpi_bus.h>
-#include <acpi_drivers.h>
-#include <glue.h>
+#include <precomp.h>
#define NDEBUG
#include <debug.h>
ACPI_HANDLE handle,
void *context)
{
- DPRINT1("acpi_bus_data_handler not implemented");
+ DPRINT1("acpi_bus_data_handler not implemented\n");
/* TBD */
}
else {
/*
- * Get the device's power state either directly (via _PSC) or
+ * Get the device's power state either directly (via _PSC) or
* indirectly (via power resources).
*/
if (device->power.flags.explicit_get) {
- status = acpi_evaluate_integer(device->handle, "_PSC",
+ status = acpi_evaluate_integer(device->handle, "_PSC",
NULL, &psc);
if (ACPI_FAILURE(status))
return_VALUE(AE_NOT_FOUND);
* On transitions to a high-powered state we first apply power (via
* power resources) then evalute _PSx. Conversly for transitions to
* a lower-powered state.
- */
+ */
if (state < device->power.state) {
if (device->power.flags.power_resources) {
result = acpi_power_transition(device, state);
goto end;
}
if (device->power.states[state].flags.explicit_set) {
- status = AcpiEvaluateObject(device->handle,
+ status = AcpiEvaluateObject(device->handle,
object_name, NULL, NULL);
if (ACPI_FAILURE(status)) {
result = AE_NOT_FOUND;
}
else {
if (device->power.states[state].flags.explicit_set) {
- status = AcpiEvaluateObject(device->handle,
+ status = AcpiEvaluateObject(device->handle,
object_name, NULL, NULL);
if (ACPI_FAILURE(status)) {
result = AE_NOT_FOUND;
struct acpi_device *device = SystemArgument1;
ULONG_PTR TypeData = (ULONG_PTR)SystemArgument2;
KIRQL OldIrql;
-
- event = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_bus_event), 'IPCA');
+
+ event = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_bus_event), 'epcA');
if (!event)
return;
-
+
sprintf(event->device_class, "%s", device->pnp.device_class);
sprintf(event->bus_id, "%s", device->pnp.bus_id);
event->type = (TypeData & 0xFF000000) >> 24;
{
ULONG_PTR TypeData = 0;
- DPRINT("acpi_bus_generate_event");
+ DPRINT("acpi_bus_generate_event\n");
if (!device)
return_VALUE(AE_BAD_PARAMETER);
/* drop event on the floor if no one's listening */
if (!event_is_open)
return_VALUE(0);
-
+
/* Data shouldn't even get near 24 bits */
ASSERT(!(data & 0xFF000000));
-
+
TypeData = data;
TypeData |= type << 24;
//DECLARE_WAITQUEUE(wait, current);
- DPRINT("acpi_bus_receive_event");
+ DPRINT("acpi_bus_receive_event\n");
if (!event)
return AE_BAD_PARAMETER;
memcpy(event, entry, sizeof(struct acpi_bus_event));
- ExFreePoolWithTag(entry, 'IPCA');
+ ExFreePoolWithTag(entry, 'epcA');
return_VALUE(0);
}
*/
static int
acpi_bus_walk (
- struct acpi_device *start,
- acpi_bus_walk_callback callback,
- int direction,
+ struct acpi_device *start,
+ acpi_bus_walk_callback callback,
+ int direction,
void *data)
{
int result = 0;
* ---------------
* Callback for all 'system-level' device notifications (values 0x00-0x7F).
*/
-static void
+static void
acpi_bus_notify (
ACPI_HANDLE handle,
UINT32 type,
//blocking_notifier_call_chain(&acpi_bus_notify_list,
// type, (void *)handle);
+ acpi_bus_get_device(handle, &device);
+
switch (type) {
case ACPI_NOTIFY_BUS_CHECK:
- DPRINT("Received BUS CHECK notification for device [%s]\n",
- device->pnp.bus_id);
+ DPRINT("Received BUS CHECK notification for device [%s]\n",
+ device ? device->pnp.bus_id : "n/a");
acpi_bus_check_scope(handle);
- /*
+ /*
* TBD: We'll need to outsource certain events to non-ACPI
* drivers via the device manager (device.c).
*/
break;
case ACPI_NOTIFY_DEVICE_CHECK:
- DPRINT("Received DEVICE CHECK notification for device [%s]\n",
- device->pnp.bus_id);
+ DPRINT("Received DEVICE CHECK notification for device [%s]\n",
+ device ? device->pnp.bus_id : "n/a");
acpi_bus_check_device(handle);
- /*
+ /*
* TBD: We'll need to outsource certain events to non-ACPI
* drivers via the device manager (device.c).
*/
break;
case ACPI_NOTIFY_DEVICE_WAKE:
- DPRINT("Received DEVICE WAKE notification for device [%s]\n",
- device->pnp.bus_id);
+ DPRINT("Received DEVICE WAKE notification for device [%s]\n",
+ device ? device->pnp.bus_id : "n/a");
acpi_bus_check_device(handle);
/*
* TBD: We'll need to outsource certain events to non-ACPI
break;
case ACPI_NOTIFY_EJECT_REQUEST:
- DPRINT1("Received EJECT REQUEST notification for device [%s]\n",
- device->pnp.bus_id);
+ DPRINT1("Received EJECT REQUEST notification for device [%s]\n",
+ device ? device->pnp.bus_id : "n/a");
/* TBD */
break;
case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
- DPRINT1("Received DEVICE CHECK LIGHT notification for device [%s]\n",
- device->pnp.bus_id);
+ DPRINT1("Received DEVICE CHECK LIGHT notification for device [%s]\n",
+ device ? device->pnp.bus_id : "n/a");
/* TBD: Exactly what does 'light' mean? */
break;
case ACPI_NOTIFY_FREQUENCY_MISMATCH:
- DPRINT1("Received FREQUENCY MISMATCH notification for device [%s]\n",
- device->pnp.bus_id);
+ DPRINT1("Received FREQUENCY MISMATCH notification for device [%s]\n",
+ device ? device->pnp.bus_id : "n/a");
/* TBD */
break;
case ACPI_NOTIFY_BUS_MODE_MISMATCH:
- DPRINT1("Received BUS MODE MISMATCH notification for device [%s]\n",
- device->pnp.bus_id);
+ DPRINT1("Received BUS MODE MISMATCH notification for device [%s]\n",
+ device ? device->pnp.bus_id : "n/a");
/* TBD */
break;
case ACPI_NOTIFY_POWER_FAULT:
- DPRINT1("Received POWER FAULT notification for device [%s]\n",
- device->pnp.bus_id);
+ DPRINT1("Received POWER FAULT notification for device [%s]\n",
+ device ? device->pnp.bus_id : "n/a");
/* TBD */
break;
default:
- DPRINT1("Received unknown/unsupported notification [%08x]\n",
- type);
+ DPRINT1("Received unknown/unsupported notification [%08x] for device [%s]\n",
+ type, device ? device->pnp.bus_id : "n/a");
break;
}
- acpi_bus_get_device(handle, &device);
if (device) {
driver = device->driver;
if (driver && driver->ops.notify &&
/**
- * acpi_bus_match
+ * acpi_bus_match
* --------------
* Checks the device's hardware (_HID) or compatible (_CID) ids to see if it
* matches the specified driver's criteria.
goto Done;
if (device->flags.compatible_ids) {
- ACPI_DEVICE_ID_LIST *cid_list = device->pnp.cid_list;
+ ACPI_PNP_DEVICE_ID_LIST *cid_list = device->pnp.cid_list;
int i;
/* compare multiple _CID entries against driver ids */
error = -2;
Done:
-
+
return error;
}
/**
- * acpi_bus_driver_init
+ * acpi_bus_driver_init
* --------------------
- * Used to initialize a device via its device driver. Called whenever a
+ * Used to initialize a device via its device driver. Called whenever a
* driver is bound to a device. Invokes the driver's add() and start() ops.
*/
static int
acpi_bus_driver_init (
- struct acpi_device *device,
+ struct acpi_device *device,
struct acpi_driver *driver)
{
int result = 0;
/**
- * acpi_bus_attach
+ * acpi_bus_attach
* -------------
- * Callback for acpi_bus_walk() used to find devices that match a specific
+ * Callback for acpi_bus_walk() used to find devices that match a specific
* driver's criteria and then attach the driver.
*/
static int
acpi_bus_attach (
- struct acpi_device *device,
- int level,
+ struct acpi_device *device,
+ int level,
void *data)
{
int result = 0;
DPRINT("Found driver [%s] for device [%s]\n",
driver->name, device->pnp.bus_id);
-
+
result = acpi_bus_driver_init(device, driver);
if (result)
return_VALUE(result);
/**
- * acpi_bus_unattach
+ * acpi_bus_unattach
* -----------------
- * Callback for acpi_bus_walk() used to find devices that match a specific
+ * Callback for acpi_bus_walk() used to find devices that match a specific
* driver's criteria and unattach the driver.
*/
static int
acpi_bus_unattach (
- struct acpi_device *device,
- int level,
+ struct acpi_device *device,
+ int level,
void *data)
{
int result = 0;
/**
- * acpi_bus_find_driver
+ * acpi_bus_find_driver
* --------------------
* Parses the list of registered drivers looking for a driver applicable for
* the specified device.
/**
- * acpi_bus_register_driver
- * ------------------------
+ * acpi_bus_register_driver
+ * ------------------------
* Registers a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and binds.
*/
list_add_tail(&driver->node, &acpi_bus_drivers);
up(&acpi_bus_drivers_lock);
- acpi_bus_walk(acpi_root, acpi_bus_attach,
+ acpi_bus_walk(acpi_root, acpi_bus_attach,
WALK_DOWN, driver);
return_VALUE(driver->references);
/**
- * acpi_bus_unregister_driver
+ * acpi_bus_unregister_driver
* --------------------------
* Unregisters a driver with the ACPI bus. Searches the namespace for all
* devices that match the driver's criteria and unbinds.
Device Enumeration
-------------------------------------------------------------------------- */
-static int
+static int
acpi_bus_get_flags (
struct acpi_device *device)
{
}
-int
+int
acpi_bus_add (
struct acpi_device **child,
struct acpi_device *parent,
struct acpi_device *device = NULL;
char bus_id[5] = {'?',0};
ACPI_BUFFER buffer;
- ACPI_DEVICE_INFO *info;
+ ACPI_DEVICE_INFO *info = NULL;
char *hid = NULL;
char *uid = NULL;
- ACPI_DEVICE_ID_LIST *cid_list = NULL;
+ ACPI_PNP_DEVICE_ID_LIST *cid_list = NULL;
int i = 0;
- char static_uid_buffer[5];
+ acpi_unique_id static_uid_buffer;
if (!child)
return_VALUE(AE_BAD_PARAMETER);
- device = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_device), 'IPCA');
+ device = ExAllocatePoolWithTag(NonPagedPool,sizeof(struct acpi_device), 'DpcA');
if (!device) {
DPRINT1("Memory allocation error\n");
return_VALUE(-12);
*/
switch (type) {
case ACPI_BUS_TYPE_SYSTEM:
- sprintf(device->pnp.bus_id, "%s", "ACPI");
+ snprintf(device->pnp.bus_id, sizeof(device->pnp.bus_id), "%s", "ACPI");
break;
case ACPI_BUS_TYPE_POWER_BUTTONF:
case ACPI_BUS_TYPE_POWER_BUTTON:
- sprintf(device->pnp.bus_id, "%s", "PWRF");
+ snprintf(device->pnp.bus_id, sizeof(device->pnp.bus_id), "%s", "PWRF");
break;
case ACPI_BUS_TYPE_SLEEP_BUTTONF:
case ACPI_BUS_TYPE_SLEEP_BUTTON:
- sprintf(device->pnp.bus_id, "%s", "SLPF");
+ snprintf(device->pnp.bus_id, sizeof(device->pnp.bus_id), "%s", "SLPF");
break;
default:
buffer.Length = sizeof(bus_id);
buffer.Pointer = bus_id;
AcpiGetName(handle, ACPI_SINGLE_NAME, &buffer);
-
+
/* Clean up trailing underscores (if any) */
for (i = 3; i > 1; i--) {
if (bus_id[i] == '_')
else
break;
}
- sprintf(device->pnp.bus_id, "%s", bus_id);
+ snprintf(device->pnp.bus_id, sizeof(device->pnp.bus_id), "%s", bus_id);
buffer.Pointer = NULL;
- /* HACK: Skip HPET */
- if (strstr(device->pnp.bus_id, "HPET"))
- {
- DPRINT1("Using HPET hack\n");
- result = -1;
- goto end;
- }
-
break;
}
ACPI_DEBUG_PRINT((ACPI_DB_ERROR,
"Error reading device info\n"));
result = AE_NOT_FOUND;
+ info = NULL;
goto end;
}
if (info->Valid & ACPI_VALID_HID)
uid = info->UniqueId.String;
if (info->Valid & ACPI_VALID_CID) {
cid_list = &info->CompatibleIdList;
- device->pnp.cid_list = ExAllocatePoolWithTag(NonPagedPool,cid_list->ListSize, 'IPCA');
- if (device->pnp.cid_list)
- memcpy(device->pnp.cid_list, cid_list, cid_list->ListSize);
+ device->pnp.cid_list = ExAllocatePoolWithTag(NonPagedPool,cid_list->ListSize, 'DpcA');
+ if (device->pnp.cid_list) {
+ char *p = (char *)&device->pnp.cid_list->Ids[cid_list->Count];
+ device->pnp.cid_list->Count = cid_list->Count;
+ device->pnp.cid_list->ListSize = cid_list->ListSize;
+ for (i = 0; i < cid_list->Count; i++) {
+ device->pnp.cid_list->Ids[i].Length = cid_list->Ids[i].Length;
+ device->pnp.cid_list->Ids[i].String = p;
+ ASSERT(p + cid_list->Ids[i].Length <= (char *)device->pnp.cid_list + cid_list->ListSize);
+ memcpy(device->pnp.cid_list->Ids[i].String,
+ cid_list->Ids[i].String, cid_list->Ids[i].Length);
+ p += cid_list->Ids[i].Length;
+ }
+ }
else
DPRINT("Memory allocation error\n");
}
case ACPI_BUS_TYPE_POWER:
hid = ACPI_POWER_HID;
uid = static_uid_buffer;
- sprintf(uid, "%d", (PowerDeviceCount++));
+ snprintf(uid, sizeof(static_uid_buffer), "%d", (PowerDeviceCount++));
break;
case ACPI_BUS_TYPE_PROCESSOR:
hid = ACPI_PROCESSOR_HID;
uid = static_uid_buffer;
- sprintf(uid, "_%d", (ProcessorCount++));
+ snprintf(uid, sizeof(static_uid_buffer), "_%d", (ProcessorCount++));
break;
case ACPI_BUS_TYPE_SYSTEM:
hid = ACPI_SYSTEM_HID;
case ACPI_BUS_TYPE_THERMAL:
hid = ACPI_THERMAL_HID;
uid = static_uid_buffer;
- sprintf(uid, "%d", (ThermalZoneCount++));
+ snprintf(uid, sizeof(static_uid_buffer), "%d", (ThermalZoneCount++));
break;
case ACPI_BUS_TYPE_POWER_BUTTON:
hid = ACPI_BUTTON_HID_POWER;
uid = static_uid_buffer;
- sprintf(uid, "%d", (PowerButtonCount++));
+ snprintf(uid, sizeof(static_uid_buffer), "%d", (PowerButtonCount++));
break;
case ACPI_BUS_TYPE_POWER_BUTTONF:
hid = ACPI_BUTTON_HID_POWERF;
uid = static_uid_buffer;
- sprintf(uid, "%d", (FixedPowerButtonCount++));
+ snprintf(uid, sizeof(static_uid_buffer), "%d", (FixedPowerButtonCount++));
break;
case ACPI_BUS_TYPE_SLEEP_BUTTON:
hid = ACPI_BUTTON_HID_SLEEP;
uid = static_uid_buffer;
- sprintf(uid, "%d", (SleepButtonCount++));
+ snprintf(uid, sizeof(static_uid_buffer), "%d", (SleepButtonCount++));
break;
case ACPI_BUS_TYPE_SLEEP_BUTTONF:
hid = ACPI_BUTTON_HID_SLEEPF;
uid = static_uid_buffer;
- sprintf(uid, "%d", (FixedSleepButtonCount++));
+ snprintf(uid, sizeof(static_uid_buffer), "%d", (FixedSleepButtonCount++));
break;
}
- /*
+ /*
* \_SB
* ----
* Fix for the system root bus device -- the only root-level device.
*/
if (((ACPI_HANDLE)parent == ACPI_ROOT_OBJECT) && (type == ACPI_BUS_TYPE_DEVICE)) {
hid = ACPI_BUS_HID;
- sprintf(device->pnp.device_name, "%s", ACPI_BUS_DEVICE_NAME);
- sprintf(device->pnp.device_class, "%s", ACPI_BUS_CLASS);
+ snprintf(device->pnp.device_name, sizeof(device->pnp.device_name), "%s", ACPI_BUS_DEVICE_NAME);
+ snprintf(device->pnp.device_class, sizeof(device->pnp.device_class), "%s", ACPI_BUS_CLASS);
}
if (hid) {
- sprintf(device->pnp.hardware_id, "%s", hid);
- device->flags.hardware_id = 1;
+ device->pnp.hardware_id = ExAllocatePoolWithTag(NonPagedPool, strlen(hid) + 1, 'DpcA');
+ if (device->pnp.hardware_id) {
+ snprintf(device->pnp.hardware_id, strlen(hid) + 1, "%s", hid);
+ device->flags.hardware_id = 1;
+ }
}
if (uid) {
- sprintf(device->pnp.unique_id, "%s", uid);
+ snprintf(device->pnp.unique_id, sizeof(device->pnp.unique_id), "%s", uid);
device->flags.unique_id = 1;
}
/*
* Bind _ADR-Based Devices
* -----------------------
- * If there's a a bus address (_ADR) then we utilize the parent's
+ * If there's a a bus address (_ADR) then we utilize the parent's
* 'bind' function (if exists) to bind the ACPI- and natively-
* enumerated device representations.
*/
acpi_bus_find_driver(device);
end:
+ if (info != NULL)
+ ACPI_FREE(info);
if (result) {
if (device->pnp.cid_list) {
- ExFreePoolWithTag(device->pnp.cid_list, 'IPCA');
+ ExFreePoolWithTag(device->pnp.cid_list, 'DpcA');
}
- ExFreePoolWithTag(device, 'IPCA');
+ if (device->pnp.hardware_id) {
+ ExFreePoolWithTag(device->pnp.hardware_id, 'DpcA');
+ }
+ ExFreePoolWithTag(device, 'DpcA');
return_VALUE(result);
}
*child = device;
static int
acpi_bus_remove (
- struct acpi_device *device,
+ struct acpi_device *device,
int type)
{
acpi_device_unregister(device);
- if (device && device->pnp.cid_list)
- ExFreePoolWithTag(device->pnp.cid_list, 'IPCA');
+ if (device->pnp.cid_list)
+ ExFreePoolWithTag(device->pnp.cid_list, 'DpcA');
+
+ if (device->pnp.hardware_id)
+ ExFreePoolWithTag(device->pnp.hardware_id, 'DpcA');
if (device)
- ExFreePoolWithTag(device, 'IPCA');
+ ExFreePoolWithTag(device, 'DpcA');
return_VALUE(0);
}
parent = start;
phandle = start->handle;
-
+
/*
* Parse through the ACPI namespace, identify all 'devices', and
* create a new 'struct acpi_device' for each.
* power button is present.
*/
if (AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON)
- result = acpi_bus_add(&device, acpi_root,
+ result = acpi_bus_add(&device, acpi_root,
NULL, ACPI_BUS_TYPE_POWER_BUTTON);
else
{
* the we have a control method button just like above.
*/
if (AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON)
- result = acpi_bus_add(&device, acpi_root,
+ result = acpi_bus_add(&device, acpi_root,
NULL, ACPI_BUS_TYPE_SLEEP_BUTTON);
else
{
int result = 0;
ACPI_STATUS status = AE_OK;
- DPRINT("acpi_bus_init");
+ DPRINT("acpi_bus_init\n");
KeInitializeDpc(&event_dpc, acpi_bus_generate_event_dpc, NULL);
/*
* Register the for all standard device notifications.
*/
- status = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, &acpi_bus_notify, NULL);
+ status = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, acpi_bus_notify, NULL);
if (ACPI_FAILURE(status)) {
DPRINT1("Unable to register for device notifications\n");
result = AE_NOT_FOUND;
/*
* Create the root device in the bus's device tree
*/
- result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
+ result = acpi_bus_add(&acpi_root, NULL, ACPI_ROOT_OBJECT,
ACPI_BUS_TYPE_SYSTEM);
if (result)
goto error2;
/* Mimic structured exception handling */
error2:
AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
- ACPI_SYSTEM_NOTIFY, &acpi_bus_notify);
+ ACPI_SYSTEM_NOTIFY, acpi_bus_notify);
error1:
AcpiTerminate();
return_VALUE(AE_NOT_FOUND);
{
ACPI_STATUS status = AE_OK;
- DPRINT("acpi_bus_exit");
+ DPRINT1("acpi_bus_exit\n");
status = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
ACPI_SYSTEM_NOTIFY, acpi_bus_notify);
{
int result = 0;
- DPRINT("acpi_init");
+ DPRINT("acpi_init\n");
DPRINT("Subsystem revision %08x\n",ACPI_CA_VERSION);
- KeInitializeSpinLock(&acpi_bus_event_lock);
+ KeInitializeSpinLock(&acpi_bus_event_lock);
KeInitializeEvent(&AcpiEventQueue, NotificationEvent, FALSE);
ExInitializeFastMutex(&acpi_bus_drivers_lock);
void
acpi_exit (void)
{
- DPRINT("acpi_exit");
+ DPRINT("acpi_exit\n");
#ifdef CONFIG_PM
pm_active = 0;