File:  [DragonFly] / src / sys / dev / acpica5 / acpi.c
Revision 1.4: download - view: text, annotated - select for diffs
Wed May 19 22:52:40 2004 UTC (10 years, 7 months ago) by dillon
Branches: MAIN
CVS tags: HEAD
Device layer rollup commit.

* cdevsw_add() is now required.  cdevsw_add() and cdevsw_remove() may specify
  a mask/match indicating the range of supported minor numbers.  Multiple
  cdevsw_add()'s using the same major number, but distinctly different
  ranges, may be issued.  All devices that failed to call cdevsw_add() before
  now do.

* cdevsw_remove() now automatically marks all devices within its supported
  range as being destroyed.

* vnode->v_rdev is no longer resolved when the vnode is created.  Instead,
  only v_udev (a newly added field) is resolved.  v_rdev is resolved when
  the vnode is opened and cleared on the last close.

* A great deal of code was making rather dubious assumptions with regards
  to the validity of devices associated with vnodes, primarily due to
  the persistence of a device structure due to being indexed by (major, minor)
  instead of by (cdevsw, major, minor).  In particular, if you run a program
  which connects to a USB device and then you pull the USB device and plug
  it back in, the vnode subsystem will continue to believe that the device
  is open when, in fact, it isn't (because it was destroyed and recreated).

  In particular, note that all the VFS mount procedures now check devices
  via v_udev instead of v_rdev prior to calling VOP_OPEN(), since v_rdev
  is NULL prior to the first open.

* The disk layer's device interaction has been rewritten.  The disk layer
  (i.e. the slice and disklabel management layer) no longer overloads
  its data onto the device structure representing the underlying physical
  disk.  Instead, the disk layer uses the new cdevsw_add() functionality
  to register its own cdevsw using the underlying device's major number,
  and simply does NOT register the underlying device's cdevsw.  No
  confusion is created because the device hash is now based on
  (cdevsw,major,minor) rather then (major,minor).

  NOTE: This also means that underlying raw disk devices may use the entire
  device minor number instead of having to reserve the bits used by the disk
  layer, and also means that can we (theoretically) stack a fully
  disklabel-supported 'disk' on top of any block device.

* The new reference counting scheme prevents this by associating a device
  with a cdevsw and disconnecting the device from its cdevsw when the cdevsw
  is removed.  Additionally, all udev2dev() lookups run through the cdevsw
  mask/match and only successfully find devices still associated with an
  active cdevsw.

* Major work on MFS:  MFS no longer shortcuts vnode and device creation.  It
  now creates a real vnode and a real device and implements real open and
  close VOPs.  Additionally, due to the disk layer changes, MFS is no longer
  limited to 255 mounts.  The new limit is 16 million.  Since MFS creates a
  real device node, mount_mfs will now create a real /dev/mfs<PID> device
  that can be read from userland (e.g. so you can dump an MFS filesystem).

* BUF AND DEVICE STRATEGY changes.  The struct buf contains a b_dev field.
  In order to properly handle stacked devices we now require that the b_dev
  field be initialized before the device strategy routine is called.  This
  required some additional work in various VFS implementations.  To enforce
  this requirement, biodone() now sets b_dev to NODEV.  The new disk layer
  will adjust b_dev before forwarding a request to the actual physical
  device.

* A bug in the ISO CD boot sequence which resulted in a panic has been fixed.

Testing by: lots of people, but David Rhodus found the most aggregious bugs.

    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.4 2004/05/19 22:52:40 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:     cdevsw_add(&acpi_cdevsw, 0, 0);
  527:     sc->acpi_dev_t = make_dev(&acpi_cdevsw, 0, UID_ROOT, GID_WHEEL, 0644,
  528: 			      "acpi");
  529:     sc->acpi_dev_t->si_drv1 = sc;
  530: 
  531: #ifdef ACPI_DEBUGGER
  532:     debugpoint = getenv("debug.acpi.debugger");
  533:     if (debugpoint) {
  534: 	if (strcmp(debugpoint, "running") == 0)
  535: 	    acpi_EnterDebugger();
  536: 	freeenv(debugpoint);
  537:     }
  538: #endif
  539: 
  540: #ifdef ACPI_USE_THREADS
  541:     if ((error = acpi_task_thread_init()))
  542: 	goto out;
  543: #endif
  544: 
  545:     if ((error = acpi_machdep_init(dev)))
  546: 	goto out;
  547: 
  548:     /* Register ACPI again to pass the correct argument of pm_func. */
  549:     power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, sc);
  550: 
  551:     if (!acpi_disabled("bus"))
  552: 	acpi_probe_children(dev);
  553: 
  554:     error = 0;
  555: 
  556:  out:
  557:     ACPI_UNLOCK;
  558:     return_VALUE (error);
  559: }
  560: 
  561: /*
  562:  * Handle a new device being added
  563:  */
  564: static device_t
  565: acpi_add_child(device_t bus, int order, const char *name, int unit)
  566: {
  567:     struct acpi_device	*ad;
  568:     device_t		child;
  569: 
  570:     ad = malloc(sizeof(*ad), M_ACPIDEV, M_INTWAIT | M_ZERO);
  571: 
  572:     resource_list_init(&ad->ad_rl);
  573:     
  574:     child = device_add_child_ordered(bus, order, name, unit);
  575:     if (child != NULL)
  576: 	device_set_ivars(child, ad);
  577:     return (child);
  578: }
  579: 
  580: static int
  581: acpi_print_child(device_t bus, device_t child)
  582: {
  583:     struct acpi_device	 *adev = device_get_ivars(child);
  584:     struct resource_list *rl = &adev->ad_rl;
  585:     int retval = 0;
  586: 
  587:     retval += bus_print_child_header(bus, child);
  588:     retval += resource_list_print_type(rl, "port",  SYS_RES_IOPORT, "%#lx");
  589:     retval += resource_list_print_type(rl, "iomem", SYS_RES_MEMORY, "%#lx");
  590:     retval += resource_list_print_type(rl, "irq",   SYS_RES_IRQ,    "%ld");
  591:     retval += resource_list_print_type(rl, "drq",   SYS_RES_DRQ,    "%ld");
  592:     retval += bus_print_child_footer(bus, child);
  593: 
  594:     return (retval);
  595: }
  596: 
  597: 
  598: /*
  599:  * Handle per-device ivars
  600:  */
  601: static int
  602: acpi_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
  603: {
  604:     struct acpi_device	*ad;
  605: 
  606:     if ((ad = device_get_ivars(child)) == NULL) {
  607: 	printf("device has no ivars\n");
  608: 	return (ENOENT);
  609:     }
  610: 
  611:     /* ACPI and ISA compatibility ivars */
  612:     switch(index) {
  613:     case ACPI_IVAR_HANDLE:
  614: 	*(ACPI_HANDLE *)result = ad->ad_handle;
  615: 	break;
  616:     case ACPI_IVAR_MAGIC:
  617: 	*(int *)result = ad->ad_magic;
  618: 	break;
  619:     case ACPI_IVAR_PRIVATE:
  620: 	*(void **)result = ad->ad_private;
  621: 	break;
  622:     case ISA_IVAR_VENDORID:
  623:     case ISA_IVAR_SERIAL:
  624:     case ISA_IVAR_COMPATID:
  625: 	*(int *)result = -1;
  626: 	break;
  627:     case ISA_IVAR_LOGICALID:
  628: 	*(int *)result = acpi_isa_get_logicalid(child);
  629: 	break;
  630:     default:
  631: 	return (ENOENT);
  632:     }
  633: 
  634:     return (0);
  635: }
  636: 
  637: static int
  638: acpi_write_ivar(device_t dev, device_t child, int index, uintptr_t value)
  639: {
  640:     struct acpi_device	*ad;
  641: 
  642:     if ((ad = device_get_ivars(child)) == NULL) {
  643: 	printf("device has no ivars\n");
  644: 	return (ENOENT);
  645:     }
  646: 
  647:     switch(index) {
  648:     case ACPI_IVAR_HANDLE:
  649: 	ad->ad_handle = (ACPI_HANDLE)value;
  650: 	break;
  651:     case ACPI_IVAR_MAGIC:
  652: 	ad->ad_magic = (int)value;
  653: 	break;
  654:     case ACPI_IVAR_PRIVATE:
  655: 	ad->ad_private = (void *)value;
  656: 	break;
  657:     default:
  658: 	panic("bad ivar write request (%d)", index);
  659: 	return (ENOENT);
  660:     }
  661: 
  662:     return (0);
  663: }
  664: 
  665: ACPI_HANDLE
  666: acpi_get_handle(device_t dev)
  667: {
  668:     uintptr_t up;
  669:     ACPI_HANDLE	h;
  670: 
  671:     if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_HANDLE, &up))
  672: 	return(NULL);
  673:     h = (ACPI_HANDLE)up;
  674:     return (h);
  675: }
  676: 	    
  677: int
  678: acpi_set_handle(device_t dev, ACPI_HANDLE h)
  679: {
  680:     uintptr_t up;
  681: 
  682:     up = (uintptr_t)h;
  683:     return (BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_HANDLE, up));
  684: }
  685: 	    
  686: int
  687: acpi_get_magic(device_t dev)
  688: {
  689:     uintptr_t up;
  690:     int	m;
  691: 
  692:     if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_MAGIC, &up))
  693: 	return(0);
  694:     m = (int)up;
  695:     return (m);
  696: }
  697: 
  698: int
  699: acpi_set_magic(device_t dev, int m)
  700: {
  701:     uintptr_t up;
  702: 
  703:     up = (uintptr_t)m;
  704:     return (BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_MAGIC, up));
  705: }
  706: 
  707: void *
  708: acpi_get_private(device_t dev)
  709: {
  710:     uintptr_t up;
  711:     void *p;
  712: 
  713:     if (BUS_READ_IVAR(device_get_parent(dev), dev, ACPI_IVAR_PRIVATE, &up))
  714: 	return (NULL);
  715:     p = (void *)up;
  716:     return (p);
  717: }
  718: 
  719: int
  720: acpi_set_private(device_t dev, void *p)
  721: {
  722:     uintptr_t up;
  723: 
  724:     up = (uintptr_t)p;
  725:     return (BUS_WRITE_IVAR(device_get_parent(dev), dev, ACPI_IVAR_PRIVATE, up));
  726: }
  727: 
  728: ACPI_OBJECT_TYPE
  729: acpi_get_type(device_t dev)
  730: {
  731:     ACPI_HANDLE		h;
  732:     ACPI_OBJECT_TYPE	t;
  733: 
  734:     if ((h = acpi_get_handle(dev)) == NULL)
  735: 	return (ACPI_TYPE_NOT_FOUND);
  736:     if (AcpiGetType(h, &t) != AE_OK)
  737: 	return (ACPI_TYPE_NOT_FOUND);
  738:     return (t);
  739: }
  740: 
  741: /*
  742:  * Handle child resource allocation/removal
  743:  */
  744: static int
  745: acpi_set_resource(device_t dev, device_t child, int type, int rid,
  746: 		  u_long start, u_long count)
  747: {
  748:     struct acpi_device		*ad = device_get_ivars(child);
  749:     struct resource_list	*rl = &ad->ad_rl;
  750: 
  751:     resource_list_add(rl, type, rid, start, start + count -1, count);
  752: 
  753:     return(0);
  754: }
  755: 
  756: static int
  757: acpi_get_resource(device_t dev, device_t child, int type, int rid,
  758: 		  u_long *startp, u_long *countp)
  759: {
  760:     struct acpi_device		*ad = device_get_ivars(child);
  761:     struct resource_list	*rl = &ad->ad_rl;
  762:     struct resource_list_entry	*rle;
  763: 
  764:     rle = resource_list_find(rl, type, rid);
  765:     if (!rle)
  766: 	return(ENOENT);
  767: 	
  768:     if (startp)
  769: 	*startp = rle->start;
  770:     if (countp)
  771: 	*countp = rle->count;
  772: 
  773:     return (0);
  774: }
  775: 
  776: static struct resource *
  777: acpi_alloc_resource(device_t bus, device_t child, int type, int *rid,
  778: 		    u_long start, u_long end, u_long count, u_int flags)
  779: {
  780:     struct acpi_device *ad = device_get_ivars(child);
  781:     struct resource_list *rl = &ad->ad_rl;
  782: 
  783:     return (resource_list_alloc(rl, bus, child, type, rid, start, end, count,
  784: 	    flags));
  785: }
  786: 
  787: static int
  788: acpi_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r)
  789: {
  790:     struct acpi_device *ad = device_get_ivars(child);
  791:     struct resource_list *rl = &ad->ad_rl;
  792: 
  793:     return (resource_list_release(rl, bus, child, type, rid, r));
  794: }
  795: 
  796: /* Allocate an IO port or memory resource, given its GAS. */
  797: struct resource *
  798: acpi_bus_alloc_gas(device_t dev, int *rid, ACPI_GENERIC_ADDRESS *gas)
  799: {
  800:     int type;
  801: 
  802:     if (gas == NULL || !ACPI_VALID_ADDRESS(gas->Address) ||
  803: 	gas->RegisterBitWidth < 8)
  804: 	return (NULL);
  805: 
  806:     switch (gas->AddressSpaceId) {
  807:     case ACPI_ADR_SPACE_SYSTEM_MEMORY:
  808: 	type = SYS_RES_MEMORY;
  809: 	break;
  810:     case ACPI_ADR_SPACE_SYSTEM_IO:
  811: 	type = SYS_RES_IOPORT;
  812: 	break;
  813:     default:
  814: 	return (NULL);
  815:     }
  816: 
  817:     bus_set_resource(dev, type, *rid, gas->Address, gas->RegisterBitWidth / 8);
  818:     return (bus_alloc_resource(dev, type, rid, 0, ~0, 1, RF_ACTIVE));
  819: }
  820: 
  821: /*
  822:  * Handle ISA-like devices probing for a PnP ID to match.
  823:  */
  824: #define PNP_EISAID(s)				\
  825: 	((((s[0] - '@') & 0x1f) << 2)		\
  826: 	 | (((s[1] - '@') & 0x18) >> 3)		\
  827: 	 | (((s[1] - '@') & 0x07) << 13)	\
  828: 	 | (((s[2] - '@') & 0x1f) << 8)		\
  829: 	 | (PNP_HEXTONUM(s[4]) << 16)		\
  830: 	 | (PNP_HEXTONUM(s[3]) << 20)		\
  831: 	 | (PNP_HEXTONUM(s[6]) << 24)		\
  832: 	 | (PNP_HEXTONUM(s[5]) << 28))
  833: 
  834: static uint32_t
  835: acpi_isa_get_logicalid(device_t dev)
  836: {
  837:     ACPI_DEVICE_INFO	*devinfo;
  838:     ACPI_BUFFER		buf;
  839:     ACPI_HANDLE		h;
  840:     ACPI_STATUS		error;
  841:     u_int32_t		pnpid;
  842:     ACPI_LOCK_DECL;
  843: 
  844:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  845: 
  846:     pnpid = 0;
  847:     buf.Pointer = NULL;
  848:     buf.Length = ACPI_ALLOCATE_BUFFER;
  849: 
  850:     ACPI_LOCK;
  851:     
  852:     /* Fetch and validate the HID. */
  853:     if ((h = acpi_get_handle(dev)) == NULL)
  854: 	goto out;
  855:     error = AcpiGetObjectInfo(h, &buf);
  856:     if (ACPI_FAILURE(error))
  857: 	goto out;
  858:     devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
  859: 
  860:     if ((devinfo->Valid & ACPI_VALID_HID) != 0)
  861: 	pnpid = PNP_EISAID(devinfo->HardwareId.Value);
  862: 
  863: out:
  864:     if (buf.Pointer != NULL)
  865: 	AcpiOsFree(buf.Pointer);
  866:     ACPI_UNLOCK;
  867:     return_VALUE (pnpid);
  868: }
  869: 
  870: static int
  871: acpi_isa_get_compatid(device_t dev, uint32_t *cids, int count)
  872: {
  873:     ACPI_DEVICE_INFO	*devinfo;
  874:     ACPI_BUFFER		buf;
  875:     ACPI_HANDLE		h;
  876:     ACPI_STATUS		error;
  877:     uint32_t		*pnpid;
  878:     int			valid, i;
  879:     ACPI_LOCK_DECL;
  880: 
  881:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  882: 
  883:     pnpid = cids;
  884:     valid = 0;
  885:     buf.Pointer = NULL;
  886:     buf.Length = ACPI_ALLOCATE_BUFFER;
  887: 
  888:     ACPI_LOCK;
  889:     
  890:     /* Fetch and validate the CID */
  891:     if ((h = acpi_get_handle(dev)) == NULL)
  892: 	goto out;
  893:     error = AcpiGetObjectInfo(h, &buf);
  894:     if (ACPI_FAILURE(error))
  895: 	goto out;
  896:     devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
  897:     if ((devinfo->Valid & ACPI_VALID_CID) == 0)
  898: 	goto out;
  899: 
  900:     if (devinfo->CompatibilityId.Count < count)
  901: 	count = devinfo->CompatibilityId.Count;
  902:     for (i = 0; i < count; i++) {
  903: 	if (strncmp(devinfo->CompatibilityId.Id[i].Value, "PNP", 3) != 0)
  904: 	    continue;
  905: 	*pnpid++ = PNP_EISAID(devinfo->CompatibilityId.Id[i].Value);
  906: 	valid++;
  907:     }
  908: 
  909: out:
  910:     if (buf.Pointer != NULL)
  911: 	AcpiOsFree(buf.Pointer);
  912:     ACPI_UNLOCK;
  913:     return_VALUE (valid);
  914: }
  915: 
  916: static int
  917: acpi_isa_pnp_probe(device_t bus, device_t child, struct isa_pnp_id *ids)
  918: {
  919:     int			result, cid_count, i;
  920:     uint32_t		lid, cids[8];
  921: 
  922:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  923: 
  924:     /*
  925:      * ISA-style drivers attached to ACPI may persist and
  926:      * probe manually if we return ENOENT.  We never want
  927:      * that to happen, so don't ever return it.
  928:      */
  929:     result = ENXIO;
  930: 
  931:     /* Scan the supplied IDs for a match */
  932:     lid = acpi_isa_get_logicalid(child);
  933:     cid_count = acpi_isa_get_compatid(child, cids, 8);
  934:     while (ids && ids->ip_id) {
  935: 	if (lid == ids->ip_id) {
  936: 	    result = 0;
  937: 	    goto out;
  938: 	}
  939: 	for (i = 0; i < cid_count; i++) {
  940: 	    if (cids[i] == ids->ip_id) {
  941: 		result = 0;
  942: 		goto out;
  943: 	    }
  944: 	}
  945: 	ids++;
  946:     }
  947: 
  948:  out:
  949:     return_VALUE (result);
  950: }
  951: 
  952: /*
  953:  * Scan relevant portions of the ACPI namespace and attach child devices.
  954:  *
  955:  * Note that we only expect to find devices in the \_PR_, \_TZ_, \_SI_ and
  956:  * \_SB_ scopes, and \_PR_ and \_TZ_ become obsolete in the ACPI 2.0 spec.
  957:  */
  958: static void
  959: acpi_probe_children(device_t bus)
  960: {
  961:     ACPI_HANDLE	parent;
  962:     ACPI_STATUS	status;
  963:     static char	*scopes[] = {"\\_PR_", "\\_TZ_", "\\_SI", "\\_SB_", NULL};
  964:     int		i;
  965: 
  966:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
  967:     ACPI_ASSERTLOCK;
  968: 
  969:     /* Create any static children by calling device identify methods. */
  970:     ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "device identify routines\n"));
  971:     bus_generic_probe(bus);
  972: 
  973:     /*
  974:      * Scan the namespace and insert placeholders for all the devices that
  975:      * we find.
  976:      *
  977:      * Note that we use AcpiWalkNamespace rather than AcpiGetDevices because
  978:      * we want to create nodes for all devices, not just those that are
  979:      * currently present. (This assumes that we don't want to create/remove
  980:      * devices as they appear, which might be smarter.)
  981:      */
  982:     ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "namespace scan\n"));
  983:     for (i = 0; scopes[i] != NULL; i++) {
  984: 	status = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent);
  985: 	if (ACPI_SUCCESS(status)) {
  986: 	    AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100, acpi_probe_child,
  987: 			      bus, NULL);
  988: 	}
  989:     }
  990: 
  991:     /*
  992:      * Scan all of the child devices we have created and let them probe/attach.
  993:      */
  994:     ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "first bus_generic_attach\n"));
  995:     bus_generic_attach(bus);
  996: 
  997:     /*
  998:      * Some of these children may have attached others as part of their attach
  999:      * process (eg. the root PCI bus driver), so rescan.
 1000:      */
 1001:     ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "second bus_generic_attach\n"));
 1002:     bus_generic_attach(bus);
 1003: 
 1004:     ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "done attaching children\n"));
 1005:     return_VOID;
 1006: }
 1007: 
 1008: /*
 1009:  * Evaluate a child device and determine whether we might attach a device to
 1010:  * it.
 1011:  */
 1012: static ACPI_STATUS
 1013: acpi_probe_child(ACPI_HANDLE handle, UINT32 level, void *context, void **status)
 1014: {
 1015:     ACPI_OBJECT_TYPE	type;
 1016:     device_t		child, bus = (device_t)context;
 1017: 
 1018:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1019: 
 1020:     /* Skip this device if we think we'll have trouble with it. */
 1021:     if (acpi_avoid(handle))
 1022: 	return_ACPI_STATUS (AE_OK);
 1023: 
 1024:     if (ACPI_SUCCESS(AcpiGetType(handle, &type))) {
 1025: 	switch(type) {
 1026: 	case ACPI_TYPE_DEVICE:
 1027: 	case ACPI_TYPE_PROCESSOR:
 1028: 	case ACPI_TYPE_THERMAL:
 1029: 	case ACPI_TYPE_POWER:
 1030: 	    if (acpi_disabled("children"))
 1031: 		break;
 1032: 
 1033: 	    /* 
 1034: 	     * Create a placeholder device for this node.  Sort the placeholder
 1035: 	     * so that the probe/attach passes will run breadth-first.
 1036: 	     */
 1037: 	    ACPI_DEBUG_PRINT((ACPI_DB_OBJECTS, "scanning '%s'\n",
 1038: 			     acpi_name(handle)));
 1039: 	    child = BUS_ADD_CHILD(bus, level * 10, NULL, -1);
 1040: 	    if (child == NULL)
 1041: 		break;
 1042: 	    acpi_set_handle(child, handle);
 1043: 
 1044: 	    /*
 1045: 	     * Check that the device is present.  If it's not present,
 1046: 	     * leave it disabled (so that we have a device_t attached to
 1047: 	     * the handle, but we don't probe it).
 1048: 	     */
 1049: 	    if (type == ACPI_TYPE_DEVICE && !acpi_DeviceIsPresent(child)) {
 1050: 		device_disable(child);
 1051: 		break;
 1052: 	    }
 1053: 
 1054: 	    /*
 1055: 	     * Get the device's resource settings and attach them.
 1056: 	     * Note that if the device has _PRS but no _CRS, we need
 1057: 	     * to decide when it's appropriate to try to configure the
 1058: 	     * device.  Ignore the return value here; it's OK for the
 1059: 	     * device not to have any resources.
 1060: 	     */
 1061: 	    acpi_parse_resources(child, handle, &acpi_res_parse_set);
 1062: 
 1063: 	    /* If we're debugging, probe/attach now rather than later */
 1064: 	    ACPI_DEBUG_EXEC(device_probe_and_attach(child));
 1065: 	    break;
 1066: 	}
 1067:     }
 1068: 
 1069:     return_ACPI_STATUS (AE_OK);
 1070: }
 1071: 
 1072: static void
 1073: acpi_shutdown_pre_sync(void *arg, int howto)
 1074: {
 1075:     struct acpi_softc *sc = arg;
 1076: 
 1077:     ACPI_ASSERTLOCK;
 1078: 
 1079:     /*
 1080:      * Disable all ACPI events before soft off, otherwise the system
 1081:      * will be turned on again on some laptops.
 1082:      *
 1083:      * XXX this should probably be restricted to masking some events just
 1084:      *     before powering down, since we may still need ACPI during the
 1085:      *     shutdown process.
 1086:      */
 1087:     if (sc->acpi_disable_on_poweroff)
 1088: 	acpi_Disable(sc);
 1089: }
 1090: 
 1091: static void
 1092: acpi_shutdown_final(void *arg, int howto)
 1093: {
 1094:     ACPI_STATUS	status;
 1095: 
 1096:     ACPI_ASSERTLOCK;
 1097: 
 1098:     if ((howto & RB_POWEROFF) != 0) {
 1099: 	printf("Powering system off using ACPI\n");
 1100: 	status = AcpiEnterSleepStatePrep(acpi_off_state);
 1101: 	if (ACPI_FAILURE(status)) {
 1102: 	    printf("AcpiEnterSleepStatePrep failed - %s\n",
 1103: 		   AcpiFormatException(status));
 1104: 	    return;
 1105: 	}
 1106: 	ACPI_DISABLE_IRQS();
 1107: 	status = AcpiEnterSleepState(acpi_off_state);
 1108: 	if (ACPI_FAILURE(status)) {
 1109: 	    printf("ACPI power-off failed - %s\n", AcpiFormatException(status));
 1110: 	} else {
 1111: 	    DELAY(1000000);
 1112: 	    printf("ACPI power-off failed - timeout\n");
 1113: 	}
 1114:     } else {
 1115: 	printf("Shutting down ACPI\n");
 1116: 	AcpiTerminate();
 1117:     }
 1118: }
 1119: 
 1120: static void
 1121: acpi_enable_fixed_events(struct acpi_softc *sc)
 1122: {
 1123:     static int	first_time = 1;
 1124: 
 1125:     ACPI_ASSERTLOCK;
 1126: 
 1127:     /* Enable and clear fixed events and install handlers. */
 1128:     if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
 1129: 	AcpiClearEvent(ACPI_EVENT_POWER_BUTTON);
 1130: 	AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
 1131: 				     acpi_event_power_button_sleep, sc);
 1132: 	if (first_time)
 1133: 	    device_printf(sc->acpi_dev, "Power Button (fixed)\n");
 1134:     }
 1135:     if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
 1136: 	AcpiClearEvent(ACPI_EVENT_SLEEP_BUTTON);
 1137: 	AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
 1138: 				     acpi_event_sleep_button_sleep, sc);
 1139: 	if (first_time)
 1140: 	    device_printf(sc->acpi_dev, "Sleep Button (fixed)\n");
 1141:     }
 1142: 
 1143:     first_time = 0;
 1144: }
 1145: 
 1146: /*
 1147:  * Returns true if the device is actually present and should
 1148:  * be attached to.  This requires the present, enabled, UI-visible 
 1149:  * and diagnostics-passed bits to be set.
 1150:  */
 1151: BOOLEAN
 1152: acpi_DeviceIsPresent(device_t dev)
 1153: {
 1154:     ACPI_DEVICE_INFO	*devinfo;
 1155:     ACPI_HANDLE		h;
 1156:     ACPI_BUFFER		buf;
 1157:     ACPI_STATUS		error;
 1158:     int			ret;
 1159: 
 1160:     ACPI_ASSERTLOCK;
 1161:     
 1162:     ret = FALSE;
 1163:     if ((h = acpi_get_handle(dev)) == NULL)
 1164: 	return (FALSE);
 1165:     buf.Pointer = NULL;
 1166:     buf.Length = ACPI_ALLOCATE_BUFFER;
 1167:     error = AcpiGetObjectInfo(h, &buf);
 1168:     if (ACPI_FAILURE(error))
 1169: 	return (FALSE);
 1170:     devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
 1171: 
 1172:     /* If no _STA method, must be present */
 1173:     if ((devinfo->Valid & ACPI_VALID_STA) == 0)
 1174: 	ret = TRUE;
 1175: 
 1176:     /* Return true for 'present' and 'functioning' */
 1177:     if ((devinfo->CurrentStatus & 0x9) == 0x9)
 1178: 	ret = TRUE;
 1179: 
 1180:     AcpiOsFree(buf.Pointer);
 1181:     return (ret);
 1182: }
 1183: 
 1184: /*
 1185:  * Returns true if the battery is actually present and inserted.
 1186:  */
 1187: BOOLEAN
 1188: acpi_BatteryIsPresent(device_t dev)
 1189: {
 1190:     ACPI_DEVICE_INFO	*devinfo;
 1191:     ACPI_HANDLE		h;
 1192:     ACPI_BUFFER		buf;
 1193:     ACPI_STATUS		error;
 1194:     int			ret;
 1195: 
 1196:     ACPI_ASSERTLOCK;
 1197:     
 1198:     ret = FALSE;
 1199:     if ((h = acpi_get_handle(dev)) == NULL)
 1200: 	return (FALSE);
 1201:     buf.Pointer = NULL;
 1202:     buf.Length = ACPI_ALLOCATE_BUFFER;
 1203:     error = AcpiGetObjectInfo(h, &buf);
 1204:     if (ACPI_FAILURE(error))
 1205: 	return (FALSE);
 1206:     devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
 1207: 
 1208:     /* If no _STA method, must be present */
 1209:     if ((devinfo->Valid & ACPI_VALID_STA) == 0)
 1210: 	ret = TRUE;
 1211: 
 1212:     /* Return true for 'present' and 'functioning' */
 1213:     if ((devinfo->CurrentStatus & 0x19) == 0x19)
 1214: 	ret = TRUE;
 1215: 
 1216:     AcpiOsFree(buf.Pointer);
 1217:     return (ret);
 1218: }
 1219: 
 1220: /*
 1221:  * Match a HID string against a device
 1222:  */
 1223: BOOLEAN
 1224: acpi_MatchHid(device_t dev, char *hid) 
 1225: {
 1226:     ACPI_DEVICE_INFO	*devinfo;
 1227:     ACPI_HANDLE		h;
 1228:     ACPI_BUFFER		buf;
 1229:     ACPI_STATUS		error;
 1230:     int			ret, i;
 1231: 
 1232:     ACPI_ASSERTLOCK;
 1233: 
 1234:     ret = FALSE;
 1235:     if (hid == NULL)
 1236: 	return (FALSE);
 1237:     if ((h = acpi_get_handle(dev)) == NULL)
 1238: 	return (FALSE);
 1239:     buf.Pointer = NULL;
 1240:     buf.Length = ACPI_ALLOCATE_BUFFER;
 1241:     error = AcpiGetObjectInfo(h, &buf);
 1242:     if (ACPI_FAILURE(error))
 1243: 	return (FALSE);
 1244:     devinfo = (ACPI_DEVICE_INFO *)buf.Pointer;
 1245: 
 1246:     if ((devinfo->Valid & ACPI_VALID_HID) != 0 &&
 1247: 	strcmp(hid, devinfo->HardwareId.Value) == 0)
 1248: 	    ret = TRUE;
 1249:     else if ((devinfo->Valid & ACPI_VALID_CID) != 0) {
 1250: 	for (i = 0; i < devinfo->CompatibilityId.Count; i++) {
 1251: 	    if (strcmp(hid, devinfo->CompatibilityId.Id[i].Value) == 0) {
 1252: 		ret = TRUE;
 1253: 		break;
 1254: 	    }
 1255: 	}
 1256:     }
 1257: 
 1258:     AcpiOsFree(buf.Pointer);
 1259:     return (ret);
 1260: }
 1261: 
 1262: /*
 1263:  * Return the handle of a named object within our scope, ie. that of (parent)
 1264:  * or one if its parents.
 1265:  */
 1266: ACPI_STATUS
 1267: acpi_GetHandleInScope(ACPI_HANDLE parent, char *path, ACPI_HANDLE *result)
 1268: {
 1269:     ACPI_HANDLE		r;
 1270:     ACPI_STATUS		status;
 1271: 
 1272:     ACPI_ASSERTLOCK;
 1273: 
 1274:     /* Walk back up the tree to the root */
 1275:     for (;;) {
 1276: 	status = AcpiGetHandle(parent, path, &r);
 1277: 	if (ACPI_SUCCESS(status)) {
 1278: 	    *result = r;
 1279: 	    return (AE_OK);
 1280: 	}
 1281: 	if (status != AE_NOT_FOUND)
 1282: 	    return (AE_OK);
 1283: 	if (ACPI_FAILURE(AcpiGetParent(parent, &r)))
 1284: 	    return (AE_NOT_FOUND);
 1285: 	parent = r;
 1286:     }
 1287: }
 1288: 
 1289: /*
 1290:  * Allocate a buffer with a preset data size.
 1291:  */
 1292: ACPI_BUFFER *
 1293: acpi_AllocBuffer(int size)
 1294: {
 1295:     ACPI_BUFFER	*buf;
 1296: 
 1297:     buf = malloc(size + sizeof(*buf), M_ACPIDEV, M_INTWAIT);
 1298:     buf->Length = size;
 1299:     buf->Pointer = (void *)(buf + 1);
 1300:     return (buf);
 1301: }
 1302: 
 1303: /*
 1304:  * Evaluate a path that should return an integer.
 1305:  */
 1306: ACPI_STATUS
 1307: acpi_EvaluateInteger(ACPI_HANDLE handle, char *path, int *number)
 1308: {
 1309:     ACPI_STATUS	status;
 1310:     ACPI_BUFFER	buf;
 1311:     ACPI_OBJECT	param;
 1312: 
 1313:     ACPI_ASSERTLOCK;
 1314: 
 1315:     if (handle == NULL)
 1316: 	handle = ACPI_ROOT_OBJECT;
 1317: 
 1318:     /*
 1319:      * Assume that what we've been pointed at is an Integer object, or
 1320:      * a method that will return an Integer.
 1321:      */
 1322:     buf.Pointer = &param;
 1323:     buf.Length = sizeof(param);
 1324:     status = AcpiEvaluateObject(handle, path, NULL, &buf);
 1325:     if (ACPI_SUCCESS(status)) {
 1326: 	if (param.Type == ACPI_TYPE_INTEGER)
 1327: 	    *number = param.Integer.Value;
 1328: 	else
 1329: 	    status = AE_TYPE;
 1330:     }
 1331: 
 1332:     /* 
 1333:      * In some applications, a method that's expected to return an Integer
 1334:      * may instead return a Buffer (probably to simplify some internal
 1335:      * arithmetic).  We'll try to fetch whatever it is, and if it's a Buffer,
 1336:      * convert it into an Integer as best we can.
 1337:      *
 1338:      * This is a hack.
 1339:      */
 1340:     if (status == AE_BUFFER_OVERFLOW) {
 1341: 	if ((buf.Pointer = AcpiOsAllocate(buf.Length)) == NULL) {
 1342: 	    status = AE_NO_MEMORY;
 1343: 	} else {
 1344: 	    status = AcpiEvaluateObject(handle, path, NULL, &buf);
 1345: 	    if (ACPI_SUCCESS(status))
 1346: 		status = acpi_ConvertBufferToInteger(&buf, number);
 1347: 	    AcpiOsFree(buf.Pointer);
 1348: 	}
 1349:     }
 1350:     return (status);
 1351: }
 1352: 
 1353: ACPI_STATUS
 1354: acpi_ConvertBufferToInteger(ACPI_BUFFER *bufp, int *number)
 1355: {
 1356:     ACPI_OBJECT	*p;
 1357:     int		i;
 1358: 
 1359:     p = (ACPI_OBJECT *)bufp->Pointer;
 1360:     if (p->Type == ACPI_TYPE_INTEGER) {
 1361: 	*number = p->Integer.Value;
 1362: 	return (AE_OK);
 1363:     }
 1364:     if (p->Type != ACPI_TYPE_BUFFER)
 1365: 	return (AE_TYPE);
 1366:     if (p->Buffer.Length > sizeof(int))
 1367: 	return (AE_BAD_DATA);
 1368: 
 1369:     *number = 0;
 1370:     for (i = 0; i < p->Buffer.Length; i++)
 1371: 	*number += (*(p->Buffer.Pointer + i) << (i * 8));
 1372:     return (AE_OK);
 1373: }
 1374: 
 1375: /*
 1376:  * Iterate over the elements of an a package object, calling the supplied
 1377:  * function for each element.
 1378:  *
 1379:  * XXX possible enhancement might be to abort traversal on error.
 1380:  */
 1381: ACPI_STATUS
 1382: acpi_ForeachPackageObject(ACPI_OBJECT *pkg,
 1383: 	void (*func)(ACPI_OBJECT *comp, void *arg), void *arg)
 1384: {
 1385:     ACPI_OBJECT	*comp;
 1386:     int		i;
 1387:     
 1388:     if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE)
 1389: 	return (AE_BAD_PARAMETER);
 1390: 
 1391:     /* Iterate over components */
 1392:     i = 0;
 1393:     comp = pkg->Package.Elements;
 1394:     for (; i < pkg->Package.Count; i++, comp++)
 1395: 	func(comp, arg);
 1396: 
 1397:     return (AE_OK);
 1398: }
 1399: 
 1400: /*
 1401:  * Find the (index)th resource object in a set.
 1402:  */
 1403: ACPI_STATUS
 1404: acpi_FindIndexedResource(ACPI_BUFFER *buf, int index, ACPI_RESOURCE **resp)
 1405: {
 1406:     ACPI_RESOURCE	*rp;
 1407:     int			i;
 1408: 
 1409:     rp = (ACPI_RESOURCE *)buf->Pointer;
 1410:     i = index;
 1411:     while (i-- > 0) {
 1412: 	/* Range check */	
 1413: 	if (rp > (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
 1414: 	    return (AE_BAD_PARAMETER);
 1415: 
 1416: 	/* Check for terminator */
 1417: 	if (rp->Id == ACPI_RSTYPE_END_TAG || rp->Length == 0)
 1418: 	    return (AE_NOT_FOUND);
 1419: 	rp = ACPI_NEXT_RESOURCE(rp);
 1420:     }
 1421:     if (resp != NULL)
 1422: 	*resp = rp;
 1423: 
 1424:     return (AE_OK);
 1425: }
 1426: 
 1427: /*
 1428:  * Append an ACPI_RESOURCE to an ACPI_BUFFER.
 1429:  *
 1430:  * Given a pointer to an ACPI_RESOURCE structure, expand the ACPI_BUFFER
 1431:  * provided to contain it.  If the ACPI_BUFFER is empty, allocate a sensible
 1432:  * backing block.  If the ACPI_RESOURCE is NULL, return an empty set of
 1433:  * resources.
 1434:  */
 1435: #define ACPI_INITIAL_RESOURCE_BUFFER_SIZE	512
 1436: 
 1437: ACPI_STATUS
 1438: acpi_AppendBufferResource(ACPI_BUFFER *buf, ACPI_RESOURCE *res)
 1439: {
 1440:     ACPI_RESOURCE	*rp;
 1441:     void		*newp;
 1442:     
 1443:     /* Initialise the buffer if necessary. */
 1444:     if (buf->Pointer == NULL) {
 1445: 	buf->Length = ACPI_INITIAL_RESOURCE_BUFFER_SIZE;
 1446: 	if ((buf->Pointer = AcpiOsAllocate(buf->Length)) == NULL)
 1447: 	    return (AE_NO_MEMORY);
 1448: 	rp = (ACPI_RESOURCE *)buf->Pointer;
 1449: 	rp->Id = ACPI_RSTYPE_END_TAG;
 1450: 	rp->Length = 0;
 1451:     }
 1452:     if (res == NULL)
 1453: 	return (AE_OK);
 1454:     
 1455:     /*
 1456:      * Scan the current buffer looking for the terminator.
 1457:      * This will either find the terminator or hit the end
 1458:      * of the buffer and return an error.
 1459:      */
 1460:     rp = (ACPI_RESOURCE *)buf->Pointer;
 1461:     for (;;) {
 1462: 	/* Range check, don't go outside the buffer */
 1463: 	if (rp >= (ACPI_RESOURCE *)((u_int8_t *)buf->Pointer + buf->Length))
 1464: 	    return (AE_BAD_PARAMETER);
 1465: 	if (rp->Id == ACPI_RSTYPE_END_TAG || rp->Length == 0)
 1466: 	    break;
 1467: 	rp = ACPI_NEXT_RESOURCE(rp);
 1468:     }
 1469: 
 1470:     /*
 1471:      * Check the size of the buffer and expand if required.
 1472:      *
 1473:      * Required size is:
 1474:      *	size of existing resources before terminator + 
 1475:      *	size of new resource and header +
 1476:      * 	size of terminator.
 1477:      *
 1478:      * Note that this loop should really only run once, unless
 1479:      * for some reason we are stuffing a *really* huge resource.
 1480:      */
 1481:     while ((((u_int8_t *)rp - (u_int8_t *)buf->Pointer) + 
 1482: 	    res->Length + ACPI_RESOURCE_LENGTH_NO_DATA +
 1483: 	    ACPI_RESOURCE_LENGTH) >= buf->Length) {
 1484: 	if ((newp = AcpiOsAllocate(buf->Length * 2)) == NULL)
 1485: 	    return (AE_NO_MEMORY);
 1486: 	bcopy(buf->Pointer, newp, buf->Length);
 1487: 	rp = (ACPI_RESOURCE *)((u_int8_t *)newp +
 1488: 			       ((u_int8_t *)rp - (u_int8_t *)buf->Pointer));
 1489: 	AcpiOsFree(buf->Pointer);
 1490: 	buf->Pointer = newp;
 1491: 	buf->Length += buf->Length;
 1492:     }
 1493:     
 1494:     /* Insert the new resource. */
 1495:     bcopy(res, rp, res->Length + ACPI_RESOURCE_LENGTH_NO_DATA);
 1496:     
 1497:     /* And add the terminator. */
 1498:     rp = ACPI_NEXT_RESOURCE(rp);
 1499:     rp->Id = ACPI_RSTYPE_END_TAG;
 1500:     rp->Length = 0;
 1501: 
 1502:     return (AE_OK);
 1503: }
 1504: 
 1505: /*
 1506:  * Set interrupt model.
 1507:  */
 1508: ACPI_STATUS
 1509: acpi_SetIntrModel(int model)
 1510: {
 1511:     ACPI_OBJECT_LIST ArgList;
 1512:     ACPI_OBJECT Arg;
 1513: 
 1514:     Arg.Type = ACPI_TYPE_INTEGER;
 1515:     Arg.Integer.Value = model;
 1516:     ArgList.Count = 1;
 1517:     ArgList.Pointer = &Arg;
 1518:     return (AcpiEvaluateObject(ACPI_ROOT_OBJECT, "_PIC", &ArgList, NULL));
 1519: }
 1520: 
 1521: #define ACPI_MINIMUM_AWAKETIME	5
 1522: 
 1523: static void
 1524: acpi_sleep_enable(void *arg)
 1525: {
 1526:     ((struct acpi_softc *)arg)->acpi_sleep_disabled = 0;
 1527: }
 1528: 
 1529: /*
 1530:  * Set the system sleep state
 1531:  *
 1532:  * Currently we support S1-S5 but S4 is only S4BIOS
 1533:  */
 1534: ACPI_STATUS
 1535: acpi_SetSleepState(struct acpi_softc *sc, int state)
 1536: {
 1537:     ACPI_STATUS	status = AE_OK;
 1538:     UINT8	TypeA;
 1539:     UINT8	TypeB;
 1540: 
 1541:     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 1542:     ACPI_ASSERTLOCK;
 1543: 
 1544:     /* Avoid reentry if already attempting to suspend. */
 1545:     if (sc->acpi_sstate != ACPI_STATE_S0)
 1546: 	return_ACPI_STATUS (AE_BAD_PARAMETER);
 1547: 
 1548:     /* We recently woke up so don't suspend again for a while. */
 1549:     if (sc->acpi_sleep_disabled)
 1550: 	return_ACPI_STATUS (AE_OK);
 1551: 
 1552:     switch (state) {
 1553:     case ACPI_STATE_S1:
 1554:     case ACPI_STATE_S2:
 1555:     case ACPI_STATE_S3:
 1556:     case ACPI_STATE_S4:
 1557: 	status = AcpiGetSleepTypeData((UINT8)state, &TypeA, &TypeB);
 1558: 	if (status == AE_NOT_FOUND) {
 1559: 	    device_printf(sc->acpi_dev,
 1560: 			  "Sleep state S%d not supported by BIOS\n", state);
 1561: 	    break;
 1562: 	} else if (ACPI_FAILURE(status)) {
 1563: 	    device_printf(sc->acpi_dev, "AcpiGetSleepTypeData failed - %s\n",
 1564: 			  AcpiFormatException(status));
 1565: 	    break;
 1566: 	}
 1567: 
 1568: 	sc->acpi_sstate = state;
 1569: 	sc->acpi_sleep_disabled = 1;
 1570: 
 1571: 	/* Inform all devices that we are going to sleep. */
 1572: 	if (DEVICE_SUSPEND(root_bus) != 0) {
 1573: 	    /*
 1574: 	     * Re-wake the system.
 1575: 	     *
 1576: 	     * XXX note that a better two-pass approach with a 'veto' pass
 1577: 	     *     followed by a "real thing" pass would be better, but the
 1578: 	     *     current bus interface does not provide for this.
 1579: 	     */
 1580: 	    DEVICE_RESUME(root_bus);
 1581: 	    return_ACPI_STATUS (AE_ERROR);
 1582: 	}
 1583: 
 1584: 	status = AcpiEnterSleepStatePrep(state);
 1585: 	if (ACPI_FAILURE(status)) {
 1586: 	    device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n",
 1587: 			  AcpiFormatException(status));
 1588: 	    break;
 1589: 	}
 1590: 
 1591: 	if (sc->acpi_sleep_delay > 0)
 1592: 	    DELAY(sc->acpi_sleep_delay * 1000000);
 1593: 
 1594: 	if (state != ACPI_STATE_S1) {
 1595: 	    acpi_sleep_machdep(sc, state);
 1596: 
 1597: 	    /* AcpiEnterSleepState() may be incomplete, unlock if locked. */
 1598: 	    if (AcpiGbl_MutexInfo[ACPI_MTX_HARDWARE].OwnerId !=
 1599: 		ACPI_MUTEX_NOT_ACQUIRED) {
 1600: 
 1601: 		AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
 1602: 	    }
 1603: 
 1604: 	    /* Re-enable ACPI hardware on wakeup from sleep state 4. */
 1605: 	    if (state == ACPI_STATE_S4)
 1606: 		AcpiEnable();
 1607: 	} else {
 1608: 	    status = AcpiEnterSleepState((UINT8)state);
 1609: 	    if (ACPI_FAILURE(status)) {
 1610: 		device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
 1611: 			      AcpiFormatException(status));
 1612: 		break;
 1613: 	    }
 1614: 	}
 1615: 	AcpiLeaveSleepState((UINT8)state);
 1616: 	DEVICE_RESUME(root_bus);
 1617: 	sc->acpi_sstate = ACPI_STATE_S0;
 1618: 	acpi_enable_fixed_events(sc);
 1619: 	break;
 1620:     case ACPI_STATE_S5:
 1621: 	/*
 1622: 	 * Shut down cleanly and power off.  This will call us back through the
 1623: 	 * shutdown handlers.
 1624: 	 */
 1625: 	shutdown_nice(RB_POWEROFF);
 1626: 	break;
 1627:     case ACPI_STATE_S0:
 1628:     default:
 1629: 	status = AE_BAD_PARAMETER;
 1630: 	break;
 1631:     }
 1632: 
 1633:     /* Disable a second sleep request for a short period */
 1634:     if (sc->acpi_sleep_disabled)
 1635: 	timeout(acpi_sleep_enable, (caddr_t)sc, hz * ACPI_MINIMUM_AWAKETIME);
 1636: 
 1637:     return_ACPI_STATUS (status);
 1638: }
 1639: 
 1640: /*
 1641:  * Enable/Disable ACPI
 1642:  */
 1643: ACPI_STATUS
 1644: acpi_Enable(struct acpi_softc *sc)
 1645: {
 1646:     ACPI_STATUS	status;
 1647:     u_int32_t	flags;
 1648: 
 1649:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1650:     ACPI_ASSERTLOCK;
 1651: 
 1652:     flags = ACPI_NO_ADDRESS_SPACE_INIT | ACPI_NO_HARDWARE_INIT |
 1653: 	    ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT;
 1654:     if (!sc->acpi_enabled)
 1655: 	status = AcpiEnableSubsystem(flags);
 1656:     else
 1657: 	status = AE_OK;
 1658: 
 1659:     if (status == AE_OK)
 1660: 	sc->acpi_enabled = 1;
 1661: 
 1662:     return_ACPI_STATUS (status);
 1663: }
 1664: 
 1665: ACPI_STATUS
 1666: acpi_Disable(struct acpi_softc *sc)
 1667: {
 1668:     ACPI_STATUS	status;
 1669: 
 1670:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1671:     ACPI_ASSERTLOCK;
 1672: 
 1673:     if (sc->acpi_enabled)
 1674: 	status = AcpiDisable();
 1675:     else
 1676: 	status = AE_OK;
 1677: 
 1678:     if (status == AE_OK)
 1679: 	sc->acpi_enabled = 0;
 1680: 
 1681:     return_ACPI_STATUS (status);
 1682: }
 1683: 
 1684: /*
 1685:  * ACPI Event Handlers
 1686:  */
 1687: 
 1688: /* System Event Handlers (registered by EVENTHANDLER_REGISTER) */
 1689: 
 1690: static void
 1691: acpi_system_eventhandler_sleep(void *arg, int state)
 1692: {
 1693:     ACPI_LOCK_DECL;
 1694:     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 1695: 
 1696:     ACPI_LOCK;
 1697:     if (state >= ACPI_STATE_S0 && state <= ACPI_S_STATES_MAX)
 1698: 	acpi_SetSleepState((struct acpi_softc *)arg, state);
 1699:     ACPI_UNLOCK;
 1700:     return_VOID;
 1701: }
 1702: 
 1703: static void
 1704: acpi_system_eventhandler_wakeup(void *arg, int state)
 1705: {
 1706:     ACPI_LOCK_DECL;
 1707:     ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
 1708: 
 1709:     /* Well, what to do? :-) */
 1710: 
 1711:     ACPI_LOCK;
 1712:     ACPI_UNLOCK;
 1713: 
 1714:     return_VOID;
 1715: }
 1716: 
 1717: /* 
 1718:  * ACPICA Event Handlers (FixedEvent, also called from button notify handler)
 1719:  */
 1720: UINT32
 1721: acpi_event_power_button_sleep(void *context)
 1722: {
 1723:     struct acpi_softc	*sc = (struct acpi_softc *)context;
 1724: 
 1725:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1726: 
 1727:     EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_power_button_sx);
 1728: 
 1729:     return_VALUE (ACPI_INTERRUPT_HANDLED);
 1730: }
 1731: 
 1732: UINT32
 1733: acpi_event_power_button_wake(void *context)
 1734: {
 1735:     struct acpi_softc	*sc = (struct acpi_softc *)context;
 1736: 
 1737:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1738: 
 1739:     EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_power_button_sx);
 1740: 
 1741:     return_VALUE (ACPI_INTERRUPT_HANDLED);
 1742: }
 1743: 
 1744: UINT32
 1745: acpi_event_sleep_button_sleep(void *context)
 1746: {
 1747:     struct acpi_softc	*sc = (struct acpi_softc *)context;
 1748: 
 1749:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1750: 
 1751:     EVENTHANDLER_INVOKE(acpi_sleep_event, sc->acpi_sleep_button_sx);
 1752: 
 1753:     return_VALUE (ACPI_INTERRUPT_HANDLED);
 1754: }
 1755: 
 1756: UINT32
 1757: acpi_event_sleep_button_wake(void *context)
 1758: {
 1759:     struct acpi_softc	*sc = (struct acpi_softc *)context;
 1760: 
 1761:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1762: 
 1763:     EVENTHANDLER_INVOKE(acpi_wakeup_event, sc->acpi_sleep_button_sx);
 1764: 
 1765:     return_VALUE (ACPI_INTERRUPT_HANDLED);
 1766: }
 1767: 
 1768: /*
 1769:  * XXX This is kinda ugly, and should not be here.
 1770:  */
 1771: struct acpi_staticbuf {
 1772:     ACPI_BUFFER	buffer;
 1773:     char	data[512];
 1774: };
 1775: 
 1776: char *
 1777: acpi_name(ACPI_HANDLE handle)
 1778: {
 1779:     static struct acpi_staticbuf	buf;
 1780: 
 1781:     ACPI_ASSERTLOCK;
 1782: 
 1783:     buf.buffer.Length = 512;
 1784:     buf.buffer.Pointer = &buf.data[0];
 1785: 
 1786:     if (ACPI_SUCCESS(AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf.buffer)))
 1787: 	return (buf.buffer.Pointer);
 1788: 
 1789:     return ("(unknown path)");
 1790: }
 1791: 
 1792: /*
 1793:  * Debugging/bug-avoidance.  Avoid trying to fetch info on various
 1794:  * parts of the namespace.
 1795:  */
 1796: int
 1797: acpi_avoid(ACPI_HANDLE handle)
 1798: {
 1799:     char	*cp, *env, *np;
 1800:     int		len;
 1801: 
 1802:     np = acpi_name(handle);
 1803:     if (*np == '\\')
 1804: 	np++;
 1805:     if ((env = getenv("debug.acpi.avoid")) == NULL)
 1806: 	return (0);
 1807: 
 1808:     /* Scan the avoid list checking for a match */
 1809:     cp = env;
 1810:     for (;;) {
 1811: 	while ((*cp != 0) && isspace(*cp))
 1812: 	    cp++;
 1813: 	if (*cp == 0)
 1814: 	    break;
 1815: 	len = 0;
 1816: 	while ((cp[len] != 0) && !isspace(cp[len]))
 1817: 	    len++;
 1818: 	if (!strncmp(cp, np, len)) {
 1819: 	    freeenv(env);
 1820: 	    return(1);
 1821: 	}
 1822: 	cp += len;
 1823:     }
 1824:     freeenv(env);
 1825: 
 1826:     return (0);
 1827: }
 1828: 
 1829: /*
 1830:  * Debugging/bug-avoidance.  Disable ACPI subsystem components.
 1831:  */
 1832: int
 1833: acpi_disabled(char *subsys)
 1834: {
 1835:     char	*cp, *env;
 1836:     int		len;
 1837: 
 1838:     if ((env = getenv("debug.acpi.disable")) == NULL)
 1839: 	return (0);
 1840:     if (!strcmp(env, "all")) {
 1841: 	freeenv(env);
 1842: 	return (1);
 1843:     }
 1844: 
 1845:     /* scan the disable list checking for a match */
 1846:     cp = env;
 1847:     for (;;) {
 1848: 	while ((*cp != 0) && isspace(*cp))
 1849: 	    cp++;
 1850: 	if (*cp == 0)
 1851: 	    break;
 1852: 	len = 0;
 1853: 	while ((cp[len] != 0) && !isspace(cp[len]))
 1854: 	    len++;
 1855: 	if (!strncmp(cp, subsys, len)) {
 1856: 	    freeenv(env);
 1857: 	    return (1);
 1858: 	}
 1859: 	cp += len;
 1860:     }
 1861:     freeenv(env);
 1862: 
 1863:     return (0);
 1864: }
 1865: 
 1866: /*
 1867:  * Device wake capability enable/disable.
 1868:  */
 1869: void
 1870: acpi_device_enable_wake_capability(ACPI_HANDLE h, int enable)
 1871: {
 1872:     ACPI_OBJECT_LIST		ArgList;
 1873:     ACPI_OBJECT			Arg;
 1874: 
 1875:     /*
 1876:      * TBD: All Power Resources referenced by elements 2 through N
 1877:      *      of the _PRW object are put into the ON state.
 1878:      */
 1879: 
 1880:     ArgList.Count = 1;
 1881:     ArgList.Pointer = &Arg;
 1882: 
 1883:     Arg.Type = ACPI_TYPE_INTEGER;
 1884:     Arg.Integer.Value = enable;
 1885: 
 1886:     (void)AcpiEvaluateObject(h, "_PSW", &ArgList, NULL);
 1887: }
 1888: 
 1889: void
 1890: acpi_device_enable_wake_event(ACPI_HANDLE h)
 1891: {
 1892:     struct acpi_softc		*sc;
 1893:     ACPI_STATUS			status;
 1894:     ACPI_BUFFER			prw_buffer;
 1895:     ACPI_OBJECT			*res;
 1896: 
 1897:     ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
 1898: 
 1899:     sc = devclass_get_softc(acpi_devclass, 0);
 1900:     if (sc == NULL)
 1901: 	return;
 1902: 
 1903:     /*
 1904:      * _PRW object is only required for devices that have the ability
 1905:      * to wake the system from a system sleeping state.
 1906:      */
 1907:     prw_buffer.Length = ACPI_ALLOCATE_BUFFER;
 1908:     status = AcpiEvaluateObject(h, "_PRW", NULL, &prw_buffer);
 1909:     if (ACPI_FAILURE(status))
 1910: 	return;
 1911: 
 1912:     res = (ACPI_OBJECT *)prw_buffer.Pointer;
 1913:     if (res == NULL)
 1914: 	return;
 1915: 
 1916:     if ((res->Type != ACPI_TYPE_PACKAGE) || (res->Package.Count < 2)) {
 1917: 	goto out;
 1918:     }
 1919: 
 1920:     /*
 1921:      * The element 1 of the _PRW object:
 1922:      * The lowest power system sleeping state that can be entered
 1923:      * while still providing wake functionality.
 1924:      * The sleeping state being entered must be greater or equal to
 1925:      * the power state declared in element 1 of the _PRW object.
 1926:      */
 1927:     if (res->Package.Elements[1].Type != ACPI_TYPE_INTEGER)
 1928: 	goto out;
 1929: 
 1930:     if (sc->acpi_sstate > res->Package.Elements[1].Integer.Value)
 1931: 	goto out;
 1932: 
 1933:     /*
 1934:      * The element 0 of the _PRW object:
 1935:      */
 1936:     switch(res->Package.Elements[0].Type) {
 1937:     case ACPI_TYPE_INTEGER:
 1938: 	/* 
 1939: 	 * If the data type of this package element is numeric, then this
 1940: 	 * _PRW package element is the bit index in the GPEx_EN, in the
 1941: 	 * GPE blocks described in the FADT, of the enable bit that is
 1942: 	 * enabled for the wake event.
 1943: 	 */
 1944: 
 1945: 	status = AcpiEnableGpe(NULL, res->Package.Elements[0].Integer.Value,
 1946: 			       ACPI_EVENT_WAKE_ENABLE);
 1947: 	if (ACPI_FAILURE(status))
 1948: 	    printf("%s: EnableEvent Failed\n", __func__);
 1949: 	break;
 1950:     case ACPI_TYPE_PACKAGE:
 1951: 	/*
 1952: 	 * XXX TBD
 1953: 	 *
 1954: 	 * If the data type of this package element is a package, then this
 1955: 	 * _PRW package element is itself a package containing two
 1956: 	 * elements. The first is an object reference to the GPE Block
 1957: 	 * device that contains the GPE that will be triggered by the wake
 1958: 	 * event. The second element is numeric and it contains the bit
 1959: 	 * index in the GPEx_EN, in the GPE Block referenced by the
 1960: 	 * first element in the package, of the enable bit that is enabled for
 1961: 	 * the wake event.
 1962: 	 * For example, if this field is a package then it is of the form:
 1963: 	 * Package() {\_SB.PCI0.ISA.GPE, 2}
 1964: 	 */
 1965: 	break;
 1966:     default:
 1967: 	break;
 1968:     }
 1969: 
 1970: out:
 1971:     if (prw_buffer.Pointer != NULL)
 1972: 	AcpiOsFree(prw_buffer.Pointer);
 1973: }
 1974: 
 1975: /*
 1976:  * Control interface.
 1977:  *
 1978:  * We multiplex ioctls for all participating ACPI devices here.  Individual 
 1979:  * drivers wanting to be accessible via /dev/acpi should use the
 1980:  * register/deregister interface to make their handlers visible.
 1981:  */
 1982: struct acpi_ioctl_hook
 1983: {
 1984:     TAILQ_ENTRY(acpi_ioctl_hook) link;
 1985:     u_long			 cmd;
 1986:     acpi_ioctl_fn		 fn;
 1987:     void			 *arg;
 1988: };
 1989: 
 1990: static TAILQ_HEAD(,acpi_ioctl_hook)	acpi_ioctl_hooks;
 1991: static int				acpi_ioctl_hooks_initted;
 1992: 
 1993: /*
 1994:  * Register an ioctl handler.
 1995:  */
 1996: int
 1997: acpi_register_ioctl(u_long cmd, acpi_ioctl_fn fn, void *arg)
 1998: {
 1999:     struct acpi_ioctl_hook	*hp;
 2000: 
 2001:     hp = malloc(sizeof(*hp), M_ACPIDEV, M_INTWAIT);
 2002:     hp->cmd = cmd;
 2003:     hp->fn = fn;
 2004:     hp->arg = arg;
 2005:     if (acpi_ioctl_hooks_initted == 0) {
 2006: 	TAILQ_INIT(&acpi_ioctl_hooks);
 2007: 	acpi_ioctl_hooks_initted = 1;
 2008:     }
 2009:     TAILQ_INSERT_TAIL(&acpi_ioctl_hooks, hp, link);
 2010:     return (0);
 2011: }
 2012: 
 2013: /*
 2014:  * Deregister an ioctl handler.
 2015:  */
 2016: void	
 2017: acpi_deregister_ioctl(u_long cmd, acpi_ioctl_fn fn)
 2018: {
 2019:     struct acpi_ioctl_hook	*hp;
 2020: 
 2021:     TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link)
 2022: 	if ((hp->cmd == cmd) && (hp->fn == fn))
 2023: 	    break;
 2024: 
 2025:     if (hp != NULL) {
 2026: 	TAILQ_REMOVE(&acpi_ioctl_hooks, hp, link);
 2027: 	free(hp, M_ACPIDEV);
 2028:     }
 2029: }
 2030: 
 2031: static int
 2032: acpiopen(dev_t dev, int flag, int fmt, d_thread_t *td)
 2033: {
 2034:     return (0);
 2035: }
 2036: 
 2037: static int
 2038: acpiclose(dev_t dev, int flag, int fmt, d_thread_t *td)
 2039: {
 2040:     return (0);
 2041: }
 2042: 
 2043: static int
 2044: acpiioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, d_thread_t *td)
 2045: {
 2046:     struct acpi_softc		*sc;
 2047:     struct acpi_ioctl_hook	*hp;
 2048:     int				error, xerror, state;
 2049:     ACPI_LOCK_DECL;
 2050: 
 2051:     ACPI_LOCK;
 2052: 
 2053:     error = state = 0;
 2054:     sc = dev->si_drv1;
 2055: 
 2056:     /*
 2057:      * Scan the list of registered ioctls, looking for handlers.
 2058:      */
 2059:     if (acpi_ioctl_hooks_initted) {
 2060: 	TAILQ_FOREACH(hp, &acpi_ioctl_hooks, link) {
 2061: 	    if (hp->cmd == cmd) {
 2062: 		xerror = hp->fn(cmd, addr, hp->arg);
 2063: 		if (xerror != 0)
 2064: 		    error = xerror;
 2065: 		goto out;
 2066: 	    }
 2067: 	}
 2068:     }
 2069: 
 2070:     /*
 2071:      * Core ioctls are not permitted for non-writable user.
 2072:      * Currently, other ioctls just fetch information.
 2073:      * Not changing system behavior.
 2074:      */
 2075:     if((flag & FWRITE) == 0)
 2076: 	return (EPERM);
 2077: 
 2078:     /* Core system ioctls. */
 2079:     switch (cmd) {
 2080:     case ACPIIO_ENABLE:
 2081: 	if (ACPI_FAILURE(acpi_Enable(sc)))
 2082: 	    error = ENXIO;
 2083: 	break;
 2084:     case ACPIIO_DISABLE:
 2085: 	if (ACPI_FAILURE(acpi_Disable(sc)))
 2086: 	    error = ENXIO;
 2087: 	break;
 2088:     case ACPIIO_SETSLPSTATE:
 2089: 	if (!sc->acpi_enabled) {
 2090: 	    error = ENXIO;
 2091: 	    break;
 2092: 	}
 2093: 	state = *(int *)addr;
 2094: 	if (state >= ACPI_STATE_S0  && state <= ACPI_S_STATES_MAX) {
 2095: 	    if (ACPI_FAILURE(acpi_SetSleepState(sc, state)))
 2096: 		error = EINVAL;
 2097: 	} else {
 2098: 	    error = EINVAL;
 2099: 	}
 2100: 	break;
 2101:     default:
 2102: 	if (error == 0)
 2103: 	    error = EINVAL;
 2104: 	break;
 2105:     }
 2106: 
 2107: out:
 2108:     ACPI_UNLOCK;
 2109:     return (error);
 2110: }
 2111: 
 2112: static int
 2113: acpi_supported_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
 2114: {
 2115:     char sleep_state[4];
 2116:     char buf[16];
 2117:     int error;
 2118:     UINT8 state, TypeA, TypeB;
 2119: 
 2120:     buf[0] = '\0';
 2121:     for (state = ACPI_STATE_S1; state < ACPI_S_STATES_MAX+1; state++) {
 2122: 	if (ACPI_SUCCESS(AcpiGetSleepTypeData(state, &TypeA, &TypeB))) {
 2123: 	    sprintf(sleep_state, "S%d ", state);
 2124: 	    strcat(buf, sleep_state);
 2125: 	}
 2126:     }
 2127:     error = sysctl_handle_string(oidp, buf, sizeof(buf), req);
 2128:     return (error);
 2129: }
 2130: 
 2131: static int
 2132: acpi_sleep_state_sysctl(SYSCTL_HANDLER_ARGS)
 2133: {
 2134:     char sleep_state[10];
 2135:     int error;
 2136:     u_int new_state, old_state;
 2137: 
 2138:     old_state = *(u_int *)oidp->oid_arg1;
 2139:     if (old_state > ACPI_S_STATES_MAX+1) {
 2140: 	strcpy(sleep_state, "unknown");
 2141:     } else {
 2142: 	bzero(sleep_state, sizeof(sleep_state));
 2143: 	strncpy(sleep_state, sleep_state_names[old_state],
 2144: 		sizeof(sleep_state_names[old_state]));
 2145:     }
 2146:     error = sysctl_handle_string(oidp, sleep_state, sizeof(sleep_state), req);
 2147:     if (error == 0 && req->newptr != NULL) {
 2148: 	new_state = ACPI_STATE_S0;
 2149: 	for (; new_state <= ACPI_S_STATES_MAX + 1; new_state++) {
 2150: 	    if (strncmp(sleep_state, sleep_state_names[new_state],
 2151: 			sizeof(sleep_state)) == 0)
 2152: 		break;
 2153: 	}
 2154: 	if (new_state <= ACPI_S_STATES_MAX + 1) {
 2155: 	    if (new_state != old_state)
 2156: 		*(u_int *)oidp->oid_arg1 = new_state;
 2157: 	} else {
 2158: 	    error = EINVAL;
 2159: 	}
 2160:     }
 2161: 
 2162:     return (error);
 2163: }
 2164: 
 2165: /* Inform devctl(4) when we receive a Notify. */
 2166: void
 2167: acpi_UserNotify(const char *subsystem, ACPI_HANDLE h, uint8_t notify)
 2168: {
 2169:     char		notify_buf[16];
 2170:     ACPI_BUFFER		handle_buf;
 2171:     ACPI_STATUS		status;
 2172: 
 2173:     if (subsystem == NULL)
 2174: 	return;
 2175: 
 2176:     handle_buf.Pointer = NULL;
 2177:     handle_buf.Length = ACPI_ALLOCATE_BUFFER;
 2178:     status = AcpiNsHandleToPathname(h, &handle_buf);
 2179:     if (ACPI_FAILURE(status))
 2180: 	return;
 2181:     snprintf(notify_buf, sizeof(notify_buf), "notify=0x%02x", notify);
 2182: #if 0
 2183:     devctl_notify("ACPI", subsystem, handle_buf.Pointer, notify_buf);
 2184: #endif
 2185:     AcpiOsFree(handle_buf.Pointer);
 2186: }
 2187: 
 2188: #ifdef ACPI_DEBUG
 2189: /*
 2190:  * Support for parsing debug options from the kernel environment.
 2191:  *
 2192:  * Bits may be set in the AcpiDbgLayer and AcpiDbgLevel debug registers
 2193:  * by specifying the names of the bits in the debug.acpi.layer and
 2194:  * debug.acpi.level environment variables.  Bits may be unset by 
 2195:  * prefixing the bit name with !.
 2196:  */
 2197: struct debugtag
 2198: {
 2199:     char	*name;
 2200:     UINT32	value;
 2201: };
 2202: 
 2203: static struct debugtag	dbg_layer[] = {
 2204:     {"ACPI_UTILITIES",		ACPI_UTILITIES},
 2205:     {"ACPI_HARDWARE",		ACPI_HARDWARE},
 2206:     {"ACPI_EVENTS",		ACPI_EVENTS},
 2207:     {"ACPI_TABLES",		ACPI_TABLES},
 2208:     {"ACPI_NAMESPACE",		ACPI_NAMESPACE},
 2209:     {"ACPI_PARSER",		ACPI_PARSER},
 2210:     {"ACPI_DISPATCHER",		ACPI_DISPATCHER},
 2211:     {"ACPI_EXECUTER",		ACPI_EXECUTER},
 2212:     {"ACPI_RESOURCES",		ACPI_RESOURCES},
 2213:     {"ACPI_CA_DEBUGGER",	ACPI_CA_DEBUGGER},
 2214:     {"ACPI_OS_SERVICES",	ACPI_OS_SERVICES},
 2215:     {"ACPI_CA_DISASSEMBLER",	ACPI_CA_DISASSEMBLER},
 2216:     {"ACPI_ALL_COMPONENTS",	ACPI_ALL_COMPONENTS},
 2217: 
 2218:     {"ACPI_BUS",		ACPI_BUS},
 2219:     {"ACPI_SYSTEM",		ACPI_SYSTEM},
 2220:     {"ACPI_POWER",		ACPI_POWER},
 2221:     {"ACPI_EC", 		ACPI_EC},
 2222:     {"ACPI_AC_ADAPTER",		ACPI_AC_ADAPTER},
 2223:     {"ACPI_BATTERY",		ACPI_BATTERY},
 2224:     {"ACPI_BUTTON",		ACPI_BUTTON},
 2225:     {"ACPI_PROCESSOR",		ACPI_PROCESSOR},
 2226:     {"ACPI_THERMAL",		ACPI_THERMAL},
 2227:     {"ACPI_FAN",		ACPI_FAN},
 2228:     {"ACPI_ALL_DRIVERS",	ACPI_ALL_DRIVERS},
 2229:     {NULL, 0}
 2230: };
 2231: 
 2232: static struct debugtag dbg_level[] = {
 2233:     {"ACPI_LV_ERROR",		ACPI_LV_ERROR},
 2234:     {"ACPI_LV_WARN",		ACPI_LV_WARN},
 2235:     {"ACPI_LV_INIT",		ACPI_LV_INIT},
 2236:     {"ACPI_LV_DEBUG_OBJECT",	ACPI_LV_DEBUG_OBJECT},
 2237:     {"ACPI_LV_INFO",		ACPI_LV_INFO},
 2238:     {"ACPI_LV_ALL_EXCEPTIONS",	ACPI_LV_ALL_EXCEPTIONS},
 2239: 
 2240:     /* Trace verbosity level 1 [Standard Trace Level] */
 2241:     {"ACPI_LV_INIT_NAMES",	ACPI_LV_INIT_NAMES},
 2242:     {"ACPI_LV_PARSE",		ACPI_LV_PARSE},
 2243:     {"ACPI_LV_LOAD",		ACPI_LV_LOAD},
 2244:     {"ACPI_LV_DISPATCH",	ACPI_LV_DISPATCH},
 2245:     {"ACPI_LV_EXEC",		ACPI_LV_EXEC},
 2246:     {"ACPI_LV_NAMES",		ACPI_LV_NAMES},
 2247:     {"ACPI_LV_OPREGION",	ACPI_LV_OPREGION},
 2248:     {"ACPI_LV_BFIELD",		ACPI_LV_BFIELD},
 2249:     {"ACPI_LV_TABLES",		ACPI_LV_TABLES},
 2250:     {"ACPI_LV_VALUES",		ACPI_LV_VALUES},
 2251:     {"ACPI_LV_OBJECTS",		ACPI_LV_OBJECTS},
 2252:     {"ACPI_LV_RESOURCES",	ACPI_LV_RESOURCES},
 2253:     {"ACPI_LV_USER_REQUESTS",	ACPI_LV_USER_REQUESTS},
 2254:     {"ACPI_LV_PACKAGE",		ACPI_LV_PACKAGE},
 2255:     {"ACPI_LV_VERBOSITY1",	ACPI_LV_VERBOSITY1},
 2256: 
 2257:     /* Trace verbosity level 2 [Function tracing and memory allocation] */
 2258:     {"ACPI_LV_ALLOCATIONS",	ACPI_LV_ALLOCATIONS},
 2259:     {"ACPI_LV_FUNCTIONS",	ACPI_LV_FUNCTIONS},
 2260:     {"ACPI_LV_OPTIMIZATIONS",	ACPI_LV_OPTIMIZATIONS},
 2261:     {"ACPI_LV_VERBOSITY2",	ACPI_LV_VERBOSITY2},
 2262:     {"ACPI_LV_ALL",		ACPI_LV_ALL},
 2263: 
 2264:     /* Trace verbosity level 3 [Threading, I/O, and Interrupts] */
 2265:     {"ACPI_LV_MUTEX",		ACPI_LV_MUTEX},
 2266:     {"ACPI_LV_THREADS",		ACPI_LV_THREADS},
 2267:     {"ACPI_LV_IO",		ACPI_LV_IO},
 2268:     {"ACPI_LV_INTERRUPTS",	ACPI_LV_INTERRUPTS},
 2269:     {"ACPI_LV_VERBOSITY3",	ACPI_LV_VERBOSITY3},
 2270: 
 2271:     /* Exceptionally verbose output -- also used in the global "DebugLevel"  */
 2272:     {"ACPI_LV_AML_DISASSEMBLE",	ACPI_LV_AML_DISASSEMBLE},
 2273:     {"ACPI_LV_VERBOSE_INFO",	ACPI_LV_VERBOSE_INFO},
 2274:     {"ACPI_LV_FULL_TABLES",	ACPI_LV_FULL_TABLES},
 2275:     {"ACPI_LV_EVENTS",		ACPI_LV_EVENTS},
 2276:     {"ACPI_LV_VERBOSE",		ACPI_LV_VERBOSE},
 2277:     {NULL, 0}
 2278: };    
 2279: 
 2280: static void
 2281: acpi_parse_debug(char *cp, struct debugtag *tag, UINT32 *flag)
 2282: {
 2283:     char	*ep;
 2284:     int		i, l;
 2285:     int		set;
 2286: 
 2287:     while (*cp) {
 2288: 	if (isspace(*cp)) {
 2289: 	    cp++;
 2290: 	    continue;
 2291: 	}
 2292: 	ep = cp;
 2293: 	while (*ep && !isspace(*ep))
 2294: 	    ep++;
 2295: 	if (*cp == '!') {
 2296: 	    set = 0;
 2297: 	    cp++;
 2298: 	    if (cp == ep)
 2299: 		continue;
 2300: 	} else {
 2301: 	    set = 1;
 2302: 	}
 2303: 	l = ep - cp;
 2304: 	for (i = 0; tag[i].name != NULL; i++) {
 2305: 	    if (!strncmp(cp, tag[i].name, l)) {
 2306: 		if (set)
 2307: 		    *flag |= tag[i].value;
 2308: 		else
 2309: 		    *flag &= ~tag[i].value;
 2310: 		printf("ACPI_DEBUG: set '%s'\n", tag[i].name);
 2311: 	    }
 2312: 	}
 2313: 	cp = ep;
 2314:     }
 2315: }
 2316: 
 2317: static void
 2318: acpi_set_debugging(void *junk)
 2319: {
 2320:     char	*cp;
 2321: 
 2322:     if (cold) {
 2323: 	AcpiDbgLayer = 0;
 2324: 	AcpiDbgLevel = 0;
 2325:     }
 2326: 
 2327:     if ((cp = getenv("debug.acpi.layer")) != NULL) {
 2328: 	acpi_parse_debug(cp, &dbg_layer[0], &AcpiDbgLayer);
 2329: 	freeenv(cp);
 2330:     }
 2331:     if ((cp = getenv("debug.acpi.level")) != NULL) {
 2332: 	acpi_parse_debug(cp, &dbg_level[0], &AcpiDbgLevel);
 2333: 	freeenv(cp);
 2334:     }
 2335: 
 2336:     if (cold) {
 2337: 	printf("ACPI debug layer 0x%x debug level 0x%x\n",
 2338: 	       AcpiDbgLayer, AcpiDbgLevel);
 2339:     }
 2340: }
 2341: SYSINIT(acpi_debugging, SI_SUB_TUNABLES, SI_ORDER_ANY, acpi_set_debugging,
 2342: 	NULL);
 2343: 
 2344: static int
 2345: acpi_debug_sysctl(SYSCTL_HANDLER_ARGS)
 2346: {
 2347:     int		 error, *dbg;
 2348:     struct	 debugtag *tag;
 2349:     struct	 sbuf sb;
 2350: 
 2351:     if (sbuf_new(&sb, NULL, 128, SBUF_AUTOEXTEND) == NULL)
 2352: 	return (ENOMEM);
 2353:     if (strcmp(oidp->oid_arg1, "debug.acpi.layer") == 0) {
 2354: 	tag = &dbg_layer[0];
 2355: 	dbg = &AcpiDbgLayer;
 2356:     } else {
 2357: 	tag = &dbg_level[0];
 2358: 	dbg = &AcpiDbgLevel;
 2359:     }
 2360: 
 2361:     /* Get old values if this is a get request. */
 2362:     if (*dbg == 0) {
 2363: 	sbuf_cpy(&sb, "NONE");
 2364:     } else if (req->newptr == NULL) {
 2365: 	for (; tag->name != NULL; tag++) {
 2366: 	    if ((*dbg & tag->value) == tag->value)
 2367: 		sbuf_printf(&sb, "%s ", tag->name);
 2368: 	}
 2369:     }
 2370:     sbuf_trim(&sb);
 2371:     sbuf_finish(&sb);
 2372: 
 2373:     error = sysctl_handle_string(oidp, sbuf_data(&sb), sbuf_len(&sb), req);
 2374:     sbuf_delete(&sb);
 2375: 
 2376:     /* If the user is setting a string, parse it. */
 2377:     if (error == 0 && req->newptr != NULL) {
 2378: 	*dbg = 0;
 2379: 	setenv((char *)oidp->oid_arg1, (char *)req->newptr);
 2380: 	acpi_set_debugging(NULL);
 2381:     }
 2382: 
 2383:     return (error);
 2384: }
 2385: SYSCTL_PROC(_debug_acpi, OID_AUTO, layer, CTLFLAG_RW | CTLTYPE_STRING,
 2386: 	    "debug.acpi.layer", 0, acpi_debug_sysctl, "A", "");
 2387: SYSCTL_PROC(_debug_acpi, OID_AUTO, level, CTLFLAG_RW | CTLTYPE_STRING,
 2388: 	    "debug.acpi.level", 0, acpi_debug_sysctl, "A", "");
 2389: #endif
 2390: 
 2391: static int
 2392: acpi_pm_func(u_long cmd, void *arg, ...)
 2393: {
 2394: 	int	state, acpi_state;
 2395: 	int	error;
 2396: 	struct	acpi_softc *sc;
 2397: 	va_list	ap;
 2398: 
 2399: 	error = 0;
 2400: 	switch (cmd) {
 2401: 	case POWER_CMD_SUSPEND:
 2402: 		sc = (struct acpi_softc *)arg;
 2403: 		if (sc == NULL) {
 2404: 			error = EINVAL;
 2405: 			goto out;
 2406: 		}
 2407: 
 2408: 		va_start(ap, arg);
 2409: 		state = va_arg(ap, int);
 2410: 		va_end(ap);	
 2411: 
 2412: 		switch (state) {
 2413: 		case POWER_SLEEP_STATE_STANDBY:
 2414: 			acpi_state = sc->acpi_standby_sx;
 2415: 			break;
 2416: 		case POWER_SLEEP_STATE_SUSPEND:
 2417: 			acpi_state = sc->acpi_suspend_sx;
 2418: 			break;
 2419: 		case POWER_SLEEP_STATE_HIBERNATE:
 2420: 			acpi_state = ACPI_STATE_S4;
 2421: 			break;
 2422: 		default:
 2423: 			error = EINVAL;
 2424: 			goto out;
 2425: 		}
 2426: 
 2427: 		acpi_SetSleepState(sc, acpi_state);
 2428: 		break;
 2429: 	default:
 2430: 		error = EINVAL;
 2431: 		goto out;
 2432: 	}
 2433: 
 2434: out:
 2435: 	return (error);
 2436: }
 2437: 
 2438: static void
 2439: acpi_pm_register(void *arg)
 2440: {
 2441:     if (!cold || resource_disabled("acpi", 0))
 2442: 	return;
 2443: 
 2444:     power_pm_register(POWER_PM_TYPE_ACPI, acpi_pm_func, NULL);
 2445: }
 2446: 
 2447: SYSINIT(power, SI_SUB_KLD, SI_ORDER_ANY, acpi_pm_register, 0);