summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpica/acpi.c312
1 files changed, 183 insertions, 129 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index c3e3f76..867494e 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2000 Takanori Watanabe <takawata@jp.freebsd.org>
* Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
- * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2000, 2001 Michael Smith
* Copyright (c) 2000 BSDi
* All rights reserved.
*
@@ -57,7 +57,7 @@ MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices");
/*
* Hooks for the ACPI CA debugging infrastructure
*/
-#define _COMPONENT ACPI_BUS_MANAGER
+#define _COMPONENT ACPI_BUS
MODULE_NAME("ACPI")
/*
@@ -91,6 +91,8 @@ static const char* sleep_state_names[] = {
/* this has to be static, as the softc is gone when we need it */
static int acpi_off_state = ACPI_STATE_S5;
+struct mtx acpi_mutex;
+
static void acpi_identify(driver_t *driver, device_t parent);
static int acpi_probe(device_t dev);
static int acpi_attach(device_t dev);
@@ -185,6 +187,9 @@ acpi_identify(driver_t *driver, device_t parent)
if (device_find_child(parent, "acpi", 0) != NULL)
return_VOID;
+ /* initialise the ACPI mutex */
+ mtx_init(&acpi_mutex, "ACPI global lock", MTX_DEF);
+
/*
* Start up the ACPI CA subsystem.
*/
@@ -223,31 +228,36 @@ acpi_probe(device_t dev)
{
ACPI_TABLE_HEADER th;
char buf[20];
+ ACPI_STATUS status;
int error;
FUNCTION_TRACE(__func__);
+ ACPI_LOCK;
- if ((error = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th)) != AE_OK) {
- device_printf(dev, "couldn't get XSDT header: %s\n", acpi_strerror(error));
- return_VALUE(ENXIO);
+ if ((status = AcpiGetTableHeader(ACPI_TABLE_XSDT, 1, &th)) != AE_OK) {
+ device_printf(dev, "couldn't get XSDT header: %s\n", acpi_strerror(status));
+ error = ENXIO;
+ } else {
+ sprintf(buf, "%.6s %.8s", th.OemId, th.OemTableId);
+ device_set_desc_copy(dev, buf);
+ error = 0;
}
- sprintf(buf, "%.6s %.8s", th.OemId, th.OemTableId);
- device_set_desc_copy(dev, buf);
-
- return_VALUE(0);
+ ACPI_UNLOCK;
+ return_VALUE(error);
}
static int
acpi_attach(device_t dev)
{
struct acpi_softc *sc;
+ ACPI_STATUS status;
int error;
#ifdef ENABLE_DEBUGGER
char *debugpoint = getenv("debug.acpi.debugger");
#endif
FUNCTION_TRACE(__func__);
-
+ ACPI_LOCK;
sc = device_get_softc(dev);
bzero(sc, sizeof(*sc));
sc->acpi_dev = dev;
@@ -260,26 +270,27 @@ acpi_attach(device_t dev)
/*
* Install the default address space handlers.
*/
- if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
+ error = ENXIO;
+ if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_SYSTEM_MEMORY,
ACPI_DEFAULT_HANDLER,
NULL, NULL)) != AE_OK) {
- device_printf(dev, "could not initialise SystemMemory handler: %s\n", acpi_strerror(error));
- return_VALUE(ENXIO);
+ device_printf(dev, "could not initialise SystemMemory handler: %s\n", acpi_strerror(status));
+ goto out;
}
- if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
+ if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_SYSTEM_IO,
ACPI_DEFAULT_HANDLER,
NULL, NULL)) != AE_OK) {
- device_printf(dev, "could not initialise SystemIO handler: %s\n", acpi_strerror(error));
- return_VALUE(ENXIO);
+ device_printf(dev, "could not initialise SystemIO handler: %s\n", acpi_strerror(status));
+ goto out;
}
- if ((error = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
+ if ((status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
ACPI_ADR_SPACE_PCI_CONFIG,
ACPI_DEFAULT_HANDLER,
NULL, NULL)) != AE_OK) {
- device_printf(dev, "could not initialise PciConfig handler: %s\n", acpi_strerror(error));
- return_VALUE(ENXIO);
+ device_printf(dev, "could not initialise PciConfig handler: %s\n", acpi_strerror(status));
+ goto out;
}
/*
@@ -295,9 +306,9 @@ acpi_attach(device_t dev)
if (debugpoint && !strcmp(debugpoint, "enable"))
acpi_EnterDebugger();
#endif
- if ((error = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT)) != AE_OK) {
- device_printf(dev, "could not enable ACPI: %s\n", acpi_strerror(error));
- return_VALUE(ENXIO);
+ if ((status = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT)) != AE_OK) {
+ device_printf(dev, "could not enable ACPI: %s\n", acpi_strerror(status));
+ goto out;
}
/*
@@ -368,7 +379,11 @@ acpi_attach(device_t dev)
if (debugpoint && !strcmp(debugpoint, "running"))
acpi_EnterDebugger();
#endif
- return_VALUE(0);
+ error = 0;
+
+ out:
+ ACPI_UNLOCK;
+ return_VALUE(error);
}
/*
@@ -570,6 +585,7 @@ acpi_probe_children(device_t bus)
int i;
FUNCTION_TRACE(__func__);
+ ACPI_ASSERTLOCK;
/*
* Create any static children by calling device identify methods.
@@ -650,6 +666,9 @@ acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
static void
acpi_shutdown_pre_sync(void *arg, int howto)
{
+
+ ACPI_ASSERTLOCK;
+
/*
* Disable all ACPI events before soft off, otherwise the system
* will be turned on again on some laptops.
@@ -666,6 +685,8 @@ acpi_shutdown_final(void *arg, int howto)
{
ACPI_STATUS status;
+ ACPI_ASSERTLOCK;
+
if (howto & RB_POWEROFF) {
printf("Power system off using ACPI...\n");
if ((status = AcpiEnterSleepState(acpi_off_state)) != AE_OK) {
@@ -680,30 +701,32 @@ acpi_shutdown_final(void *arg, int howto)
static void
acpi_enable_fixed_events(struct acpi_softc *sc)
{
- static int first_time = 1;
+ static int first_time = 1;
#define MSGFORMAT "%s button is handled as a fixed feature programming model.\n"
- /* Enable and clear fixed events and install handlers. */
- if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
- AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
- AcpiClearEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
- AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
- acpi_eventhandler_power_button_for_sleep, sc);
- if (first_time) {
- device_printf(sc->acpi_dev, MSGFORMAT, "power");
- }
+ ACPI_ASSERTLOCK;
+
+ /* Enable and clear fixed events and install handlers. */
+ if ((AcpiGbl_FADT != NULL) && (AcpiGbl_FADT->PwrButton == 0)) {
+ AcpiEnableEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
+ AcpiClearEvent(ACPI_EVENT_POWER_BUTTON, ACPI_EVENT_FIXED);
+ AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
+ acpi_eventhandler_power_button_for_sleep, sc);
+ if (first_time) {
+ device_printf(sc->acpi_dev, MSGFORMAT, "power");
}
- if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
- AcpiEnableEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
- AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
- AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
- acpi_eventhandler_sleep_button_for_sleep, sc);
- if (first_time) {
- device_printf(sc->acpi_dev, MSGFORMAT, "sleep");
- }
+ }
+ if ((AcpiGbl_FADT != NULL) && (AcpiGbl_FADT->SleepButton == 0)) {
+ AcpiEnableEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
+ AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON, ACPI_EVENT_FIXED);
+ AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
+ acpi_eventhandler_sleep_button_for_sleep, sc);
+ if (first_time) {
+ device_printf(sc->acpi_dev, MSGFORMAT, "sleep");
}
+ }
- first_time = 0;
+ first_time = 0;
}
/*
@@ -717,6 +740,8 @@ acpi_DeviceIsPresent(device_t dev)
ACPI_HANDLE h;
ACPI_DEVICE_INFO devinfo;
ACPI_STATUS error;
+
+ ACPI_ASSERTLOCK;
if ((h = acpi_get_handle(dev)) == NULL)
return(FALSE);
@@ -737,6 +762,8 @@ acpi_MatchHid(device_t dev, char *hid)
ACPI_DEVICE_INFO devinfo;
ACPI_STATUS error;
+ ACPI_ASSERTLOCK;
+
if (hid == NULL)
return(FALSE);
if ((h = acpi_get_handle(dev)) == NULL)
@@ -758,6 +785,8 @@ acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result)
ACPI_HANDLE r;
ACPI_STATUS status;
+ ACPI_ASSERTLOCK;
+
/* walk back up the tree to the root */
for (;;) {
status = AcpiGetHandle(parent, path, &r);
@@ -797,6 +826,8 @@ acpi_GetIntoBuffer(ACPI_HANDLE handle, ACPI_STATUS (*func)(ACPI_HANDLE, ACPI_BUF
{
ACPI_STATUS status;
+ ACPI_ASSERTLOCK;
+
buf->Length = 0;
buf->Pointer = NULL;
@@ -820,6 +851,8 @@ acpi_EvaluateIntoBuffer(ACPI_HANDLE object, ACPI_STRING pathname, ACPI_OBJECT_LI
{
ACPI_STATUS status;
+ ACPI_ASSERTLOCK;
+
buf->Length = 0;
buf->Pointer = NULL;
@@ -840,6 +873,8 @@ acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number)
ACPI_BUFFER buf;
ACPI_OBJECT param;
+ ACPI_ASSERTLOCK;
+
if (handle == NULL)
handle = ACPI_ROOT_OBJECT;
buf.Pointer = &param;
@@ -880,87 +915,92 @@ acpi_ForeachPackageObject(ACPI_OBJECT *pkg, void (* func)(ACPI_OBJECT *comp, voi
static ACPI_STATUS __inline
acpi_wakeup(UINT8 state)
{
- UINT16 Count;
- ACPI_STATUS Status;
- ACPI_OBJECT_LIST Arg_list;
- ACPI_OBJECT Arg;
- ACPI_OBJECT Objects[3]; /* package plus 2 number objects */
- ACPI_BUFFER ReturnBuffer;
-
- FUNCTION_TRACE_U32(__func__, state);
-
- /* wait for the WAK_STS bit */
- Count = 0;
- while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
- AcpiOsSleepUsec(1000);
- /*
- * Some BIOSes don't set WAK_STS at all,
- * give up waiting for wakeup if we time out.
- */
- if (Count > 1000) {
- break; /* giving up */
- }
- Count++;
+ UINT16 Count;
+ ACPI_STATUS Status;
+ ACPI_OBJECT_LIST Arg_list;
+ ACPI_OBJECT Arg;
+ ACPI_OBJECT Objects[3]; /* package plus 2 number objects */
+ ACPI_BUFFER ReturnBuffer;
+
+ FUNCTION_TRACE_U32(__func__, state);
+ ACPI_ASSERTLOCK;
+
+ /* wait for the WAK_STS bit */
+ Count = 0;
+ while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
+ AcpiOsSleepUsec(1000);
+ /*
+ * Some BIOSes don't set WAK_STS at all,
+ * give up waiting for wakeup if we time out.
+ */
+ if (Count > 1000) {
+ printf("ACPI: timed out waiting for WAK_STS, continuing\n");
+ break; /* giving up */
}
+ Count++;
+ }
+ /*
+ * Evaluate the _WAK method
+ */
+ bzero(&Arg_list, sizeof(Arg_list));
+ Arg_list.Count = 1;
+ Arg_list.Pointer = &Arg;
+
+ bzero(&Arg, sizeof(Arg));
+ Arg.Type = ACPI_TYPE_INTEGER;
+ Arg.Integer.Value = state;
+
+ /*
+ * Set up _WAK result code buffer.
+ *
+ * XXX should use acpi_EvaluateIntoBuffer
+ */
+ bzero(Objects, sizeof(Objects));
+ ReturnBuffer.Length = sizeof(Objects);
+ ReturnBuffer.Pointer = Objects;
+ AcpiEvaluateObject (NULL, "\\_WAK", &Arg_list, &ReturnBuffer);
+
+ Status = AE_OK;
+
+ /* Check result code for _WAK */
+ if (Objects[0].Type != ACPI_TYPE_PACKAGE ||
+ Objects[1].Type != ACPI_TYPE_INTEGER ||
+ Objects[2].Type != ACPI_TYPE_INTEGER) {
/*
- * Evaluate the _WAK method
+ * In many BIOSes, _WAK doesn't return a result code.
+ * We don't need to worry about it too much :-).
*/
- MEMSET(&Arg_list, 0, sizeof(Arg_list));
- Arg_list.Count = 1;
- Arg_list.Pointer = &Arg;
-
- MEMSET(&Arg, 0, sizeof(Arg));
- Arg.Type = ACPI_TYPE_INTEGER;
- Arg.Integer.Value = state;
-
- /* Set up _WAK result code buffer */
- MEMSET(Objects, 0, sizeof(Objects));
- ReturnBuffer.Length = sizeof(Objects);
- ReturnBuffer.Pointer = Objects;
-
- AcpiEvaluateObject (NULL, "\\_WAK", &Arg_list, &ReturnBuffer);
-
- Status = AE_OK;
- /* Check result code for _WAK */
- if (Objects[0].Type != ACPI_TYPE_PACKAGE ||
- Objects[1].Type != ACPI_TYPE_INTEGER ||
- Objects[2].Type != ACPI_TYPE_INTEGER) {
- /*
- * In many BIOSes, _WAK doesn't return a result code.
- * We don't need to worry about it too much :-).
- */
- DEBUG_PRINT (ACPI_INFO,
+ DEBUG_PRINT(ACPI_INFO,
("acpi_wakeup: _WAK result code is corrupted, "
"but should be OK.\n"));
- } else {
- /* evaluate status code */
- switch (Objects[1].Integer.Value) {
- case 0x00000001:
- DEBUG_PRINT (ACPI_ERROR,
- ("acpi_wakeup: Wake was signaled "
- "but failed due to lack of power.\n"));
- Status = AE_ERROR;
- break;
+ } else {
+ /* evaluate status code */
+ switch (Objects[1].Integer.Value) {
+ case 0x00000001:
+ DEBUG_PRINT(ACPI_ERROR,
+ ("acpi_wakeup: Wake was signaled "
+ "but failed due to lack of power.\n"));
+ Status = AE_ERROR;
+ break;
- case 0x00000002:
- DEBUG_PRINT (ACPI_ERROR,
- ("acpi_wakeup: Wake was signaled "
- "but failed due to thermal condition.\n"));
- Status = AE_ERROR;
- break;
- }
- /* evaluate PSS code */
- if (Objects[2].Integer.Value == 0) {
- DEBUG_PRINT (ACPI_ERROR,
- ("acpi_wakeup: The targeted S-state "
- "was not entered because of too much current "
- "being drawn from the power supply.\n"));
- Status = AE_ERROR;
- }
+ case 0x00000002:
+ DEBUG_PRINT(ACPI_ERROR,
+ ("acpi_wakeup: Wake was signaled "
+ "but failed due to thermal condition.\n"));
+ Status = AE_ERROR;
+ break;
}
-
- return_ACPI_STATUS(Status);
+ /* evaluate PSS code */
+ if (Objects[2].Integer.Value == 0) {
+ DEBUG_PRINT(ACPI_ERROR,
+ ("acpi_wakeup: The targeted S-state "
+ "was not entered because of too much current "
+ "being drawn from the power supply.\n"));
+ Status = AE_ERROR;
+ }
+ }
+ return_ACPI_STATUS(Status);
}
/*
@@ -974,6 +1014,7 @@ acpi_SetSleepState(struct acpi_softc *sc, int state)
ACPI_STATUS status = AE_OK;
FUNCTION_TRACE_U32(__func__, state);
+ ACPI_ASSERTLOCK;
switch (state) {
case ACPI_STATE_S0: /* XXX only for testing */
@@ -1038,6 +1079,7 @@ acpi_Enable(struct acpi_softc *sc)
u_int32_t flags;
FUNCTION_TRACE(__func__);
+ ACPI_ASSERTLOCK;
flags = ACPI_NO_ADDRESS_SPACE_INIT | ACPI_NO_HARDWARE_INIT |
ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
@@ -1057,6 +1099,7 @@ acpi_Disable(struct acpi_softc *sc)
ACPI_STATUS status;
FUNCTION_TRACE(__func__);
+ ACPI_ASSERTLOCK;
if (sc->acpi_enabled) {
status = AcpiDisable();
@@ -1079,8 +1122,10 @@ acpi_system_eventhandler_sleep(void *arg, int state)
{
FUNCTION_TRACE_U32(__func__, state);
+ ACPI_LOCK;
if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
acpi_SetSleepState((struct acpi_softc *)arg, state);
+ ACPI_UNLOCK;
return_VOID;
}
@@ -1091,6 +1136,9 @@ acpi_system_eventhandler_wakeup(void *arg, int state)
/* Well, what to do? :-) */
+ ACPI_LOCK;
+ ACPI_UNLOCK;
+
return_VOID;
}
@@ -1171,6 +1219,8 @@ acpi_name(ACPI_HANDLE handle)
{
static struct acpi_staticbuf buf;
+ ACPI_ASSERTLOCK;
+
buf.buffer.Length = 512;
buf.buffer.Pointer = &buf.data[0];
@@ -1321,6 +1371,8 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
struct acpi_ioctl_hook *hp;
int error, xerror, state;
+ ACPI_LOCK;
+
error = state = 0;
sc = dev->si_drv1;
@@ -1372,6 +1424,7 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p)
}
out:
+ ACPI_UNLOCK;
return(error);
}
@@ -1383,21 +1436,24 @@ acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
u_int new_state, old_state;
old_state = *(u_int *)oidp->oid_arg1;
- if (old_state > ACPI_S_STATES_MAX)
+ if (old_state > ACPI_S_STATES_MAX) {
strcpy(sleep_state, "unknown");
- else
+ } else {
strncpy(sleep_state, sleep_state_names[old_state],
- sizeof(sleep_state_names[old_state]));
+ sizeof(sleep_state_names[old_state]));
+ }
error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
if (error == 0 && req->newptr != NULL) {
- for (new_state = ACPI_STATE_S0; new_state <= ACPI_S_STATES_MAX; new_state++)
+ for (new_state = ACPI_STATE_S0; new_state <= ACPI_S_STATES_MAX; new_state++) {
if (strncmp(sleep_state, sleep_state_names[new_state],
- sizeof(sleep_state)) == 0)
+ sizeof(sleep_state)) == 0)
break;
- if (new_state != old_state && new_state <= ACPI_S_STATES_MAX)
+ }
+ if ((new_state != old_state) && (new_state <= ACPI_S_STATES_MAX)) {
*(u_int *)oidp->oid_arg1 = new_state;
- else
+ } else {
error = EINVAL;
+ }
}
return(error);
}
@@ -1427,17 +1483,16 @@ static struct debugtag dbg_layer[] = {
{"ACPI_DISPATCHER", ACPI_DISPATCHER},
{"ACPI_EXECUTER", ACPI_EXECUTER},
{"ACPI_RESOURCES", ACPI_RESOURCES},
- {"ACPI_DEVICES", ACPI_DEVICES},
{"ACPI_POWER", ACPI_POWER},
- {"ACPI_BUS_MANAGER", ACPI_BUS_MANAGER},
- {"ACPI_POWER_CONTROL", ACPI_POWER_CONTROL},
- {"ACPI_EMBEDDED_CONTROLLER", ACPI_EMBEDDED_CONTROLLER},
- {"ACPI_PROCESSOR_CONTROL", ACPI_PROCESSOR_CONTROL},
+ {"ACPI_BUS", ACPI_BUS},
+ {"ACPI_POWER", ACPI_POWER},
+ {"ACPI_EC", ACPI_EC},
+ {"ACPI_PROCESSOR", ACPI_PROCESSOR},
{"ACPI_AC_ADAPTER", ACPI_AC_ADAPTER},
{"ACPI_BATTERY", ACPI_BATTERY},
{"ACPI_BUTTON", ACPI_BUTTON},
{"ACPI_SYSTEM", ACPI_SYSTEM},
- {"ACPI_THERMAL_ZONE", ACPI_THERMAL_ZONE},
+ {"ACPI_THERMAL", ACPI_THERMAL},
{"ACPI_DEBUGGER", ACPI_DEBUGGER},
{"ACPI_OS_SERVICES", ACPI_OS_SERVICES},
{"ACPI_ALL_COMPONENTS", ACPI_ALL_COMPONENTS},
@@ -1734,4 +1789,3 @@ acpi_battery_register(int type, int phys_unit)
return(0);
}
-
OpenPOWER on IntegriCloud