Home | History | Annotate | Line # | Download | only in acpi
acpi.c revision 1.7.2.4
      1  1.7.2.4   gehenna /*	$NetBSD: acpi.c,v 1.7.2.4 2002/08/29 05:22:20 gehenna Exp $	*/
      2      1.1   thorpej 
      3      1.1   thorpej /*
      4      1.1   thorpej  * Copyright 2001 Wasabi Systems, Inc.
      5      1.1   thorpej  * All rights reserved.
      6      1.1   thorpej  *
      7      1.1   thorpej  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
      8      1.1   thorpej  *
      9      1.1   thorpej  * Redistribution and use in source and binary forms, with or without
     10      1.1   thorpej  * modification, are permitted provided that the following conditions
     11      1.1   thorpej  * are met:
     12      1.1   thorpej  * 1. Redistributions of source code must retain the above copyright
     13      1.1   thorpej  *    notice, this list of conditions and the following disclaimer.
     14      1.1   thorpej  * 2. Redistributions in binary form must reproduce the above copyright
     15      1.1   thorpej  *    notice, this list of conditions and the following disclaimer in the
     16      1.1   thorpej  *    documentation and/or other materials provided with the distribution.
     17      1.1   thorpej  * 3. All advertising materials mentioning features or use of this software
     18      1.1   thorpej  *    must display the following acknowledgement:
     19      1.1   thorpej  *	This product includes software developed for the NetBSD Project by
     20      1.1   thorpej  *	Wasabi Systems, Inc.
     21      1.1   thorpej  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
     22      1.1   thorpej  *    or promote products derived from this software without specific prior
     23      1.1   thorpej  *    written permission.
     24      1.1   thorpej  *
     25      1.1   thorpej  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
     26      1.1   thorpej  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     27      1.1   thorpej  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     28      1.1   thorpej  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
     29      1.1   thorpej  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     30      1.1   thorpej  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     31      1.1   thorpej  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     32      1.1   thorpej  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     33      1.1   thorpej  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     34      1.1   thorpej  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     35      1.1   thorpej  * POSSIBILITY OF SUCH DAMAGE.
     36      1.1   thorpej  */
     37      1.1   thorpej 
     38      1.1   thorpej /*
     39      1.1   thorpej  * Autoconfiguration support for the Intel ACPI Component Architecture
     40      1.1   thorpej  * ACPI reference implementation.
     41      1.1   thorpej  */
     42      1.5     lukem 
     43      1.5     lukem #include <sys/cdefs.h>
     44  1.7.2.4   gehenna __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.7.2.4 2002/08/29 05:22:20 gehenna Exp $");
     45      1.1   thorpej 
     46      1.1   thorpej #include <sys/param.h>
     47      1.1   thorpej #include <sys/systm.h>
     48      1.1   thorpej #include <sys/device.h>
     49      1.1   thorpej #include <sys/malloc.h>
     50      1.1   thorpej 
     51      1.1   thorpej #include <dev/acpi/acpica.h>
     52      1.1   thorpej #include <dev/acpi/acpireg.h>
     53      1.1   thorpej #include <dev/acpi/acpivar.h>
     54      1.1   thorpej #include <dev/acpi/acpi_osd.h>
     55      1.1   thorpej 
     56  1.7.2.4   gehenna #ifndef ACPI_PCI_FIXUP
     57  1.7.2.4   gehenna #define ACPI_PCI_FIXUP 1
     58  1.7.2.4   gehenna #endif
     59  1.7.2.4   gehenna 
     60  1.7.2.4   gehenna #ifndef ACPI_ACTIVATE_DEV
     61  1.7.2.4   gehenna #define ACPI_ACTIVATE_DEV 0
     62  1.7.2.4   gehenna #endif
     63  1.7.2.4   gehenna 
     64  1.7.2.4   gehenna #if ACPI_PCI_FIXUP
     65  1.7.2.4   gehenna #include <dev/acpi/acpica/Subsystem/acnamesp.h> /* AcpiNsGetNodeByPath() */
     66  1.7.2.4   gehenna #include <dev/pci/pcidevs.h>
     67  1.7.2.4   gehenna #endif
     68  1.7.2.4   gehenna 
     69  1.7.2.2   gehenna #include <machine/acpi_machdep.h>
     70  1.7.2.2   gehenna 
     71      1.1   thorpej #ifdef ENABLE_DEBUGGER
     72      1.1   thorpej #define	ACPI_DBGR_INIT		0x01
     73      1.1   thorpej #define	ACPI_DBGR_TABLES	0x02
     74      1.1   thorpej #define	ACPI_DBGR_ENABLE	0x04
     75      1.1   thorpej #define	ACPI_DBGR_PROBE		0x08
     76      1.1   thorpej #define	ACPI_DBGR_RUNNING	0x10
     77      1.1   thorpej 
     78      1.1   thorpej int	acpi_dbgr = 0x00;
     79      1.1   thorpej #endif
     80      1.1   thorpej 
     81      1.1   thorpej int	acpi_match(struct device *, struct cfdata *, void *);
     82      1.1   thorpej void	acpi_attach(struct device *, struct device *, void *);
     83      1.1   thorpej 
     84      1.1   thorpej int	acpi_print(void *aux, const char *);
     85      1.1   thorpej 
     86      1.1   thorpej extern struct cfdriver acpi_cd;
     87      1.1   thorpej 
     88      1.1   thorpej struct cfattach acpi_ca = {
     89      1.1   thorpej 	sizeof(struct acpi_softc), acpi_match, acpi_attach,
     90      1.1   thorpej };
     91      1.1   thorpej 
     92      1.1   thorpej /*
     93      1.1   thorpej  * This is a flag we set when the ACPI subsystem is active.  Machine
     94      1.1   thorpej  * dependent code may wish to skip other steps (such as attaching
     95      1.1   thorpej  * subsystems that ACPI supercedes) when ACPI is active.
     96      1.1   thorpej  */
     97      1.1   thorpej int	acpi_active;
     98      1.1   thorpej 
     99      1.1   thorpej /*
    100      1.1   thorpej  * Pointer to the ACPI subsystem's state.  There can be only
    101      1.1   thorpej  * one ACPI instance.
    102      1.1   thorpej  */
    103      1.1   thorpej struct acpi_softc *acpi_softc;
    104      1.1   thorpej 
    105      1.1   thorpej void		acpi_shutdown(void *);
    106      1.1   thorpej ACPI_STATUS	acpi_disable(struct acpi_softc *sc);
    107      1.1   thorpej void		acpi_build_tree(struct acpi_softc *);
    108      1.1   thorpej ACPI_STATUS	acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
    109      1.1   thorpej 
    110      1.1   thorpej void		acpi_enable_fixed_events(struct acpi_softc *);
    111  1.7.2.4   gehenna #if ACPI_PCI_FIXUP
    112  1.7.2.4   gehenna void		acpi_pci_fixup(struct acpi_softc *);
    113  1.7.2.4   gehenna #endif
    114  1.7.2.4   gehenna #if ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV
    115  1.7.2.4   gehenna ACPI_STATUS	acpi_allocate_resources(ACPI_HANDLE handle);
    116  1.7.2.4   gehenna #endif
    117      1.1   thorpej 
    118      1.1   thorpej /*
    119      1.1   thorpej  * acpi_probe:
    120      1.1   thorpej  *
    121      1.1   thorpej  *	Probe for ACPI support.  This is called by the
    122      1.1   thorpej  *	machine-dependent ACPI front-end.  All of the
    123      1.1   thorpej  *	actual work is done by ACPICA.
    124      1.1   thorpej  *
    125      1.1   thorpej  *	NOTE: This is not an autoconfiguration interface function.
    126      1.1   thorpej  */
    127      1.1   thorpej int
    128      1.1   thorpej acpi_probe(void)
    129      1.1   thorpej {
    130      1.1   thorpej 	static int beenhere;
    131      1.1   thorpej 	ACPI_STATUS rv;
    132      1.1   thorpej 
    133      1.1   thorpej 	if (beenhere != 0)
    134      1.1   thorpej 		panic("acpi_probe: ACPI has already been probed");
    135      1.1   thorpej 	beenhere = 1;
    136      1.1   thorpej 
    137      1.1   thorpej 	/*
    138      1.1   thorpej 	 * Start up ACPICA.
    139      1.1   thorpej 	 */
    140      1.1   thorpej #ifdef ENABLE_DEBUGGER
    141      1.1   thorpej 	if (acpi_dbgr & ACPI_DBGR_INIT)
    142      1.1   thorpej 		acpi_osd_debugger();
    143      1.1   thorpej #endif
    144      1.1   thorpej 
    145      1.1   thorpej 	rv = AcpiInitializeSubsystem();
    146      1.1   thorpej 	if (rv != AE_OK) {
    147      1.1   thorpej 		printf("ACPI: unable to initialize ACPICA: %d\n", rv);
    148      1.1   thorpej 		return (0);
    149      1.1   thorpej 	}
    150      1.1   thorpej 
    151      1.1   thorpej #ifdef ENABLE_DEBUGGER
    152      1.1   thorpej 	if (acpi_dbgr & ACPI_DBGR_TABLES)
    153      1.1   thorpej 		acpi_osd_debugger();
    154      1.1   thorpej #endif
    155      1.1   thorpej 
    156      1.1   thorpej 	rv = AcpiLoadTables();
    157      1.1   thorpej 	if (rv != AE_OK) {
    158      1.1   thorpej 		printf("ACPI: unable to load tables: %d\n", rv);
    159      1.1   thorpej 		return (0);
    160      1.1   thorpej 	}
    161      1.1   thorpej 
    162      1.1   thorpej 	/*
    163      1.1   thorpej 	 * Looks like we have ACPI!
    164      1.1   thorpej 	 */
    165      1.1   thorpej 
    166      1.1   thorpej 	return (1);
    167      1.1   thorpej }
    168      1.1   thorpej 
    169      1.1   thorpej /*
    170      1.1   thorpej  * acpi_match:
    171      1.1   thorpej  *
    172      1.1   thorpej  *	Autoconfiguration `match' routine.
    173      1.1   thorpej  */
    174      1.1   thorpej int
    175      1.1   thorpej acpi_match(struct device *parent, struct cfdata *match, void *aux)
    176      1.1   thorpej {
    177      1.1   thorpej 	struct acpibus_attach_args *aa = aux;
    178      1.1   thorpej 
    179      1.1   thorpej 	if (strcmp(aa->aa_busname, acpi_cd.cd_name) != 0)
    180      1.1   thorpej 		return (0);
    181      1.1   thorpej 
    182      1.1   thorpej 	/*
    183      1.1   thorpej 	 * XXX Check other locators?  Hard to know -- machine
    184      1.1   thorpej 	 * dependent code has already checked for the presence
    185      1.1   thorpej 	 * of ACPI by calling acpi_probe(), so I suppose we
    186      1.1   thorpej 	 * don't really have to do anything else.
    187      1.1   thorpej 	 */
    188      1.1   thorpej 	return (1);
    189      1.1   thorpej }
    190      1.1   thorpej 
    191      1.1   thorpej /*
    192      1.1   thorpej  * acpi_attach:
    193      1.1   thorpej  *
    194      1.1   thorpej  *	Autoconfiguration `attach' routine.  Finish initializing
    195      1.1   thorpej  *	ACPICA (some initialization was done in acpi_probe(),
    196      1.1   thorpej  *	which was required to check for the presence of ACPI),
    197      1.1   thorpej  *	and enable the ACPI subsystem.
    198      1.1   thorpej  */
    199      1.1   thorpej void
    200      1.1   thorpej acpi_attach(struct device *parent, struct device *self, void *aux)
    201      1.1   thorpej {
    202      1.1   thorpej 	struct acpi_softc *sc = (void *) self;
    203      1.1   thorpej 	struct acpibus_attach_args *aa = aux;
    204      1.1   thorpej 	ACPI_STATUS rv;
    205      1.1   thorpej 
    206      1.1   thorpej 	printf("\n");
    207      1.1   thorpej 
    208      1.1   thorpej 	if (acpi_softc != NULL)
    209      1.1   thorpej 		panic("acpi_attach: ACPI has already been attached");
    210      1.1   thorpej 
    211      1.1   thorpej 	sc->sc_iot = aa->aa_iot;
    212      1.1   thorpej 	sc->sc_memt = aa->aa_memt;
    213      1.1   thorpej 	sc->sc_pc = aa->aa_pc;
    214      1.1   thorpej 	sc->sc_pciflags = aa->aa_pciflags;
    215      1.1   thorpej 
    216      1.1   thorpej 	acpi_softc = sc;
    217      1.1   thorpej 
    218      1.1   thorpej 	/*
    219      1.1   thorpej 	 * Install the default address space handlers.
    220      1.1   thorpej 	 */
    221      1.1   thorpej 
    222      1.1   thorpej 	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
    223      1.1   thorpej 	    ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
    224      1.1   thorpej 	if (rv != AE_OK) {
    225      1.1   thorpej 		printf("%s: unable to install SYSTEM MEMORY handler: %d\n",
    226      1.1   thorpej 		    sc->sc_dev.dv_xname, rv);
    227      1.1   thorpej 		return;
    228      1.1   thorpej 	}
    229      1.1   thorpej 
    230      1.1   thorpej 	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
    231      1.1   thorpej 	    ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
    232      1.1   thorpej 	if (rv != AE_OK) {
    233      1.1   thorpej 		printf("%s: unable to install SYSTEM IO handler: %d\n",
    234      1.1   thorpej 		    sc->sc_dev.dv_xname, rv);
    235      1.1   thorpej 		return;
    236      1.1   thorpej 	}
    237      1.1   thorpej 
    238      1.1   thorpej 	rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
    239      1.1   thorpej 	    ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
    240      1.1   thorpej 	if (rv != AE_OK) {
    241      1.1   thorpej 		printf("%s: unable to install PCI CONFIG handler: %d\n",
    242      1.1   thorpej 		    sc->sc_dev.dv_xname, rv);
    243      1.1   thorpej 		return;
    244      1.1   thorpej 	}
    245      1.1   thorpej 
    246      1.1   thorpej 	/*
    247      1.1   thorpej 	 * Bring ACPI on-line.
    248      1.1   thorpej 	 *
    249      1.1   thorpej 	 * Note that we request that _STA (device init) and _INI (object init)
    250      1.1   thorpej 	 * methods not be run.
    251      1.1   thorpej 	 *
    252      1.1   thorpej 	 * XXX We need to arrange for the object init pass after we have
    253      1.1   thorpej 	 * XXX attached all of our children.
    254      1.1   thorpej 	 */
    255      1.1   thorpej #ifdef ENABLE_DEBUGGER
    256      1.1   thorpej 	if (acpi_dbgr & ACPI_DBGR_ENABLE)
    257      1.1   thorpej 		acpi_osd_debugger();
    258      1.1   thorpej #endif
    259      1.1   thorpej 	rv = AcpiEnableSubsystem(ACPI_NO_DEVICE_INIT | ACPI_NO_OBJECT_INIT);
    260      1.1   thorpej 	if (rv != AE_OK) {
    261      1.1   thorpej 		printf("%s: unable to enable ACPI: %d\n",
    262      1.1   thorpej 		    sc->sc_dev.dv_xname, rv);
    263      1.1   thorpej 		return;
    264      1.1   thorpej 	}
    265      1.1   thorpej 	acpi_active = 1;
    266      1.1   thorpej 
    267      1.1   thorpej 	/*
    268      1.1   thorpej 	 * Set up the default sleep state to enter when various
    269      1.1   thorpej 	 * switches are activated.
    270      1.1   thorpej 	 */
    271      1.1   thorpej 	sc->sc_switch_sleep[ACPI_SWITCH_POWERBUTTON] = ACPI_STATE_S5;
    272      1.1   thorpej 	sc->sc_switch_sleep[ACPI_SWITCH_SLEEPBUTTON] = ACPI_STATE_S1;
    273      1.1   thorpej 	sc->sc_switch_sleep[ACPI_SWITCH_LID]	     = ACPI_STATE_S1;
    274      1.1   thorpej 
    275      1.1   thorpej 	/* Our current state is "awake". */
    276      1.1   thorpej 	sc->sc_sleepstate = ACPI_STATE_S0;
    277      1.1   thorpej 
    278  1.7.2.1   gehenna 	/* Show SCI interrupt. */
    279  1.7.2.1   gehenna 	if (AcpiGbl_FADT != NULL)
    280  1.7.2.1   gehenna 		printf("%s: SCI interrupting at irq %d\n",
    281  1.7.2.1   gehenna 			sc->sc_dev.dv_xname, AcpiGbl_FADT->SciInt);
    282      1.1   thorpej 	/*
    283      1.1   thorpej 	 * Check for fixed-hardware features.
    284      1.1   thorpej 	 */
    285      1.1   thorpej 	acpi_enable_fixed_events(sc);
    286      1.1   thorpej 
    287      1.1   thorpej 	/*
    288  1.7.2.4   gehenna 	 * Fix up PCI devices.
    289  1.7.2.4   gehenna 	 */
    290  1.7.2.4   gehenna #if ACPI_PCI_FIXUP
    291  1.7.2.4   gehenna 	acpi_pci_fixup(sc);
    292  1.7.2.4   gehenna #endif
    293  1.7.2.4   gehenna 
    294  1.7.2.4   gehenna 	/*
    295      1.1   thorpej 	 * Scan the namespace and build our device tree.
    296      1.1   thorpej 	 */
    297      1.1   thorpej #ifdef ENABLE_DEBUGGER
    298      1.1   thorpej 	if (acpi_dbgr & ACPI_DBGR_PROBE)
    299      1.1   thorpej 		acpi_osd_debugger();
    300      1.1   thorpej #endif
    301      1.1   thorpej 	acpi_build_tree(sc);
    302      1.1   thorpej 
    303      1.1   thorpej 	/*
    304      1.1   thorpej 	 * Register a shutdown hook that disables certain ACPI
    305      1.1   thorpej 	 * events that might happen and confuse us while we're
    306      1.1   thorpej 	 * trying to shut down.
    307      1.1   thorpej 	 */
    308      1.1   thorpej 	sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
    309      1.1   thorpej 	if (sc->sc_sdhook == NULL)
    310      1.1   thorpej 		printf("%s: WARNING: unable to register shutdown hook\n",
    311      1.1   thorpej 		    sc->sc_dev.dv_xname);
    312      1.1   thorpej 
    313      1.1   thorpej #ifdef ENABLE_DEBUGGER
    314      1.1   thorpej 	if (acpi_dbgr & ACPI_DBGR_RUNNING)
    315      1.1   thorpej 		acpi_osd_debugger();
    316      1.1   thorpej #endif
    317      1.1   thorpej }
    318      1.1   thorpej 
    319      1.1   thorpej /*
    320      1.1   thorpej  * acpi_shutdown:
    321      1.1   thorpej  *
    322      1.1   thorpej  *	Shutdown hook for ACPI -- disable some events that
    323      1.1   thorpej  *	might confuse us.
    324      1.1   thorpej  */
    325      1.1   thorpej void
    326      1.1   thorpej acpi_shutdown(void *arg)
    327      1.1   thorpej {
    328      1.1   thorpej 	struct acpi_softc *sc = arg;
    329      1.1   thorpej 
    330      1.1   thorpej 	if (acpi_disable(sc) != AE_OK)
    331      1.1   thorpej 		printf("%s: WARNING: unable to disable ACPI\n",
    332      1.1   thorpej 		    sc->sc_dev.dv_xname);
    333      1.1   thorpej }
    334      1.1   thorpej 
    335      1.1   thorpej /*
    336      1.1   thorpej  * acpi_disable:
    337      1.1   thorpej  *
    338      1.1   thorpej  *	Disable ACPI.
    339      1.1   thorpej  */
    340      1.1   thorpej ACPI_STATUS
    341      1.1   thorpej acpi_disable(struct acpi_softc *sc)
    342      1.1   thorpej {
    343      1.1   thorpej 	ACPI_STATUS rv = AE_OK;
    344      1.1   thorpej 
    345      1.1   thorpej 	if (acpi_active) {
    346      1.1   thorpej 		rv = AcpiDisable();
    347      1.1   thorpej 		if (rv == AE_OK)
    348      1.1   thorpej 			acpi_active = 0;
    349      1.1   thorpej 	}
    350      1.1   thorpej 	return (rv);
    351      1.1   thorpej }
    352      1.1   thorpej 
    353      1.1   thorpej struct acpi_make_devnode_state {
    354      1.1   thorpej 	struct acpi_softc *softc;
    355      1.1   thorpej 	struct acpi_scope *scope;
    356      1.1   thorpej };
    357      1.1   thorpej 
    358      1.1   thorpej /*
    359      1.1   thorpej  * acpi_build_tree:
    360      1.1   thorpej  *
    361      1.1   thorpej  *	Scan relevant portions of the ACPI namespace and attach
    362      1.1   thorpej  *	child devices.
    363      1.1   thorpej  */
    364      1.1   thorpej void
    365      1.1   thorpej acpi_build_tree(struct acpi_softc *sc)
    366      1.1   thorpej {
    367      1.1   thorpej 	static const char *scopes[] = {
    368      1.1   thorpej 		"\\_PR_",	/* ACPI 1.0 processor namespace */
    369      1.1   thorpej 		"\\_SB_",	/* system bus namespace */
    370      1.1   thorpej 		"\\_SI_",	/* system idicator namespace */
    371      1.1   thorpej 		"\\_TZ_",	/* ACPI 1.0 thermal zone namespace */
    372      1.1   thorpej 		NULL,
    373      1.1   thorpej 	};
    374      1.1   thorpej 	struct acpi_attach_args aa;
    375      1.1   thorpej 	struct acpi_make_devnode_state state;
    376      1.1   thorpej 	struct acpi_scope *as;
    377      1.1   thorpej 	struct acpi_devnode *ad;
    378      1.1   thorpej 	ACPI_HANDLE parent;
    379      1.1   thorpej 	int i;
    380      1.1   thorpej 
    381      1.1   thorpej 	TAILQ_INIT(&sc->sc_scopes);
    382      1.1   thorpej 
    383      1.1   thorpej 	state.softc = sc;
    384      1.1   thorpej 
    385      1.1   thorpej 	/*
    386      1.1   thorpej 	 * Scan the namespace and build our tree.
    387      1.1   thorpej 	 */
    388      1.1   thorpej 	for (i = 0; scopes[i] != NULL; i++) {
    389      1.1   thorpej 		as = malloc(sizeof(*as), M_DEVBUF, M_WAITOK);
    390      1.1   thorpej 		as->as_name = scopes[i];
    391      1.1   thorpej 		TAILQ_INIT(&as->as_devnodes);
    392      1.1   thorpej 
    393      1.1   thorpej 		TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
    394      1.1   thorpej 
    395      1.1   thorpej 		state.scope = as;
    396      1.1   thorpej 
    397      1.1   thorpej 		if (AcpiGetHandle(ACPI_ROOT_OBJECT, (char *) scopes[i],
    398      1.1   thorpej 		    &parent) == AE_OK) {
    399      1.1   thorpej 			AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
    400      1.1   thorpej 			    acpi_make_devnode, &state, NULL);
    401      1.1   thorpej 		}
    402      1.1   thorpej 
    403      1.1   thorpej 		/* Now, for this namespace, try and attach the devices. */
    404      1.1   thorpej 		TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
    405      1.1   thorpej 			aa.aa_node = ad;
    406      1.1   thorpej 			aa.aa_iot = sc->sc_iot;
    407      1.1   thorpej 			aa.aa_memt = sc->sc_memt;
    408      1.1   thorpej 			aa.aa_pc = sc->sc_pc;
    409      1.1   thorpej 			aa.aa_pciflags = sc->sc_pciflags;
    410      1.1   thorpej 
    411      1.1   thorpej 			/*
    412      1.1   thorpej 			 * XXX We only attach devices which are:
    413      1.1   thorpej 			 *
    414      1.1   thorpej 			 *	- present
    415      1.1   thorpej 			 *	- enabled
    416      1.1   thorpej 			 *	- functioning properly
    417      1.1   thorpej 			 *
    418      1.1   thorpej 			 * However, if enabled, it's decoding resources,
    419      1.1   thorpej 			 * so we should claim them, if possible.  Requires
    420      1.1   thorpej 			 * changes to bus_space(9).
    421      1.1   thorpej 			 */
    422      1.1   thorpej 			if ((ad->ad_devinfo.CurrentStatus &
    423      1.1   thorpej 			     (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
    424  1.7.2.1   gehenna 			      ACPI_STA_DEV_OK)) !=
    425      1.1   thorpej 			    (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
    426  1.7.2.1   gehenna 			     ACPI_STA_DEV_OK))
    427      1.1   thorpej 				continue;
    428      1.1   thorpej 
    429      1.1   thorpej 			/*
    430      1.1   thorpej 			 * XXX Same problem as above...
    431      1.1   thorpej 			 */
    432      1.1   thorpej 			if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
    433      1.1   thorpej 				continue;
    434      1.1   thorpej 
    435      1.1   thorpej 			ad->ad_device = config_found(&sc->sc_dev,
    436      1.1   thorpej 			    &aa, acpi_print);
    437      1.1   thorpej 		}
    438      1.1   thorpej 	}
    439      1.1   thorpej }
    440      1.1   thorpej 
    441  1.7.2.4   gehenna #if ACPI_ACTIVATE_DEV
    442  1.7.2.4   gehenna static void
    443  1.7.2.4   gehenna acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO *di)
    444  1.7.2.4   gehenna {
    445  1.7.2.4   gehenna 	ACPI_STATUS rv;
    446  1.7.2.4   gehenna 
    447  1.7.2.4   gehenna #ifdef ACPI_DEBUG
    448  1.7.2.4   gehenna 	printf("acpi_activate_device: %s, old status=%x\n",
    449  1.7.2.4   gehenna 	       di->HardwareId, di->CurrentStatus);
    450  1.7.2.4   gehenna #endif
    451  1.7.2.4   gehenna 
    452  1.7.2.4   gehenna 	rv = acpi_allocate_resources(handle);
    453  1.7.2.4   gehenna 	if (ACPI_FAILURE(rv)) {
    454  1.7.2.4   gehenna 		printf("acpi: activate failed for %s\n", di->HardwareId);
    455  1.7.2.4   gehenna 	}
    456  1.7.2.4   gehenna 
    457  1.7.2.4   gehenna 	(void)AcpiGetObjectInfo(handle, di);
    458  1.7.2.4   gehenna #ifdef ACPI_DEBUG
    459  1.7.2.4   gehenna 	printf("acpi_activate_device: %s, new status=%x\n",
    460  1.7.2.4   gehenna 	       di->HardwareId, di->CurrentStatus);
    461  1.7.2.4   gehenna #endif
    462  1.7.2.4   gehenna }
    463  1.7.2.4   gehenna #endif /* ACPI_ACTIVATE_DEV */
    464  1.7.2.4   gehenna 
    465      1.1   thorpej /*
    466      1.1   thorpej  * acpi_make_devnode:
    467      1.1   thorpej  *
    468      1.1   thorpej  *	Make an ACPI devnode.
    469      1.1   thorpej  */
    470      1.1   thorpej ACPI_STATUS
    471      1.1   thorpej acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
    472      1.1   thorpej     void **status)
    473      1.1   thorpej {
    474      1.1   thorpej 	struct acpi_make_devnode_state *state = context;
    475      1.4   thorpej #ifdef ACPI_DEBUG
    476      1.1   thorpej 	struct acpi_softc *sc = state->softc;
    477      1.4   thorpej #endif
    478      1.1   thorpej 	struct acpi_scope *as = state->scope;
    479      1.1   thorpej 	struct acpi_devnode *ad;
    480  1.7.2.4   gehenna 	ACPI_DEVICE_INFO devinfo;
    481      1.1   thorpej 	ACPI_OBJECT_TYPE type;
    482      1.1   thorpej 	ACPI_STATUS rv;
    483      1.1   thorpej 
    484      1.1   thorpej 	if (AcpiGetType(handle, &type) == AE_OK) {
    485  1.7.2.4   gehenna 		rv = AcpiGetObjectInfo(handle, &devinfo);
    486  1.7.2.4   gehenna 		if (rv != AE_OK) {
    487  1.7.2.4   gehenna #ifdef ACPI_DEBUG
    488  1.7.2.4   gehenna 			printf("%s: AcpiGetObjectInfo failed\n",
    489  1.7.2.4   gehenna 			    sc->sc_dev.dv_xname);
    490  1.7.2.4   gehenna #endif
    491  1.7.2.4   gehenna 			goto out; /* XXX why return OK */
    492  1.7.2.4   gehenna 		}
    493  1.7.2.4   gehenna 
    494      1.1   thorpej 		switch (type) {
    495      1.1   thorpej 		case ACPI_TYPE_DEVICE:
    496  1.7.2.4   gehenna #if ACPI_ACTIVATE_DEV
    497  1.7.2.4   gehenna 			if ((devinfo.Valid & ACPI_VALID_STA) &&
    498  1.7.2.4   gehenna 			    (devinfo.CurrentStatus &
    499  1.7.2.4   gehenna 			     (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) ==
    500  1.7.2.4   gehenna 			    ACPI_STA_DEV_PRESENT)
    501  1.7.2.4   gehenna 				acpi_activate_device(handle, &devinfo);
    502  1.7.2.4   gehenna 			/* FALLTHROUGH */
    503  1.7.2.4   gehenna #endif
    504  1.7.2.4   gehenna 
    505      1.1   thorpej 		case ACPI_TYPE_PROCESSOR:
    506      1.1   thorpej 		case ACPI_TYPE_THERMAL:
    507      1.1   thorpej 		case ACPI_TYPE_POWER:
    508      1.6   tsutsui 			ad = malloc(sizeof(*ad), M_DEVBUF, M_NOWAIT|M_ZERO);
    509      1.1   thorpej 			if (ad == NULL)
    510      1.1   thorpej 				return (AE_NO_MEMORY);
    511      1.1   thorpej 
    512      1.1   thorpej 			ad->ad_handle = handle;
    513      1.1   thorpej 			ad->ad_level = level;
    514      1.1   thorpej 			ad->ad_scope = as;
    515      1.1   thorpej 			ad->ad_type = type;
    516      1.1   thorpej 
    517      1.1   thorpej 			TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
    518      1.1   thorpej 
    519      1.1   thorpej 			rv = AcpiGetObjectInfo(handle, &ad->ad_devinfo);
    520      1.1   thorpej 			if (rv != AE_OK)
    521      1.1   thorpej 				goto out;
    522      1.1   thorpej 
    523      1.1   thorpej 			if ((ad->ad_devinfo.Valid & ACPI_VALID_HID) == 0)
    524      1.1   thorpej 				goto out;
    525      1.1   thorpej 
    526  1.7.2.4   gehenna #ifdef ACPI_EXTRA_DEBUG
    527      1.1   thorpej 			printf("%s: HID %s found in scope %s level %d\n",
    528      1.1   thorpej 			    sc->sc_dev.dv_xname, ad->ad_devinfo.HardwareId,
    529      1.1   thorpej 			    as->as_name, ad->ad_level);
    530      1.1   thorpej 			if (ad->ad_devinfo.Valid & ACPI_VALID_UID)
    531      1.1   thorpej 				printf("       UID %s\n",
    532      1.1   thorpej 				    ad->ad_devinfo.UniqueId);
    533      1.1   thorpej 			if (ad->ad_devinfo.Valid & ACPI_VALID_ADR)
    534      1.1   thorpej 				printf("       ADR 0x%016qx\n",
    535      1.1   thorpej 				    ad->ad_devinfo.Address);
    536      1.1   thorpej 			if (ad->ad_devinfo.Valid & ACPI_VALID_STA)
    537      1.1   thorpej 				printf("       STA 0x%08x\n",
    538      1.1   thorpej 				    ad->ad_devinfo.CurrentStatus);
    539      1.1   thorpej #endif
    540      1.1   thorpej 		}
    541      1.1   thorpej 	}
    542      1.1   thorpej  out:
    543      1.1   thorpej 	return (AE_OK);
    544      1.1   thorpej }
    545      1.1   thorpej 
    546      1.1   thorpej /*
    547      1.1   thorpej  * acpi_print:
    548      1.1   thorpej  *
    549      1.1   thorpej  *	Autoconfiguration print routine.
    550      1.1   thorpej  */
    551      1.1   thorpej int
    552      1.1   thorpej acpi_print(void *aux, const char *pnp)
    553      1.1   thorpej {
    554      1.1   thorpej 	struct acpi_attach_args *aa = aux;
    555      1.7  sommerfe #if 0
    556      1.4   thorpej 	char *str;
    557      1.7  sommerfe #endif
    558      1.1   thorpej 
    559      1.4   thorpej 	if (pnp) {
    560      1.4   thorpej 		printf("%s ", aa->aa_node->ad_devinfo.HardwareId);
    561      1.7  sommerfe #if 0 /* Not until we fix acpi_eval_string */
    562      1.4   thorpej 		if (acpi_eval_string(aa->aa_node->ad_handle,
    563      1.4   thorpej 		    "_STR", &str) == AE_OK) {
    564      1.4   thorpej 			printf("[%s] ", str);
    565      1.4   thorpej 			AcpiOsFree(str);
    566      1.4   thorpej 		}
    567      1.7  sommerfe #endif
    568      1.4   thorpej 		printf("at %s", pnp);
    569      1.4   thorpej 	}
    570      1.1   thorpej 
    571      1.1   thorpej 	return (UNCONF);
    572      1.1   thorpej }
    573      1.1   thorpej 
    574      1.1   thorpej /*****************************************************************************
    575      1.1   thorpej  * ACPI fixed-hardware feature handlers
    576      1.1   thorpej  *****************************************************************************/
    577      1.1   thorpej 
    578      1.1   thorpej UINT32		acpi_fixed_power_button_handler(void *);
    579      1.1   thorpej UINT32		acpi_fixed_sleep_button_handler(void *);
    580      1.1   thorpej 
    581      1.1   thorpej /*
    582      1.1   thorpej  * acpi_enable_fixed_events:
    583      1.1   thorpej  *
    584      1.1   thorpej  *	Enable any fixed-hardware feature handlers.
    585      1.1   thorpej  */
    586      1.1   thorpej void
    587      1.1   thorpej acpi_enable_fixed_events(struct acpi_softc *sc)
    588      1.1   thorpej {
    589      1.1   thorpej 	static int beenhere;
    590      1.1   thorpej 	ACPI_STATUS rv;
    591      1.1   thorpej 
    592      1.1   thorpej 	/*
    593      1.1   thorpej 	 * Check for fixed-hardware buttons.
    594      1.1   thorpej 	 */
    595      1.1   thorpej 
    596      1.1   thorpej 	if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
    597      1.1   thorpej 		if (beenhere == 0)
    598      1.1   thorpej 			printf("%s: fixed-feature power button present\n",
    599      1.1   thorpej 			    sc->sc_dev.dv_xname);
    600      1.1   thorpej 		rv = AcpiInstallFixedEventHandler(ACPI_EVENT_POWER_BUTTON,
    601      1.1   thorpej 		    acpi_fixed_power_button_handler, sc);
    602      1.1   thorpej 		if (rv != AE_OK)
    603      1.1   thorpej 			printf("%s: unable to install handler for fixed "
    604      1.1   thorpej 			    "power button: %d\n", sc->sc_dev.dv_xname, rv);
    605      1.1   thorpej 	}
    606      1.1   thorpej 
    607      1.1   thorpej 	if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
    608      1.1   thorpej 		if (beenhere == 0)
    609      1.1   thorpej 			printf("%s: fixed-feature sleep button present\n",
    610      1.1   thorpej 			    sc->sc_dev.dv_xname);
    611      1.1   thorpej 		rv = AcpiInstallFixedEventHandler(ACPI_EVENT_SLEEP_BUTTON,
    612      1.1   thorpej 		    acpi_fixed_sleep_button_handler, sc);
    613      1.1   thorpej 		if (rv != AE_OK)
    614      1.1   thorpej 			printf("%s: unable to install handler for fixed "
    615      1.1   thorpej 			    "power button: %d\n", sc->sc_dev.dv_xname, rv);
    616      1.1   thorpej 	}
    617      1.1   thorpej 
    618      1.1   thorpej 	beenhere = 1;
    619      1.1   thorpej }
    620      1.1   thorpej 
    621      1.1   thorpej /*
    622      1.1   thorpej  * acpi_fixed_power_button_handler:
    623      1.1   thorpej  *
    624      1.1   thorpej  *	Fixed event handler for the power button.
    625      1.1   thorpej  */
    626      1.1   thorpej UINT32
    627      1.1   thorpej acpi_fixed_power_button_handler(void *context)
    628      1.1   thorpej {
    629      1.1   thorpej 	struct acpi_softc *sc = context;
    630      1.1   thorpej 
    631      1.1   thorpej 	/* XXX XXX XXX */
    632      1.1   thorpej 
    633      1.1   thorpej 	printf("%s: fixed power button pressed\n", sc->sc_dev.dv_xname);
    634      1.1   thorpej 
    635  1.7.2.1   gehenna 	return (ACPI_INTERRUPT_HANDLED);
    636      1.1   thorpej }
    637      1.1   thorpej 
    638      1.1   thorpej /*
    639      1.1   thorpej  * acpi_fixed_sleep_button_handler:
    640      1.1   thorpej  *
    641      1.1   thorpej  *	Fixed event handler for the sleep button.
    642      1.1   thorpej  */
    643      1.1   thorpej UINT32
    644      1.1   thorpej acpi_fixed_sleep_button_handler(void *context)
    645      1.1   thorpej {
    646      1.1   thorpej 	struct acpi_softc *sc = context;
    647      1.1   thorpej 
    648      1.1   thorpej 	/* XXX XXX XXX */
    649      1.1   thorpej 
    650      1.1   thorpej 	printf("%s: fixed sleep button pressed\n", sc->sc_dev.dv_xname);
    651      1.1   thorpej 
    652  1.7.2.1   gehenna 	return (ACPI_INTERRUPT_HANDLED);
    653      1.1   thorpej }
    654      1.1   thorpej 
    655      1.1   thorpej /*****************************************************************************
    656      1.1   thorpej  * ACPI utility routines.
    657      1.1   thorpej  *****************************************************************************/
    658      1.1   thorpej 
    659      1.2   thorpej /*
    660      1.2   thorpej  * acpi_eval_integer:
    661      1.2   thorpej  *
    662      1.2   thorpej  *	Evaluate an integer object.
    663      1.2   thorpej  */
    664      1.1   thorpej ACPI_STATUS
    665      1.1   thorpej acpi_eval_integer(ACPI_HANDLE handle, char *path, int *valp)
    666      1.1   thorpej {
    667      1.1   thorpej 	ACPI_STATUS rv;
    668      1.1   thorpej 	ACPI_BUFFER buf;
    669      1.1   thorpej 	ACPI_OBJECT param;
    670      1.1   thorpej 
    671      1.1   thorpej 	if (handle == NULL)
    672      1.1   thorpej 		handle = ACPI_ROOT_OBJECT;
    673      1.1   thorpej 
    674      1.1   thorpej 	buf.Pointer = &param;
    675      1.1   thorpej 	buf.Length = sizeof(param);
    676      1.1   thorpej 
    677      1.1   thorpej 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    678      1.1   thorpej 	if (rv == AE_OK) {
    679      1.1   thorpej 		if (param.Type == ACPI_TYPE_INTEGER)
    680      1.1   thorpej 			*valp = param.Integer.Value;
    681      1.1   thorpej 		else
    682      1.1   thorpej 			rv = AE_TYPE;
    683      1.1   thorpej 	}
    684      1.1   thorpej 
    685      1.4   thorpej 	return (rv);
    686      1.4   thorpej }
    687      1.4   thorpej 
    688      1.7  sommerfe #if 0
    689      1.4   thorpej /*
    690      1.4   thorpej  * acpi_eval_string:
    691      1.4   thorpej  *
    692      1.7  sommerfe  *	Evaluate a (Unicode) string object.
    693      1.7  sommerfe  * XXX current API may leak memory, so don't use this.
    694      1.4   thorpej  */
    695      1.4   thorpej ACPI_STATUS
    696      1.4   thorpej acpi_eval_string(ACPI_HANDLE handle, char *path, char **stringp)
    697      1.4   thorpej {
    698      1.4   thorpej 	ACPI_STATUS rv;
    699      1.4   thorpej 	ACPI_BUFFER buf;
    700      1.7  sommerfe 	ACPI_OBJECT *param;
    701      1.4   thorpej 
    702      1.4   thorpej 	if (handle == NULL)
    703      1.4   thorpej 		handle = ACPI_ROOT_OBJECT;
    704      1.4   thorpej 
    705      1.4   thorpej 	buf.Pointer = NULL;
    706      1.4   thorpej 	buf.Length = 0;
    707      1.4   thorpej 
    708      1.4   thorpej 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    709      1.4   thorpej 	if (rv != AE_BUFFER_OVERFLOW)
    710      1.4   thorpej 		return (rv);
    711      1.4   thorpej 
    712      1.4   thorpej 	buf.Pointer = AcpiOsAllocate(buf.Length);
    713      1.4   thorpej 	if (buf.Pointer == NULL)
    714      1.4   thorpej 		return (AE_NO_MEMORY);
    715      1.4   thorpej 
    716      1.4   thorpej 	rv = AcpiEvaluateObject(handle, path, NULL, &buf);
    717      1.7  sommerfe 	param = (ACPI_OBJECT *)buf.Pointer;
    718      1.4   thorpej 	if (rv == AE_OK) {
    719      1.7  sommerfe 		if (param->Type == ACPI_TYPE_STRING) {
    720      1.7  sommerfe 			/* XXX may leak buf.Pointer!! */
    721      1.7  sommerfe 			*stringp = param->String.Pointer;
    722      1.4   thorpej 			return (AE_OK);
    723      1.4   thorpej 		}
    724      1.4   thorpej 		rv = AE_TYPE;
    725      1.4   thorpej 	}
    726      1.4   thorpej 
    727      1.4   thorpej 	AcpiOsFree(buf.Pointer);
    728      1.7  sommerfe 	return (rv);
    729      1.7  sommerfe }
    730      1.7  sommerfe #endif
    731      1.7  sommerfe 
    732      1.7  sommerfe 
    733      1.7  sommerfe /*
    734      1.7  sommerfe  * acpi_eval_struct:
    735      1.7  sommerfe  *
    736      1.7  sommerfe  *	Evaluate a more complex structure.  Caller must free buf.Pointer.
    737      1.7  sommerfe  */
    738      1.7  sommerfe ACPI_STATUS
    739      1.7  sommerfe acpi_eval_struct(ACPI_HANDLE handle, char *path, ACPI_BUFFER *bufp)
    740      1.7  sommerfe {
    741      1.7  sommerfe 	ACPI_STATUS rv;
    742      1.7  sommerfe 
    743      1.7  sommerfe 	if (handle == NULL)
    744      1.7  sommerfe 		handle = ACPI_ROOT_OBJECT;
    745      1.7  sommerfe 
    746      1.7  sommerfe 	bufp->Pointer = NULL;
    747      1.7  sommerfe 	bufp->Length = 0;
    748      1.7  sommerfe 
    749      1.7  sommerfe 	rv = AcpiEvaluateObject(handle, path, NULL, bufp);
    750      1.7  sommerfe 	if (rv != AE_BUFFER_OVERFLOW)
    751      1.7  sommerfe 		return (rv);
    752      1.7  sommerfe 
    753      1.7  sommerfe 	bufp->Pointer = AcpiOsAllocate(bufp->Length);
    754      1.7  sommerfe 	if (bufp->Pointer == NULL)
    755      1.7  sommerfe 		return (AE_NO_MEMORY);
    756      1.7  sommerfe 
    757      1.7  sommerfe 	rv = AcpiEvaluateObject(handle, path, NULL, bufp);
    758      1.7  sommerfe 
    759      1.1   thorpej 	return (rv);
    760      1.2   thorpej }
    761      1.2   thorpej 
    762      1.2   thorpej /*
    763      1.2   thorpej  * acpi_get:
    764      1.2   thorpej  *
    765      1.2   thorpej  *	Fetch data info the specified (empty) ACPI buffer.
    766      1.2   thorpej  */
    767      1.2   thorpej ACPI_STATUS
    768      1.2   thorpej acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
    769      1.2   thorpej     ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
    770      1.2   thorpej {
    771      1.2   thorpej 	ACPI_STATUS rv;
    772      1.2   thorpej 
    773      1.2   thorpej 	buf->Pointer = NULL;
    774      1.2   thorpej 	buf->Length = 0;
    775      1.2   thorpej 
    776      1.2   thorpej 	rv = (*getit)(handle, buf);
    777      1.2   thorpej 	if (rv != AE_BUFFER_OVERFLOW)
    778      1.2   thorpej 		return (rv);
    779      1.2   thorpej 
    780  1.7.2.1   gehenna 	buf->Pointer = AcpiOsAllocate(buf->Length);
    781      1.2   thorpej 	if (buf->Pointer == NULL)
    782      1.2   thorpej 		return (AE_NO_MEMORY);
    783  1.7.2.1   gehenna 	memset(buf->Pointer, 0, buf->Length);
    784      1.2   thorpej 
    785      1.2   thorpej 	return ((*getit)(handle, buf));
    786  1.7.2.2   gehenna }
    787  1.7.2.2   gehenna 
    788  1.7.2.2   gehenna 
    789  1.7.2.2   gehenna /*****************************************************************************
    790  1.7.2.2   gehenna  * ACPI sleep support.
    791  1.7.2.2   gehenna  *****************************************************************************/
    792  1.7.2.2   gehenna 
    793  1.7.2.2   gehenna static int
    794  1.7.2.2   gehenna is_available_state(struct acpi_softc *sc, int state)
    795  1.7.2.2   gehenna {
    796  1.7.2.2   gehenna 	UINT8 type_a, type_b;
    797  1.7.2.2   gehenna 
    798  1.7.2.2   gehenna 	return (ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
    799  1.7.2.2   gehenna 						  &type_a, &type_b)));
    800  1.7.2.2   gehenna }
    801  1.7.2.2   gehenna 
    802  1.7.2.2   gehenna /*
    803  1.7.2.2   gehenna  * acpi_enter_sleep_state:
    804  1.7.2.2   gehenna  *
    805  1.7.2.2   gehenna  *	enter to the specified sleep state.
    806  1.7.2.2   gehenna  */
    807  1.7.2.2   gehenna 
    808  1.7.2.2   gehenna ACPI_STATUS
    809  1.7.2.2   gehenna acpi_enter_sleep_state(struct acpi_softc *sc, int state)
    810  1.7.2.2   gehenna {
    811  1.7.2.2   gehenna 	int s;
    812  1.7.2.2   gehenna 	ACPI_STATUS ret = AE_OK;
    813  1.7.2.2   gehenna 
    814  1.7.2.2   gehenna 	switch (state) {
    815  1.7.2.2   gehenna 	case ACPI_STATE_S0:
    816  1.7.2.2   gehenna 		break;
    817  1.7.2.2   gehenna 	case ACPI_STATE_S1:
    818  1.7.2.2   gehenna 	case ACPI_STATE_S2:
    819  1.7.2.2   gehenna 	case ACPI_STATE_S3:
    820  1.7.2.2   gehenna 	case ACPI_STATE_S4:
    821  1.7.2.2   gehenna 		if (!is_available_state(sc, state)) {
    822  1.7.2.2   gehenna 			printf("acpi: cannot enter the sleep state (%d).\n",
    823  1.7.2.2   gehenna 			       state);
    824  1.7.2.2   gehenna 			break;
    825  1.7.2.2   gehenna 		}
    826  1.7.2.2   gehenna 		ret = AcpiEnterSleepStatePrep(state);
    827  1.7.2.2   gehenna 		if (ACPI_FAILURE(ret)) {
    828  1.7.2.2   gehenna 			printf("acpi: failed preparing to sleep (%s)\n",
    829  1.7.2.2   gehenna 			       AcpiFormatException(ret));
    830  1.7.2.2   gehenna 			break;
    831  1.7.2.2   gehenna 		}
    832  1.7.2.2   gehenna 		if (state==ACPI_STATE_S1) {
    833  1.7.2.2   gehenna 			/* just enter the state */
    834  1.7.2.3   gehenna 			acpi_md_OsDisableInterrupt();
    835  1.7.2.2   gehenna 			AcpiEnterSleepState((UINT8)state);
    836  1.7.2.2   gehenna 			AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
    837  1.7.2.2   gehenna 		} else {
    838  1.7.2.2   gehenna 			/* XXX: powerhooks(9) framework is too poor to
    839  1.7.2.2   gehenna 			 * support ACPI sleep state...
    840  1.7.2.2   gehenna 			 */
    841  1.7.2.2   gehenna 			dopowerhooks(PWR_SOFTSUSPEND);
    842  1.7.2.2   gehenna 			s = splhigh();
    843  1.7.2.2   gehenna 			dopowerhooks(PWR_SUSPEND);
    844  1.7.2.2   gehenna 			acpi_md_sleep(state);
    845  1.7.2.2   gehenna 			dopowerhooks(PWR_RESUME);
    846  1.7.2.2   gehenna 			splx(s);
    847  1.7.2.2   gehenna 			dopowerhooks(PWR_SOFTRESUME);
    848  1.7.2.2   gehenna 			if (state==ACPI_STATE_S4)
    849  1.7.2.2   gehenna 				AcpiEnable();
    850  1.7.2.2   gehenna 		}
    851  1.7.2.2   gehenna 		AcpiLeaveSleepState((UINT8)state);
    852  1.7.2.2   gehenna 		break;
    853  1.7.2.2   gehenna 	case ACPI_STATE_S5:
    854  1.7.2.2   gehenna 		AcpiEnterSleepStatePrep(ACPI_STATE_S5);
    855  1.7.2.3   gehenna 		acpi_md_OsDisableInterrupt();
    856  1.7.2.2   gehenna 		AcpiEnterSleepState(ACPI_STATE_S5);
    857  1.7.2.2   gehenna 		printf("WARNING: powerdown failed!\n");
    858  1.7.2.2   gehenna 		break;
    859  1.7.2.2   gehenna 	}
    860  1.7.2.2   gehenna 
    861  1.7.2.2   gehenna 	return (ret);
    862      1.1   thorpej }
    863  1.7.2.4   gehenna 
    864  1.7.2.4   gehenna #if ACPI_PCI_FIXUP
    865  1.7.2.4   gehenna ACPI_STATUS acpi_pci_fixup_bus(ACPI_HANDLE, UINT32, void *, void **);
    866  1.7.2.4   gehenna /*
    867  1.7.2.4   gehenna  * acpi_pci_fixup:
    868  1.7.2.4   gehenna  *
    869  1.7.2.4   gehenna  *	Set up PCI devices that BIOS didn't handle right.
    870  1.7.2.4   gehenna  *	Iterate through all devices and try to get the _PTR
    871  1.7.2.4   gehenna  *	(PCI Routing Table).  If it exists then make sure all
    872  1.7.2.4   gehenna  *	interrupt links that it uses are working.
    873  1.7.2.4   gehenna  */
    874  1.7.2.4   gehenna void
    875  1.7.2.4   gehenna acpi_pci_fixup(struct acpi_softc *sc)
    876  1.7.2.4   gehenna {
    877  1.7.2.4   gehenna 	ACPI_HANDLE parent;
    878  1.7.2.4   gehenna 
    879  1.7.2.4   gehenna #ifdef ACPI_DEBUG
    880  1.7.2.4   gehenna 	printf("acpi_pci_fixup starts:\n");
    881  1.7.2.4   gehenna #endif
    882  1.7.2.4   gehenna 	if (AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent) != AE_OK)
    883  1.7.2.4   gehenna 		return;
    884  1.7.2.4   gehenna 	sc->sc_pci_bus = 0;
    885  1.7.2.4   gehenna 	AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100,
    886  1.7.2.4   gehenna 	    acpi_pci_fixup_bus, sc, NULL);
    887  1.7.2.4   gehenna }
    888  1.7.2.4   gehenna 
    889  1.7.2.4   gehenna static ACPI_HANDLE
    890  1.7.2.4   gehenna acpi_get_node(char *name)
    891  1.7.2.4   gehenna {
    892  1.7.2.4   gehenna 	ACPI_NAMESPACE_NODE *ObjDesc;
    893  1.7.2.4   gehenna 	ACPI_STATUS Status;
    894  1.7.2.4   gehenna 
    895  1.7.2.4   gehenna 	Status = AcpiNsGetNodeByPath(name, NULL, 0, &ObjDesc);
    896  1.7.2.4   gehenna 	if (ACPI_FAILURE (Status)) {
    897  1.7.2.4   gehenna 		printf("acpi_get_node: could not find: %s\n",
    898  1.7.2.4   gehenna 		       AcpiFormatException (Status));
    899  1.7.2.4   gehenna 		return NULL;
    900  1.7.2.4   gehenna 	}
    901  1.7.2.4   gehenna 	return ObjDesc;
    902  1.7.2.4   gehenna }
    903  1.7.2.4   gehenna 
    904  1.7.2.4   gehenna static uint
    905  1.7.2.4   gehenna acpi_get_intr(ACPI_HANDLE handle)
    906  1.7.2.4   gehenna {
    907  1.7.2.4   gehenna 	ACPI_BUFFER ret;
    908  1.7.2.4   gehenna 	ACPI_STATUS rv;
    909  1.7.2.4   gehenna 	ACPI_RESOURCE *res;
    910  1.7.2.4   gehenna 	ACPI_RESOURCE_IRQ *irq;
    911  1.7.2.4   gehenna 	uint intr;
    912  1.7.2.4   gehenna 
    913  1.7.2.4   gehenna 	intr = -1;
    914  1.7.2.4   gehenna 	rv = acpi_get(handle, &ret, AcpiGetCurrentResources);
    915  1.7.2.4   gehenna 	if (ACPI_FAILURE(rv))
    916  1.7.2.4   gehenna 		return (intr);
    917  1.7.2.4   gehenna 	for (res = ret.Pointer; res->Id != ACPI_RSTYPE_END_TAG;
    918  1.7.2.4   gehenna 	     res = ACPI_NEXT_RESOURCE(res)) {
    919  1.7.2.4   gehenna 		if (res->Id == ACPI_RSTYPE_IRQ) {
    920  1.7.2.4   gehenna 			irq = (ACPI_RESOURCE_IRQ *)&res->Data;
    921  1.7.2.4   gehenna 			if (irq->NumberOfInterrupts == 1)
    922  1.7.2.4   gehenna 				intr = irq->Interrupts[0];
    923  1.7.2.4   gehenna 			break;
    924  1.7.2.4   gehenna 		}
    925  1.7.2.4   gehenna 	}
    926  1.7.2.4   gehenna 	free(ret.Pointer, M_DEVBUF);
    927  1.7.2.4   gehenna 	return (intr);
    928  1.7.2.4   gehenna }
    929  1.7.2.4   gehenna 
    930  1.7.2.4   gehenna static void
    931  1.7.2.4   gehenna acpi_pci_set_line(int bus, int dev, int pin, int line)
    932  1.7.2.4   gehenna {
    933  1.7.2.4   gehenna 	ACPI_STATUS err;
    934  1.7.2.4   gehenna 	ACPI_PCI_ID pid;
    935  1.7.2.4   gehenna 	UINT32 intr, id, bhlc;
    936  1.7.2.4   gehenna 	int func, nfunc;
    937  1.7.2.4   gehenna 
    938  1.7.2.4   gehenna 	pid.Bus = bus;
    939  1.7.2.4   gehenna 	pid.Device = dev;
    940  1.7.2.4   gehenna 	pid.Function = 0;
    941  1.7.2.4   gehenna 
    942  1.7.2.4   gehenna 	err = AcpiOsReadPciConfiguration(&pid, PCI_BHLC_REG, &bhlc, 32);
    943  1.7.2.4   gehenna 	if (err)
    944  1.7.2.4   gehenna 		return;
    945  1.7.2.4   gehenna 	if (PCI_HDRTYPE_MULTIFN(bhlc))
    946  1.7.2.4   gehenna 		nfunc = 8;
    947  1.7.2.4   gehenna 	else
    948  1.7.2.4   gehenna 		nfunc = 1;
    949  1.7.2.4   gehenna 
    950  1.7.2.4   gehenna 	for (func = 0; func < nfunc; func++) {
    951  1.7.2.4   gehenna 		pid.Function = func;
    952  1.7.2.4   gehenna 
    953  1.7.2.4   gehenna 		err = AcpiOsReadPciConfiguration(&pid, PCI_ID_REG, &id, 32);
    954  1.7.2.4   gehenna 		if (err || PCI_VENDOR(id) == PCI_VENDOR_INVALID ||
    955  1.7.2.4   gehenna 		    PCI_VENDOR(id) == 0)
    956  1.7.2.4   gehenna 			continue;
    957  1.7.2.4   gehenna 
    958  1.7.2.4   gehenna 		err = AcpiOsReadPciConfiguration(&pid, PCI_INTERRUPT_REG,
    959  1.7.2.4   gehenna 			  &intr, 32);
    960  1.7.2.4   gehenna 		if (err) {
    961  1.7.2.4   gehenna 			printf("AcpiOsReadPciConfiguration failed %d\n", err);
    962  1.7.2.4   gehenna 			return;
    963  1.7.2.4   gehenna 		}
    964  1.7.2.4   gehenna 		if (pin == PCI_INTERRUPT_PIN(intr) &&
    965  1.7.2.4   gehenna 		    line != PCI_INTERRUPT_LINE(intr)) {
    966  1.7.2.4   gehenna #ifdef ACPI_DEBUG
    967  1.7.2.4   gehenna 			printf("acpi fixup pci intr: %d:%d:%d %c: %d -> %d\n",
    968  1.7.2.4   gehenna 			       bus, dev, func,
    969  1.7.2.4   gehenna 			       pin + '@', PCI_INTERRUPT_LINE(intr),
    970  1.7.2.4   gehenna 			       line);
    971  1.7.2.4   gehenna #endif
    972  1.7.2.4   gehenna 			intr &= ~(PCI_INTERRUPT_LINE_MASK <<
    973  1.7.2.4   gehenna 				  PCI_INTERRUPT_LINE_SHIFT);
    974  1.7.2.4   gehenna 			intr |= line << PCI_INTERRUPT_LINE_SHIFT;
    975  1.7.2.4   gehenna 			err = AcpiOsWritePciConfiguration(&pid,
    976  1.7.2.4   gehenna 				  PCI_INTERRUPT_REG, intr, 32);
    977  1.7.2.4   gehenna 			if (err) {
    978  1.7.2.4   gehenna 				printf("AcpiOsWritePciConfiguration failed"
    979  1.7.2.4   gehenna 				       " %d\n", err);
    980  1.7.2.4   gehenna 				return;
    981  1.7.2.4   gehenna 			}
    982  1.7.2.4   gehenna 		}
    983  1.7.2.4   gehenna 	}
    984  1.7.2.4   gehenna }
    985  1.7.2.4   gehenna 
    986  1.7.2.4   gehenna ACPI_STATUS
    987  1.7.2.4   gehenna acpi_pci_fixup_bus(ACPI_HANDLE handle, UINT32 level, void *context,
    988  1.7.2.4   gehenna 		   void **status)
    989  1.7.2.4   gehenna {
    990  1.7.2.4   gehenna 	struct acpi_softc *sc = context;
    991  1.7.2.4   gehenna 	ACPI_STATUS rv;
    992  1.7.2.4   gehenna 	ACPI_BUFFER buf;
    993  1.7.2.4   gehenna 	UINT8 *Buffer;
    994  1.7.2.4   gehenna 	ACPI_PCI_ROUTING_TABLE *PrtElement;
    995  1.7.2.4   gehenna 	ACPI_HANDLE link;
    996  1.7.2.4   gehenna 	uint line;
    997  1.7.2.4   gehenna 
    998  1.7.2.4   gehenna 	rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable);
    999  1.7.2.4   gehenna 	if (ACPI_FAILURE(rv))
   1000  1.7.2.4   gehenna 		return (AE_OK);
   1001  1.7.2.4   gehenna 
   1002  1.7.2.4   gehenna #ifdef ACPI_DEBUG
   1003  1.7.2.4   gehenna 	printf("%s: fixing up PCI\n", sc->sc_dev.dv_xname);
   1004  1.7.2.4   gehenna #endif
   1005  1.7.2.4   gehenna 
   1006  1.7.2.4   gehenna         for (Buffer = buf.Pointer; ; Buffer += PrtElement->Length) {
   1007  1.7.2.4   gehenna 		PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer;
   1008  1.7.2.4   gehenna 		if (PrtElement->Length == 0)
   1009  1.7.2.4   gehenna 			break;
   1010  1.7.2.4   gehenna 		if (PrtElement->Source == NULL)
   1011  1.7.2.4   gehenna 			continue;
   1012  1.7.2.4   gehenna 
   1013  1.7.2.4   gehenna 		link = acpi_get_node(PrtElement->Source);
   1014  1.7.2.4   gehenna 		if (link == NULL)
   1015  1.7.2.4   gehenna 			continue;
   1016  1.7.2.4   gehenna 		line = acpi_get_intr(link);
   1017  1.7.2.4   gehenna 		if (line == -1) {
   1018  1.7.2.4   gehenna #ifdef ACPI_DEBUG
   1019  1.7.2.4   gehenna 			printf("%s: fixing up link %s\n", sc->sc_dev.dv_xname,
   1020  1.7.2.4   gehenna 			    PrtElement->Source);
   1021  1.7.2.4   gehenna #endif
   1022  1.7.2.4   gehenna 			rv = acpi_allocate_resources(link);
   1023  1.7.2.4   gehenna 			if (ACPI_FAILURE(rv)) {
   1024  1.7.2.4   gehenna 				printf("%s: interrupt allocation failed %s\n",
   1025  1.7.2.4   gehenna 				    sc->sc_dev.dv_xname, PrtElement->Source);
   1026  1.7.2.4   gehenna 				continue;
   1027  1.7.2.4   gehenna 			}
   1028  1.7.2.4   gehenna 			line = acpi_get_intr(link);
   1029  1.7.2.4   gehenna 			if (line == -1) {
   1030  1.7.2.4   gehenna 				printf("%s: get intr failed %s\n",
   1031  1.7.2.4   gehenna 				    sc->sc_dev.dv_xname, PrtElement->Source);
   1032  1.7.2.4   gehenna 				continue;
   1033  1.7.2.4   gehenna 			}
   1034  1.7.2.4   gehenna 		}
   1035  1.7.2.4   gehenna 
   1036  1.7.2.4   gehenna 		acpi_pci_set_line(sc->sc_pci_bus, PrtElement->Address >> 16,
   1037  1.7.2.4   gehenna 		    PrtElement->Pin + 1, line);
   1038  1.7.2.4   gehenna 	}
   1039  1.7.2.4   gehenna 
   1040  1.7.2.4   gehenna 	sc->sc_pci_bus++;
   1041  1.7.2.4   gehenna 
   1042  1.7.2.4   gehenna 	free(buf.Pointer, M_DEVBUF);
   1043  1.7.2.4   gehenna 	return (AE_OK);
   1044  1.7.2.4   gehenna }
   1045  1.7.2.4   gehenna #endif /* ACPI_PCI_FIXUP */
   1046  1.7.2.4   gehenna 
   1047  1.7.2.4   gehenna #if ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV
   1048  1.7.2.4   gehenna /* XXX This very incomplete */
   1049  1.7.2.4   gehenna ACPI_STATUS
   1050  1.7.2.4   gehenna acpi_allocate_resources(ACPI_HANDLE handle)
   1051  1.7.2.4   gehenna {
   1052  1.7.2.4   gehenna 	ACPI_BUFFER bufp, bufc, bufn;
   1053  1.7.2.4   gehenna 	ACPI_RESOURCE *resp, *resc, *resn;
   1054  1.7.2.4   gehenna 	ACPI_RESOURCE_IRQ *irq;
   1055  1.7.2.4   gehenna 	ACPI_STATUS rv;
   1056  1.7.2.4   gehenna 	uint delta;
   1057  1.7.2.4   gehenna 
   1058  1.7.2.4   gehenna 	rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
   1059  1.7.2.4   gehenna 	if (ACPI_FAILURE(rv))
   1060  1.7.2.4   gehenna 		goto out;
   1061  1.7.2.4   gehenna 	rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
   1062  1.7.2.4   gehenna 	if (ACPI_FAILURE(rv)) {
   1063  1.7.2.4   gehenna 		goto out1;
   1064  1.7.2.4   gehenna 	}
   1065  1.7.2.4   gehenna 
   1066  1.7.2.4   gehenna 	bufn.Length = 1000;
   1067  1.7.2.4   gehenna 	bufn.Pointer = resn = malloc(bufn.Length, M_DEVBUF, M_WAITOK);
   1068  1.7.2.4   gehenna 	resp = bufp.Pointer;
   1069  1.7.2.4   gehenna 	resc = bufc.Pointer;
   1070  1.7.2.4   gehenna 	while (resc->Id != ACPI_RSTYPE_END_TAG &&
   1071  1.7.2.4   gehenna 	       resp->Id != ACPI_RSTYPE_END_TAG) {
   1072  1.7.2.4   gehenna 		while (resc->Id != resp->Id && resp->Id != ACPI_RSTYPE_END_TAG)
   1073  1.7.2.4   gehenna 			resp = ACPI_NEXT_RESOURCE(resp);
   1074  1.7.2.4   gehenna 		if (resp->Id == ACPI_RSTYPE_END_TAG)
   1075  1.7.2.4   gehenna 			break;
   1076  1.7.2.4   gehenna 		/* Found identical Id */
   1077  1.7.2.4   gehenna 		resn->Id = resc->Id;
   1078  1.7.2.4   gehenna 		switch (resc->Id) {
   1079  1.7.2.4   gehenna 		case ACPI_RSTYPE_IRQ:
   1080  1.7.2.4   gehenna 			memcpy(&resn->Data, &resp->Data,
   1081  1.7.2.4   gehenna 			       sizeof(ACPI_RESOURCE_IRQ));
   1082  1.7.2.4   gehenna 			irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
   1083  1.7.2.4   gehenna 			irq->Interrupts[0] =
   1084  1.7.2.4   gehenna 			    ((ACPI_RESOURCE_IRQ *)&resp->Data)->
   1085  1.7.2.4   gehenna 			        Interrupts[irq->NumberOfInterrupts-1];
   1086  1.7.2.4   gehenna 			irq->NumberOfInterrupts = 1;
   1087  1.7.2.4   gehenna 			resn->Length = ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_IRQ);
   1088  1.7.2.4   gehenna 			break;
   1089  1.7.2.4   gehenna 		case ACPI_RSTYPE_IO:
   1090  1.7.2.4   gehenna 			memcpy(&resn->Data, &resp->Data,
   1091  1.7.2.4   gehenna 			       sizeof(ACPI_RESOURCE_IO));
   1092  1.7.2.4   gehenna 			resn->Length = resp->Length;
   1093  1.7.2.4   gehenna 			break;
   1094  1.7.2.4   gehenna 		default:
   1095  1.7.2.4   gehenna 			printf("acpi_allocate_resources: res=%d\n", resc->Id);
   1096  1.7.2.4   gehenna 			rv = AE_BAD_DATA;
   1097  1.7.2.4   gehenna 			goto out2;
   1098  1.7.2.4   gehenna 		}
   1099  1.7.2.4   gehenna 		resc = ACPI_NEXT_RESOURCE(resc);
   1100  1.7.2.4   gehenna 		resn = ACPI_NEXT_RESOURCE(resn);
   1101  1.7.2.4   gehenna 		delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
   1102  1.7.2.4   gehenna 		if (delta >= bufn.Length-ACPI_SIZEOF_RESOURCE(ACPI_RESOURCE_DATA)) {
   1103  1.7.2.4   gehenna 			bufn.Length *= 2;
   1104  1.7.2.4   gehenna 			bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
   1105  1.7.2.4   gehenna 					       M_DEVBUF, M_WAITOK);
   1106  1.7.2.4   gehenna 			resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
   1107  1.7.2.4   gehenna 		}
   1108  1.7.2.4   gehenna 	}
   1109  1.7.2.4   gehenna 	if (resc->Id != ACPI_RSTYPE_END_TAG) {
   1110  1.7.2.4   gehenna 		printf("acpi_allocate_resources: resc not exhausted\n");
   1111  1.7.2.4   gehenna 		rv = AE_BAD_DATA;
   1112  1.7.2.4   gehenna 		goto out3;
   1113  1.7.2.4   gehenna 	}
   1114  1.7.2.4   gehenna 
   1115  1.7.2.4   gehenna 	resn->Id = ACPI_RSTYPE_END_TAG;
   1116  1.7.2.4   gehenna 	rv = AcpiSetCurrentResources(handle, &bufn);
   1117  1.7.2.4   gehenna 	if (ACPI_FAILURE(rv)) {
   1118  1.7.2.4   gehenna 		printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n",
   1119  1.7.2.4   gehenna 		       AcpiFormatException(rv));
   1120  1.7.2.4   gehenna 	}
   1121  1.7.2.4   gehenna 
   1122  1.7.2.4   gehenna out3:
   1123  1.7.2.4   gehenna 	free(bufn.Pointer, M_DEVBUF);
   1124  1.7.2.4   gehenna out2:
   1125  1.7.2.4   gehenna 	free(bufc.Pointer, M_DEVBUF);
   1126  1.7.2.4   gehenna out1:
   1127  1.7.2.4   gehenna 	free(bufp.Pointer, M_DEVBUF);
   1128  1.7.2.4   gehenna out:
   1129  1.7.2.4   gehenna 	return rv;
   1130  1.7.2.4   gehenna }
   1131  1.7.2.4   gehenna #endif /* ACPI_PCI_FIXUP || ACPI_ACTIVATE_DEV */
   1132