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