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