[BACK]Return to acpi.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / acpi

Annotation of src/sys/dev/acpi/acpi.c, Revision 1.148.2.2

1.148.2.1  uebayasi    1: /*     $NetBSD$        */
1.50      mycroft     2:
                      3: /*-
1.101     ad          4:  * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
1.50      mycroft     5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Charles M. Hannum of By Noon Software, Inc.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
1.1       thorpej    31:
                     32: /*
1.148.2.2! uebayasi   33:  * Copyright (c) 2003 Wasabi Systems, Inc.
        !            34:  * All rights reserved.
        !            35:  *
        !            36:  * Written by Frank van der Linden for Wasabi Systems, Inc.
        !            37:  *
        !            38:  * Redistribution and use in source and binary forms, with or without
        !            39:  * modification, are permitted provided that the following conditions
        !            40:  * are met:
        !            41:  * 1. Redistributions of source code must retain the above copyright
        !            42:  *    notice, this list of conditions and the following disclaimer.
        !            43:  * 2. Redistributions in binary form must reproduce the above copyright
        !            44:  *    notice, this list of conditions and the following disclaimer in the
        !            45:  *    documentation and/or other materials provided with the distribution.
        !            46:  * 3. All advertising materials mentioning features or use of this software
        !            47:  *    must display the following acknowledgement:
        !            48:  *      This product includes software developed for the NetBSD Project by
        !            49:  *      Wasabi Systems, Inc.
        !            50:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
        !            51:  *    or promote products derived from this software without specific prior
        !            52:  *    written permission.
        !            53:  *
        !            54:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
        !            55:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
        !            56:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
        !            57:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
        !            58:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
        !            59:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
        !            60:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
        !            61:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
        !            62:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
        !            63:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
        !            64:  * POSSIBILITY OF SUCH DAMAGE.
        !            65:  */
        !            66:
        !            67: /*
1.34      thorpej    68:  * Copyright 2001, 2003 Wasabi Systems, Inc.
1.1       thorpej    69:  * All rights reserved.
                     70:  *
                     71:  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
                     72:  *
                     73:  * Redistribution and use in source and binary forms, with or without
                     74:  * modification, are permitted provided that the following conditions
                     75:  * are met:
                     76:  * 1. Redistributions of source code must retain the above copyright
                     77:  *    notice, this list of conditions and the following disclaimer.
                     78:  * 2. Redistributions in binary form must reproduce the above copyright
                     79:  *    notice, this list of conditions and the following disclaimer in the
                     80:  *    documentation and/or other materials provided with the distribution.
                     81:  * 3. All advertising materials mentioning features or use of this software
                     82:  *    must display the following acknowledgement:
                     83:  *     This product includes software developed for the NetBSD Project by
                     84:  *     Wasabi Systems, Inc.
                     85:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
                     86:  *    or promote products derived from this software without specific prior
                     87:  *    written permission.
                     88:  *
                     89:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
                     90:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     91:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     92:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
                     93:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     94:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     95:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     96:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     97:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     98:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     99:  * POSSIBILITY OF SUCH DAMAGE.
                    100:  */
                    101:
1.5       lukem     102: #include <sys/cdefs.h>
1.148.2.1  uebayasi  103: __KERNEL_RCSID(0, "$NetBSD$");
1.27      christos  104:
                    105: #include "opt_acpi.h"
1.73      sekiya    106: #include "opt_pcifixup.h"
1.1       thorpej   107:
                    108: #include <sys/param.h>
                    109: #include <sys/device.h>
1.148.2.1  uebayasi  110: #include <sys/kernel.h>
1.1       thorpej   111: #include <sys/malloc.h>
1.148.2.2! uebayasi  112: #include <sys/module.h>
1.100     xtraeme   113: #include <sys/mutex.h>
1.78      cube      114: #include <sys/sysctl.h>
1.148.2.1  uebayasi  115: #include <sys/systm.h>
1.148.2.2! uebayasi  116: #include <sys/timetc.h>
1.1       thorpej   117:
                    118: #include <dev/acpi/acpireg.h>
                    119: #include <dev/acpi/acpivar.h>
                    120: #include <dev/acpi/acpi_osd.h>
1.148.2.1  uebayasi  121: #include <dev/acpi/acpi_pci.h>
                    122: #include <dev/acpi/acpi_power.h>
1.90      drochner  123: #include <dev/acpi/acpi_timer.h>
1.127     jmcneill  124: #include <dev/acpi/acpi_wakedev.h>
1.148.2.1  uebayasi  125:
                    126: #define _COMPONENT     ACPI_BUS_COMPONENT
                    127: ACPI_MODULE_NAME       ("acpi")
1.132     mlelstv   128:
1.74      sekiya    129: #if defined(ACPI_PCI_FIXUP)
1.93      christos  130: #error The option ACPI_PCI_FIXUP has been obsoleted by PCI_INTR_FIXUP_DISABLED.  Please adjust your kernel configuration file.
1.74      sekiya    131: #endif
                    132:
1.93      christos  133: #ifdef PCI_INTR_FIXUP_DISABLED
1.13      augustss  134: #include <dev/pci/pcidevs.h>
                    135: #endif
                    136:
1.33      christos  137: MALLOC_DECLARE(M_ACPI);
                    138:
1.10      tshiozak  139: #include <machine/acpi_machdep.h>
1.39      kochi     140:
1.40      kochi     141: #ifdef ACPI_DEBUGGER
1.1       thorpej   142: #define        ACPI_DBGR_INIT          0x01
                    143: #define        ACPI_DBGR_TABLES        0x02
                    144: #define        ACPI_DBGR_ENABLE        0x04
                    145: #define        ACPI_DBGR_PROBE         0x08
                    146: #define        ACPI_DBGR_RUNNING       0x10
                    147:
1.82      kochi     148: static int acpi_dbgr = 0x00;
1.1       thorpej   149: #endif
                    150:
                    151: /*
                    152:  * This is a flag we set when the ACPI subsystem is active.  Machine
                    153:  * dependent code may wish to skip other steps (such as attaching
                    154:  * subsystems that ACPI supercedes) when ACPI is active.
                    155:  */
                    156: int    acpi_active;
1.93      christos  157: int    acpi_force_load;
1.123     jmcneill  158: int    acpi_suspended = 0;
1.148.2.2! uebayasi  159: int    acpi_verbose_loaded = 0;
1.1       thorpej   160:
1.148.2.2! uebayasi  161: struct acpi_softc      *acpi_softc;
        !           162: static uint64_t                 acpi_root_pointer;
        !           163: extern kmutex_t                 acpi_interrupt_list_mtx;
        !           164: extern struct           cfdriver acpi_cd;
        !           165: static ACPI_HANDLE      acpi_scopes[4];
        !           166: ACPI_TABLE_HEADER      *madt_header;
1.1       thorpej   167:
1.32      tshiozak  168: /*
1.148.2.1  uebayasi  169:  * This structure provides a context for the ACPI
                    170:  * namespace walk performed in acpi_build_tree().
1.32      tshiozak  171:  */
1.148.2.1  uebayasi  172: struct acpi_walkcontext {
                    173:        struct acpi_softc       *aw_sc;
                    174:        struct acpi_devnode     *aw_parent;
                    175: };
1.32      tshiozak  176:
1.79      cube      177: /*
1.147     jruoho    178:  * Ignored HIDs.
1.116     jmcneill  179:  */
                    180: static const char * const acpi_ignored_ids[] = {
                    181: #if defined(i386) || defined(x86_64)
                    182:        "PNP0000",      /* AT interrupt controller is handled internally */
                    183:        "PNP0200",      /* AT DMA controller is handled internally */
1.137     cegger    184:        "PNP0A??",      /* PCI Busses are handled internally */
1.116     jmcneill  185:        "PNP0B00",      /* AT RTC is handled internally */
1.143     jruoho    186:        "PNP0C0B",      /* No need for "ACPI fan" driver */
1.116     jmcneill  187:        "PNP0C0F",      /* ACPI PCI link devices are handled internally */
1.148.2.1  uebayasi  188:        "IFX0102",      /* No driver for Infineon TPM */
                    189:        "INT0800",      /* No driver for Intel Firmware Hub device */
1.116     jmcneill  190: #endif
                    191: #if defined(x86_64)
                    192:        "PNP0C04",      /* FPU is handled internally */
                    193: #endif
                    194:        NULL
                    195: };
                    196:
1.148.2.1  uebayasi  197: static int             acpi_match(device_t, cfdata_t, void *);
                    198: static int             acpi_submatch(device_t, cfdata_t, const int *, void *);
                    199: static void            acpi_attach(device_t, device_t, void *);
                    200: static int             acpi_detach(device_t, int);
                    201: static void            acpi_childdet(device_t, device_t);
                    202: static bool            acpi_suspend(device_t, const pmf_qual_t *);
                    203: static bool            acpi_resume(device_t, const pmf_qual_t *);
1.78      cube      204:
1.64      kochi     205: static void            acpi_build_tree(struct acpi_softc *);
1.148.2.1  uebayasi  206: static ACPI_STATUS     acpi_make_devnode(ACPI_HANDLE, uint32_t,
                    207:                                          void *, void **);
                    208: static ACPI_STATUS     acpi_make_devnode_post(ACPI_HANDLE, uint32_t,
                    209:                                               void *, void **);
                    210:
                    211: #ifdef ACPI_ACTIVATE_DEV
                    212: static void            acpi_activate_device(ACPI_HANDLE, ACPI_DEVICE_INFO **);
                    213: static ACPI_STATUS     acpi_allocate_resources(ACPI_HANDLE);
                    214: #endif
                    215:
                    216: static int             acpi_rescan(device_t, const char *, const int *);
                    217: static void            acpi_rescan_nodes(struct acpi_softc *);
                    218: static void            acpi_rescan_capabilities(struct acpi_softc *);
                    219: static int             acpi_print(void *aux, const char *);
                    220:
                    221: static void            acpi_notify_handler(ACPI_HANDLE, uint32_t, void *);
                    222:
                    223: static void            acpi_register_fixed_button(struct acpi_softc *, int);
                    224: static void            acpi_deregister_fixed_button(struct acpi_softc *, int);
                    225: static uint32_t                acpi_fixed_button_handler(void *);
                    226: static void            acpi_fixed_button_pressed(void *);
                    227:
                    228: static void            acpi_sleep_init(struct acpi_softc *);
1.1       thorpej   229:
1.148.2.2! uebayasi  230: static int             sysctl_hw_acpi_fixedstats(SYSCTLFN_PROTO);
        !           231: static int             sysctl_hw_acpi_sleepstate(SYSCTLFN_PROTO);
        !           232: static int             sysctl_hw_acpi_sleepstates(SYSCTLFN_PROTO);
1.1       thorpej   233:
1.148.2.1  uebayasi  234: static bool              acpi_is_scope(struct acpi_devnode *);
1.108     jmcneill  235: static ACPI_TABLE_HEADER *acpi_map_rsdt(void);
1.148.2.1  uebayasi  236: static void              acpi_unmap_rsdt(ACPI_TABLE_HEADER *);
1.108     jmcneill  237:
1.148.2.2! uebayasi  238: void                   acpi_print_verbose_stub(struct acpi_softc *);
        !           239: void                   acpi_print_dev_stub(const char *);
        !           240:
        !           241: void (*acpi_print_verbose)(struct acpi_softc *) = acpi_print_verbose_stub;
        !           242: void (*acpi_print_dev)(const char *) = acpi_print_dev_stub;
1.148.2.1  uebayasi  243:
                    244: CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc),
                    245:     acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet);
1.123     jmcneill  246:
1.1       thorpej   247: /*
1.148.2.1  uebayasi  248:  * Probe for ACPI support.
1.1       thorpej   249:  *
1.148.2.1  uebayasi  250:  * This is called by the machine-dependent ACPI front-end.
                    251:  * Note: this is not an autoconfiguration interface function.
1.1       thorpej   252:  */
                    253: int
                    254: acpi_probe(void)
                    255: {
1.108     jmcneill  256:        ACPI_TABLE_HEADER *rsdt;
1.148.2.1  uebayasi  257:        const char *func;
                    258:        static int once;
                    259:        bool initialized;
1.1       thorpej   260:        ACPI_STATUS rv;
                    261:
1.148.2.1  uebayasi  262:        if (once != 0)
                    263:                panic("%s: already probed", __func__);
                    264:
                    265:        once = 1;
                    266:        func = NULL;
                    267:        initialized = false;
1.1       thorpej   268:
1.103     ad        269:        mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE);
1.32      tshiozak  270:
1.1       thorpej   271:        /*
                    272:         * Start up ACPICA.
                    273:         */
1.40      kochi     274: #ifdef ACPI_DEBUGGER
1.1       thorpej   275:        if (acpi_dbgr & ACPI_DBGR_INIT)
                    276:                acpi_osd_debugger();
                    277: #endif
                    278:
1.148.2.1  uebayasi  279:        CTASSERT(TRUE == true);
                    280:        CTASSERT(FALSE == false);
                    281:
                    282:        AcpiGbl_AllMethodsSerialized = false;
                    283:        AcpiGbl_EnableInterpreterSlack = true;
1.104     jmcneill  284:
1.1       thorpej   285:        rv = AcpiInitializeSubsystem();
                    286:
1.148.2.1  uebayasi  287:        if (ACPI_SUCCESS(rv))
                    288:                initialized = true;
                    289:        else {
                    290:                func = "AcpiInitializeSubsystem()";
                    291:                goto fail;
1.104     jmcneill  292:        }
                    293:
1.148.2.1  uebayasi  294:        /*
                    295:         * Allocate space for RSDT/XSDT and DSDT,
                    296:         * but allow resizing if more tables exist.
                    297:         */
                    298:        rv = AcpiInitializeTables(NULL, 2, true);
                    299:
1.104     jmcneill  300:        if (ACPI_FAILURE(rv)) {
1.148.2.1  uebayasi  301:                func = "AcpiInitializeTables()";
                    302:                goto fail;
1.104     jmcneill  303:        }
                    304:
1.40      kochi     305: #ifdef ACPI_DEBUGGER
1.1       thorpej   306:        if (acpi_dbgr & ACPI_DBGR_TABLES)
                    307:                acpi_osd_debugger();
                    308: #endif
                    309:
                    310:        rv = AcpiLoadTables();
1.148.2.1  uebayasi  311:
1.56      mycroft   312:        if (ACPI_FAILURE(rv)) {
1.148.2.1  uebayasi  313:                func = "AcpiLoadTables()";
                    314:                goto fail;
1.1       thorpej   315:        }
                    316:
1.108     jmcneill  317:        rsdt = acpi_map_rsdt();
1.148.2.1  uebayasi  318:
1.108     jmcneill  319:        if (rsdt == NULL) {
1.148.2.1  uebayasi  320:                func = "acpi_map_rsdt()";
                    321:                rv = AE_ERROR;
                    322:                goto fail;
1.108     jmcneill  323:        }
1.107     jmcneill  324:
1.148.2.1  uebayasi  325:        if (acpi_force_load == 0 && (acpi_find_quirks() & ACPI_QUIRK_BROKEN)) {
                    326:                aprint_normal("ACPI: BIOS is listed as broken:\n");
                    327:                aprint_normal("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, "
1.93      christos  328:                       "AslId <%4.4s,%08x>\n",
1.108     jmcneill  329:                        rsdt->OemId, rsdt->OemTableId,
                    330:                        rsdt->OemRevision,
                    331:                        rsdt->AslCompilerId,
                    332:                        rsdt->AslCompilerRevision);
1.148.2.1  uebayasi  333:                aprint_normal("ACPI: Not used. Set acpi_force_load to use.\n");
1.108     jmcneill  334:                acpi_unmap_rsdt(rsdt);
1.130     jmcneill  335:                AcpiTerminate();
1.93      christos  336:                return 0;
                    337:        }
                    338:
1.108     jmcneill  339:        acpi_unmap_rsdt(rsdt);
                    340:
1.104     jmcneill  341:        rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE));
1.148.2.1  uebayasi  342:
1.104     jmcneill  343:        if (ACPI_FAILURE(rv)) {
1.148.2.1  uebayasi  344:                func = "AcpiEnableSubsystem()";
                    345:                goto fail;
1.104     jmcneill  346:        }
                    347:
1.1       thorpej   348:        /*
                    349:         * Looks like we have ACPI!
                    350:         */
1.63      kochi     351:        return 1;
1.1       thorpej   352:
1.148.2.1  uebayasi  353: fail:
                    354:        KASSERT(rv != AE_OK);
                    355:        KASSERT(func != NULL);
1.98      cube      356:
1.148.2.1  uebayasi  357:        aprint_error("%s: failed to probe ACPI: %s\n",
                    358:            func, AcpiFormatException(rv));
                    359:
                    360:        if (initialized != false)
                    361:                (void)AcpiTerminate();
                    362:
                    363:        return 0;
1.98      cube      364: }
                    365:
1.148.2.2! uebayasi  366: void
        !           367: acpi_disable(void)
        !           368: {
        !           369:
        !           370:        if (AcpiGbl_FADT.SmiCommand != 0)
        !           371:                AcpiDisable();
        !           372: }
        !           373:
1.98      cube      374: int
                    375: acpi_check(device_t parent, const char *ifattr)
                    376: {
                    377:        return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL);
                    378: }
                    379:
1.1       thorpej   380: /*
1.148.2.1  uebayasi  381:  * Autoconfiguration.
1.1       thorpej   382:  */
1.64      kochi     383: static int
1.126     cegger    384: acpi_match(device_t parent, cfdata_t match, void *aux)
1.1       thorpej   385: {
                    386:        /*
1.148.2.1  uebayasi  387:         * XXX: Nada; MD code has called acpi_probe().
1.1       thorpej   388:         */
1.63      kochi     389:        return 1;
1.1       thorpej   390: }
                    391:
1.148.2.1  uebayasi  392: static int
                    393: acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
1.111     dyoung    394: {
1.148.2.1  uebayasi  395:        struct cfattach *ca;
1.111     dyoung    396:
1.148.2.1  uebayasi  397:        ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
1.124     dyoung    398:
1.148.2.1  uebayasi  399:        return (ca == &acpi_ca);
1.111     dyoung    400: }
                    401:
1.64      kochi     402: static void
1.111     dyoung    403: acpi_attach(device_t parent, device_t self, void *aux)
1.1       thorpej   404: {
1.111     dyoung    405:        struct acpi_softc *sc = device_private(self);
1.1       thorpej   406:        struct acpibus_attach_args *aa = aux;
1.108     jmcneill  407:        ACPI_TABLE_HEADER *rsdt;
1.148.2.1  uebayasi  408:        ACPI_STATUS rv;
1.1       thorpej   409:
1.116     jmcneill  410:        aprint_naive("\n");
                    411:        aprint_normal(": Intel ACPICA %08x\n", ACPI_CA_VERSION);
1.1       thorpej   412:
                    413:        if (acpi_softc != NULL)
1.148.2.1  uebayasi  414:                panic("%s: already attached", __func__);
1.37      kochi     415:
1.108     jmcneill  416:        rsdt = acpi_map_rsdt();
1.148.2.1  uebayasi  417:
                    418:        if (rsdt == NULL)
                    419:                aprint_error_dev(self, "X/RSDT: Not found\n");
                    420:        else {
                    421:                aprint_verbose_dev(self,
1.111     dyoung    422:                    "X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
1.108     jmcneill  423:                    rsdt->OemId, rsdt->OemTableId,
                    424:                    rsdt->OemRevision,
                    425:                    rsdt->AslCompilerId, rsdt->AslCompilerRevision);
1.148.2.1  uebayasi  426:        }
                    427:
1.108     jmcneill  428:        acpi_unmap_rsdt(rsdt);
1.1       thorpej   429:
1.113     jmcneill  430:        sc->sc_dev = self;
1.148.2.1  uebayasi  431:        sc->sc_root = NULL;
                    432:
                    433:        sc->sc_sleepstate = ACPI_STATE_S0;
1.36      fvdl      434:        sc->sc_quirks = acpi_find_quirks();
                    435:
1.148.2.1  uebayasi  436:        sysmon_power_settype("acpi");
                    437:
1.1       thorpej   438:        sc->sc_iot = aa->aa_iot;
                    439:        sc->sc_memt = aa->aa_memt;
                    440:        sc->sc_pc = aa->aa_pc;
                    441:        sc->sc_pciflags = aa->aa_pciflags;
1.19      jmcneill  442:        sc->sc_ic = aa->aa_ic;
1.1       thorpej   443:
1.148.2.1  uebayasi  444:        SIMPLEQ_INIT(&sc->ad_head);
                    445:
1.1       thorpej   446:        acpi_softc = sc;
                    447:
1.148.2.1  uebayasi  448:        if (pmf_device_register(self, acpi_suspend, acpi_resume) != true)
1.104     jmcneill  449:                aprint_error_dev(self, "couldn't establish power handler\n");
                    450:
                    451:        /*
1.1       thorpej   452:         * Bring ACPI on-line.
                    453:         */
1.40      kochi     454: #ifdef ACPI_DEBUGGER
1.1       thorpej   455:        if (acpi_dbgr & ACPI_DBGR_ENABLE)
                    456:                acpi_osd_debugger();
                    457: #endif
1.47      mycroft   458:
1.104     jmcneill  459: #define ACPI_ENABLE_PHASE1 \
                    460:     (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
                    461: #define ACPI_ENABLE_PHASE2 \
                    462:     (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
                    463:      ACPI_NO_ADDRESS_SPACE_INIT)
                    464:
                    465:        rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
1.148.2.1  uebayasi  466:
                    467:        if (ACPI_FAILURE(rv))
                    468:                goto fail;
1.104     jmcneill  469:
                    470:        acpi_md_callback();
                    471:
                    472:        rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
1.60      kochi     473:
1.148.2.1  uebayasi  474:        if (ACPI_FAILURE(rv))
                    475:                goto fail;
                    476:
                    477:        /*
                    478:         * Early EC handler initialization if ECDT table is available.
                    479:         */
                    480:        config_found_ia(self, "acpiecdtbus", aa, NULL);
1.60      kochi     481:
1.104     jmcneill  482:        rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
1.1       thorpej   483:
1.148.2.1  uebayasi  484:        if (ACPI_FAILURE(rv))
                    485:                goto fail;
                    486:
                    487:        /*
                    488:         * Install global notify handlers.
                    489:         */
                    490:        rv = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT,
                    491:            ACPI_SYSTEM_NOTIFY, acpi_notify_handler, NULL);
                    492:
                    493:        if (ACPI_FAILURE(rv))
                    494:                goto fail;
                    495:
                    496:        rv = AcpiInstallNotifyHandler(ACPI_ROOT_OBJECT,
                    497:            ACPI_DEVICE_NOTIFY, acpi_notify_handler, NULL);
                    498:
                    499:        if (ACPI_FAILURE(rv))
                    500:                goto fail;
                    501:
                    502:        acpi_active = 1;
1.1       thorpej   503:
1.9       kanaoka   504:        /* Show SCI interrupt. */
1.148.2.1  uebayasi  505:        aprint_verbose_dev(self, "SCI interrupting at int %u\n",
1.111     dyoung    506:            AcpiGbl_FADT.SciInterrupt);
1.104     jmcneill  507:
1.1       thorpej   508:        /*
1.148.2.1  uebayasi  509:         * Install fixed-event handlers.
1.1       thorpej   510:         */
1.148.2.1  uebayasi  511:        acpi_register_fixed_button(sc, ACPI_EVENT_POWER_BUTTON);
                    512:        acpi_register_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON);
                    513:
1.148.2.2! uebayasi  514:        acpitimer_init(sc);
1.1       thorpej   515:
1.40      kochi     516: #ifdef ACPI_DEBUGGER
1.1       thorpej   517:        if (acpi_dbgr & ACPI_DBGR_PROBE)
                    518:                acpi_osd_debugger();
                    519: #endif
                    520:
1.148.2.1  uebayasi  521:        /*
                    522:         * Scan the namespace and build our device tree.
                    523:         */
                    524:        acpi_build_tree(sc);
                    525:        acpi_sleep_init(sc);
1.78      cube      526:
1.40      kochi     527: #ifdef ACPI_DEBUGGER
1.1       thorpej   528:        if (acpi_dbgr & ACPI_DBGR_RUNNING)
                    529:                acpi_osd_debugger();
                    530: #endif
1.148     jruoho    531:
                    532: #ifdef ACPI_DEBUG
                    533:        acpi_debug_init();
                    534: #endif
1.148.2.1  uebayasi  535:
1.148.2.2! uebayasi  536:        /*
        !           537:         * Print debug information.
        !           538:         */
        !           539:        acpi_print_verbose(sc);
        !           540:
1.148.2.1  uebayasi  541:        return;
                    542:
                    543: fail:
                    544:        aprint_error("%s: failed to initialize ACPI: %s\n",
                    545:            __func__, AcpiFormatException(rv));
1.1       thorpej   546: }
                    547:
1.148.2.1  uebayasi  548: /*
                    549:  * XXX: This is incomplete.
                    550:  */
1.124     dyoung    551: static int
                    552: acpi_detach(device_t self, int flags)
                    553: {
1.148.2.1  uebayasi  554:        struct acpi_softc *sc = device_private(self);
                    555:        ACPI_STATUS rv;
1.124     dyoung    556:        int rc;
                    557:
1.148.2.1  uebayasi  558:        rv = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
                    559:            ACPI_SYSTEM_NOTIFY, acpi_notify_handler);
                    560:
                    561:        if (ACPI_FAILURE(rv))
                    562:                return EBUSY;
                    563:
                    564:        rv = AcpiRemoveNotifyHandler(ACPI_ROOT_OBJECT,
                    565:            ACPI_DEVICE_NOTIFY, acpi_notify_handler);
                    566:
                    567:        if (ACPI_FAILURE(rv))
                    568:                return EBUSY;
1.124     dyoung    569:
                    570:        if ((rc = config_detach_children(self, flags)) != 0)
                    571:                return rc;
                    572:
                    573:        if ((rc = acpitimer_detach()) != 0)
                    574:                return rc;
                    575:
1.148.2.1  uebayasi  576:        acpi_deregister_fixed_button(sc, ACPI_EVENT_POWER_BUTTON);
                    577:        acpi_deregister_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON);
1.124     dyoung    578:
1.148.2.1  uebayasi  579:        pmf_device_deregister(self);
1.124     dyoung    580:
1.148.2.1  uebayasi  581:        acpi_softc = NULL;
1.124     dyoung    582:
1.148.2.1  uebayasi  583:        return 0;
                    584: }
1.124     dyoung    585:
1.148.2.1  uebayasi  586: /*
                    587:  * XXX: Need to reclaim any resources? Yes.
                    588:  */
                    589: static void
                    590: acpi_childdet(device_t self, device_t child)
                    591: {
                    592:        struct acpi_softc *sc = device_private(self);
                    593:        struct acpi_devnode *ad;
1.124     dyoung    594:
1.148.2.1  uebayasi  595:        if (sc->sc_apmbus == child)
                    596:                sc->sc_apmbus = NULL;
1.124     dyoung    597:
1.148.2.1  uebayasi  598:        SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1.124     dyoung    599:
1.148.2.1  uebayasi  600:                if (ad->ad_device == child)
                    601:                        ad->ad_device = NULL;
                    602:        }
1.124     dyoung    603: }
                    604:
1.123     jmcneill  605: static bool
1.148.2.1  uebayasi  606: acpi_suspend(device_t dv, const pmf_qual_t *qual)
1.123     jmcneill  607: {
1.148.2.1  uebayasi  608:
1.123     jmcneill  609:        acpi_suspended = 1;
1.148.2.1  uebayasi  610:
1.123     jmcneill  611:        return true;
                    612: }
                    613:
                    614: static bool
1.148.2.1  uebayasi  615: acpi_resume(device_t dv, const pmf_qual_t *qual)
1.123     jmcneill  616: {
1.148.2.1  uebayasi  617:
1.123     jmcneill  618:        acpi_suspended = 0;
1.148.2.1  uebayasi  619:
1.123     jmcneill  620:        return true;
                    621: }
                    622:
1.1       thorpej   623: /*
1.148.2.1  uebayasi  624:  * Namespace scan.
1.1       thorpej   625:  */
1.148.2.1  uebayasi  626: static void
                    627: acpi_build_tree(struct acpi_softc *sc)
                    628: {
                    629:        struct acpi_walkcontext awc;
                    630:
                    631:        /*
                    632:         * Get the root scope handles.
                    633:         */
                    634:        KASSERT(__arraycount(acpi_scopes) == 4);
                    635:
                    636:        (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_PR_", &acpi_scopes[0]);
                    637:        (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &acpi_scopes[1]);
                    638:        (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SI_", &acpi_scopes[2]);
                    639:        (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_TZ_", &acpi_scopes[3]);
                    640:
                    641:        /*
                    642:         * Make the root node.
                    643:         */
                    644:        awc.aw_sc = sc;
                    645:        awc.aw_parent = NULL;
                    646:
                    647:        (void)acpi_make_devnode(ACPI_ROOT_OBJECT, 0, &awc, NULL);
                    648:
                    649:        KASSERT(sc->sc_root == NULL);
                    650:        KASSERT(awc.aw_parent != NULL);
                    651:
                    652:        sc->sc_root = awc.aw_parent;
                    653:
                    654:        /*
                    655:         * Build the internal namespace.
                    656:         */
                    657:        (void)AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, UINT32_MAX,
                    658:            acpi_make_devnode, acpi_make_devnode_post, &awc, NULL);
                    659:
                    660:        /*
                    661:         * Scan the internal namespace.
                    662:         */
1.148.2.2! uebayasi  663:        (void)acpi_rescan(sc->sc_dev, NULL, NULL);
        !           664:
1.148.2.1  uebayasi  665:        acpi_rescan_capabilities(sc);
                    666:
                    667:        (void)acpi_pcidev_scan(sc->sc_root);
                    668: }
                    669:
1.64      kochi     670: static ACPI_STATUS
1.148.2.1  uebayasi  671: acpi_make_devnode(ACPI_HANDLE handle, uint32_t level,
                    672:     void *context, void **status)
1.1       thorpej   673: {
1.148.2.1  uebayasi  674:        struct acpi_walkcontext *awc = context;
                    675:        struct acpi_softc *sc = awc->aw_sc;
                    676:        struct acpi_devnode *ad;
                    677:        ACPI_DEVICE_INFO *devinfo;
                    678:        ACPI_OBJECT_TYPE type;
                    679:        ACPI_NAME_UNION *anu;
                    680:        ACPI_STATUS rv;
                    681:        int clear, i;
1.1       thorpej   682:
1.148.2.1  uebayasi  683:        rv = AcpiGetObjectInfo(handle, &devinfo);
                    684:
                    685:        if (ACPI_FAILURE(rv))
                    686:                return AE_OK;   /* Do not terminate the walk. */
                    687:
                    688:        type = devinfo->Type;
                    689:
                    690:        switch (type) {
                    691:
                    692:        case ACPI_TYPE_DEVICE:
                    693:
                    694: #ifdef ACPI_ACTIVATE_DEV
                    695:                acpi_activate_device(handle, &devinfo);
                    696: #endif
                    697:
                    698:        case ACPI_TYPE_PROCESSOR:
                    699:        case ACPI_TYPE_THERMAL:
                    700:        case ACPI_TYPE_POWER:
                    701:
                    702:                ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT | M_ZERO);
                    703:
                    704:                if (ad == NULL)
                    705:                        return AE_NO_MEMORY;
                    706:
                    707:                ad->ad_device = NULL;
                    708:                ad->ad_notify = NULL;
                    709:                ad->ad_pciinfo = NULL;
                    710:
                    711:                ad->ad_type = type;
                    712:                ad->ad_handle = handle;
                    713:                ad->ad_devinfo = devinfo;
                    714:
                    715:                ad->ad_root = sc->sc_dev;
                    716:                ad->ad_parent = awc->aw_parent;
                    717:
                    718:                anu = (ACPI_NAME_UNION *)&devinfo->Name;
                    719:                ad->ad_name[4] = '\0';
                    720:
                    721:                for (i = 3, clear = 0; i >= 0; i--) {
                    722:
                    723:                        if (clear == 0 && anu->Ascii[i] == '_')
                    724:                                ad->ad_name[i] = '\0';
                    725:                        else {
                    726:                                ad->ad_name[i] = anu->Ascii[i];
                    727:                                clear = 1;
                    728:                        }
                    729:                }
                    730:
                    731:                if (ad->ad_name[0] == '\0')
                    732:                        ad->ad_name[0] = '_';
                    733:
                    734:                SIMPLEQ_INIT(&ad->ad_child_head);
                    735:                SIMPLEQ_INSERT_TAIL(&sc->ad_head, ad, ad_list);
                    736:
1.148.2.2! uebayasi  737:                acpi_set_node(ad);
        !           738:
1.148.2.1  uebayasi  739:                if (ad->ad_parent != NULL) {
                    740:
                    741:                        SIMPLEQ_INSERT_TAIL(&ad->ad_parent->ad_child_head,
                    742:                            ad, ad_child_list);
                    743:                }
                    744:
                    745:                awc->aw_parent = ad;
1.1       thorpej   746:        }
1.148.2.1  uebayasi  747:
                    748:        return AE_OK;
1.1       thorpej   749: }
                    750:
1.148.2.1  uebayasi  751: static ACPI_STATUS
                    752: acpi_make_devnode_post(ACPI_HANDLE handle, uint32_t level,
                    753:     void *context, void **status)
                    754: {
                    755:        struct acpi_walkcontext *awc = context;
1.1       thorpej   756:
1.148.2.1  uebayasi  757:        KASSERT(awc != NULL);
                    758:        KASSERT(awc->aw_parent != NULL);
                    759:
                    760:        if (handle == awc->aw_parent->ad_handle)
                    761:                awc->aw_parent = awc->aw_parent->ad_parent;
                    762:
                    763:        return AE_OK;
                    764: }
                    765:
                    766: #ifdef ACPI_ACTIVATE_DEV
1.64      kochi     767: static void
1.148.2.1  uebayasi  768: acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
1.1       thorpej   769: {
1.148.2.1  uebayasi  770:        static const int valid = ACPI_VALID_STA | ACPI_VALID_HID;
                    771:        ACPI_DEVICE_INFO *newdi;
1.56      mycroft   772:        ACPI_STATUS rv;
1.148.2.1  uebayasi  773:        uint32_t old;
1.1       thorpej   774:
                    775:        /*
1.148.2.1  uebayasi  776:         * If the device is valid and present,
                    777:         * but not enabled, try to activate it.
1.1       thorpej   778:         */
1.148.2.1  uebayasi  779:        if (((*di)->Valid & valid) != valid)
                    780:                return;
                    781:
                    782:        old = (*di)->CurrentStatus;
1.1       thorpej   783:
1.148.2.1  uebayasi  784:        if ((old & (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED)) !=
                    785:            ACPI_STA_DEVICE_PRESENT)
                    786:                return;
1.1       thorpej   787:
1.148.2.1  uebayasi  788:        rv = acpi_allocate_resources(handle);
1.1       thorpej   789:
1.148.2.1  uebayasi  790:        if (ACPI_FAILURE(rv))
                    791:                goto fail;
                    792:
                    793:        rv = AcpiGetObjectInfo(handle, &newdi);
                    794:
                    795:        if (ACPI_FAILURE(rv))
                    796:                goto fail;
                    797:
                    798:        ACPI_FREE(*di);
                    799:        *di = newdi;
                    800:
                    801:        aprint_verbose_dev(acpi_softc->sc_dev,
                    802:            "%s activated, STA 0x%08X -> STA 0x%08X\n",
                    803:            (*di)->HardwareId.String, old, (*di)->CurrentStatus);
                    804:
                    805:        return;
                    806:
                    807: fail:
                    808:        aprint_error_dev(acpi_softc->sc_dev, "failed to "
                    809:            "activate %s\n", (*di)->HardwareId.String);
                    810: }
                    811:
                    812: /*
                    813:  * XXX: This very incomplete.
                    814:  */
                    815: ACPI_STATUS
                    816: acpi_allocate_resources(ACPI_HANDLE handle)
                    817: {
                    818:        ACPI_BUFFER bufp, bufc, bufn;
                    819:        ACPI_RESOURCE *resp, *resc, *resn;
                    820:        ACPI_RESOURCE_IRQ *irq;
                    821:        ACPI_RESOURCE_EXTENDED_IRQ *xirq;
                    822:        ACPI_STATUS rv;
                    823:        uint delta;
                    824:
                    825:        rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
                    826:        if (ACPI_FAILURE(rv))
                    827:                goto out;
                    828:        rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
                    829:        if (ACPI_FAILURE(rv)) {
                    830:                goto out1;
                    831:        }
                    832:
                    833:        bufn.Length = 1000;
                    834:        bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
                    835:        resp = bufp.Pointer;
                    836:        resc = bufc.Pointer;
                    837:        while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG &&
                    838:               resp->Type != ACPI_RESOURCE_TYPE_END_TAG) {
                    839:                while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG)
                    840:                        resp = ACPI_NEXT_RESOURCE(resp);
                    841:                if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG)
                    842:                        break;
                    843:                /* Found identical Id */
                    844:                resn->Type = resc->Type;
                    845:                switch (resc->Type) {
                    846:                case ACPI_RESOURCE_TYPE_IRQ:
                    847:                        memcpy(&resn->Data, &resp->Data,
                    848:                               sizeof(ACPI_RESOURCE_IRQ));
                    849:                        irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
                    850:                        irq->Interrupts[0] =
                    851:                            ((ACPI_RESOURCE_IRQ *)&resp->Data)->
                    852:                                Interrupts[irq->InterruptCount-1];
                    853:                        irq->InterruptCount = 1;
                    854:                        resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
                    855:                        break;
                    856:                case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
                    857:                        memcpy(&resn->Data, &resp->Data,
                    858:                               sizeof(ACPI_RESOURCE_EXTENDED_IRQ));
                    859:                        xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data;
                    860: #if 0
                    861:                        /*
                    862:                         * XXX: Not duplicating the interrupt logic above
                    863:                         *      because its not clear what it accomplishes.
                    864:                         */
                    865:                        xirq->Interrupts[0] =
                    866:                            ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)->
                    867:                            Interrupts[irq->NumberOfInterrupts-1];
                    868:                        xirq->NumberOfInterrupts = 1;
                    869: #endif
                    870:                        resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
                    871:                        break;
                    872:                case ACPI_RESOURCE_TYPE_IO:
                    873:                        memcpy(&resn->Data, &resp->Data,
                    874:                               sizeof(ACPI_RESOURCE_IO));
                    875:                        resn->Length = resp->Length;
                    876:                        break;
                    877:                default:
                    878:                        aprint_error_dev(acpi_softc->sc_dev,
                    879:                            "%s: invalid type %u\n", __func__, resc->Type);
                    880:                        rv = AE_BAD_DATA;
                    881:                        goto out2;
                    882:                }
                    883:                resc = ACPI_NEXT_RESOURCE(resc);
                    884:                resn = ACPI_NEXT_RESOURCE(resn);
                    885:                resp = ACPI_NEXT_RESOURCE(resp);
                    886:                delta = (uint8_t *)resn - (uint8_t *)bufn.Pointer;
                    887:                if (delta >=
                    888:                    bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) {
                    889:                        bufn.Length *= 2;
                    890:                        bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
                    891:                                               M_ACPI, M_WAITOK);
                    892:                        resn = (ACPI_RESOURCE *)((uint8_t *)bufn.Pointer +
                    893:                            delta);
1.1       thorpej   894:                }
1.124     dyoung    895:        }
                    896:
1.148.2.1  uebayasi  897:        if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
                    898:                aprint_error_dev(acpi_softc->sc_dev,
                    899:                    "%s: resc not exhausted\n", __func__);
                    900:                rv = AE_BAD_DATA;
                    901:                goto out3;
                    902:        }
1.127     jmcneill  903:
1.148.2.1  uebayasi  904:        resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
                    905:        rv = AcpiSetCurrentResources(handle, &bufn);
                    906:
                    907:        if (ACPI_FAILURE(rv))
                    908:                aprint_error_dev(acpi_softc->sc_dev, "%s: failed to set "
                    909:                    "resources: %s\n", __func__, AcpiFormatException(rv));
1.137     cegger    910:
1.148.2.1  uebayasi  911: out3:
                    912:        free(bufn.Pointer, M_ACPI);
                    913: out2:
                    914:        ACPI_FREE(bufc.Pointer);
                    915: out1:
                    916:        ACPI_FREE(bufp.Pointer);
                    917: out:
                    918:        return rv;
1.124     dyoung    919: }
1.148.2.1  uebayasi  920: #endif /* ACPI_ACTIVATE_DEV */
1.1       thorpej   921:
1.148.2.1  uebayasi  922: /*
                    923:  * Device attachment.
                    924:  */
1.124     dyoung    925: static int
                    926: acpi_rescan(device_t self, const char *ifattr, const int *locators)
                    927: {
                    928:        struct acpi_softc *sc = device_private(self);
                    929:
                    930:        if (ifattr_match(ifattr, "acpinodebus"))
                    931:                acpi_rescan_nodes(sc);
                    932:
1.148.2.1  uebayasi  933:        if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL)
                    934:                sc->sc_apmbus = config_found_ia(sc->sc_dev,
                    935:                    "acpiapmbus", NULL, NULL);
1.148.2.2! uebayasi  936:
        !           937:        return 0;
1.124     dyoung    938: }
                    939:
                    940: static void
                    941: acpi_rescan_nodes(struct acpi_softc *sc)
                    942: {
1.148.2.1  uebayasi  943:        struct acpi_attach_args aa;
                    944:        struct acpi_devnode *ad;
                    945:        ACPI_DEVICE_INFO *di;
1.124     dyoung    946:
1.148.2.1  uebayasi  947:        SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1.124     dyoung    948:
1.148.2.1  uebayasi  949:                if (ad->ad_device != NULL)
                    950:                        continue;
1.124     dyoung    951:
1.148.2.1  uebayasi  952:                /*
                    953:                 * There is a bug in ACPICA: it defines the type
                    954:                 * of the scopes incorrectly for its own reasons.
                    955:                 */
                    956:                if (acpi_is_scope(ad) != false)
                    957:                        continue;
                    958:
                    959:                di = ad->ad_devinfo;
                    960:
                    961:                /*
                    962:                 * We only attach devices which are present, enabled, and
                    963:                 * functioning properly. However, if a device is enabled,
                    964:                 * it is decoding resources and we should claim these,
                    965:                 * if possible. This requires changes to bus_space(9).
1.148.2.2! uebayasi  966:                 * Note: there is a possible race condition, because _STA
        !           967:                 * may have changed since di->CurrentStatus was set.
1.148.2.1  uebayasi  968:                 */
                    969:                if (di->Type == ACPI_TYPE_DEVICE) {
1.25      jmcneill  970:
1.148.2.1  uebayasi  971:                        if ((di->Valid & ACPI_VALID_STA) != 0 &&
                    972:                            (di->CurrentStatus & ACPI_STA_OK) != ACPI_STA_OK)
1.104     jmcneill  973:                                continue;
1.148.2.1  uebayasi  974:                }
1.1       thorpej   975:
1.148.2.1  uebayasi  976:                /*
                    977:                 * The same problem as above. As for example
                    978:                 * thermal zones and power resources do not
                    979:                 * have a valid HID, only evaluate devices.
                    980:                 */
                    981:                if (di->Type == ACPI_TYPE_DEVICE &&
                    982:                   (di->Valid & ACPI_VALID_HID) == 0)
                    983:                        continue;
                    984:
                    985:                /*
                    986:                 * Handled internally.
                    987:                 */
1.148.2.2! uebayasi  988:                if (di->Type == ACPI_TYPE_POWER)
1.148.2.1  uebayasi  989:                        continue;
1.116     jmcneill  990:
1.148.2.1  uebayasi  991:                /*
                    992:                 * Skip ignored HIDs.
                    993:                 */
                    994:                if (acpi_match_hid(di, acpi_ignored_ids))
                    995:                        continue;
                    996:
                    997:                aa.aa_node = ad;
                    998:                aa.aa_iot = sc->sc_iot;
                    999:                aa.aa_memt = sc->sc_memt;
                   1000:                aa.aa_pc = sc->sc_pc;
                   1001:                aa.aa_pciflags = sc->sc_pciflags;
                   1002:                aa.aa_ic = sc->sc_ic;
1.116     jmcneill 1003:
1.148.2.1  uebayasi 1004:                ad->ad_device = config_found_ia(sc->sc_dev,
                   1005:                    "acpinodebus", &aa, acpi_print);
1.1       thorpej  1006:        }
                   1007: }
                   1008:
1.15      augustss 1009: static void
1.148.2.1  uebayasi 1010: acpi_rescan_capabilities(struct acpi_softc *sc)
1.15      augustss 1011: {
1.148.2.1  uebayasi 1012:        struct acpi_devnode *ad;
                   1013:        ACPI_HANDLE tmp;
1.15      augustss 1014:        ACPI_STATUS rv;
                   1015:
1.148.2.1  uebayasi 1016:        SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1.15      augustss 1017:
1.148.2.2! uebayasi 1018:                if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
1.148.2.1  uebayasi 1019:                        continue;
                   1020:
                   1021:                /*
                   1022:                 * Scan power resource capabilities.
                   1023:                 *
                   1024:                 * If any power states are supported,
                   1025:                 * at least _PR0 and _PR3 must be present.
                   1026:                 */
                   1027:                rv = AcpiGetHandle(ad->ad_handle, "_PR0", &tmp);
1.1       thorpej  1028:
1.148.2.1  uebayasi 1029:                if (ACPI_SUCCESS(rv)) {
                   1030:                        ad->ad_flags |= ACPI_DEVICE_POWER;
                   1031:                        acpi_power_add(ad);
1.15      augustss 1032:                }
                   1033:
1.148.2.1  uebayasi 1034:                /*
                   1035:                 * Scan wake-up capabilities.
                   1036:                 */
                   1037:                rv = AcpiGetHandle(ad->ad_handle, "_PRW", &tmp);
1.43      mycroft  1038:
1.148.2.1  uebayasi 1039:                if (ACPI_SUCCESS(rv)) {
                   1040:                        ad->ad_flags |= ACPI_DEVICE_WAKEUP;
                   1041:                        acpi_wakedev_add(ad);
1.1       thorpej  1042:                }
                   1043:        }
                   1044: }
                   1045:
1.64      kochi    1046: static int
1.1       thorpej  1047: acpi_print(void *aux, const char *pnp)
                   1048: {
                   1049:        struct acpi_attach_args *aa = aux;
1.56      mycroft  1050:        ACPI_STATUS rv;
1.1       thorpej  1051:
1.4       thorpej  1052:        if (pnp) {
1.54      kochi    1053:                if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
                   1054:                        char *pnpstr =
1.128     jmcneill 1055:                            aa->aa_node->ad_devinfo->HardwareId.String;
1.121     mlelstv  1056:                        ACPI_BUFFER buf;
1.27      christos 1057:
1.102     cube     1058:                        aprint_normal("%s (%s) ", aa->aa_node->ad_name,
                   1059:                            pnpstr);
1.121     mlelstv  1060:
1.140     jruoho   1061:                        rv = acpi_eval_struct(aa->aa_node->ad_handle,
                   1062:                            "_STR", &buf);
1.56      mycroft  1063:                        if (ACPI_SUCCESS(rv)) {
1.121     mlelstv  1064:                                ACPI_OBJECT *obj = buf.Pointer;
                   1065:                                switch (obj->Type) {
                   1066:                                case ACPI_TYPE_STRING:
                   1067:                                        aprint_normal("[%s] ", obj->String.Pointer);
                   1068:                                        break;
                   1069:                                case ACPI_TYPE_BUFFER:
                   1070:                                        aprint_normal("buffer %p ", obj->Buffer.Pointer);
                   1071:                                        break;
                   1072:                                default:
1.148.2.1  uebayasi 1073:                                        aprint_normal("type %u ",obj->Type);
1.121     mlelstv  1074:                                        break;
                   1075:                                }
1.132     mlelstv  1076:                                ACPI_FREE(buf.Pointer);
1.27      christos 1077:                        }
1.148.2.2! uebayasi 1078:                        else
        !          1079:                                acpi_print_dev(pnpstr);
1.62      kochi    1080:
1.104     jmcneill 1081:                        aprint_normal("at %s", pnp);
                   1082:                } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) {
1.102     cube     1083:                        aprint_normal("%s (ACPI Object Type '%s' "
                   1084:                            "[0x%02x]) ", aa->aa_node->ad_name,
                   1085:                             AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
                   1086:                             aa->aa_node->ad_devinfo->Type);
1.104     jmcneill 1087:                        aprint_normal("at %s", pnp);
                   1088:                } else
                   1089:                        return 0;
1.21      matt     1090:        } else {
1.102     cube     1091:                aprint_normal(" (%s", aa->aa_node->ad_name);
1.54      kochi    1092:                if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
1.128     jmcneill 1093:                        aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.String);
1.54      kochi    1094:                        if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
1.70      christos 1095:                                const char *uid;
1.41      kochi    1096:
1.128     jmcneill 1097:                                uid = aa->aa_node->ad_devinfo->UniqueId.String;
1.48      mycroft  1098:                                if (uid[0] == '\0')
1.41      kochi    1099:                                        uid = "<null>";
                   1100:                                aprint_normal("-%s", uid);
                   1101:                        }
1.22      jmcneill 1102:                }
1.102     cube     1103:                aprint_normal(")");
1.4       thorpej  1104:        }
1.1       thorpej  1105:
1.63      kochi    1106:        return UNCONF;
1.1       thorpej  1107: }
                   1108:
1.147     jruoho   1109: /*
1.148.2.1  uebayasi 1110:  * Notify.
1.147     jruoho   1111:  */
1.148.2.1  uebayasi 1112: static void
                   1113: acpi_notify_handler(ACPI_HANDLE handle, uint32_t event, void *aux)
1.136     cegger   1114: {
1.148.2.1  uebayasi 1115:        struct acpi_softc *sc = acpi_softc;
                   1116:        struct acpi_devnode *ad;
1.136     cegger   1117:
1.148.2.1  uebayasi 1118:        KASSERT(sc != NULL);
                   1119:        KASSERT(aux == NULL);
                   1120:        KASSERT(acpi_active != 0);
1.136     cegger   1121:
1.148.2.1  uebayasi 1122:        if (acpi_suspended != 0)
                   1123:                return;
1.136     cegger   1124:
1.148.2.1  uebayasi 1125:        /*
                   1126:         *  System: 0x00 - 0x7F.
                   1127:         *  Device: 0x80 - 0xFF.
                   1128:         */
                   1129:        switch (event) {
1.136     cegger   1130:
1.148.2.1  uebayasi 1131:        case ACPI_NOTIFY_BUS_CHECK:
                   1132:        case ACPI_NOTIFY_DEVICE_CHECK:
                   1133:        case ACPI_NOTIFY_DEVICE_WAKE:
                   1134:        case ACPI_NOTIFY_EJECT_REQUEST:
                   1135:        case ACPI_NOTIFY_DEVICE_CHECK_LIGHT:
                   1136:        case ACPI_NOTIFY_FREQUENCY_MISMATCH:
                   1137:        case ACPI_NOTIFY_BUS_MODE_MISMATCH:
                   1138:        case ACPI_NOTIFY_POWER_FAULT:
                   1139:        case ACPI_NOTIFY_CAPABILITIES_CHECK:
                   1140:        case ACPI_NOTIFY_DEVICE_PLD_CHECK:
                   1141:        case ACPI_NOTIFY_RESERVED:
                   1142:        case ACPI_NOTIFY_LOCALITY_UPDATE:
                   1143:                break;
                   1144:        }
1.136     cegger   1145:
1.148.2.1  uebayasi 1146:        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "notification 0x%02X for "
                   1147:                "%s (%p)\n", event, acpi_name(handle), handle));
1.4       thorpej  1148:
1.148.2.1  uebayasi 1149:        /*
                   1150:         * We deliver notifications only to drivers
                   1151:         * that have been succesfully attached and
                   1152:         * that have registered a handler with us.
                   1153:         * The opaque pointer is always the device_t.
                   1154:         */
                   1155:        SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1.145     jruoho   1156:
1.148.2.1  uebayasi 1157:                if (ad->ad_device == NULL)
                   1158:                        continue;
1.145     jruoho   1159:
1.148.2.1  uebayasi 1160:                if (ad->ad_notify == NULL)
                   1161:                        continue;
1.145     jruoho   1162:
1.148.2.1  uebayasi 1163:                if (ad->ad_handle != handle)
                   1164:                        continue;
1.145     jruoho   1165:
1.148.2.1  uebayasi 1166:                (*ad->ad_notify)(ad->ad_handle, event, ad->ad_device);
                   1167:
                   1168:                return;
1.145     jruoho   1169:        }
1.4       thorpej  1170:
1.148.2.1  uebayasi 1171:        aprint_debug_dev(sc->sc_dev, "unhandled notify 0x%02X "
                   1172:            "for %s (%p)\n", event, acpi_name(handle), handle);
                   1173: }
1.4       thorpej  1174:
1.148.2.1  uebayasi 1175: bool
                   1176: acpi_register_notify(struct acpi_devnode *ad, ACPI_NOTIFY_HANDLER notify)
                   1177: {
                   1178:        struct acpi_softc *sc = acpi_softc;
1.46      mycroft  1179:
1.148.2.1  uebayasi 1180:        KASSERT(sc != NULL);
                   1181:        KASSERT(acpi_active != 0);
1.145     jruoho   1182:
1.148.2.1  uebayasi 1183:        if (acpi_suspended != 0)
                   1184:                goto fail;
1.145     jruoho   1185:
1.148.2.1  uebayasi 1186:        if (ad == NULL || notify == NULL)
                   1187:                goto fail;
1.145     jruoho   1188:
1.148.2.1  uebayasi 1189:        ad->ad_notify = notify;
1.7       sommerfe 1190:
1.148.2.1  uebayasi 1191:        return true;
1.7       sommerfe 1192:
1.148.2.1  uebayasi 1193: fail:
                   1194:        aprint_error_dev(sc->sc_dev, "failed to register notify "
                   1195:            "handler for %s (%p)\n", ad->ad_name, ad->ad_handle);
1.7       sommerfe 1196:
1.148.2.1  uebayasi 1197:        return false;
                   1198: }
1.7       sommerfe 1199:
1.148.2.1  uebayasi 1200: void
                   1201: acpi_deregister_notify(struct acpi_devnode *ad)
                   1202: {
1.7       sommerfe 1203:
1.148.2.1  uebayasi 1204:        ad->ad_notify = NULL;
1.2       thorpej  1205: }
                   1206:
                   1207: /*
1.148.2.1  uebayasi 1208:  * Fixed buttons.
1.146     jruoho   1209:  */
1.148.2.1  uebayasi 1210: static void
                   1211: acpi_register_fixed_button(struct acpi_softc *sc, int event)
1.146     jruoho   1212: {
1.148.2.1  uebayasi 1213:        struct sysmon_pswitch *smpsw;
                   1214:        ACPI_STATUS rv;
                   1215:        int type;
1.146     jruoho   1216:
1.148.2.1  uebayasi 1217:        switch (event) {
1.146     jruoho   1218:
1.148.2.1  uebayasi 1219:        case ACPI_EVENT_POWER_BUTTON:
1.146     jruoho   1220:
1.148.2.1  uebayasi 1221:                if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0)
                   1222:                        return;
1.146     jruoho   1223:
1.148.2.1  uebayasi 1224:                type = PSWITCH_TYPE_POWER;
                   1225:                smpsw = &sc->sc_smpsw_power;
                   1226:                break;
1.146     jruoho   1227:
1.148.2.1  uebayasi 1228:        case ACPI_EVENT_SLEEP_BUTTON:
1.146     jruoho   1229:
1.148.2.1  uebayasi 1230:                if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0)
                   1231:                        return;
1.146     jruoho   1232:
1.148.2.1  uebayasi 1233:                type = PSWITCH_TYPE_SLEEP;
                   1234:                smpsw = &sc->sc_smpsw_sleep;
                   1235:                break;
1.146     jruoho   1236:
                   1237:        default:
1.148.2.1  uebayasi 1238:                rv = AE_TYPE;
                   1239:                goto fail;
1.146     jruoho   1240:        }
                   1241:
1.148.2.1  uebayasi 1242:        smpsw->smpsw_type = type;
                   1243:        smpsw->smpsw_name = device_xname(sc->sc_dev);
1.65      kochi    1244:
1.148.2.1  uebayasi 1245:        if (sysmon_pswitch_register(smpsw) != 0) {
                   1246:                rv = AE_ERROR;
                   1247:                goto fail;
1.65      kochi    1248:        }
                   1249:
1.148.2.1  uebayasi 1250:        rv = AcpiInstallFixedEventHandler(event,
                   1251:            acpi_fixed_button_handler, smpsw);
1.65      kochi    1252:
1.148.2.2! uebayasi 1253:        if (ACPI_FAILURE(rv)) {
        !          1254:                sysmon_pswitch_unregister(smpsw);
1.148.2.1  uebayasi 1255:                goto fail;
1.148.2.2! uebayasi 1256:        }
1.65      kochi    1257:
1.148.2.1  uebayasi 1258:        aprint_debug_dev(sc->sc_dev, "fixed %s button present\n",
                   1259:            (type != ACPI_EVENT_SLEEP_BUTTON) ? "power" : "sleep");
1.54      kochi    1260:
1.148.2.1  uebayasi 1261:        return;
1.54      kochi    1262:
1.148.2.1  uebayasi 1263: fail:
                   1264:        aprint_error_dev(sc->sc_dev, "failed to register "
                   1265:            "fixed event: %s\n", AcpiFormatException(rv));
1.10      tshiozak 1266: }
                   1267:
1.118     dyoung   1268: static void
1.148.2.1  uebayasi 1269: acpi_deregister_fixed_button(struct acpi_softc *sc, int event)
1.69      kochi    1270: {
1.148.2.1  uebayasi 1271:        struct sysmon_pswitch *smpsw;
1.69      kochi    1272:        ACPI_STATUS rv;
                   1273:
1.148.2.1  uebayasi 1274:        switch (event) {
1.144     jruoho   1275:
1.148.2.1  uebayasi 1276:        case ACPI_EVENT_POWER_BUTTON:
                   1277:                smpsw = &sc->sc_smpsw_power;
1.144     jruoho   1278:
1.148.2.1  uebayasi 1279:                if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0) {
                   1280:                        KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_POWER);
                   1281:                        return;
                   1282:                }
1.144     jruoho   1283:
1.148.2.1  uebayasi 1284:                break;
1.144     jruoho   1285:
1.148.2.1  uebayasi 1286:        case ACPI_EVENT_SLEEP_BUTTON:
                   1287:                smpsw = &sc->sc_smpsw_sleep;
1.144     jruoho   1288:
1.148.2.1  uebayasi 1289:                if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0) {
                   1290:                        KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_SLEEP);
                   1291:                        return;
                   1292:                }
1.69      kochi    1293:
1.144     jruoho   1294:                break;
1.69      kochi    1295:
1.144     jruoho   1296:        default:
1.148.2.1  uebayasi 1297:                rv = AE_TYPE;
                   1298:                goto fail;
1.144     jruoho   1299:        }
1.69      kochi    1300:
1.148.2.1  uebayasi 1301:        rv = AcpiRemoveFixedEventHandler(event, acpi_fixed_button_handler);
1.69      kochi    1302:
1.148.2.1  uebayasi 1303:        if (ACPI_SUCCESS(rv)) {
                   1304:                sysmon_pswitch_unregister(smpsw);
                   1305:                return;
                   1306:        }
1.69      kochi    1307:
1.148.2.1  uebayasi 1308: fail:
                   1309:        aprint_error_dev(sc->sc_dev, "failed to deregister "
                   1310:            "fixed event: %s\n", AcpiFormatException(rv));
1.118     dyoung   1311: }
                   1312:
1.148.2.1  uebayasi 1313: static uint32_t
                   1314: acpi_fixed_button_handler(void *context)
1.118     dyoung   1315: {
1.148.2.1  uebayasi 1316:        static const int handler = OSL_NOTIFY_HANDLER;
                   1317:        struct sysmon_pswitch *smpsw = context;
1.118     dyoung   1318:
1.148.2.1  uebayasi 1319:        (void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw);
1.10      tshiozak 1320:
1.148.2.1  uebayasi 1321:        return ACPI_INTERRUPT_HANDLED;
                   1322: }
                   1323:
                   1324: static void
                   1325: acpi_fixed_button_pressed(void *context)
1.10      tshiozak 1326: {
1.148.2.1  uebayasi 1327:        struct sysmon_pswitch *smpsw = context;
1.10      tshiozak 1328:
1.148.2.2! uebayasi 1329:        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s fixed button pressed\n",
        !          1330:                (smpsw->smpsw_type != ACPI_EVENT_SLEEP_BUTTON) ?
        !          1331:                "power" : "sleep"));
1.148.2.1  uebayasi 1332:
                   1333:        sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
1.10      tshiozak 1334: }
                   1335:
                   1336: /*
1.148.2.1  uebayasi 1337:  * Sleep.
1.10      tshiozak 1338:  */
1.148.2.1  uebayasi 1339: static void
                   1340: acpi_sleep_init(struct acpi_softc *sc)
                   1341: {
                   1342:        uint8_t a, b, i;
                   1343:        ACPI_STATUS rv;
1.10      tshiozak 1344:
1.148.2.1  uebayasi 1345:        CTASSERT(ACPI_STATE_S0 == 0 && ACPI_STATE_S1 == 1);
                   1346:        CTASSERT(ACPI_STATE_S2 == 2 && ACPI_STATE_S3 == 3);
                   1347:        CTASSERT(ACPI_STATE_S4 == 4 && ACPI_STATE_S5 == 5);
                   1348:
                   1349:        /*
                   1350:         * Evaluate supported sleep states.
                   1351:         */
                   1352:        for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) {
                   1353:
                   1354:                rv = AcpiGetSleepTypeData(i, &a, &b);
                   1355:
                   1356:                if (ACPI_SUCCESS(rv))
                   1357:                        sc->sc_sleepstates |= __BIT(i);
                   1358:        }
                   1359: }
                   1360:
                   1361: void
1.10      tshiozak 1362: acpi_enter_sleep_state(struct acpi_softc *sc, int state)
                   1363: {
1.148.2.1  uebayasi 1364:        ACPI_STATUS rv;
1.104     jmcneill 1365:        int err;
1.10      tshiozak 1366:
1.148.2.1  uebayasi 1367:        if (state == sc->sc_sleepstate)
                   1368:                return;
1.92      christos 1369:
1.148.2.1  uebayasi 1370:        aprint_normal_dev(sc->sc_dev, "entering state S%d\n", state);
1.92      christos 1371:
1.10      tshiozak 1372:        switch (state) {
1.148.2.1  uebayasi 1373:
1.10      tshiozak 1374:        case ACPI_STATE_S0:
1.148.2.1  uebayasi 1375:                sc->sc_sleepstate = ACPI_STATE_S0;
                   1376:                return;
                   1377:
1.10      tshiozak 1378:        case ACPI_STATE_S1:
                   1379:        case ACPI_STATE_S2:
                   1380:        case ACPI_STATE_S3:
                   1381:        case ACPI_STATE_S4:
1.148.2.1  uebayasi 1382:
                   1383:                if ((sc->sc_sleepstates & __BIT(state)) == 0) {
                   1384:                        aprint_error_dev(sc->sc_dev, "sleep state "
                   1385:                            "S%d is not available\n", state);
                   1386:                        return;
1.10      tshiozak 1387:                }
1.104     jmcneill 1388:
1.148.2.1  uebayasi 1389:                /*
                   1390:                 * Evaluate the _TTS method. This should be done before
                   1391:                 * pmf_system_suspend(9) and the evaluation of _PTS.
                   1392:                 * We should also re-evaluate this once we return to
                   1393:                 * S0 or if we abort the sleep state transition in the
                   1394:                 * middle (see ACPI 3.0, section 7.3.6). In reality,
                   1395:                 * however, the _TTS method is seldom seen in the field.
                   1396:                 */
                   1397:                rv = acpi_eval_set_integer(NULL, "\\_TTS", state);
                   1398:
                   1399:                if (ACPI_SUCCESS(rv))
                   1400:                        aprint_debug_dev(sc->sc_dev, "evaluated _TTS\n");
                   1401:
                   1402:                if (state != ACPI_STATE_S1 &&
                   1403:                    pmf_system_suspend(PMF_Q_NONE) != true) {
1.113     jmcneill 1404:                        aprint_error_dev(sc->sc_dev, "aborting suspend\n");
1.104     jmcneill 1405:                        break;
                   1406:                }
                   1407:
1.148.2.1  uebayasi 1408:                /*
                   1409:                 * This will evaluate the  _PTS and _SST methods,
                   1410:                 * but unlike the documentation claims, not _GTS,
                   1411:                 * which is evaluated in AcpiEnterSleepState().
                   1412:                 * This must be called with interrupts enabled.
                   1413:                 */
                   1414:                rv = AcpiEnterSleepStatePrep(state);
                   1415:
                   1416:                if (ACPI_FAILURE(rv)) {
                   1417:                        aprint_error_dev(sc->sc_dev, "failed to prepare "
                   1418:                            "S%d: %s\n", state, AcpiFormatException(rv));
1.10      tshiozak 1419:                        break;
                   1420:                }
1.104     jmcneill 1421:
1.148.2.2! uebayasi 1422:                /*
        !          1423:                 * After the _PTS method has been evaluated, we can
        !          1424:                 * enable wake and evaluate _PSW (ACPI 4.0, p. 284).
        !          1425:                 */
        !          1426:                acpi_wakedev_commit(sc, state);
        !          1427:
1.148.2.1  uebayasi 1428:                sc->sc_sleepstate = state;
                   1429:
1.92      christos 1430:                if (state == ACPI_STATE_S1) {
1.148.2.1  uebayasi 1431:
                   1432:                        /* Just enter the state. */
1.12      kanaoka  1433:                        acpi_md_OsDisableInterrupt();
1.148.2.1  uebayasi 1434:                        rv = AcpiEnterSleepState(state);
                   1435:
                   1436:                        if (ACPI_FAILURE(rv))
                   1437:                                aprint_error_dev(sc->sc_dev, "failed to "
                   1438:                                    "enter S1: %s\n", AcpiFormatException(rv));
                   1439:
                   1440:                        (void)AcpiLeaveSleepState(state);
                   1441:
1.10      tshiozak 1442:                } else {
1.148.2.1  uebayasi 1443:
1.104     jmcneill 1444:                        err = acpi_md_sleep(state);
1.148.2.1  uebayasi 1445:
1.104     jmcneill 1446:                        if (state == ACPI_STATE_S4)
1.10      tshiozak 1447:                                AcpiEnable();
1.148.2.1  uebayasi 1448:
1.133     dyoung   1449:                        pmf_system_bus_resume(PMF_Q_NONE);
1.148.2.1  uebayasi 1450:                        (void)AcpiLeaveSleepState(state);
1.133     dyoung   1451:                        pmf_system_resume(PMF_Q_NONE);
1.10      tshiozak 1452:                }
1.104     jmcneill 1453:
1.10      tshiozak 1454:                break;
1.148.2.1  uebayasi 1455:
1.10      tshiozak 1456:        case ACPI_STATE_S5:
1.148.2.1  uebayasi 1457:
                   1458:                (void)acpi_eval_set_integer(NULL, "\\_TTS", ACPI_STATE_S5);
                   1459:
                   1460:                rv = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
                   1461:
                   1462:                if (ACPI_FAILURE(rv)) {
                   1463:                        aprint_error_dev(sc->sc_dev, "failed to prepare "
                   1464:                            "S%d: %s\n", state, AcpiFormatException(rv));
1.42      kochi    1465:                        break;
                   1466:                }
1.148.2.1  uebayasi 1467:
1.104     jmcneill 1468:                DELAY(1000000);
1.10      tshiozak 1469:
1.148.2.1  uebayasi 1470:                sc->sc_sleepstate = state;
                   1471:                acpi_md_OsDisableInterrupt();
1.13      augustss 1472:
1.148.2.1  uebayasi 1473:                (void)AcpiEnterSleepState(ACPI_STATE_S5);
1.13      augustss 1474:
1.148.2.1  uebayasi 1475:                aprint_error_dev(sc->sc_dev, "WARNING: powerdown failed!\n");
1.13      augustss 1476:
1.148.2.1  uebayasi 1477:                break;
1.13      augustss 1478:        }
                   1479:
1.148.2.1  uebayasi 1480:        sc->sc_sleepstate = ACPI_STATE_S0;
1.13      augustss 1481:
1.148.2.1  uebayasi 1482:        (void)acpi_eval_set_integer(NULL, "\\_TTS", ACPI_STATE_S0);
1.13      augustss 1483: }
1.79      cube     1484:
1.148.2.1  uebayasi 1485: /*
                   1486:  * Sysctl.
                   1487:  */
1.79      cube     1488: SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
                   1489: {
1.148.2.1  uebayasi 1490:        const struct sysctlnode *mnode, *rnode;
                   1491:        int err;
1.79      cube     1492:
1.148.2.1  uebayasi 1493:        err = sysctl_createv(clog, 0, NULL, &rnode,
                   1494:            CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw",
                   1495:            NULL, NULL, 0, NULL, 0,
                   1496:            CTL_HW, CTL_EOL);
                   1497:
                   1498:        if (err != 0)
1.79      cube     1499:                return;
                   1500:
1.148.2.1  uebayasi 1501:        err = sysctl_createv(clog, 0, &rnode, &rnode,
                   1502:            CTLFLAG_PERMANENT, CTLTYPE_NODE,
                   1503:            "acpi", SYSCTL_DESCR("ACPI subsystem parameters"),
1.79      cube     1504:            NULL, 0, NULL, 0,
1.148.2.1  uebayasi 1505:            CTL_CREATE, CTL_EOL);
                   1506:
                   1507:        if (err != 0)
1.79      cube     1508:                return;
                   1509:
1.148.2.1  uebayasi 1510:        (void)sysctl_createv(NULL, 0, &rnode, NULL,
                   1511:            CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
                   1512:            "root", SYSCTL_DESCR("ACPI root pointer"),
1.109     jmcneill 1513:            NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer),
1.148.2.1  uebayasi 1514:            CTL_CREATE, CTL_EOL);
                   1515:
                   1516:        (void)sysctl_createv(NULL, 0, &rnode, NULL,
                   1517:            CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_STRING,
                   1518:            "supported_states", SYSCTL_DESCR("Supported system states"),
                   1519:            sysctl_hw_acpi_sleepstates, 0, NULL, 0,
                   1520:            CTL_CREATE, CTL_EOL);
                   1521:
                   1522:        err = sysctl_createv(NULL, 0, NULL, &mnode,
                   1523:            CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep",
                   1524:            NULL, NULL, 0, NULL, 0,
                   1525:            CTL_MACHDEP, CTL_EOL);
                   1526:
                   1527:        if (err == 0) {
                   1528:
                   1529:                (void)sysctl_createv(NULL, 0, &mnode, NULL,
                   1530:                    CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
                   1531:                    "sleep_state", SYSCTL_DESCR("System sleep state"),
                   1532:                    sysctl_hw_acpi_sleepstate, 0, NULL, 0,
                   1533:                    CTL_CREATE, CTL_EOL);
                   1534:        }
                   1535:
                   1536:        err = sysctl_createv(clog, 0, &rnode, &rnode,
                   1537:            CTLFLAG_PERMANENT, CTLTYPE_NODE,
                   1538:            "stat", SYSCTL_DESCR("ACPI statistics"),
                   1539:            NULL, 0, NULL, 0,
                   1540:            CTL_CREATE, CTL_EOL);
                   1541:
                   1542:        if (err != 0)
1.86      jmcneill 1543:                return;
1.148.2.1  uebayasi 1544:
                   1545:        (void)sysctl_createv(clog, 0, &rnode, NULL,
                   1546:            CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
                   1547:            "gpe", SYSCTL_DESCR("Number of dispatched GPEs"),
                   1548:            NULL, 0, &AcpiGpeCount, sizeof(AcpiGpeCount),
                   1549:            CTL_CREATE, CTL_EOL);
                   1550:
                   1551:        (void)sysctl_createv(clog, 0, &rnode, NULL,
                   1552:            CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
                   1553:            "sci", SYSCTL_DESCR("Number of SCI interrupts"),
                   1554:            NULL, 0, &AcpiSciCount, sizeof(AcpiSciCount),
                   1555:            CTL_CREATE, CTL_EOL);
                   1556:
                   1557:        (void)sysctl_createv(clog, 0, &rnode, NULL,
                   1558:            CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
                   1559:            "fixed", SYSCTL_DESCR("Number of fixed events"),
                   1560:            sysctl_hw_acpi_fixedstats, 0, NULL, 0,
                   1561:            CTL_CREATE, CTL_EOL);
                   1562:
                   1563:        (void)sysctl_createv(clog, 0, &rnode, NULL,
                   1564:            CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
                   1565:            "method", SYSCTL_DESCR("Number of methods executed"),
                   1566:            NULL, 0, &AcpiMethodCount, sizeof(AcpiMethodCount),
                   1567:            CTL_CREATE, CTL_EOL);
                   1568:
                   1569:        CTASSERT(sizeof(AcpiGpeCount) == sizeof(uint64_t));
                   1570:        CTASSERT(sizeof(AcpiSciCount) == sizeof(uint64_t));
                   1571: }
                   1572:
                   1573: static int
                   1574: sysctl_hw_acpi_fixedstats(SYSCTLFN_ARGS)
                   1575: {
                   1576:        struct sysctlnode node;
                   1577:        uint64_t t;
                   1578:        int err, i;
                   1579:
                   1580:        for (i = t = 0; i < __arraycount(AcpiFixedEventCount); i++)
                   1581:                t += AcpiFixedEventCount[i];
                   1582:
                   1583:        node = *rnode;
                   1584:        node.sysctl_data = &t;
                   1585:
                   1586:        err = sysctl_lookup(SYSCTLFN_CALL(&node));
                   1587:
                   1588:        if (err || newp == NULL)
                   1589:                return err;
                   1590:
                   1591:        return 0;
1.86      jmcneill 1592: }
                   1593:
                   1594: static int
                   1595: sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
                   1596: {
1.148.2.1  uebayasi 1597:        struct acpi_softc *sc = acpi_softc;
1.86      jmcneill 1598:        struct sysctlnode node;
1.148.2.1  uebayasi 1599:        int err, t;
                   1600:
                   1601:        if (acpi_softc == NULL)
                   1602:                return ENOSYS;
1.86      jmcneill 1603:
                   1604:        node = *rnode;
1.148.2.1  uebayasi 1605:        t = sc->sc_sleepstate;
1.86      jmcneill 1606:        node.sysctl_data = &t;
1.148.2.1  uebayasi 1607:
                   1608:        err = sysctl_lookup(SYSCTLFN_CALL(&node));
                   1609:
                   1610:        if (err || newp == NULL)
                   1611:                return err;
                   1612:
                   1613:        if (t < ACPI_STATE_S0 || t > ACPI_STATE_S5)
                   1614:                return EINVAL;
                   1615:
                   1616:        acpi_enter_sleep_state(sc, t);
                   1617:
                   1618:        return 0;
                   1619: }
                   1620:
                   1621: static int
                   1622: sysctl_hw_acpi_sleepstates(SYSCTLFN_ARGS)
                   1623: {
                   1624:        struct acpi_softc *sc = acpi_softc;
                   1625:        struct sysctlnode node;
                   1626:        char t[3 * 6 + 1];
                   1627:        int err;
1.86      jmcneill 1628:
1.92      christos 1629:        if (acpi_softc == NULL)
                   1630:                return ENOSYS;
1.86      jmcneill 1631:
1.148.2.1  uebayasi 1632:        (void)memset(t, '\0', sizeof(t));
                   1633:
                   1634:        (void)snprintf(t, sizeof(t), "%s%s%s%s%s%s",
                   1635:            ((sc->sc_sleepstates & __BIT(0)) != 0) ? "S0 " : "",
                   1636:            ((sc->sc_sleepstates & __BIT(1)) != 0) ? "S1 " : "",
                   1637:            ((sc->sc_sleepstates & __BIT(2)) != 0) ? "S2 " : "",
                   1638:            ((sc->sc_sleepstates & __BIT(3)) != 0) ? "S3 " : "",
                   1639:            ((sc->sc_sleepstates & __BIT(4)) != 0) ? "S4 " : "",
                   1640:            ((sc->sc_sleepstates & __BIT(5)) != 0) ? "S5 " : "");
                   1641:
                   1642:        node = *rnode;
                   1643:        node.sysctl_data = &t;
                   1644:
                   1645:        err = sysctl_lookup(SYSCTLFN_CALL(&node));
                   1646:
                   1647:        if (err || newp == NULL)
                   1648:                return err;
1.86      jmcneill 1649:
                   1650:        return 0;
1.79      cube     1651: }
1.108     jmcneill 1652:
1.148.2.1  uebayasi 1653: /*
1.148.2.2! uebayasi 1654:  * Tables.
1.148.2.1  uebayasi 1655:  */
                   1656: ACPI_PHYSICAL_ADDRESS
                   1657: acpi_OsGetRootPointer(void)
                   1658: {
                   1659:        ACPI_PHYSICAL_ADDRESS PhysicalAddress;
                   1660:
                   1661:        /*
                   1662:         * We let MD code handle this since there are multiple ways to do it:
                   1663:         *
                   1664:         *      IA-32: Use AcpiFindRootPointer() to locate the RSDP.
                   1665:         *
                   1666:         *      IA-64: Use the EFI.
                   1667:         */
                   1668:        PhysicalAddress = acpi_md_OsGetRootPointer();
                   1669:
                   1670:        if (acpi_root_pointer == 0)
                   1671:                acpi_root_pointer = PhysicalAddress;
                   1672:
                   1673:        return PhysicalAddress;
                   1674: }
                   1675:
1.108     jmcneill 1676: static ACPI_TABLE_HEADER *
                   1677: acpi_map_rsdt(void)
                   1678: {
                   1679:        ACPI_PHYSICAL_ADDRESS paddr;
                   1680:        ACPI_TABLE_RSDP *rsdp;
                   1681:
                   1682:        paddr = AcpiOsGetRootPointer();
1.148.2.1  uebayasi 1683:
                   1684:        if (paddr == 0)
1.108     jmcneill 1685:                return NULL;
1.148.2.1  uebayasi 1686:
1.108     jmcneill 1687:        rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP));
1.148.2.1  uebayasi 1688:
                   1689:        if (rsdp == NULL)
1.108     jmcneill 1690:                return NULL;
1.148.2.1  uebayasi 1691:
1.108     jmcneill 1692:        if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress)
1.148.2.1  uebayasi 1693:                paddr = rsdp->XsdtPhysicalAddress;
1.108     jmcneill 1694:        else
1.148.2.1  uebayasi 1695:                paddr = rsdp->RsdtPhysicalAddress;
                   1696:
1.108     jmcneill 1697:        AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP));
                   1698:
                   1699:        return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER));
                   1700: }
                   1701:
                   1702: static void
                   1703: acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt)
                   1704: {
1.148.2.1  uebayasi 1705:
1.108     jmcneill 1706:        if (rsdt == NULL)
                   1707:                return;
                   1708:
                   1709:        AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER));
                   1710: }
1.148.2.2! uebayasi 1711:
        !          1712: /*
        !          1713:  * XXX: Refactor to be a generic function that maps tables.
        !          1714:  */
        !          1715: ACPI_STATUS
        !          1716: acpi_madt_map(void)
        !          1717: {
        !          1718:        ACPI_STATUS  rv;
        !          1719:
        !          1720:        if (madt_header != NULL)
        !          1721:                return AE_ALREADY_EXISTS;
        !          1722:
        !          1723:        rv = AcpiGetTable(ACPI_SIG_MADT, 1, &madt_header);
        !          1724:
        !          1725:        if (ACPI_FAILURE(rv))
        !          1726:                return rv;
        !          1727:
        !          1728:        return AE_OK;
        !          1729: }
        !          1730:
        !          1731: void
        !          1732: acpi_madt_unmap(void)
        !          1733: {
        !          1734:        madt_header = NULL;
        !          1735: }
        !          1736:
        !          1737: /*
        !          1738:  * XXX: Refactor to be a generic function that walks tables.
        !          1739:  */
        !          1740: void
        !          1741: acpi_madt_walk(ACPI_STATUS (*func)(ACPI_SUBTABLE_HEADER *, void *), void *aux)
        !          1742: {
        !          1743:        ACPI_SUBTABLE_HEADER *hdrp;
        !          1744:        char *madtend, *where;
        !          1745:
        !          1746:        madtend = (char *)madt_header + madt_header->Length;
        !          1747:        where = (char *)madt_header + sizeof (ACPI_TABLE_MADT);
        !          1748:
        !          1749:        while (where < madtend) {
        !          1750:
        !          1751:                hdrp = (ACPI_SUBTABLE_HEADER *)where;
        !          1752:
        !          1753:                if (ACPI_FAILURE(func(hdrp, aux)))
        !          1754:                        break;
        !          1755:
        !          1756:                where += hdrp->Length;
        !          1757:        }
        !          1758: }
        !          1759:
        !          1760: /*
        !          1761:  * Miscellaneous.
        !          1762:  */
        !          1763: static bool
        !          1764: acpi_is_scope(struct acpi_devnode *ad)
        !          1765: {
        !          1766:        int i;
        !          1767:
        !          1768:        /*
        !          1769:         * Return true if the node is a root scope.
        !          1770:         */
        !          1771:        if (ad->ad_parent == NULL)
        !          1772:                return false;
        !          1773:
        !          1774:        if (ad->ad_parent->ad_handle != ACPI_ROOT_OBJECT)
        !          1775:                return false;
        !          1776:
        !          1777:        for (i = 0; i < __arraycount(acpi_scopes); i++) {
        !          1778:
        !          1779:                if (acpi_scopes[i] == NULL)
        !          1780:                        continue;
        !          1781:
        !          1782:                if (ad->ad_handle == acpi_scopes[i])
        !          1783:                        return true;
        !          1784:        }
        !          1785:
        !          1786:        return false;
        !          1787: }
        !          1788:
        !          1789: /*
        !          1790:  * ACPIVERBOSE.
        !          1791:  */
        !          1792: void
        !          1793: acpi_load_verbose(void)
        !          1794: {
        !          1795:
        !          1796:        if (acpi_verbose_loaded == 0) {
        !          1797:                mutex_enter(&module_lock);
        !          1798:                module_autoload("acpiverbose", MODULE_CLASS_MISC);
        !          1799:                mutex_exit(&module_lock);
        !          1800:        }
        !          1801: }
        !          1802:
        !          1803: void
        !          1804: acpi_print_verbose_stub(struct acpi_softc *sc)
        !          1805: {
        !          1806:
        !          1807:        acpi_load_verbose();
        !          1808:
        !          1809:        if (acpi_verbose_loaded != 0)
        !          1810:                acpi_print_verbose(sc);
        !          1811: }
        !          1812:
        !          1813: void
        !          1814: acpi_print_dev_stub(const char *pnpstr)
        !          1815: {
        !          1816:
        !          1817:        acpi_load_verbose();
        !          1818:
        !          1819:        if (acpi_verbose_loaded != 0)
        !          1820:                acpi_print_dev(pnpstr);
        !          1821: }

CVSweb <webmaster@jp.NetBSD.org>