DEVFS - remove dev_ops_add(), dev_ops_get(), and get_dev()
[dragonfly.git] / sys / dev / acpica5 / acpi.c
CommitLineData
5ed44076
MD
1/*-
2 * Copyright (c) 2000 Takanori Watanabe <takawata@jp.freebsd.org>
3 * Copyright (c) 2000 Mitsuru IWASAKI <iwasaki@jp.freebsd.org>
4 * Copyright (c) 2000, 2001 Michael Smith
5 * Copyright (c) 2000 BSDi
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
c8b4f0e6 29 * $FreeBSD: src/sys/dev/acpica/acpi.c,v 1.160 2004/06/14 03:52:19 njl Exp $
71fc104f 30 * $DragonFly: src/sys/dev/acpica5/acpi.c,v 1.37 2008/10/03 00:26:21 hasso Exp $
5ed44076
MD
31 */
32
33#include "opt_acpi.h"
34#include <sys/param.h>
35#include <sys/kernel.h>
36#include <sys/proc.h>
37#include <sys/fcntl.h>
38#include <sys/malloc.h>
39#include <sys/bus.h>
40#include <sys/conf.h>
fef8985e 41#include <sys/device.h>
5ed44076
MD
42#include <sys/reboot.h>
43#include <sys/sysctl.h>
44#include <sys/ctype.h>
45#include <sys/linker.h>
46#include <sys/power.h>
47#include <sys/sbuf.h>
1f7ab7c9
MD
48#include <sys/rman.h>
49
1a5f156c 50#include <sys/thread2.h>
e1eeedd0 51#include <sys/lock.h>
5ed44076
MD
52
53#include <machine/clock.h>
f9d8cd12 54#include <machine/globaldata.h>
5ed44076
MD
55#include <bus/isa/isavar.h>
56
57#include "acpi.h"
58#include <dev/acpica5/acpivar.h>
59#include <dev/acpica5/acpiio.h>
60#include <acnamesp.h>
61
62MALLOC_DEFINE(M_ACPIDEV, "acpidev", "ACPI devices");
63
64/* Hooks for the ACPI CA debugging infrastructure */
65#define _COMPONENT ACPI_BUS
66ACPI_MODULE_NAME("ACPI")
67
68static d_open_t acpiopen;
69static d_close_t acpiclose;
70static d_ioctl_t acpiioctl;
71
72#define CDEV_MAJOR 152
fef8985e
MD
73static struct dev_ops acpi_ops = {
74 { "acpi", CDEV_MAJOR, 0 },
75 .d_open = acpiopen,
76 .d_close = acpiclose,
77 .d_ioctl = acpiioctl
5ed44076
MD
78};
79
5ed44076
MD
80#if __FreeBSD_version >= 500000
81struct mtx acpi_mutex;
82#endif
83
c8b4f0e6
YT
84/* Local pools for managing system resources for ACPI child devices. */
85struct rman acpi_rman_io, acpi_rman_mem;
86
f9d8cd12
MD
87struct acpi_quirks {
88 char *OemId;
89 uint32_t OemRevision;
90 char *value;
91};
92
93#define ACPI_OEM_REV_ANY 0
94
95static struct acpi_quirks acpi_quirks_table[] = {
96#ifdef notyet
97 /* Bad PCI routing table. Used on some SuperMicro boards. */
98 { "PTLTD ", 0x06040000, "pci_link" },
99#endif
54ca5b45
TS
100#ifdef ACPI_QUIRK_VMWARE
101 /*
102 * VMware's ACPI-fast24 timer runs roughly 65 times too fast, and not
103 * predictably/monotonic either. This is observed at least under SMP
104 * conditions.
105 *
106 * NOTE: this combination of OemId and OemRevision is NOT unique; it is
107 * known or suspected that at least some SuperMicro boards (see above) and
108 * the Compaq Presario 1952 use this combination. That's why this quirks
109 * entry is guarded by an #ifdef, and associated config option.
110 */
111 { "PTLTD ", 0x06040000, "timer" },
112#endif /* ACPI_QUIRK_VMWARE */
f9d8cd12
MD
113 { NULL, 0, NULL }
114};
115
5ed44076 116static int acpi_modevent(struct module *mod, int event, void *junk);
39b5d600 117static int acpi_identify(driver_t *driver, device_t parent);
5ed44076
MD
118static int acpi_probe(device_t dev);
119static int acpi_attach(device_t dev);
49e48b8a 120static int acpi_shutdown(device_t dev);
f9d8cd12 121static void acpi_quirks_set(void);
2581072f
MD
122static device_t acpi_add_child(device_t bus, device_t parent, int order,
123 const char *name, int unit);
5ed44076
MD
124static int acpi_print_child(device_t bus, device_t child);
125static int acpi_read_ivar(device_t dev, device_t child, int index,
126 uintptr_t *result);
127static int acpi_write_ivar(device_t dev, device_t child, int index,
128 uintptr_t value);
c8b4f0e6 129static struct resource_list *acpi_get_rlist(device_t dev, device_t child);
5ed44076
MD
130static struct resource *acpi_alloc_resource(device_t bus, device_t child,
131 int type, int *rid, u_long start, u_long end,
132 u_long count, u_int flags);
133static int acpi_release_resource(device_t bus, device_t child, int type,
134 int rid, struct resource *r);
135static uint32_t acpi_isa_get_logicalid(device_t dev);
136static int acpi_isa_get_compatid(device_t dev, uint32_t *cids, int count);
676159d4 137static char *acpi_device_id_probe(device_t bus, device_t dev, char **ids);
5ed44076
MD
138static int acpi_isa_pnp_probe(device_t bus, device_t child,
139 struct isa_pnp_id *ids);
140static void acpi_probe_children(device_t bus);
141static ACPI_STATUS acpi_probe_child(ACPI_HANDLE handle, UINT32 level,
142 void *context, void **status);
143static void acpi_shutdown_pre_sync(void *arg, int howto);
144static void acpi_shutdown_final(void *arg, int howto);
f9d8cd12 145static void acpi_shutdown_poweroff(void *arg);
5ed44076 146static void acpi_enable_fixed_events(struct acpi_softc *sc);
49e48b8a
MD
147static int acpi_parse_prw(ACPI_HANDLE h, struct acpi_prw_data *prw);
148static ACPI_STATUS acpi_wake_limit(ACPI_HANDLE h, UINT32 level, void *context,
149 void **status);
150static int acpi_wake_limit_walk(int sstate);
151static int acpi_wake_sysctl_walk(device_t dev);
edf5636b 152#ifdef dfly_notyet
49e48b8a 153static int acpi_wake_set_sysctl(SYSCTL_HANDLER_ARGS);
edf5636b 154#endif
5ed44076
MD
155static void acpi_system_eventhandler_sleep(void *arg, int state);
156static void acpi_system_eventhandler_wakeup(void *arg, int state);
157static int acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
158static int acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS);
159static int acpi_pm_func(u_long cmd, void *arg, ...);
f9d8cd12
MD
160static int acpi_child_location_str_method(device_t acdev, device_t child,
161 char *buf, size_t buflen);
162static int acpi_child_pnpinfo_str_method(device_t acdev, device_t child,
163 char *buf, size_t buflen);
5ed44076
MD
164
165static device_method_t acpi_methods[] = {
166 /* Device interface */
167 DEVMETHOD(device_identify, acpi_identify),
168 DEVMETHOD(device_probe, acpi_probe),
169 DEVMETHOD(device_attach, acpi_attach),
49e48b8a 170 DEVMETHOD(device_shutdown, acpi_shutdown),
5ed44076 171 DEVMETHOD(device_detach, bus_generic_detach),
5ed44076
MD
172 DEVMETHOD(device_suspend, bus_generic_suspend),
173 DEVMETHOD(device_resume, bus_generic_resume),
174
175 /* Bus interface */
176 DEVMETHOD(bus_add_child, acpi_add_child),
177 DEVMETHOD(bus_print_child, acpi_print_child),
178 DEVMETHOD(bus_read_ivar, acpi_read_ivar),
179 DEVMETHOD(bus_write_ivar, acpi_write_ivar),
c8b4f0e6
YT
180 DEVMETHOD(bus_get_resource_list, acpi_get_rlist),
181 DEVMETHOD(bus_set_resource, bus_generic_rl_set_resource),
182 DEVMETHOD(bus_get_resource, bus_generic_rl_get_resource),
5ed44076
MD
183 DEVMETHOD(bus_alloc_resource, acpi_alloc_resource),
184 DEVMETHOD(bus_release_resource, acpi_release_resource),
f9d8cd12
MD
185 DEVMETHOD(bus_child_pnpinfo_str, acpi_child_pnpinfo_str_method),
186 DEVMETHOD(bus_child_location_str, acpi_child_location_str_method),
5ed44076
MD
187 DEVMETHOD(bus_driver_added, bus_generic_driver_added),
188 DEVMETHOD(bus_activate_resource, bus_generic_activate_resource),
189 DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource),
190 DEVMETHOD(bus_setup_intr, bus_generic_setup_intr),
191 DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr),
192
676159d4
HT
193 /* ACPI bus */
194 DEVMETHOD(acpi_id_probe, acpi_device_id_probe),
195
5ed44076
MD
196 /* ISA emulation */
197 DEVMETHOD(isa_pnp_probe, acpi_isa_pnp_probe),
198
199 {0, 0}
200};
201
202static driver_t acpi_driver = {
203 "acpi",
204 acpi_methods,
205 sizeof(struct acpi_softc),
206};
207
208static devclass_t acpi_devclass;
209DRIVER_MODULE(acpi, nexus, acpi_driver, acpi_devclass, acpi_modevent, 0);
f9d8cd12
MD
210MODULE_VERSION(acpi, 1);
211
212static const char* sleep_state_names[] = {
213 "S0", "S1", "S2", "S3", "S4", "S5", "NONE"};
5ed44076
MD
214
215SYSCTL_NODE(_debug, OID_AUTO, acpi, CTLFLAG_RW, NULL, "ACPI debugging");
216static char acpi_ca_version[12];
217SYSCTL_STRING(_debug_acpi, OID_AUTO, acpi_ca_version, CTLFLAG_RD,
218 acpi_ca_version, 0, "Version of Intel ACPI-CA");
219
220/*
f9d8cd12
MD
221 * Allow override of whether methods execute in parallel or not.
222 * Enable this for serial behavior, which fixes "AE_ALREADY_EXISTS"
223 * errors for AML that really can't handle parallel method execution.
224 * It is off by default since this breaks recursive methods and
225 * some IBMs use such code.
226 */
227static int acpi_serialize_methods;
228TUNABLE_INT("hw.acpi.serialize_methods", &acpi_serialize_methods);
229
230/*
5ed44076
MD
231 * ACPI can only be loaded as a module by the loader; activating it after
232 * system bootstrap time is not useful, and can be fatal to the system.
233 * It also cannot be unloaded, since the entire system bus heirarchy hangs
234 * off it.
235 */
236static int
237acpi_modevent(struct module *mod, int event, void *junk)
238{
239 switch(event) {
240 case MOD_LOAD:
241 if (!cold) {
e3869ec7 242 kprintf("The ACPI driver cannot be loaded after boot.\n");
5ed44076
MD
243 return (EPERM);
244 }
245 break;
246 case MOD_UNLOAD:
247 if (!cold && power_pm_get_type() == POWER_PM_TYPE_ACPI)
248 return (EBUSY);
249 break;
250 default:
251 break;
252 }
253 return (0);
254}
255
256/*
257 * Perform early initialization.
258 */
259ACPI_STATUS
260acpi_Startup(void)
261{
262#ifdef ACPI_DEBUGGER
263 char *debugpoint;
264#endif
265 static int error, started = 0;
266
267 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
268
269 if (started)
f9d8cd12 270 return_VALUE (error);
5ed44076
MD
271 started = 1;
272
5ed44076
MD
273 /* Start up the ACPI CA subsystem. */
274#ifdef ACPI_DEBUGGER
bc01a404 275 debugpoint = kgetenv("debug.acpi.debugger");
5ed44076
MD
276 if (debugpoint) {
277 if (!strcmp(debugpoint, "init"))
278 acpi_EnterDebugger();
728aa6ee 279 kfreeenv(debugpoint);
5ed44076
MD
280 }
281#endif
e1eeedd0
YT
282 error = AcpiInitializeTables(NULL, 16, TRUE);
283 if (ACPI_FAILURE(error)) {
284 kprintf("ACPI: table initialization failed:\n");
f9d8cd12 285 return_VALUE (error);
5ed44076 286 }
f9d8cd12
MD
287
288 /* Set up any quirks we have for this XSDT. */
289 acpi_quirks_set();
290 if (acpi_disabled("acpi"))
291 return_VALUE (AE_ERROR);
292
293 return_VALUE (AE_OK);
5ed44076
MD
294}
295
296/*
297 * Detect ACPI, perform early initialisation
298 */
39b5d600 299static int
5ed44076
MD
300acpi_identify(driver_t *driver, device_t parent)
301{
302 device_t child;
303
39b5d600
MD
304 /*
305 * No sense rescanning an ACPI 'bus'.
306 */
307 if (device_get_state(parent) == DS_ATTACHED)
308 return(0);
309
5ed44076
MD
310 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
311
312 if (!cold)
39b5d600 313 return (ENXIO);
5ed44076
MD
314
315 /* Check that we haven't been disabled with a hint. */
316 if (resource_disabled("acpi", 0))
39b5d600 317 return (ENXIO);
5ed44076 318
5ed44076
MD
319 /* Make sure we're not being doubly invoked. */
320 if (device_find_child(parent, "acpi", 0) != NULL)
39b5d600 321 return (ENXIO);
5ed44076
MD
322
323 /* Initialize ACPI-CA. */
324 if (ACPI_FAILURE(acpi_Startup()))
39b5d600 325 return (ENXIO);
5ed44076 326
f8c7a42d 327 ksnprintf(acpi_ca_version, sizeof(acpi_ca_version), "%#x", ACPI_CA_VERSION);
f9d8cd12 328
5ed44076 329 /* Attach the actual ACPI device. */
2581072f 330 if ((child = BUS_ADD_CHILD(parent, parent, 0, "acpi", 0)) == NULL) {
5ed44076 331 device_printf(parent, "ACPI: could not attach\n");
39b5d600 332 return (ENXIO);
5ed44076 333 }
39b5d600 334 return (0);
5ed44076
MD
335}
336
337/*
e1eeedd0
YT
338 * Get a mapping of the root table header, as ACPICA code no longer
339 * keeps local copy of RSDT/XSDT
340 *
341 * return value: if non-NULL, mapped physical address of root table header.
342 * caller is supposed to unmap the region by AcpiOsUnmapMemory()
343 */
344static ACPI_TABLE_HEADER *
345acpi_map_rsdt_header(void)
346{
347 ACPI_PHYSICAL_ADDRESS rsdp_addr, addr;
348 ACPI_TABLE_RSDP *rsdp;
349
3641b7ca 350 if ((rsdp_addr = AcpiOsGetRootPointer()) == 0)
e1eeedd0
YT
351 return(NULL);
352 if ((rsdp = AcpiOsMapMemory(rsdp_addr, sizeof(*rsdp))) == NULL)
353 return(NULL);
354 if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress)
355 addr = (ACPI_PHYSICAL_ADDRESS)rsdp->XsdtPhysicalAddress;
356 else
357 addr = (ACPI_PHYSICAL_ADDRESS)rsdp->RsdtPhysicalAddress;
358 AcpiOsUnmapMemory(rsdp, sizeof(*rsdp));
359
360 return AcpiOsMapMemory(addr, sizeof(ACPI_TABLE_HEADER));
361}
362
363/*
5ed44076
MD
364 * Fetch some descriptive data from ACPI to put in our attach message
365 */
366static int
367acpi_probe(device_t dev)
368{
e1eeedd0 369 ACPI_TABLE_HEADER *th;
5ed44076
MD
370 char buf[20];
371 int error;
372 struct sbuf sb;
5ed44076
MD
373 ACPI_LOCK_DECL;
374
375 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
376
377 if (power_pm_get_type() != POWER_PM_TYPE_NONE &&
378 power_pm_get_type() != POWER_PM_TYPE_ACPI) {
379
380 device_printf(dev, "Other PM system enabled.\n");
381 return_VALUE(ENXIO);
382 }
383
384 ACPI_LOCK;
385
e1eeedd0
YT
386 th = acpi_map_rsdt_header();
387 if (th == NULL) {
388 device_printf(dev, "couldn't get RSDT header\n");
5ed44076 389 error = ENXIO;
e1eeedd0 390 goto unlock;
5ed44076 391 }
e1eeedd0
YT
392
393 sbuf_new(&sb, buf, sizeof(buf), SBUF_FIXEDLEN);
394 sbuf_bcat(&sb, th->OemId, 6);
395 sbuf_trim(&sb);
396 sbuf_putc(&sb, ' ');
397 sbuf_bcat(&sb, th->OemTableId, 8);
398 sbuf_trim(&sb);
399 sbuf_finish(&sb);
400 device_set_desc_copy(dev, sbuf_data(&sb));
401 sbuf_delete(&sb);
402 AcpiOsUnmapMemory(th, sizeof(*th));
403 error = 0;
404unlock:
5ed44076
MD
405 ACPI_UNLOCK;
406 return_VALUE(error);
407}
408
409static int
410acpi_attach(device_t dev)
411{
412 struct acpi_softc *sc;
413 ACPI_STATUS status;
f9d8cd12 414 int error, state;
5ed44076 415 UINT32 flags;
f9d8cd12 416 UINT8 TypeA, TypeB;
5ed44076 417 char *env;
e1eeedd0 418 ACPI_TABLE_FACS *facsp;
5ed44076
MD
419#ifdef ACPI_DEBUGGER
420 char *debugpoint;
421#endif
422 ACPI_LOCK_DECL;
423
424 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
e1eeedd0
YT
425#if __FreeBSD_version >= 500000
426 /* Initialise the ACPI mutex */
427 mtx_init(&acpi_mutex, "ACPI global lock", NULL, MTX_DEF);
428#endif
429
5ed44076
MD
430 ACPI_LOCK;
431 sc = device_get_softc(dev);
432 bzero(sc, sizeof(*sc));
433 sc->acpi_dev = dev;
edf6eb70 434 callout_init(&sc->acpi_sleep_timer);
5ed44076 435
c877f0f6
YT
436 if ((error = acpi_task_thread_init())) {
437 device_printf(dev, "Could not start task thread.\n");
438 goto out;
439 }
440
e1eeedd0
YT
441 /*
442 * Set the globals from our tunables. This is needed because ACPI-CA
443 * uses UINT8 for some values and we have no tunable_byte.
444 */
445 AcpiGbl_AllMethodsSerialized = (UINT8)acpi_serialize_methods;
446 AcpiGbl_EnableInterpreterSlack = TRUE;
447
448 error = ENXIO;
5ed44076 449#ifdef ACPI_DEBUGGER
bc01a404 450 debugpoint = kgetenv("debug.acpi.debugger");
5ed44076 451 if (debugpoint) {
e1eeedd0 452 if (!strcmp(debugpoint, "tables"))
5ed44076 453 acpi_EnterDebugger();
728aa6ee 454 kfreeenv(debugpoint);
5ed44076
MD
455 }
456#endif
457
e1eeedd0
YT
458 if (ACPI_FAILURE(status = AcpiInitializeSubsystem())) {
459 kprintf("ACPI: initialisation failed: %s\n",
460 AcpiFormatException(status));
461 goto out;
462 }
463 if (ACPI_FAILURE(status = AcpiLoadTables())) {
464 kprintf("ACPI: table load failed: %s\n", AcpiFormatException(status));
465 goto out;
466 }
467
c8b4f0e6
YT
468 /* Initialize resource manager. */
469 acpi_rman_io.rm_type = RMAN_ARRAY;
470 acpi_rman_io.rm_start = 0;
471 acpi_rman_io.rm_end = 0xffff;
472 acpi_rman_io.rm_descr = "I/O ports";
473 if (rman_init(&acpi_rman_io) != 0)
474 panic("acpi rman_init IO ports failed");
475 acpi_rman_mem.rm_type = RMAN_ARRAY;
476 acpi_rman_mem.rm_start = 0;
477 acpi_rman_mem.rm_end = ~0ul;
478 acpi_rman_mem.rm_descr = "I/O memory addresses";
479 if (rman_init(&acpi_rman_mem) != 0)
480 panic("acpi rman_init memory failed");
481
e1eeedd0
YT
482#ifdef ACPI_DEBUGGER
483 debugpoint = kgetenv("debug.acpi.debugger");
484 if (debugpoint) {
485 if (!strcmp(debugpoint, "spaces"))
486 acpi_EnterDebugger();
728aa6ee 487 kfreeenv(debugpoint);
e1eeedd0
YT
488 }
489#endif
5ed44076 490 /* Install the default address space handlers. */
5ed44076
MD
491 status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
492 ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
493 if (ACPI_FAILURE(status)) {
494 device_printf(dev, "Could not initialise SystemMemory handler: %s\n",
495 AcpiFormatException(status));
496 goto out;
497 }
498 status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
499 ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
500 if (ACPI_FAILURE(status)) {
501 device_printf(dev, "Could not initialise SystemIO handler: %s\n",
502 AcpiFormatException(status));
503 goto out;
504 }
505 status = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
506 ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
507 if (ACPI_FAILURE(status)) {
508 device_printf(dev, "could not initialise PciConfig handler: %s\n",
509 AcpiFormatException(status));
510 goto out;
511 }
512
513 /*
514 * Bring ACPI fully online.
515 *
516 * Note that some systems (specifically, those with namespace evaluation
517 * issues that require the avoidance of parts of the namespace) must
518 * avoid running _INI and _STA on everything, as well as dodging the final
519 * object init pass.
520 *
521 * For these devices, we set ACPI_NO_DEVICE_INIT and ACPI_NO_OBJECT_INIT).
7beeeb16
YT
522 * For avoiding portions of the namespace without totally disabling _INI
523 * and _STA, use "debug.acpi.avoid.paths".
5ed44076
MD
524 *
525 * XXX We should arrange for the object init pass after we have attached
526 * all our child devices, but on many systems it works here.
527 */
528#ifdef ACPI_DEBUGGER
bc01a404 529 debugpoint = kgetenv("debug.acpi.debugger");
5ed44076
MD
530 if (debugpoint) {
531 if (!strcmp(debugpoint, "enable"))
532 acpi_EnterDebugger();
728aa6ee 533 kfreeenv(debugpoint);
5ed44076
MD
534 }
535#endif
536 flags = 0;
728aa6ee 537 if (ktestenv("debug.acpi.avoid"))
5ed44076
MD
538 flags = ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
539 if (ACPI_FAILURE(status = AcpiEnableSubsystem(flags))) {
540 device_printf(dev, "Could not enable ACPI: %s\n",
541 AcpiFormatException(status));
542 goto out;
543 }
544
545 /*
546 * Call the ECDT probe function to provide EC functionality before
547 * the namespace has been evaluated.
548 */
549 acpi_ec_ecdt_probe(dev);
550
551 if (ACPI_FAILURE(status = AcpiInitializeObjects(flags))) {
552 device_printf(dev, "Could not initialize ACPI objects: %s\n",
553 AcpiFormatException(status));
554 goto out;
555 }
556
557 /*
558 * Setup our sysctl tree.
559 *
560 * XXX: This doesn't check to make sure that none of these fail.
561 */
562 sysctl_ctx_init(&sc->acpi_sysctl_ctx);
563 sc->acpi_sysctl_tree = SYSCTL_ADD_NODE(&sc->acpi_sysctl_ctx,
564 SYSCTL_STATIC_CHILDREN(_hw), OID_AUTO,
565 device_get_name(dev), CTLFLAG_RD, 0, "");
566 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
567 OID_AUTO, "supported_sleep_state", CTLTYPE_STRING | CTLFLAG_RD,
568 0, 0, acpi_supported_sleep_state_sysctl, "A", "");
569 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
570 OID_AUTO, "power_button_state", CTLTYPE_STRING | CTLFLAG_RW,
571 &sc->acpi_power_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
572 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
573 OID_AUTO, "sleep_button_state", CTLTYPE_STRING | CTLFLAG_RW,
574 &sc->acpi_sleep_button_sx, 0, acpi_sleep_state_sysctl, "A", "");
575 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
576 OID_AUTO, "lid_switch_state", CTLTYPE_STRING | CTLFLAG_RW,
577 &sc->acpi_lid_switch_sx, 0, acpi_sleep_state_sysctl, "A", "");
578 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
579 OID_AUTO, "standby_state", CTLTYPE_STRING | CTLFLAG_RW,
580 &sc->acpi_standby_sx, 0, acpi_sleep_state_sysctl, "A", "");
581 SYSCTL_ADD_PROC(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
582 OID_AUTO, "suspend_state", CTLTYPE_STRING | CTLFLAG_RW,
583 &sc->acpi_suspend_sx, 0, acpi_sleep_state_sysctl, "A", "");
584 SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
585 OID_AUTO, "sleep_delay", CTLFLAG_RD | CTLFLAG_RW,
586 &sc->acpi_sleep_delay, 0, "sleep delay");
587 SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
588 OID_AUTO, "s4bios", CTLFLAG_RD | CTLFLAG_RW,
589 &sc->acpi_s4bios, 0, "S4BIOS mode");
590 SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
591 OID_AUTO, "verbose", CTLFLAG_RD | CTLFLAG_RW,
592 &sc->acpi_verbose, 0, "verbose mode");
593 SYSCTL_ADD_INT(&sc->acpi_sysctl_ctx, SYSCTL_CHILDREN(sc->acpi_sysctl_tree),
594 OID_AUTO, "disable_on_poweroff", CTLFLAG_RD | CTLFLAG_RW,
595 &sc->acpi_disable_on_poweroff, 0, "ACPI subsystem disable on poweroff");
596
597 /*
49e48b8a 598 * Default to 1 second before sleeping to give some machines time to
5ed44076
MD
599 * stabilize.
600 */
49e48b8a
MD
601 sc->acpi_sleep_delay = 1;
602 sc->acpi_disable_on_poweroff = 0;
5ed44076
MD
603 if (bootverbose)
604 sc->acpi_verbose = 1;
bc01a404 605 if ((env = kgetenv("hw.acpi.verbose")) && strcmp(env, "0")) {
5ed44076 606 sc->acpi_verbose = 1;
728aa6ee 607 kfreeenv(env);
5ed44076
MD
608 }
609
610 /* Only enable S4BIOS by default if the FACS says it is available. */
e1eeedd0
YT
611 status = AcpiGetTableByIndex(ACPI_TABLE_INDEX_FACS,
612 (ACPI_TABLE_HEADER **)&facsp);
613 if (ACPI_SUCCESS(status)) {
614 if ((facsp->Flags & ACPI_FACS_S4_BIOS_PRESENT) != 0)
5ed44076 615 sc->acpi_s4bios = 1;
e1eeedd0 616 }
5ed44076
MD
617
618 /*
f9d8cd12
MD
619 * Dispatch the default sleep state to devices. The lid switch is set
620 * to NONE by default to avoid surprising users.
5ed44076 621 */
f9d8cd12
MD
622 sc->acpi_power_button_sx = ACPI_STATE_S5;
623 sc->acpi_lid_switch_sx = ACPI_S_STATES_MAX + 1;
5ed44076
MD
624 sc->acpi_standby_sx = ACPI_STATE_S1;
625 sc->acpi_suspend_sx = ACPI_STATE_S3;
626
f9d8cd12
MD
627 /* Pick the first valid sleep state for the sleep button default. */
628 sc->acpi_sleep_button_sx = ACPI_S_STATES_MAX + 1;
629 for (state = ACPI_STATE_S1; state < ACPI_STATE_S5; state++)
630 if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) {
631 sc->acpi_sleep_button_sx = state;
632 break;
633 }
634
5ed44076
MD
635 acpi_enable_fixed_events(sc);
636
637 /*
638 * Scan the namespace and attach/initialise children.
639 */
640#ifdef ACPI_DEBUGGER
bc01a404 641 debugpoint = kgetenv("debug.acpi.debugger");
5ed44076
MD
642 if (debugpoint) {
643 if (!strcmp(debugpoint, "probe"))
644 acpi_EnterDebugger();
728aa6ee 645 kfreeenv(debugpoint);
5ed44076
MD
646 }
647#endif
648
649 /* Register our shutdown handlers */
650 EVENTHANDLER_REGISTER(shutdown_pre_sync, acpi_shutdown_pre_sync, sc,
651 SHUTDOWN_PRI_LAST);
652 EVENTHANDLER_REGISTER(shutdown_final, acpi_shutdown_final, sc,
653 SHUTDOWN_PRI_LAST);
654
655 /*
656 * Register our acpi event handlers.
657 * XXX should be configurable eg. via userland policy manager.
658 */
659 EVENTHANDLER_REGISTER(acpi_sleep_event, acpi_system_eventhandler_sleep,
660 sc, ACPI_EVENT_PRI_LAST);
661 EVENTHANDLER_REGISTER(acpi_wakeup_event, acpi_system_eventhandler_wakeup,
662 sc, ACPI_EVENT_PRI_LAST);
663
664 /* Flag our initial states. */
665 sc->acpi_enabled = 1;
666 sc->acpi_sstate = ACPI_STATE_S0;
667 sc->acpi_sleep_disabled = 0;
668
669 /* Create the control device */
fef8985e 670 sc->acpi_dev_t = make_dev(&acpi_ops, 0, UID_ROOT, GID_WHEEL, 0644,
5ed44076
MD
671 "acpi");
672 sc->acpi_dev_t->si_drv1 = sc;
673
674#ifdef ACPI_DEBUGGER
bc01a404 675 debugpoint = kgetenv("debug.acpi.debugger");
5ed44076
MD
676 if (debugpoint) {
677 if (strcmp(debugpoint, "running") == 0)
678 acpi_EnterDebugger();
728aa6ee 679 kfreeenv(debugpoint);
5ed44076
MD
680 }
681#endif
682
5ed44076
MD
683 if ((error = acpi_machdep_init(dev)))
684 goto out;
685
686 /* Register ACPI again to pass the correct argument of pm_func. */
687 power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc);
688
689 if (!acpi_disabled("bus"))
690 acpi_probe_children(dev);
691
692 error = 0;
693
694 out:
695 ACPI_UNLOCK;
a9e511df 696
ef612539 697 cputimer_intr_pmfixup();
5ed44076
MD
698 return_VALUE (error);
699}
700
49e48b8a
MD
701static int
702acpi_shutdown(device_t dev)
703{
838bef54
YT
704 /* Allow children to shutdown first. */
705 bus_generic_shutdown(dev);
49e48b8a
MD
706
707 /* Disable all wake GPEs not appropriate for reboot/poweroff. */
708 acpi_wake_limit_walk(ACPI_STATE_S5);
709 return (0);
710}
711
f9d8cd12 712static void
c436375a 713acpi_quirks_set(void)
f9d8cd12 714{
e1eeedd0 715 ACPI_TABLE_HEADER *rsdt;
f9d8cd12
MD
716 struct acpi_quirks *quirk;
717 char *env, *tmp;
718 int len;
719
720 /*
721 * If the user loaded a custom table or disabled "quirks", leave
722 * the settings alone.
723 */
724 len = 0;
bc01a404 725 if ((env = kgetenv("acpi_dsdt_load")) != NULL) {
f9d8cd12
MD
726 /* XXX No strcasecmp but this is good enough. */
727 if (*env == 'Y' || *env == 'y')
728 goto out;
54ca5b45 729 kfreeenv(env);
f9d8cd12 730 }
bc01a404 731 if ((env = kgetenv("debug.acpi.disabled")) != NULL) {
f9d8cd12
MD
732 if (strstr("quirks", env) != NULL)
733 goto out;
734 len = strlen(env);
735 }
736
737 /*
738 * Search through our quirk table and concatenate the disabled
739 * values with whatever we find.
740 */
e1eeedd0
YT
741 if ((rsdt = acpi_map_rsdt_header()) == NULL)
742 goto out;
f9d8cd12 743 for (quirk = acpi_quirks_table; quirk->OemId; quirk++) {
e1eeedd0
YT
744 if (!strncmp(rsdt->OemId, quirk->OemId, strlen(quirk->OemId)) &&
745 (rsdt->OemRevision == quirk->OemRevision ||
f9d8cd12
MD
746 quirk->OemRevision == ACPI_OEM_REV_ANY)) {
747 len += strlen(quirk->value) + 2;
efda3bd0 748 if ((tmp = kmalloc(len, M_TEMP, M_NOWAIT)) == NULL)
f9d8cd12 749 goto out;
f8c7a42d 750 ksprintf(tmp, "%s %s", env ? env : "", quirk->value);
54ca5b45 751 ksetenv("debug.acpi.disabled", tmp);
efda3bd0 752 kfree(tmp, M_TEMP);
f9d8cd12
MD
753 break;
754 }
755 }
e1eeedd0 756 AcpiOsUnmapMemory(rsdt, sizeof(*rsdt));
f9d8cd12
MD
757
758out:
759 if (env)
54ca5b45 760 kfreeenv(env);
f9d8cd12
MD
761}
762
5ed44076
MD
763/*
764 * Handle a new device being added
765 */
766static device_t
2581072f
MD
767acpi_add_child(device_t bus, device_t parent, int order,
768 const char *name, int unit)
5ed44076
MD
769{
770 struct acpi_device *ad;
771 device_t child;
772
efda3bd0 773 ad = kmalloc(sizeof(*ad), M_ACPIDEV, M_INTWAIT | M_ZERO);
5ed44076
MD
774
775 resource_list_init(&ad->ad_rl);
49e48b8a 776
2581072f 777 child = device_add_child_ordered(parent, order, name, unit);
5ed44076
MD
778 if (child != NULL)
779 device_set_ivars(child, ad);
780 return (child);
781}
782
783static int
784acpi_print_child(device_t bus, device_t child)
785{
786 struct acpi_device *adev = device_get_ivars(child);
787 struct resource_list *rl = &adev->ad_rl;
788 int retval = 0;
789
790 retval += bus_print_child_header(bus, child);
791 retval += resource_list_print_type(rl, "port", SYS_RES_IOPORT, "%#lx");
792 retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx");
793 retval += resource_list_print_type(rl, "irq", SYS_RES_IRQ, "%ld");
794 retval += resource_list_print_type(rl, "drq", SYS_RES_DRQ, "%ld");
795 retval += bus_print_child_footer(bus, child);
796
797 return (retval);
798}
799
f9d8cd12
MD
800/* Location hint for devctl(8) */
801static int
802acpi_child_location_str_method(device_t cbdev, device_t child, char *buf,
803 size_t buflen)
804{
805 struct acpi_device *dinfo = device_get_ivars(child);
806
807 if (dinfo->ad_handle)
f8c7a42d 808 ksnprintf(buf, buflen, "path=%s", acpi_name(dinfo->ad_handle));
f9d8cd12 809 else
f8c7a42d 810 ksnprintf(buf, buflen, "magic=unknown");
f9d8cd12
MD
811 return (0);
812}
813
814/* PnP information for devctl(8) */
815static int
816acpi_child_pnpinfo_str_method(device_t cbdev, device_t child, char *buf,
817 size_t buflen)
818{
819 ACPI_BUFFER adbuf = {ACPI_ALLOCATE_BUFFER, NULL};
820 ACPI_DEVICE_INFO *adinfo;
821 struct acpi_device *dinfo = device_get_ivars(child);
822 char *end;
823 int error;
824
825 error = AcpiGetObjectInfo(dinfo->ad_handle, &adbuf);
826 adinfo = (ACPI_DEVICE_INFO *) adbuf.Pointer;
827
828 if (error)
f8c7a42d 829 ksnprintf(buf, buflen, "Unknown");
f9d8cd12 830 else
f8c7a42d 831 ksnprintf(buf, buflen, "_HID=%s _UID=%lu",
f9d8cd12
MD
832 (adinfo->Valid & ACPI_VALID_HID) ?
833 adinfo->HardwareId.Value : "UNKNOWN",
834 (adinfo->Valid & ACPI_VALID_UID) ?
835 strtoul(adinfo->UniqueId.Value, &end, 10) : 0);
836
837 if (adinfo)
838 AcpiOsFree(adinfo);
839
840 return (0);
841}
5ed44076
MD
842
843/*
844 * Handle per-device ivars
845 */
846static int
847acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
848{
849 struct acpi_device *ad;
850
851 if ((ad = device_get_ivars(child)) == NULL) {
e3869ec7 852 kprintf("device has no ivars\n");
5ed44076
MD
853 return (ENOENT);
854 }
855
856 /* ACPI and ISA compatibility ivars */
857 switch(index) {
858 case ACPI_IVAR_HANDLE:
859 *(ACPI_HANDLE *)result = ad->ad_handle;
860 break;
861 case ACPI_IVAR_MAGIC:
862 *(int *)result = ad->ad_magic;
863 break;
864 case ACPI_IVAR_PRIVATE:
865 *(void **)result = ad->ad_private;
866 break;
867 case ISA_IVAR_VENDORID:
868 case ISA_IVAR_SERIAL:
869 case ISA_IVAR_COMPATID:
870 *(int *)result = -1;
871 break;
872 case ISA_IVAR_LOGICALID:
873 *(int *)result = acpi_isa_get_logicalid(child);
874 break;
875 default:
876 return (ENOENT);
877 }
878
879 return (0);
880}
881
882static int
883acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
884{
885 struct acpi_device *ad;
886
887 if ((ad = device_get_ivars(child)) == NULL) {
e3869ec7 888 kprintf("device has no ivars\n");
5ed44076
MD
889 return (ENOENT);
890 }
891
892 switch(index) {
893 case ACPI_IVAR_HANDLE:
894 ad->ad_handle = (ACPI_HANDLE)value;
895 break;
896 case ACPI_IVAR_MAGIC:
897 ad->ad_magic = (int)value;
898 break;
899 case ACPI_IVAR_PRIVATE:
900 ad->ad_private = (void *)value;
901 break;
902 default:
903 panic("bad ivar write request (%d)", index);
904 return (ENOENT);
905 }
906
907 return (0);
908}
909
5ed44076
MD
910/*
911 * Handle child resource allocation/removal
912 */
c8b4f0e6
YT
913static struct resource_list *
914acpi_get_rlist(device_t dev, device_t child)
5ed44076 915{
c8b4f0e6 916 struct acpi_device *ad;
5ed44076 917
c8b4f0e6
YT
918 ad = device_get_ivars(child);
919 return (&ad->ad_rl);
5ed44076
MD
920}
921
922static struct resource *
923acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
c8b4f0e6 924 u_long start, u_long end, u_long count, u_int flags)
5ed44076
MD
925{
926 struct acpi_device *ad = device_get_ivars(child);
927 struct resource_list *rl = &ad->ad_rl;
c8b4f0e6
YT
928 struct resource_list_entry *rle;
929 struct resource *res;
930 struct rman *rm;
931 int needactivate;
932
933 /*
934 * If this is an allocation of the "default" range for a given RID, and
935 * we know what the resources for this device are (i.e., they're on the
936 * child's resource list), use those start/end values.
937 */
938 if (start == 0UL && end == ~0UL) {
939 rle = resource_list_find(rl, type, *rid);
940 if (rle == NULL)
941 return (NULL);
942 start = rle->start;
943 end = rle->end;
944 count = rle->count;
945 }
946
947 /* If we don't manage this address, pass the request up to the parent. */
948 rle = acpi_sysres_find(type, start);
949 if (rle == NULL) {
950 return (BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid,
951 start, end, count, flags));
952 }
5ed44076 953
c8b4f0e6
YT
954 /* We only handle memory and IO resources through rman. */
955 switch (type) {
956 case SYS_RES_IOPORT:
957 rm = &acpi_rman_io;
958 break;
959 case SYS_RES_MEMORY:
960 rm = &acpi_rman_mem;
961 break;
962 default:
963 panic("acpi_alloc_resource: invalid res type %d", type);
964 }
965
966 /* If we do know it, allocate it from the local pool. */
967 needactivate = flags & RF_ACTIVE;
968 flags &= ~RF_ACTIVE;
969 res = rman_reserve_resource(rm, start, end, count, flags, child);
970 if (res == NULL)
971 return (NULL);
972
973 /* Copy the bus tag from the pre-allocated resource. */
974 rman_set_bustag(res, rman_get_bustag(rle->res));
975 if (type == SYS_RES_IOPORT)
976 rman_set_bushandle(res, res->r_start);
977
978 /* If requested, activate the resource using the parent's method. */
979 if (needactivate)
980 if (bus_activate_resource(child, type, *rid, res) != 0) {
981 rman_release_resource(res);
982 return (NULL);
983 }
984
985 return (res);
5ed44076
MD
986}
987
988static int
c8b4f0e6
YT
989acpi_release_resource(device_t bus, device_t child, int type, int rid,
990 struct resource *r)
5ed44076 991{
c8b4f0e6
YT
992 int ret;
993
994 /*
995 * If we know about this address, deactivate it and release it to the
996 * local pool. If we don't, pass this request up to the parent.
997 */
998 if (acpi_sysres_find(type, rman_get_start(r)) == NULL) {
999 if (rman_get_flags(r) & RF_ACTIVE) {
1000 ret = bus_deactivate_resource(child, type, rid, r);
1001 if (ret != 0)
1002 return (ret);
1003 }
1004 ret = rman_release_resource(r);
1005 } else
1006 ret = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, type, rid, r);
5ed44076 1007
c8b4f0e6 1008 return (ret);
5ed44076
MD
1009}
1010
1011/* Allocate an IO port or memory resource, given its GAS. */
1012struct resource *
1ce36465 1013acpi_bus_alloc_gas(device_t dev, int *rid, const ACPI_GENERIC_ADDRESS *gas,
5ebadb2c 1014 u_int flags)
5ed44076
MD
1015{
1016 int type;
1017
e1eeedd0 1018 if (gas == NULL || !ACPI_VALID_ADDRESS(gas->Address) || gas->BitWidth < 8)
5ed44076
MD
1019 return (NULL);
1020
e1eeedd0 1021 switch (gas->SpaceId) {
5ed44076
MD
1022 case ACPI_ADR_SPACE_SYSTEM_MEMORY:
1023 type = SYS_RES_MEMORY;
1024 break;
1025 case ACPI_ADR_SPACE_SYSTEM_IO:
1026 type = SYS_RES_IOPORT;
1027 break;
1028 default:
1029 return (NULL);
1030 }
1031
e1eeedd0 1032 bus_set_resource(dev, type, *rid, gas->Address, gas->BitWidth / 8);
5ebadb2c 1033 return (bus_alloc_resource_any(dev, type, rid, RF_ACTIVE | flags));
5ed44076
MD
1034}
1035
1036/*
1037 * Handle ISA-like devices probing for a PnP ID to match.
1038 */
1039#define PNP_EISAID(s) \
1040 ((((s[0] - '@') & 0x1f) << 2) \
1041 | (((s[1] - '@') & 0x18) >> 3) \
1042 | (((s[1] - '@') & 0x07) << 13) \
1043 | (((s[2] - '@') & 0x1f) << 8) \
1044 | (PNP_HEXTONUM(s[4]) << 16) \
1045 | (PNP_HEXTONUM(s[3]) << 20) \
1046 | (PNP_HEXTONUM(s[6]) << 24) \
1047 | (PNP_HEXTONUM(s[5]) << 28))
1048
1049static uint32_t
1050acpi_isa_get_logicalid(device_t dev)
1051{
1052 ACPI_DEVICE_INFO *devinfo;
1053 ACPI_BUFFER buf;
1054 ACPI_HANDLE h;
1055 ACPI_STATUS error;
1056 u_int32_t pnpid;
1057 ACPI_LOCK_DECL;
1058
1059 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
1060
1061 pnpid = 0;
1062 buf.Pointer = NULL;
1063 buf.Length = ACPI_ALLOCATE_BUFFER;
1064
1065 ACPI_LOCK;
1066
1067 /* Fetch and validate the HID. */
1068 if ((h = acpi_get_handle(dev)) == NULL)
1069 goto out;
1070 error = AcpiGetObjectInfo(h, &buf);
1071 if (ACPI_FAILURE(error))
1072 goto out;
1073 devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
1074
1075 if ((devinfo->Valid & ACPI_VALID_HID) != 0)
1076 pnpid = PNP_EISAID(devinfo->HardwareId.Value);
1077
1078out:
1079 if (buf.Pointer != NULL)
1080 AcpiOsFree(buf.Pointer);
1081 ACPI_UNLOCK;
1082 return_VALUE (pnpid);
1083}
1084
1085static int
1086acpi_isa_get_compatid(device_t dev, uint32_t *cids, int count)
1087{
1088 ACPI_DEVICE_INFO *devinfo;
1089 ACPI_BUFFER buf;
1090 ACPI_HANDLE h;
1091 ACPI_STATUS error;
1092 uint32_t *pnpid;
1093 int valid, i;
1094 ACPI_LOCK_DECL;
1095
1096 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
1097
1098 pnpid = cids;
1099 valid = 0;
1100 buf.Pointer = NULL;
1101 buf.Length = ACPI_ALLOCATE_BUFFER;
1102
1103 ACPI_LOCK;
1104
1105 /* Fetch and validate the CID */
1106 if ((h = acpi_get_handle(dev)) == NULL)
1107 goto out;
1108 error = AcpiGetObjectInfo(h, &buf);
1109 if (ACPI_FAILURE(error))
1110 goto out;
1111 devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
1112 if ((devinfo->Valid & ACPI_VALID_CID) == 0)
1113 goto out;
1114
1115 if (devinfo->CompatibilityId.Count < count)
1116 count = devinfo->CompatibilityId.Count;
1117 for (i = 0; i < count; i++) {
1118 if (strncmp(devinfo->CompatibilityId.Id[i].Value, "PNP", 3) != 0)
1119 continue;
1120 *pnpid++ = PNP_EISAID(devinfo->CompatibilityId.Id[i].Value);
1121 valid++;
1122 }
1123
1124out:
1125 if (buf.Pointer != NULL)
1126 AcpiOsFree(buf.Pointer);
1127 ACPI_UNLOCK;
1128 return_VALUE (valid);
1129}
1130
676159d4
HT
1131static char *
1132acpi_device_id_probe(device_t bus, device_t dev, char **ids)
1133{
1134 ACPI_HANDLE h;
1135 int i;
1136
1137 h = acpi_get_handle(dev);
1138 if (ids == NULL || h == NULL || acpi_get_type(dev) != ACPI_TYPE_DEVICE)
1139 return (NULL);
1140
1141 /* Try to match one of the array of IDs with a HID or CID. */
1142 for (i = 0; ids[i] != NULL; i++) {
1143 if (acpi_MatchHid(h, ids[i]))
1144 return (ids[i]);
1145 }
1146 return (NULL);
1147}
1148
5ed44076
MD
1149static int
1150acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids)
1151{
1152 int result, cid_count, i;
1153 uint32_t lid, cids[8];
1154
1155 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
1156
1157 /*
1158 * ISA-style drivers attached to ACPI may persist and
1159 * probe manually if we return ENOENT. We never want
1160 * that to happen, so don't ever return it.
1161 */
1162 result = ENXIO;
1163
1164 /* Scan the supplied IDs for a match */
1165 lid = acpi_isa_get_logicalid(child);
1166 cid_count = acpi_isa_get_compatid(child, cids, 8);
1167 while (ids && ids->ip_id) {
1168 if (lid == ids->ip_id) {
1169 result = 0;
1170 goto out;
1171 }
1172 for (i = 0; i < cid_count; i++) {
1173 if (cids[i] == ids->ip_id) {
1174 result = 0;
1175 goto out;
1176 }
1177 }
1178 ids++;
1179 }
1180
1181 out:
1182 return_VALUE (result);
1183}
1184
1185/*
1186 * Scan relevant portions of the ACPI namespace and attach child devices.
1187 *
1188 * Note that we only expect to find devices in the \_PR_, \_TZ_, \_SI_ and
1189 * \_SB_ scopes, and \_PR_ and \_TZ_ become obsolete in the ACPI 2.0 spec.
1190 */
1191static void
1192acpi_probe_children(device_t bus)
1193{
1194 ACPI_HANDLE parent;
1195 ACPI_STATUS status;
5ed44076 1196 int i;
c8b4f0e6 1197 static char *scopes[] = {"\\_PR_", "\\_TZ_", "\\_SI", "\\_SB_", NULL};
5ed44076
MD
1198
1199 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
1200 ACPI_ASSERTLOCK;
1201
5ed44076
MD
1202 /*
1203 * Scan the namespace and insert placeholders for all the devices that
c8b4f0e6 1204 * we find. We also probe/attach any early devices.
5ed44076
MD
1205 *
1206 * Note that we use AcpiWalkNamespace rather than AcpiGetDevices because
1207 * we want to create nodes for all devices, not just those that are
1208 * currently present. (This assumes that we don't want to create/remove
1209 * devices as they appear, which might be smarter.)
1210 */
1211 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "namespace scan\n"));
1212 for (i = 0; scopes[i] != NULL; i++) {
1213 status = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent);
1214 if (ACPI_SUCCESS(status)) {
1215 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, acpi_probe_child,
1216 bus, NULL);
1217 }
1218 }
1219
c8b4f0e6
YT
1220 /* Create any static children by calling device identify methods. */
1221 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "device identify routines\n"));
1222 bus_generic_probe(bus);
1223
5ed44076
MD
1224 /*
1225 * Scan all of the child devices we have created and let them probe/attach.
1226 */
1227 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "first bus_generic_attach\n"));
1228 bus_generic_attach(bus);
1229
1230 /*
1231 * Some of these children may have attached others as part of their attach
1232 * process (eg. the root PCI bus driver), so rescan.
1233 */
1234 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "second bus_generic_attach\n"));
1235 bus_generic_attach(bus);
1236
49e48b8a
MD
1237 /* Attach wake sysctls. */
1238 acpi_wake_sysctl_walk(bus);
1239
5ed44076
MD
1240 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "done attaching children\n"));
1241 return_VOID;
1242}
1243
c8b4f0e6
YT
1244static int
1245acpi_probe_order(ACPI_HANDLE handle, int level, int *order)
1246{
1247 int ret;
1248
1249 ret = 0;
1250 /* IO port and memory system resource holders are first. */
1251 if (acpi_MatchHid(handle, "PNP0C01") || acpi_MatchHid(handle, "PNP0C02")) {
1252 *order = 1;
1253 ret = 1;
1254 }
1255
1256 /* The embedded controller is needed to handle accesses early. */
1257 if (acpi_MatchHid(handle, "PNP0C09")) {
1258 *order = 2;
1259 ret = 1;
1260 }
1261
1262 *order = (level + 1) * 10;
1263 return (ret);
1264}
1265
5ed44076
MD
1266/*
1267 * Evaluate a child device and determine whether we might attach a device to
1268 * it.
1269 */
1270static ACPI_STATUS
1271acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
1272{
1273 ACPI_OBJECT_TYPE type;
c8b4f0e6
YT
1274 device_t child, bus;
1275 int order, probe_now;
5ed44076
MD
1276
1277 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
1278
1279 /* Skip this device if we think we'll have trouble with it. */
7beeeb16
YT
1280 if (acpi_avoid(handle)) {
1281 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "not scanning '%s'\n",
1282 acpi_name(handle)));
5ed44076 1283 return_ACPI_STATUS (AE_OK);
7beeeb16 1284 }
5ed44076 1285
c8b4f0e6 1286 bus = (device_t)context;
5ed44076
MD
1287 if (ACPI_SUCCESS(AcpiGetType(handle, &type))) {
1288 switch(type) {
1289 case ACPI_TYPE_DEVICE:
1290 case ACPI_TYPE_PROCESSOR:
1291 case ACPI_TYPE_THERMAL:
1292 case ACPI_TYPE_POWER:
1293 if (acpi_disabled("children"))
1294 break;
1295
1296 /*
1297 * Create a placeholder device for this node. Sort the placeholder
1298 * so that the probe/attach passes will run breadth-first.
1299 */
1300 ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "scanning '%s'\n",
1301 acpi_name(handle)));
c8b4f0e6
YT
1302 probe_now = acpi_probe_order(handle, level, &order);
1303 child = BUS_ADD_CHILD(bus, bus, order, NULL, -1);
5ed44076
MD
1304 if (child == NULL)
1305 break;
c8b4f0e6
YT
1306
1307 /* Associate the handle with the device_t and vice versa. */
5ed44076 1308 acpi_set_handle(child, handle);
c8b4f0e6 1309 AcpiAttachData(handle, acpi_fake_objhandler, child);
5ed44076 1310
49e48b8a
MD
1311 /* Check if the device can generate wake events. */
1312 if (ACPI_SUCCESS(AcpiEvaluateObject(handle, "_PRW", NULL, NULL)))
1313 device_set_flags(child, ACPI_FLAG_WAKE_CAPABLE);
1314
5ed44076
MD
1315 /*
1316 * Check that the device is present. If it's not present,
1317 * leave it disabled (so that we have a device_t attached to
1318 * the handle, but we don't probe it).
1319 */
1320 if (type == ACPI_TYPE_DEVICE && !acpi_DeviceIsPresent(child)) {
1321 device_disable(child);
1322 break;
1323 }
1324
1325 /*
1326 * Get the device's resource settings and attach them.
1327 * Note that if the device has _PRS but no _CRS, we need
1328 * to decide when it's appropriate to try to configure the
1329 * device. Ignore the return value here; it's OK for the
1330 * device not to have any resources.
1331 */
f9d8cd12 1332 acpi_parse_resources(child, handle, &acpi_res_parse_set, NULL);
5ed44076 1333
c8b4f0e6
YT
1334 /* If order was overridden, probe/attach now rather than later. */
1335 if (probe_now)
1336 device_probe_and_attach(child);
5ed44076
MD
1337 break;
1338 }
1339 }
1340
1341 return_ACPI_STATUS (AE_OK);
1342}
1343
1344static void
1345acpi_shutdown_pre_sync(void *arg, int howto)
1346{
1347 struct acpi_softc *sc = arg;
1348
1349 ACPI_ASSERTLOCK;
1350
1351 /*
1352 * Disable all ACPI events before soft off, otherwise the system
1353 * will be turned on again on some laptops.
1354 *
1355 * XXX this should probably be restricted to masking some events just
1356 * before powering down, since we may still need ACPI during the
1357 * shutdown process.
1358 */
1359 if (sc->acpi_disable_on_poweroff)
1360 acpi_Disable(sc);
1361}
1362
c8b4f0e6
YT
1363/*
1364 * AcpiAttachData() requires an object handler but never uses it. This is a
1365 * placeholder object handler so we can store a device_t in an ACPI_HANDLE.
1366 */
1367void
1368acpi_fake_objhandler(ACPI_HANDLE h, UINT32 fn, void *data)
1369{
1370}
1371
5ed44076
MD
1372static void
1373acpi_shutdown_final(void *arg, int howto)
1374{
1375 ACPI_STATUS status;
5ed44076
MD
1376 ACPI_ASSERTLOCK;
1377
f9d8cd12
MD
1378 /*
1379 * If powering off, run the actual shutdown code on each processor.
1380 * It will only perform the shutdown on the BSP. Some chipsets do
1381 * not power off the system correctly if called from an AP.
1382 */
5ed44076 1383 if ((howto & RB_POWEROFF) != 0) {
f9d8cd12 1384 status = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
5ed44076 1385 if (ACPI_FAILURE(status)) {
e3869ec7 1386 kprintf("AcpiEnterSleepStatePrep failed - %s\n",
5ed44076
MD
1387 AcpiFormatException(status));
1388 return;
1389 }
e3869ec7 1390 kprintf("Powering system off using ACPI\n");
f9d8cd12 1391 acpi_shutdown_poweroff(NULL);
5ed44076 1392 } else {
e3869ec7 1393 kprintf("Shutting down ACPI\n");
5ed44076
MD
1394 AcpiTerminate();
1395 }
1396}
1397
f9d8cd12
MD
1398/*
1399 * Since this function may be called with locks held or in an unknown
1400 * context, it cannot allocate memory, acquire locks, sleep, etc.
1401 */
1402static void
1403acpi_shutdown_poweroff(void *arg)
1404{
1405 ACPI_STATUS status;
1406
1407 ACPI_ASSERTLOCK;
1408
1409 /* Only attempt to power off if this is the BSP (cpuid 0). */
1410 if (mdcpu->mi.gd_cpuid != 0)
1411 return;
1412
1413 ACPI_DISABLE_IRQS();
1414 status = AcpiEnterSleepState(ACPI_STATE_S5);
1415 if (ACPI_FAILURE(status)) {
e3869ec7 1416 kprintf("ACPI power-off failed - %s\n", AcpiFormatException(status));
f9d8cd12
MD
1417 } else {
1418 DELAY(1000000);
e3869ec7 1419 kprintf("ACPI power-off failed - timeout\n");
f9d8cd12
MD
1420 }
1421}
1422
5ed44076
MD
1423static void
1424acpi_enable_fixed_events(struct acpi_softc *sc)
1425{
1426 static int first_time = 1;
1427
1428 ACPI_ASSERTLOCK;
1429
1430 /* Enable and clear fixed events and install handlers. */
e1eeedd0 1431 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
5ed44076
MD
1432 AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
1433 AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
1434 acpi_event_power_button_sleep, sc);
1435 if (first_time)
1436 device_printf(sc->acpi_dev, "Power Button (fixed)\n");
1437 }
e1eeedd0 1438 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
5ed44076
MD
1439 AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON);
1440 AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
1441 acpi_event_sleep_button_sleep, sc);
1442 if (first_time)
1443 device_printf(sc->acpi_dev, "Sleep Button (fixed)\n");
1444 }
1445
1446 first_time = 0;
1447}
1448
1449/*
1450 * Returns true if the device is actually present and should
1451 * be attached to. This requires the present, enabled, UI-visible
1452 * and diagnostics-passed bits to be set.
1453 */
1454BOOLEAN
1455acpi_DeviceIsPresent(device_t dev)
1456{
1457 ACPI_DEVICE_INFO *devinfo;
1458 ACPI_HANDLE h;
1459 ACPI_BUFFER buf;
1460 ACPI_STATUS error;
1461 int ret;
1462
1463 ACPI_ASSERTLOCK;
1464
1465 ret = FALSE;
1466 if ((h = acpi_get_handle(dev)) == NULL)
1467 return (FALSE);
1468 buf.Pointer = NULL;
1469 buf.Length = ACPI_ALLOCATE_BUFFER;
1470 error = AcpiGetObjectInfo(h, &buf);
1471 if (ACPI_FAILURE(error))
1472 return (FALSE);
1473 devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
1474
1475 /* If no _STA method, must be present */
1476 if ((devinfo->Valid & ACPI_VALID_STA) == 0)
1477 ret = TRUE;
1478
1479 /* Return true for 'present' and 'functioning' */
1480 if ((devinfo->CurrentStatus & 0x9) == 0x9)
1481 ret = TRUE;
1482
1483 AcpiOsFree(buf.Pointer);
1484 return (ret);
1485}
1486
1487/*
1488 * Returns true if the battery is actually present and inserted.
1489 */
1490BOOLEAN
1491acpi_BatteryIsPresent(device_t dev)
1492{
1493 ACPI_DEVICE_INFO *devinfo;
1494 ACPI_HANDLE h;
1495 ACPI_BUFFER buf;
1496 ACPI_STATUS error;
1497 int ret;
1498
1499 ACPI_ASSERTLOCK;
1500
1501 ret = FALSE;
1502 if ((h = acpi_get_handle(dev)) == NULL)
1503 return (FALSE);
1504 buf.Pointer = NULL;
1505 buf.Length = ACPI_ALLOCATE_BUFFER;
1506 error = AcpiGetObjectInfo(h, &buf);
1507 if (ACPI_FAILURE(error))
1508 return (FALSE);
1509 devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
1510
1511 /* If no _STA method, must be present */
1512 if ((devinfo->Valid & ACPI_VALID_STA) == 0)
1513 ret = TRUE;
1514
1515 /* Return true for 'present' and 'functioning' */
1516 if ((devinfo->CurrentStatus & 0x19) == 0x19)
1517 ret = TRUE;
1518
1519 AcpiOsFree(buf.Pointer);
1520 return (ret);
1521}
1522
1523/*
c8b4f0e6 1524 * Match a HID string against a handle
5ed44076
MD
1525 */
1526BOOLEAN
c8b4f0e6 1527acpi_MatchHid(ACPI_HANDLE h, char *hid)
5ed44076
MD
1528{
1529 ACPI_DEVICE_INFO *devinfo;
5ed44076
MD
1530 ACPI_BUFFER buf;
1531 ACPI_STATUS error;
1532 int ret, i;
1533
1534 ACPI_ASSERTLOCK;
1535
1536 ret = FALSE;
c8b4f0e6
YT
1537 if (hid == NULL || h == NULL)
1538 return (ret);
5ed44076
MD
1539 buf.Pointer = NULL;
1540 buf.Length = ACPI_ALLOCATE_BUFFER;
1541 error = AcpiGetObjectInfo(h, &buf);
1542 if (ACPI_FAILURE(error))
c8b4f0e6 1543 return (ret);
5ed44076
MD
1544 devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
1545
1546 if ((devinfo->Valid & ACPI_VALID_HID) != 0 &&
1547 strcmp(hid, devinfo->HardwareId.Value) == 0)
1548 ret = TRUE;
1549 else if ((devinfo->Valid & ACPI_VALID_CID) != 0) {
1550 for (i = 0; i < devinfo->CompatibilityId.Count; i++) {
1551 if (strcmp(hid, devinfo->CompatibilityId.Id[i].Value) == 0) {
1552 ret = TRUE;
1553 break;
1554 }
1555 }
1556 }
1557
1558 AcpiOsFree(buf.Pointer);
1559 return (ret);
1560}
1561
1562/*
1563 * Return the handle of a named object within our scope, ie. that of (parent)
1564 * or one if its parents.
1565 */
1566ACPI_STATUS
1567acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result)
1568{
1569 ACPI_HANDLE r;
1570 ACPI_STATUS status;
1571
1572 ACPI_ASSERTLOCK;
1573
1574 /* Walk back up the tree to the root */
1575 for (;;) {
1576 status = AcpiGetHandle(parent, path, &r);
1577 if (ACPI_SUCCESS(status)) {
1578 *result = r;
1579 return (AE_OK);
1580 }
1581 if (status != AE_NOT_FOUND)
1582 return (AE_OK);
1583 if (ACPI_FAILURE(AcpiGetParent(parent, &r)))
1584 return (AE_NOT_FOUND);
1585 parent = r;
1586 }
1587}
1588
f9d8cd12
MD
1589/* Find the difference between two PM tick counts. */
1590uint32_t
1591acpi_TimerDelta(uint32_t end, uint32_t start)
1592{
1593 uint32_t delta;
1594
1595 if (end >= start)
1596 delta = end - start;
e1eeedd0 1597 else if ((AcpiGbl_FADT.Flags & ACPI_FADT_32BIT_TIMER) == 0)
f9d8cd12
MD
1598 delta = ((0x00FFFFFF - start) + end + 1) & 0x00FFFFFF;
1599 else
1600 delta = ((0xFFFFFFFF - start) + end + 1);
1601 return (delta);
1602}
1603
5ed44076
MD
1604/*
1605 * Allocate a buffer with a preset data size.
1606 */
1607ACPI_BUFFER *
1608acpi_AllocBuffer(int size)
1609{
1610 ACPI_BUFFER *buf;
1611
efda3bd0 1612 buf = kmalloc(size + sizeof(*buf), M_ACPIDEV, M_INTWAIT);
5ed44076
MD
1613 buf->Length = size;
1614 buf->Pointer = (void *)(buf + 1);
1615 return (buf);
1616}
1617
f9d8cd12
MD
1618ACPI_STATUS
1619acpi_SetInteger(ACPI_HANDLE handle, char *path, UINT32 number)
1620{
1621 ACPI_OBJECT arg1;
1622 ACPI_OBJECT_LIST args;
1623
1624 ACPI_ASSERTLOCK;
1625
1626 arg1.Type = ACPI_TYPE_INTEGER;
1627 arg1.Integer.Value = number;
1628 args.Count = 1;
1629 args.Pointer = &arg1;
1630
1631 return (AcpiEvaluateObject(handle, path, &args, NULL));
1632}
1633
5ed44076
MD
1634/*
1635 * Evaluate a path that should return an integer.
1636 */
1637ACPI_STATUS
f9d8cd12 1638acpi_GetInteger(ACPI_HANDLE handle, char *path, UINT32 *number)
5ed44076
MD
1639{
1640 ACPI_STATUS status;
1641 ACPI_BUFFER buf;
1642 ACPI_OBJECT param;
1643
1644 ACPI_ASSERTLOCK;
1645
1646 if (handle == NULL)
1647 handle = ACPI_ROOT_OBJECT;
1648
1649 /*
1650 * Assume that what we've been pointed at is an Integer object, or
1651 * a method that will return an Integer.
1652 */
1653 buf.Pointer = &param;
1654 buf.Length = sizeof(param);
1655 status = AcpiEvaluateObject(handle, path, NULL, &buf);
1656 if (ACPI_SUCCESS(status)) {
1657 if (param.Type == ACPI_TYPE_INTEGER)
1658 *number = param.Integer.Value;
1659 else
1660 status = AE_TYPE;
1661 }
1662
1663 /*
1664 * In some applications, a method that's expected to return an Integer
1665 * may instead return a Buffer (probably to simplify some internal
1666 * arithmetic). We'll try to fetch whatever it is, and if it's a Buffer,
1667 * convert it into an Integer as best we can.
1668 *
1669 * This is a hack.
1670 */
1671 if (status == AE_BUFFER_OVERFLOW) {
1672 if ((buf.Pointer = AcpiOsAllocate(buf.Length)) == NULL) {
1673 status = AE_NO_MEMORY;
1674 } else {
1675 status = AcpiEvaluateObject(handle, path, NULL, &buf);
1676 if (ACPI_SUCCESS(status))
1677 status = acpi_ConvertBufferToInteger(&buf, number);
1678 AcpiOsFree(buf.Pointer);
1679 }
1680 }
1681 return (status);
1682}
1683
1684ACPI_STATUS
f9d8cd12 1685acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp, UINT32 *number)
5ed44076
MD
1686{
1687 ACPI_OBJECT *p;
f9d8cd12 1688 UINT8 *val;
5ed44076
MD
1689 int i;
1690
1691 p = (ACPI_OBJECT *)bufp->Pointer;
1692 if (p->Type == ACPI_TYPE_INTEGER) {
1693 *number = p->Integer.Value;
1694 return (AE_OK);
1695 }
1696 if (p->Type != ACPI_TYPE_BUFFER)
1697 return (AE_TYPE);
1698 if (p->Buffer.Length > sizeof(int))
1699 return (AE_BAD_DATA);
1700
1701 *number = 0;
f9d8cd12 1702 val = p->Buffer.Pointer;
5ed44076 1703 for (i = 0; i < p->Buffer.Length; i++)
f9d8cd12 1704 *number += val[i] << (i * 8);
5ed44076
MD
1705 return (AE_OK);
1706}
1707
1708/*
1709 * Iterate over the elements of an a package object, calling the supplied
1710 * function for each element.
1711 *
1712 * XXX possible enhancement might be to abort traversal on error.
1713 */
1714ACPI_STATUS
1715acpi_ForeachPackageObject(ACPI_OBJECT *pkg,
1716 void (*func)(ACPI_OBJECT *comp, void *arg), void *arg)
1717{
1718 ACPI_OBJECT *comp;
1719 int i;
1720
1721 if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE)
1722 return (AE_BAD_PARAMETER);
1723
1724 /* Iterate over components */
1725 i = 0;
1726 comp = pkg->Package.Elements;
1727 for (; i < pkg->Package.Count; i++, comp++)
1728 func(comp, arg);
1729
1730 return (AE_OK);
1731}
1732
1733/*
1734 * Find the (index)th resource object in a set.
1735 */
1736ACPI_STATUS
1737acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp)
1738{
1739 ACPI_RESOURCE *rp;
1740 int i;
1741
1742 rp = (ACPI_RESOURCE *)buf->Pointer;
1743 i = index;
1744 while (i-- > 0) {
1745 /* Range check */
1746 if (rp > (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
1747 return (AE_BAD_PARAMETER);
1748
1749 /* Check for terminator */
e1eeedd0 1750 if (rp->Type == ACPI_RESOURCE_TYPE_END_TAG || rp->Length == 0)
5ed44076
MD
1751 return (AE_NOT_FOUND);
1752 rp = ACPI_NEXT_RESOURCE(rp);
1753 }
1754 if (resp != NULL)
1755 *resp = rp;
1756
1757 return (AE_OK);
1758}
1759
1760/*
1761 * Append an ACPI_RESOURCE to an ACPI_BUFFER.
1762 *
1763 * Given a pointer to an ACPI_RESOURCE structure, expand the ACPI_BUFFER
1764 * provided to contain it. If the ACPI_BUFFER is empty, allocate a sensible
1765 * backing block. If the ACPI_RESOURCE is NULL, return an empty set of
1766 * resources.
1767 */
1768#define ACPI_INITIAL_RESOURCE_BUFFER_SIZE 512
1769
1770ACPI_STATUS
1771acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res)
1772{
1773 ACPI_RESOURCE *rp;
1774 void *newp;
1775
1776 /* Initialise the buffer if necessary. */
1777 if (buf->Pointer == NULL) {
1778 buf->Length = ACPI_INITIAL_RESOURCE_BUFFER_SIZE;
1779 if ((buf->Pointer = AcpiOsAllocate(buf->Length)) == NULL)
1780 return (AE_NO_MEMORY);
1781 rp = (ACPI_RESOURCE *)buf->Pointer;
e1eeedd0 1782 rp->Type = ACPI_RESOURCE_TYPE_END_TAG;
5ed44076
MD
1783 rp->Length = 0;
1784 }
1785 if (res == NULL)
1786 return (AE_OK);
1787
1788 /*
1789 * Scan the current buffer looking for the terminator.
1790 * This will either find the terminator or hit the end
1791 * of the buffer and return an error.
1792 */
1793 rp = (ACPI_RESOURCE *)buf->Pointer;
1794 for (;;) {
1795 /* Range check, don't go outside the buffer */
1796 if (rp >= (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
1797 return (AE_BAD_PARAMETER);
e1eeedd0 1798 if (rp->Type == ACPI_RESOURCE_TYPE_END_TAG || rp->Length == 0)
5ed44076
MD
1799 break;
1800 rp = ACPI_NEXT_RESOURCE(rp);
1801 }
1802
1803 /*
1804 * Check the size of the buffer and expand if required.
1805 *
1806 * Required size is:
1807 * size of existing resources before terminator +
1808 * size of new resource and header +
1809 * size of terminator.
1810 *
1811 * Note that this loop should really only run once, unless
1812 * for some reason we are stuffing a *really* huge resource.
1813 */
1814 while ((((u_int8_t *)rp - (u_int8_t *)buf->Pointer) +
e1eeedd0
YT
1815 res->Length + ACPI_RS_SIZE_NO_DATA +
1816 ACPI_RS_SIZE_MIN) >= buf->Length) {
5ed44076
MD
1817 if ((newp = AcpiOsAllocate(buf->Length * 2)) == NULL)
1818 return (AE_NO_MEMORY);
1819 bcopy(buf->Pointer, newp, buf->Length);
1820 rp = (ACPI_RESOURCE *)((u_int8_t *)newp +
1821 ((u_int8_t *)rp - (u_int8_t *)buf->Pointer));
1822 AcpiOsFree(buf->Pointer);
1823 buf->Pointer = newp;
1824 buf->Length += buf->Length;
1825 }
1826
1827 /* Insert the new resource. */
e1eeedd0 1828 bcopy(res, rp, res->Length + ACPI_RS_SIZE_NO_DATA);
5ed44076
MD
1829
1830 /* And add the terminator. */
1831 rp = ACPI_NEXT_RESOURCE(rp);
e1eeedd0 1832 rp->Type = ACPI_RESOURCE_TYPE_END_TAG;
5ed44076
MD
1833 rp->Length = 0;
1834
1835 return (AE_OK);
1836}
1837
1838/*
1839 * Set interrupt model.
1840 */
1841ACPI_STATUS
1842acpi_SetIntrModel(int model)
1843{
f9d8cd12 1844 return (acpi_SetInteger(ACPI_ROOT_OBJECT, "_PIC", model));
5ed44076
MD
1845}
1846
1847#define ACPI_MINIMUM_AWAKETIME 5
1848
1849static void
1850acpi_sleep_enable(void *arg)
1851{
1852 ((struct acpi_softc *)arg)->acpi_sleep_disabled = 0;
1853}
1854
1855/*
1856 * Set the system sleep state
1857 *
1858 * Currently we support S1-S5 but S4 is only S4BIOS
1859 */
1860ACPI_STATUS
1861acpi_SetSleepState(struct acpi_softc *sc, int state)
1862{
1863 ACPI_STATUS status = AE_OK;
1864 UINT8 TypeA;
1865 UINT8 TypeB;
1866
1867 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
1868 ACPI_ASSERTLOCK;
1869
1870 /* Avoid reentry if already attempting to suspend. */
1871 if (sc->acpi_sstate != ACPI_STATE_S0)
1872 return_ACPI_STATUS (AE_BAD_PARAMETER);
1873
1874 /* We recently woke up so don't suspend again for a while. */
1875 if (sc->acpi_sleep_disabled)
1876 return_ACPI_STATUS (AE_OK);
1877
1878 switch (state) {
1879 case ACPI_STATE_S1:
1880 case ACPI_STATE_S2:
1881 case ACPI_STATE_S3:
1882 case ACPI_STATE_S4:
1883 status = AcpiGetSleepTypeData((UINT8)state, &TypeA, &TypeB);
1884 if (status == AE_NOT_FOUND) {
1885 device_printf(sc->acpi_dev,
1886 "Sleep state S%d not supported by BIOS\n", state);
1887 break;
1888 } else if (ACPI_FAILURE(status)) {
1889 device_printf(sc->acpi_dev, "AcpiGetSleepTypeData failed - %s\n",
1890 AcpiFormatException(status));
1891 break;
1892 }
1893
1894 sc->acpi_sstate = state;
1895 sc->acpi_sleep_disabled = 1;
1896
49e48b8a
MD
1897 /* Disable all wake GPEs not appropriate for this state. */
1898 acpi_wake_limit_walk(state);
1899
5ed44076
MD
1900 /* Inform all devices that we are going to sleep. */
1901 if (DEVICE_SUSPEND(root_bus) != 0) {
1902 /*
1903 * Re-wake the system.
1904 *
1905 * XXX note that a better two-pass approach with a 'veto' pass
1906 * followed by a "real thing" pass would be better, but the
1907 * current bus interface does not provide for this.
1908 */
1909 DEVICE_RESUME(root_bus);
1910 return_ACPI_STATUS (AE_ERROR);
1911 }
1912
1913 status = AcpiEnterSleepStatePrep(state);
1914 if (ACPI_FAILURE(status)) {
1915 device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n",
1916 AcpiFormatException(status));
1917 break;
1918 }
1919
1920 if (sc->acpi_sleep_delay > 0)
1921 DELAY(sc->acpi_sleep_delay * 1000000);
1922
1923 if (state != ACPI_STATE_S1) {
1924 acpi_sleep_machdep(sc, state);
e1eeedd0 1925#if 0
5ed44076 1926 /* AcpiEnterSleepState() may be incomplete, unlock if locked. */
e1eeedd0
YT
1927 AcpiOsReleaseLock(AcpiGbl_HardwareLock, 1);
1928#endif
5ed44076
MD
1929 /* Re-enable ACPI hardware on wakeup from sleep state 4. */
1930 if (state == ACPI_STATE_S4)
1931 AcpiEnable();
1932 } else {
1933 status = AcpiEnterSleepState((UINT8)state);
1934 if (ACPI_FAILURE(status)) {
1935 device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
1936 AcpiFormatException(status));
1937 break;
1938 }
1939 }
1940 AcpiLeaveSleepState((UINT8)state);
1941 DEVICE_RESUME(root_bus);
1942 sc->acpi_sstate = ACPI_STATE_S0;
1943 acpi_enable_fixed_events(sc);
1944 break;
1945 case ACPI_STATE_S5:
1946 /*
1947 * Shut down cleanly and power off. This will call us back through the
1948 * shutdown handlers.
1949 */
1950 shutdown_nice(RB_POWEROFF);
1951 break;
1952 case ACPI_STATE_S0:
1953 default:
1954 status = AE_BAD_PARAMETER;
1955 break;
1956 }
1957
1958 /* Disable a second sleep request for a short period */
1959 if (sc->acpi_sleep_disabled)
edf6eb70
JS
1960 callout_reset(&sc->acpi_sleep_timer, hz * ACPI_MINIMUM_AWAKETIME,
1961 acpi_sleep_enable, sc);
5ed44076
MD
1962
1963 return_ACPI_STATUS (status);
1964}
1965
49e48b8a
MD
1966/* Initialize a device's wake GPE. */
1967int
1968acpi_wake_init(device_t dev, int type)
1969{
1970 struct acpi_prw_data prw;
1971
1972 /* Check that the device can wake the system. */
1973 if ((device_get_flags(dev) & ACPI_FLAG_WAKE_CAPABLE) == 0)
1974 return (ENXIO);
1975
1976 /* Evaluate _PRW to find the GPE. */
1977 if (acpi_parse_prw(acpi_get_handle(dev), &prw) != 0)
1978 return (ENXIO);
1979
1980 /* Set the requested type for the GPE (runtime, wake, or both). */
1981 if (ACPI_FAILURE(AcpiSetGpeType(prw.gpe_handle, prw.gpe_bit, type))) {
1982 device_printf(dev, "set GPE type failed\n");
1983 return (ENXIO);
1984 }
1985
1986 return (0);
1987}
1988
1989/* Enable or disable the device's wake GPE. */
1990int
1991acpi_wake_set_enable(device_t dev, int enable)
1992{
1993 struct acpi_prw_data prw;
1994 ACPI_HANDLE handle;
1995 ACPI_STATUS status;
1996 int flags;
1997
1998 /* Make sure the device supports waking the system. */
1999 flags = device_get_flags(dev);
2000 handle = acpi_get_handle(dev);
2001 if ((flags & ACPI_FLAG_WAKE_CAPABLE) == 0 || handle == NULL)
2002 return (ENXIO);
2003
2004 /* Evaluate _PRW to find the GPE. */
2005 if (acpi_parse_prw(handle, &prw) != 0)
2006 return (ENXIO);
2007
2008 if (enable) {
2009 status = AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR);
2010 if (ACPI_FAILURE(status)) {
2011 device_printf(dev, "enable wake failed\n");
2012 return (ENXIO);
2013 }
2014 device_set_flags(dev, flags | ACPI_FLAG_WAKE_ENABLED);
2015 } else {
2016 status = AcpiDisableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR);
2017 if (ACPI_FAILURE(status)) {
2018 device_printf(dev, "disable wake failed\n");
2019 return (ENXIO);
2020 }
2021 device_set_flags(dev, flags & ~ACPI_FLAG_WAKE_ENABLED);
2022 }
2023
2024 return (0);
2025}
2026
2027/* Configure a device's GPE appropriately for the new sleep state. */
2028int
2029acpi_wake_sleep_prep(device_t dev, int sstate)
2030{
2031 struct acpi_prw_data prw;
2032 ACPI_HANDLE handle;
2033 int flags;
2034
2035 /* Check that this is an ACPI device and get its GPE. */
2036 flags = device_get_flags(dev);
2037 handle = acpi_get_handle(dev);
2038 if ((flags & ACPI_FLAG_WAKE_CAPABLE) == 0 || handle == NULL)
2039 return (ENXIO);
2040
2041 /* Evaluate _PRW to find the GPE. */
2042 if (acpi_parse_prw(handle, &prw) != 0)
2043 return (ENXIO);
2044
2045 /*
2046 * TBD: All Power Resources referenced by elements 2 through N
2047 * of the _PRW object are put into the ON state.
2048 */
2049
2050 /*
2051 * If the user requested that this device wake the system and the next
2052 * sleep state is valid for this GPE, enable it and the device's wake
2053 * capability. The sleep state must be less than (i.e., higher power)
2054 * or equal to the value specified by _PRW. Return early, leaving
2055 * the appropriate power resources enabled.
2056 */
2057 if ((flags & ACPI_FLAG_WAKE_ENABLED) != 0 &&
2058 sstate <= prw.lowest_wake) {
2059 if (bootverbose)
2060 device_printf(dev, "wake_prep enabled gpe %#x for state %d\n",
2061 prw.gpe_bit, sstate);
2062 AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR);
2063 acpi_SetInteger(handle, "_PSW", 1);
2064 return (0);
2065 }
2066
2067 /*
2068 * If the device wake was disabled or this sleep state is too low for
2069 * this device, disable its wake capability and GPE.
2070 */
2071 AcpiDisableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR);
2072 acpi_SetInteger(handle, "_PSW", 0);
2073 if (bootverbose)
2074 device_printf(dev, "wake_prep disabled gpe %#x for state %d\n",
2075 prw.gpe_bit, sstate);
2076
2077 /*
2078 * TBD: All Power Resources referenced by elements 2 through N
2079 * of the _PRW object are put into the OFF state.
2080 */
2081
2082 return (0);
2083}
2084
2085/* Re-enable GPEs after wake. */
2086int
2087acpi_wake_run_prep(device_t dev)
2088{
2089 struct acpi_prw_data prw;
2090 ACPI_HANDLE handle;
2091 int flags;
2092
2093 /* Check that this is an ACPI device and get its GPE. */
2094 flags = device_get_flags(dev);
2095 handle = acpi_get_handle(dev);
2096 if ((flags & ACPI_FLAG_WAKE_CAPABLE) == 0 || handle == NULL)
2097 return (ENXIO);
2098
2099 /* Evaluate _PRW to find the GPE. */
2100 if (acpi_parse_prw(handle, &prw) != 0)
2101 return (ENXIO);
2102
2103 /*
2104 * TBD: Be sure all Power Resources referenced by elements 2 through N
2105 * of the _PRW object are in the ON state.
2106 */
2107
2108 /* Disable wake capability and if the user requested, enable the GPE. */
2109 acpi_SetInteger(handle, "_PSW", 0);
2110 if ((flags & ACPI_FLAG_WAKE_ENABLED) != 0)
2111 AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR);
2112 return (0);
2113}
2114
2115static ACPI_STATUS
2116acpi_wake_limit(ACPI_HANDLE h, UINT32 level, void *context, void **status)
2117{
2118 struct acpi_prw_data prw;
2119 int *sstate;
2120
2121 /* It's ok not to have _PRW if the device can't wake the system. */
2122 if (acpi_parse_prw(h, &prw) != 0)
2123 return (AE_OK);
2124
2125 sstate = (int *)context;
2126 if (*sstate > prw.lowest_wake)
2127 AcpiDisableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR);
2128
2129 return (AE_OK);
2130}
2131
2132/* Walk all system devices, disabling them if necessary for sstate. */
2133static int
2134acpi_wake_limit_walk(int sstate)
2135{
2136 ACPI_HANDLE sb_handle;
2137
2138 if (ACPI_SUCCESS(AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &sb_handle)))
2139 AcpiWalkNamespace(ACPI_TYPE_ANY, sb_handle, 100,
2140 acpi_wake_limit, &sstate, NULL);
2141 return (0);
2142}
2143
2144/* Walk the tree rooted at acpi0 to attach per-device wake sysctls. */
2145static int
2146acpi_wake_sysctl_walk(device_t dev)
2147{
2148 int error, i, numdevs;
2149 device_t *devlist;
2150 device_t child;
2151
2152 error = device_get_children(dev, &devlist, &numdevs);
2153 if (error != 0 || numdevs == 0)
2154 return (error);
2155 for (i = 0; i < numdevs; i++) {
2156 child = devlist[i];
2157 if (!device_is_attached(child))
2158 continue;
2159 if (device_get_flags(child) & ACPI_FLAG_WAKE_CAPABLE) {
2160#ifdef dfly_notyet
2161 SYSCTL_ADD_PROC(device_get_sysctl_ctx(child),
2162 SYSCTL_CHILDREN(device_get_sysctl_tree(child)), OID_AUTO,
2163 "wake", CTLTYPE_INT | CTLFLAG_RW, child, 0,
2164 acpi_wake_set_sysctl, "I", "Device set to wake the system");
2165#endif /* dfly_notyet */
2166 }
2167 acpi_wake_sysctl_walk(child);
2168 }
efda3bd0 2169 kfree(devlist, M_TEMP);
49e48b8a
MD
2170
2171 return (0);
2172}
2173
edf5636b 2174#ifdef dfly_notyet
49e48b8a
MD
2175/* Enable or disable wake from userland. */
2176static int
2177acpi_wake_set_sysctl(SYSCTL_HANDLER_ARGS)
2178{
2179 int enable, error;
2180 device_t dev;
2181
2182 dev = (device_t)arg1;
2183 enable = (device_get_flags(dev) & ACPI_FLAG_WAKE_ENABLED) ? 1 : 0;
2184
2185 error = sysctl_handle_int(oidp, &enable, 0, req);
2186 if (error != 0 || req->newptr == NULL)
2187 return (error);
2188 if (enable != 0 && enable != 1)
2189 return (EINVAL);
2190
2191 return (acpi_wake_set_enable(dev, enable));
2192}
edf5636b 2193#endif /* dfly_notyet */
49e48b8a
MD
2194
2195/* Parse a device's _PRW into a structure. */
2196static int
2197acpi_parse_prw(ACPI_HANDLE h, struct acpi_prw_data *prw)
2198{
2199 ACPI_STATUS status;
2200 ACPI_BUFFER prw_buffer;
2201 ACPI_OBJECT *res, *res2;
2202 int error;
2203
2204 if (h == NULL || prw == NULL)
2205 return (EINVAL);
2206
2207 /*
2208 * The _PRW object (7.2.9) is only required for devices that have the
2209 * ability to wake the system from a sleeping state.
2210 */
2211 error = EINVAL;
2212 prw_buffer.Pointer = NULL;
2213 prw_buffer.Length = ACPI_ALLOCATE_BUFFER;
2214 status = AcpiEvaluateObject(h, "_PRW", NULL, &prw_buffer);
2215 if (ACPI_FAILURE(status))
2216 return (ENOENT);
2217 res = (ACPI_OBJECT *)prw_buffer.Pointer;
2218 if (res == NULL)
2219 return (ENOENT);
2220 if (!ACPI_PKG_VALID(res, 2))
2221 goto out;
2222
2223 /*
2224 * Element 1 of the _PRW object:
2225 * The lowest power system sleeping state that can be entered while still
2226 * providing wake functionality. The sleeping state being entered must
2227 * be less than (i.e., higher power) or equal to this value.
2228 */
2229 if (acpi_PkgInt32(res, 1, &prw->lowest_wake) != 0)
2230 goto out;
2231
2232 /*
2233 * Element 0 of the _PRW object:
2234 */
2235 switch (res->Package.Elements[0].Type) {
2236 case ACPI_TYPE_INTEGER:
2237 /*
2238 * If the data type of this package element is numeric, then this
2239 * _PRW package element is the bit index in the GPEx_EN, in the
2240 * GPE blocks described in the FADT, of the enable bit that is
2241 * enabled for the wake event.
2242 */
2243 prw->gpe_handle = NULL;
2244 prw->gpe_bit = res->Package.Elements[0].Integer.Value;
2245 error = 0;
2246 break;
2247 case ACPI_TYPE_PACKAGE:
2248 /*
2249 * If the data type of this package element is a package, then this
2250 * _PRW package element is itself a package containing two
2251 * elements. The first is an object reference to the GPE Block
2252 * device that contains the GPE that will be triggered by the wake
2253 * event. The second element is numeric and it contains the bit
2254 * index in the GPEx_EN, in the GPE Block referenced by the
2255 * first element in the package, of the enable bit that is enabled for
2256 * the wake event.
2257 *
2258 * For example, if this field is a package then it is of the form:
2259 * Package() {\_SB.PCI0.ISA.GPE, 2}
2260 */
2261 res2 = &res->Package.Elements[0];
2262 if (!ACPI_PKG_VALID(res2, 2))
2263 goto out;
2264 prw->gpe_handle = acpi_GetReference(NULL, &res2->Package.Elements[0]);
2265 if (prw->gpe_handle == NULL)
2266 goto out;
2267 if (acpi_PkgInt32(res2, 1, &prw->gpe_bit) != 0)
2268 goto out;
2269 error = 0;
2270 break;
2271 default:
2272 goto out;
2273 }
2274
2275 /* XXX No power resource handling yet. */
2276 prw->power_res = NULL;
2277
2278out:
2279 if (prw_buffer.Pointer != NULL)
2280 AcpiOsFree(prw_buffer.Pointer);
2281 return (error);
2282}
2283
5ed44076
MD
2284/*
2285 * Enable/Disable ACPI
2286 */
2287ACPI_STATUS
2288acpi_Enable(struct acpi_softc *sc)
2289{
2290 ACPI_STATUS status;
2291 u_int32_t flags;
2292
2293 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
2294 ACPI_ASSERTLOCK;
2295
2296 flags = ACPI_NO_ADDRESS_SPACE_INIT | ACPI_NO_HARDWARE_INIT |
2297 ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
2298 if (!sc->acpi_enabled)
2299 status = AcpiEnableSubsystem(flags);
2300 else
2301 status = AE_OK;
2302
2303 if (status == AE_OK)
2304 sc->acpi_enabled = 1;
2305
2306 return_ACPI_STATUS (status);
2307}
2308
2309ACPI_STATUS
2310acpi_Disable(struct acpi_softc *sc)
2311{
2312 ACPI_STATUS status;
2313
2314 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
2315 ACPI_ASSERTLOCK;
2316
2317 if (sc->acpi_enabled)
2318 status = AcpiDisable();
2319 else
2320 status = AE_OK;
2321
2322 if (status == AE_OK)
2323 sc->acpi_enabled = 0;
2324
2325 return_ACPI_STATUS (status);
2326}
2327
2328/*
2329 * ACPI Event Handlers
2330 */
2331
2332/* System Event Handlers (registered by EVENTHANDLER_REGISTER) */
2333
2334static void
2335acpi_system_eventhandler_sleep(void *arg, int state)
2336{
2337 ACPI_LOCK_DECL;
2338 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
2339
2340 ACPI_LOCK;
2341 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
2342 acpi_SetSleepState((struct acpi_softc *)arg, state);
2343 ACPI_UNLOCK;
2344 return_VOID;
2345}
2346
2347static void
2348acpi_system_eventhandler_wakeup(void *arg, int state)
2349{
2350 ACPI_LOCK_DECL;
2351 ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
2352
2353 /* Well, what to do? :-) */
2354
2355 ACPI_LOCK;
2356 ACPI_UNLOCK;
2357
2358 return_VOID;
2359}
2360
2361/*
2362 * ACPICA Event Handlers (FixedEvent, also called from button notify handler)
2363 */
2364UINT32
2365acpi_event_power_button_sleep(void *context)
2366{
2367 struct acpi_softc *sc = (struct acpi_softc *)context;
2368
2369 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
2370
2371 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx);
2372
2373 return_VALUE (ACPI_INTERRUPT_HANDLED);
2374}
2375
2376UINT32
2377acpi_event_power_button_wake(void *context)
2378{
2379 struct acpi_softc *sc = (struct acpi_softc *)context;
2380
2381 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
2382
2383 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_power_button_sx);
2384
2385 return_VALUE (ACPI_INTERRUPT_HANDLED);
2386}
2387
2388UINT32
2389acpi_event_sleep_button_sleep(void *context)
2390{
2391 struct acpi_softc *sc = (struct acpi_softc *)context;
2392
2393 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
2394
2395 EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx);
2396
2397 return_VALUE (ACPI_INTERRUPT_HANDLED);
2398}
2399
2400UINT32
2401acpi_event_sleep_button_wake(void *context)
2402{
2403 struct acpi_softc *sc = (struct acpi_softc *)context;
2404
2405 ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
2406
2407 EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_sleep_button_sx);
2408
2409 return_VALUE (ACPI_INTERRUPT_HANDLED);
2410}
2411
2412/*
2413 * XXX This is kinda ugly, and should not be here.
2414 */
2415struct acpi_staticbuf {
2416 ACPI_BUFFER buffer;
2417 char data[512];
2418};
2419
2420char *
2421acpi_name(ACPI_HANDLE handle)
2422{
2423 static struct acpi_staticbuf buf;
2424
2425 ACPI_ASSERTLOCK;
2426
2427 buf.buffer.Length = 512;
2428 buf.buffer.Pointer = &buf.data[0];
2429
2430 if (ACPI_SUCCESS(AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf.buffer)))
2431 return (buf.buffer.Pointer);
2432
2433 return ("(unknown path)");
2434}
2435
2436/*
2437 * Debugging/bug-avoidance. Avoid trying to fetch info on various
2438 * parts of the namespace.
2439 */
2440int
2441acpi_avoid(ACPI_HANDLE handle)
2442{
2443 char *cp, *env, *np;
2444 int len;
2445
2446 np = acpi_name(handle);
2447 if (*np == '\\')
2448 np++;
bc01a404
MD
2449 if ((env = kgetenv("debug.acpi.avoid.paths")) == NULL &&
2450 (env = kgetenv("debug.acpi.avoid")) == NULL)
5ed44076
MD
2451 return (0);
2452
2453 /* Scan the avoid list checking for a match */
2454 cp = env;
2455 for (;;) {
2456 while ((*cp != 0) && isspace(*cp))
2457 cp++;
2458 if (*cp == 0)
2459 break;
2460 len = 0;
2461 while ((cp[len] != 0) && !isspace(cp[len]))
2462 len++;
2463 if (!strncmp(cp, np, len)) {
728aa6ee 2464 kfreeenv(env);
5ed44076
MD
2465 return(1);
2466 }
2467 cp += len;
2468 }
728aa6ee 2469 kfreeenv(env);
5ed44076
MD
2470
2471 return (0);
2472}
2473
2474/*
2df6e324
MD
2475 * Debugging/bug-avoidance. Disable ACPI subsystem components. Note that
2476 * some components may be disabled by default and can only be enabled
2477 * via acpi_enabled() (debug.acpi.enabled).
5ed44076
MD
2478 */
2479int
2480acpi_disabled(char *subsys)
2481{
2482 char *cp, *env;
2483 int len;
2484
bc01a404 2485 if ((env = kgetenv("debug.acpi.disabled")) == NULL)
5ed44076 2486 return (0);
f9d8cd12 2487 if (strcmp(env, "all") == 0) {
728aa6ee 2488 kfreeenv(env);
5ed44076
MD
2489 return (1);
2490 }
2491
f9d8cd12 2492 /* Scan the disable list, checking for a match. */
5ed44076
MD
2493 cp = env;
2494 for (;;) {
f9d8cd12 2495 while (*cp != '\0' && isspace(*cp))
5ed44076 2496 cp++;
f9d8cd12 2497 if (*cp == '\0')
5ed44076
MD
2498 break;
2499 len = 0;
f9d8cd12 2500 while (cp[len] != '\0' && !isspace(cp[len]))
5ed44076 2501 len++;
f9d8cd12 2502 if (strncmp(cp, subsys, len) == 0) {
728aa6ee 2503 kfreeenv(env);
5ed44076
MD
2504 return (1);
2505 }
2506 cp += len;
2507 }
728aa6ee 2508 kfreeenv(env);
5ed44076
MD
2509
2510 return (0);
2511}
2512
2513/*
2df6e324
MD
2514 * Debugging/bug-avoidance. Enable ACPI subsystem components. Most
2515 * components are enabled by default. The ones that are not have to be
2516 * enabled via debug.acpi.enabled.
2517 */
2518int
2519acpi_enabled(char *subsys)
2520{
2521 char *cp, *env;
2522 int len;
2523
bc01a404 2524 if ((env = kgetenv("debug.acpi.enabled")) == NULL)
2df6e324
MD
2525 return (0);
2526 if (strcmp(env, "all") == 0) {
728aa6ee 2527 kfreeenv(env);
2df6e324
MD
2528 return (1);
2529 }
2530
2531 /* Scan the enable list, checking for a match. */
2532 cp = env;
2533 for (;;) {
2534 while (*cp != '\0' && isspace(*cp))
2535 cp++;
2536 if (*cp == '\0')
2537 break;
2538 len = 0;
2539 while (cp[len] != '\0' && !isspace(cp[len]))
2540 len++;
2541 if (strncmp(cp, subsys, len) == 0) {
728aa6ee 2542 kfreeenv(env);
2df6e324
MD
2543 return (1);
2544 }
2545 cp += len;
2546 }
728aa6ee 2547 kfreeenv(env);
2df6e324
MD
2548
2549 return (0);
2550}
2551
2552/*
5ed44076
MD
2553 * Control interface.
2554 *
2555 * We multiplex ioctls for all participating ACPI devices here. Individual
2556 * drivers wanting to be accessible via /dev/acpi should use the
2557 * register/deregister interface to make their handlers visible.
2558 */
2559struct acpi_ioctl_hook
2560{
2561 TAILQ_ENTRY(acpi_ioctl_hook) link;
2562 u_long cmd;
2563 acpi_ioctl_fn fn;
2564 void *arg;
2565};
2566
2567static TAILQ_HEAD(,acpi_ioctl_hook) acpi_ioctl_hooks;
2568static int acpi_ioctl_hooks_initted;
2569
2570/*
2571 * Register an ioctl handler.
2572 */
2573int
2574acpi_register_ioctl(u_long cmd, acpi_ioctl_fn fn, void *arg)
2575{
2576 struct acpi_ioctl_hook *hp;
2577
efda3bd0 2578 hp = kmalloc(sizeof(*hp), M_ACPIDEV, M_INTWAIT);
5ed44076
MD
2579 hp->cmd = cmd;
2580 hp->fn = fn;
2581 hp->arg = arg;
2582 if (acpi_ioctl_hooks_initted == 0) {
2583 TAILQ_INIT(&acpi_ioctl_hooks);
2584 acpi_ioctl_hooks_initted = 1;
2585 }
2586 TAILQ_INSERT_TAIL(&acpi_ioctl_hooks, hp, link);
2587 return (0);
2588}
2589
2590/*
2591 * Deregister an ioctl handler.
2592 */
2593void
2594acpi_deregister_ioctl(u_long cmd, acpi_ioctl_fn fn)
2595{
2596 struct acpi_ioctl_hook *hp;
2597
2598 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link)
2599 if ((hp->cmd == cmd) && (hp->fn == fn))
2600 break;
2601
2602 if (hp != NULL) {
2603 TAILQ_REMOVE(&acpi_ioctl_hooks, hp, link);
efda3bd0 2604 kfree(hp, M_ACPIDEV);
5ed44076
MD
2605 }
2606}
2607
2608static int
fef8985e 2609acpiopen(struct dev_open_args *ap)
5ed44076
MD
2610{
2611 return (0);
2612}
2613
2614static int
fef8985e 2615acpiclose(struct dev_close_args *ap)
5ed44076
MD
2616{
2617 return (0);
2618}
2619
2620static int
fef8985e 2621acpiioctl(struct dev_ioctl_args *ap)
5ed44076
MD
2622{
2623 struct acpi_softc *sc;
2624 struct acpi_ioctl_hook *hp;
2625 int error, xerror, state;
2626 ACPI_LOCK_DECL;
2627
2628 ACPI_LOCK;
2629
2630 error = state = 0;
fef8985e 2631 sc = ap->a_head.a_dev->si_drv1;
5ed44076
MD
2632
2633 /*
2634 * Scan the list of registered ioctls, looking for handlers.
2635 */
2636 if (acpi_ioctl_hooks_initted) {
2637 TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link) {
fef8985e
MD
2638 if (hp->cmd == ap->a_cmd) {
2639 xerror = hp->fn(ap->a_cmd, ap->a_data, hp->arg);
5ed44076
MD
2640 if (xerror != 0)
2641 error = xerror;
2642 goto out;
2643 }
2644 }
2645 }
2646
2647 /*
2648 * Core ioctls are not permitted for non-writable user.
2649 * Currently, other ioctls just fetch information.
2650 * Not changing system behavior.
2651 */
2a1383fc
YT
2652 if((ap->a_fflag & FWRITE) == 0) {
2653 error = EPERM;
2654 goto out;
2655 }
5ed44076
MD
2656
2657 /* Core system ioctls. */
fef8985e 2658 switch (ap->a_cmd) {
5ed44076
MD
2659 case ACPIIO_ENABLE:
2660 if (ACPI_FAILURE(acpi_Enable(sc)))
2661 error = ENXIO;
2662 break;
2663 case ACPIIO_DISABLE:
2664 if (ACPI_FAILURE(acpi_Disable(sc)))
2665 error = ENXIO;
2666 break;
2667 case ACPIIO_SETSLPSTATE:
2668 if (!sc->acpi_enabled) {
2669 error = ENXIO;
2670 break;
2671 }
fef8985e 2672 state = *(int *)ap->a_data;
5ed44076
MD
2673 if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX) {
2674 if (ACPI_FAILURE(acpi_SetSleepState(sc, state)))
2675 error = EINVAL;
2676 } else {
2677 error = EINVAL;
2678 }
2679 break;
2680 default:
2681 if (error == 0)
2682 error = EINVAL;
2683 break;
2684 }
2685
2686out:
2687 ACPI_UNLOCK;
2688 return (error);
2689}
2690
2691static int
2692acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
2693{
2694 char sleep_state[4];
2695 char buf[16];
2696 int error;
2697 UINT8 state, TypeA, TypeB;
2698
2699 buf[0] = '\0';
f9d8cd12 2700 for (state = ACPI_STATE_S1; state < ACPI_S_STATES_MAX + 1; state++) {
5ed44076 2701 if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) {
f8c7a42d 2702 ksprintf(sleep_state, "S%d ", state);
5ed44076
MD
2703 strcat(buf, sleep_state);
2704 }
2705 }
2706 error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
2707 return (error);
2708}
2709
2710static int
2711acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
2712{
2713 char sleep_state[10];
2714 int error;
2715 u_int new_state, old_state;
2716
2717 old_state = *(u_int *)oidp->oid_arg1;
f9d8cd12 2718 if (old_state > ACPI_S_STATES_MAX + 1) {
5ed44076
MD
2719 strcpy(sleep_state, "unknown");
2720 } else {
2721 bzero(sleep_state, sizeof(sleep_state));
2722 strncpy(sleep_state, sleep_state_names[old_state],
2723 sizeof(sleep_state_names[old_state]));
2724 }
2725 error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
2726 if (error == 0 && req->newptr != NULL) {
2727 new_state = ACPI_STATE_S0;
2728 for (; new_state <= ACPI_S_STATES_MAX + 1; new_state++) {
2729 if (strncmp(sleep_state, sleep_state_names[new_state],
2730 sizeof(sleep_state)) == 0)
2731 break;
2732 }
2733 if (new_state <= ACPI_S_STATES_MAX + 1) {
2734 if (new_state != old_state)
2735 *(u_int *)oidp->oid_arg1 = new_state;
2736 } else {
2737 error = EINVAL;
2738 }
2739 }
2740
2741 return (error);
2742}
2743
2744/* Inform devctl(4) when we receive a Notify. */
2745void
2746acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, uint8_t notify)
2747{
2748 char notify_buf[16];
2749 ACPI_BUFFER handle_buf;
2750 ACPI_STATUS status;
2751
2752 if (subsystem == NULL)
2753 return;
2754
2755 handle_buf.Pointer = NULL;
2756 handle_buf.Length = ACPI_ALLOCATE_BUFFER;
2757 status = AcpiNsHandleToPathname(h, &handle_buf);
2758 if (ACPI_FAILURE(status))
2759 return;
f8c7a42d 2760 ksnprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x", notify);
5ed44076 2761 devctl_notify("ACPI", subsystem, handle_buf.Pointer, notify_buf);
5ed44076
MD
2762 AcpiOsFree(handle_buf.Pointer);
2763}
2764
2765#ifdef ACPI_DEBUG
2766/*
2767 * Support for parsing debug options from the kernel environment.
2768 *
2769 * Bits may be set in the AcpiDbgLayer and AcpiDbgLevel debug registers
2770 * by specifying the names of the bits in the debug.acpi.layer and
2771 * debug.acpi.level environment variables. Bits may be unset by
2772 * prefixing the bit name with !.
2773 */
2774struct debugtag
2775{
2776 char *name;
2777 UINT32 value;
2778};
2779
2780static struct debugtag dbg_layer[] = {
2781 {"ACPI_UTILITIES", ACPI_UTILITIES},
2782 {"ACPI_HARDWARE", ACPI_HARDWARE},
2783 {"ACPI_EVENTS", ACPI_EVENTS},
2784 {"ACPI_TABLES", ACPI_TABLES},
2785 {"ACPI_NAMESPACE", ACPI_NAMESPACE},
2786 {"ACPI_PARSER", ACPI_PARSER},
2787 {"ACPI_DISPATCHER", ACPI_DISPATCHER},
2788 {"ACPI_EXECUTER", ACPI_EXECUTER},
2789 {"ACPI_RESOURCES", ACPI_RESOURCES},
2790 {"ACPI_CA_DEBUGGER", ACPI_CA_DEBUGGER},
2791 {"ACPI_OS_SERVICES", ACPI_OS_SERVICES},
2792 {"ACPI_CA_DISASSEMBLER", ACPI_CA_DISASSEMBLER},
2793 {"ACPI_ALL_COMPONENTS", ACPI_ALL_COMPONENTS},
2794
5ed44076
MD
2795 {"ACPI_AC_ADAPTER", ACPI_AC_ADAPTER},
2796 {"ACPI_BATTERY", ACPI_BATTERY},
f9d8cd12 2797 {"ACPI_BUS", ACPI_BUS},
5ed44076 2798 {"ACPI_BUTTON", ACPI_BUTTON},
f9d8cd12
MD
2799 {"ACPI_EC", ACPI_EC},
2800 {"ACPI_FAN", ACPI_FAN},
2801 {"ACPI_POWERRES", ACPI_POWERRES},
5ed44076
MD
2802 {"ACPI_PROCESSOR", ACPI_PROCESSOR},
2803 {"ACPI_THERMAL", ACPI_THERMAL},
f9d8cd12 2804 {"ACPI_TIMER", ACPI_TIMER},
5ed44076
MD
2805 {"ACPI_ALL_DRIVERS", ACPI_ALL_DRIVERS},
2806 {NULL, 0}
2807};
2808
2809static struct debugtag dbg_level[] = {
2810 {"ACPI_LV_ERROR", ACPI_LV_ERROR},
2811 {"ACPI_LV_WARN", ACPI_LV_WARN},
2812 {"ACPI_LV_INIT", ACPI_LV_INIT},
2813 {"ACPI_LV_DEBUG_OBJECT", ACPI_LV_DEBUG_OBJECT},
2814 {"ACPI_LV_INFO", ACPI_LV_INFO},
2815 {"ACPI_LV_ALL_EXCEPTIONS", ACPI_LV_ALL_EXCEPTIONS},
2816
2817 /* Trace verbosity level 1 [Standard Trace Level] */
2818 {"ACPI_LV_INIT_NAMES", ACPI_LV_INIT_NAMES},
2819 {"ACPI_LV_PARSE", ACPI_LV_PARSE},
2820 {"ACPI_LV_LOAD", ACPI_LV_LOAD},
2821 {"ACPI_LV_DISPATCH", ACPI_LV_DISPATCH},
2822 {"ACPI_LV_EXEC", ACPI_LV_EXEC},
2823 {"ACPI_LV_NAMES", ACPI_LV_NAMES},
2824 {"ACPI_LV_OPREGION", ACPI_LV_OPREGION},
2825 {"ACPI_LV_BFIELD", ACPI_LV_BFIELD},
2826 {"ACPI_LV_TABLES", ACPI_LV_TABLES},
2827 {"ACPI_LV_VALUES", ACPI_LV_VALUES},
2828 {"ACPI_LV_OBJECTS", ACPI_LV_OBJECTS},
2829 {"ACPI_LV_RESOURCES", ACPI_LV_RESOURCES},
2830 {"ACPI_LV_USER_REQUESTS", ACPI_LV_USER_REQUESTS},
2831 {"ACPI_LV_PACKAGE", ACPI_LV_PACKAGE},
2832 {"ACPI_LV_VERBOSITY1", ACPI_LV_VERBOSITY1},
2833
2834 /* Trace verbosity level 2 [Function tracing and memory allocation] */
2835 {"ACPI_LV_ALLOCATIONS", ACPI_LV_ALLOCATIONS},
2836 {"ACPI_LV_FUNCTIONS", ACPI_LV_FUNCTIONS},
2837 {"ACPI_LV_OPTIMIZATIONS", ACPI_LV_OPTIMIZATIONS},
2838 {"ACPI_LV_VERBOSITY2", ACPI_LV_VERBOSITY2},
2839 {"ACPI_LV_ALL", ACPI_LV_ALL},
2840
2841 /* Trace verbosity level 3 [Threading, I/O, and Interrupts] */
2842 {"ACPI_LV_MUTEX", ACPI_LV_MUTEX},
2843 {"ACPI_LV_THREADS", ACPI_LV_THREADS},
2844 {"ACPI_LV_IO", ACPI_LV_IO},
2845 {"ACPI_LV_INTERRUPTS", ACPI_LV_INTERRUPTS},
2846 {"ACPI_LV_VERBOSITY3", ACPI_LV_VERBOSITY3},
2847
2848 /* Exceptionally verbose output -- also used in the global "DebugLevel" */
2849 {"ACPI_LV_AML_DISASSEMBLE", ACPI_LV_AML_DISASSEMBLE},
2850 {"ACPI_LV_VERBOSE_INFO", ACPI_LV_VERBOSE_INFO},
2851 {"ACPI_LV_FULL_TABLES", ACPI_LV_FULL_TABLES},
2852 {"ACPI_LV_EVENTS", ACPI_LV_EVENTS},
2853 {"ACPI_LV_VERBOSE", ACPI_LV_VERBOSE},
2854 {NULL, 0}
2855};
2856
2857static void
2858acpi_parse_debug(char *cp, struct debugtag *tag, UINT32 *flag)
2859{
2860 char *ep;
2861 int i, l;
2862 int set;
2863
2864 while (*cp) {
2865 if (isspace(*cp)) {
2866 cp++;
2867 continue;
2868 }
2869 ep = cp;
2870 while (*ep && !isspace(*ep))
2871 ep++;
2872 if (*cp == '!') {
2873 set = 0;
2874 cp++;
2875 if (cp == ep)
2876 continue;
2877 } else {
2878 set = 1;
2879 }
2880 l = ep - cp;
2881 for (i = 0; tag[i].name != NULL; i++) {
2882 if (!strncmp(cp, tag[i].name, l)) {
2883 if (set)
2884 *flag |= tag[i].value;
2885 else
2886 *flag &= ~tag[i].value;
5ed44076
MD
2887 }
2888 }
2889 cp = ep;
2890 }
2891}
2892
ba39e2e0
MD
2893/*
2894 * Warning: also called in early boot, before any allocators
2895 * are working.
2896 */
5ed44076
MD
2897static void
2898acpi_set_debugging(void *junk)
2899{
ba39e2e0 2900 char *layer, *level;
5ed44076
MD
2901
2902 if (cold) {
2903 AcpiDbgLayer = 0;
2904 AcpiDbgLevel = 0;
2905 }
2906
bc01a404
MD
2907 layer = kgetenv("debug.acpi.layer");
2908 level = kgetenv("debug.acpi.level");
f9d8cd12
MD
2909 if (layer == NULL && level == NULL)
2910 return;
5ed44076 2911
e3869ec7 2912 kprintf("ACPI set debug");
f9d8cd12
MD
2913 if (layer != NULL) {
2914 if (strcmp("NONE", layer) != 0)
e3869ec7 2915 kprintf(" layer '%s'", layer);
f9d8cd12 2916 acpi_parse_debug(layer, &dbg_layer[0], &AcpiDbgLayer);
728aa6ee 2917 kfreeenv(layer);
f9d8cd12
MD
2918 }
2919 if (level != NULL) {
2920 if (strcmp("NONE", level) != 0)
e3869ec7 2921 kprintf(" level '%s'", level);
f9d8cd12 2922 acpi_parse_debug(level, &dbg_level[0], &AcpiDbgLevel);
728aa6ee 2923 kfreeenv(level);
5ed44076 2924 }
e3869ec7 2925 kprintf("\n");
5ed44076 2926}
ba39e2e0
MD
2927SYSINIT(acpi_debugging, SI_BOOT1_TUNABLES, SI_ORDER_ANY,
2928 acpi_set_debugging, NULL);
5ed44076
MD
2929
2930static int
2931acpi_debug_sysctl(SYSCTL_HANDLER_ARGS)
2932{
2933 int error, *dbg;
2934 struct debugtag *tag;
2935 struct sbuf sb;
2936
2937 if (sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND) == NULL)
2938 return (ENOMEM);
2939 if (strcmp(oidp->oid_arg1, "debug.acpi.layer") == 0) {
2940 tag = &dbg_layer[0];
2941 dbg = &AcpiDbgLayer;
2942 } else {
2943 tag = &dbg_level[0];
2944 dbg = &AcpiDbgLevel;
2945 }
2946
2947 /* Get old values if this is a get request. */
2948 if (*dbg == 0) {
2949 sbuf_cpy(&sb, "NONE");
2950 } else if (req->newptr == NULL) {
2951 for (; tag->name != NULL; tag++) {
2952 if ((*dbg & tag->value) == tag->value)
2953 sbuf_printf(&sb, "%s ", tag->name);
2954 }
2955 }
2956 sbuf_trim(&sb);
2957 sbuf_finish(&sb);
2958
f9d8cd12
MD
2959 /* Copy out the old values to the user. */
2960 error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb));
5ed44076
MD
2961 sbuf_delete(&sb);
2962
2963 /* If the user is setting a string, parse it. */
2964 if (error == 0 && req->newptr != NULL) {
2965 *dbg = 0;
2895031d 2966 ksetenv(oidp->oid_arg1, req->newptr);
5ed44076
MD
2967 acpi_set_debugging(NULL);
2968 }
2969
2970 return (error);
2971}
2972SYSCTL_PROC(_debug_acpi, OID_AUTO, layer, CTLFLAG_RW | CTLTYPE_STRING,
2973 "debug.acpi.layer", 0, acpi_debug_sysctl, "A", "");
2974SYSCTL_PROC(_debug_acpi, OID_AUTO, level, CTLFLAG_RW | CTLTYPE_STRING,
2975 "debug.acpi.level", 0, acpi_debug_sysctl, "A", "");
2976#endif
2977
2978static int
2979acpi_pm_func(u_long cmd, void *arg, ...)
2980{
2981 int state, acpi_state;
2982 int error;
2983 struct acpi_softc *sc;
2984 va_list ap;
2985
2986 error = 0;
2987 switch (cmd) {
2988 case POWER_CMD_SUSPEND:
2989 sc = (struct acpi_softc *)arg;
2990 if (sc == NULL) {
2991 error = EINVAL;
2992 goto out;
2993 }
2994
2995 va_start(ap, arg);
2996 state = va_arg(ap, int);
2997 va_end(ap);
2998
2999 switch (state) {
3000 case POWER_SLEEP_STATE_STANDBY:
3001 acpi_state = sc->acpi_standby_sx;
3002 break;
3003 case POWER_SLEEP_STATE_SUSPEND:
3004 acpi_state = sc->acpi_suspend_sx;
3005 break;
3006 case POWER_SLEEP_STATE_HIBERNATE:
3007 acpi_state = ACPI_STATE_S4;
3008 break;
3009 default:
3010 error = EINVAL;
3011 goto out;
3012 }
3013
3014 acpi_SetSleepState(sc, acpi_state);
3015 break;
3016 default:
3017 error = EINVAL;
3018 goto out;
3019 }
3020
3021out:
3022 return (error);
3023}
3024
3025static void
3026acpi_pm_register(void *arg)
3027{
3028 if (!cold || resource_disabled("acpi", 0))
3029 return;
3030
3031 power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, NULL);
3032}
3033
ba39e2e0 3034SYSINIT(power, SI_BOOT2_KLD, SI_ORDER_ANY, acpi_pm_register, 0);