File:  [DragonFly] / src / sys / dev / acpica5 / acpi.c
Revision 1.3: download - view: text, annotated - select for diffs
Thu May 13 23:49:14 2004 UTC (9 years, 11 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
device switch 1/many: Remove d_autoq, add d_clone (where d_autoq was).

d_autoq was used to allow the device port dispatch to mix old-style synchronous
calls with new style messaging calls within a particular device.  It was never
used for that purpose.

d_clone will be more fully implemented as work continues.  We are going to
install d_port in the dev_t (struct specinfo) structure itself and d_clone
will be needed to allow devices to 'revector' the port on a minor-number
by minor-number basis, in particular allowing minor numbers to be directly
dispatched to distinct threads.  This is something we will be needing later
on.

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