[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.104.2.1

1.104.2.1! bouyer      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:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
1.1       thorpej    38:
                     39: /*
1.34      thorpej    40:  * Copyright 2001, 2003 Wasabi Systems, Inc.
1.1       thorpej    41:  * All rights reserved.
                     42:  *
                     43:  * Written by Jason R. Thorpe for Wasabi Systems, Inc.
                     44:  *
                     45:  * Redistribution and use in source and binary forms, with or without
                     46:  * modification, are permitted provided that the following conditions
                     47:  * are met:
                     48:  * 1. Redistributions of source code must retain the above copyright
                     49:  *    notice, this list of conditions and the following disclaimer.
                     50:  * 2. Redistributions in binary form must reproduce the above copyright
                     51:  *    notice, this list of conditions and the following disclaimer in the
                     52:  *    documentation and/or other materials provided with the distribution.
                     53:  * 3. All advertising materials mentioning features or use of this software
                     54:  *    must display the following acknowledgement:
                     55:  *     This product includes software developed for the NetBSD Project by
                     56:  *     Wasabi Systems, Inc.
                     57:  * 4. The name of Wasabi Systems, Inc. may not be used to endorse
                     58:  *    or promote products derived from this software without specific prior
                     59:  *    written permission.
                     60:  *
                     61:  * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
                     62:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     63:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     64:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
                     65:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     66:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     67:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     68:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     69:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     70:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     71:  * POSSIBILITY OF SUCH DAMAGE.
                     72:  */
                     73:
                     74: /*
                     75:  * Autoconfiguration support for the Intel ACPI Component Architecture
                     76:  * ACPI reference implementation.
                     77:  */
1.5       lukem      78:
                     79: #include <sys/cdefs.h>
1.104.2.1! bouyer     80: __KERNEL_RCSID(0, "$NetBSD$");
1.27      christos   81:
                     82: #include "opt_acpi.h"
1.73      sekiya     83: #include "opt_pcifixup.h"
1.1       thorpej    84:
                     85: #include <sys/param.h>
                     86: #include <sys/systm.h>
                     87: #include <sys/device.h>
                     88: #include <sys/malloc.h>
1.100     xtraeme    89: #include <sys/mutex.h>
1.32      tshiozak   90: #include <sys/kernel.h>
                     91: #include <sys/proc.h>
1.78      cube       92: #include <sys/sysctl.h>
1.1       thorpej    93:
                     94: #include <dev/acpi/acpica.h>
                     95: #include <dev/acpi/acpireg.h>
                     96: #include <dev/acpi/acpivar.h>
                     97: #include <dev/acpi/acpi_osd.h>
1.90      drochner   98: #include <dev/acpi/acpi_timer.h>
1.27      christos   99: #ifdef ACPIVERBOSE
                    100: #include <dev/acpi/acpidevs_data.h>
                    101: #endif
1.1       thorpej   102:
1.74      sekiya    103: #if defined(ACPI_PCI_FIXUP)
1.93      christos  104: #error The option ACPI_PCI_FIXUP has been obsoleted by PCI_INTR_FIXUP_DISABLED.  Please adjust your kernel configuration file.
1.74      sekiya    105: #endif
                    106:
1.93      christos  107: #ifdef PCI_INTR_FIXUP_DISABLED
1.13      augustss  108: #include <dev/pci/pcidevs.h>
                    109: #endif
                    110:
1.33      christos  111: MALLOC_DECLARE(M_ACPI);
                    112:
1.10      tshiozak  113: #include <machine/acpi_machdep.h>
1.39      kochi     114:
1.40      kochi     115: #ifdef ACPI_DEBUGGER
1.1       thorpej   116: #define        ACPI_DBGR_INIT          0x01
                    117: #define        ACPI_DBGR_TABLES        0x02
                    118: #define        ACPI_DBGR_ENABLE        0x04
                    119: #define        ACPI_DBGR_PROBE         0x08
                    120: #define        ACPI_DBGR_RUNNING       0x10
                    121:
1.82      kochi     122: static int acpi_dbgr = 0x00;
1.1       thorpej   123: #endif
                    124:
1.104     jmcneill  125: static ACPI_TABLE_DESC acpi_initial_tables[128];
                    126:
1.64      kochi     127: static int     acpi_match(struct device *, struct cfdata *, void *);
                    128: static void    acpi_attach(struct device *, struct device *, void *);
1.1       thorpej   129:
1.64      kochi     130: static int     acpi_print(void *aux, const char *);
1.1       thorpej   131:
1.86      jmcneill  132: static int     sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS);
                    133:
1.1       thorpej   134: extern struct cfdriver acpi_cd;
                    135:
1.17      thorpej   136: CFATTACH_DECL(acpi, sizeof(struct acpi_softc),
1.18      thorpej   137:     acpi_match, acpi_attach, NULL, NULL);
1.1       thorpej   138:
                    139: /*
                    140:  * This is a flag we set when the ACPI subsystem is active.  Machine
                    141:  * dependent code may wish to skip other steps (such as attaching
                    142:  * subsystems that ACPI supercedes) when ACPI is active.
                    143:  */
                    144: int    acpi_active;
1.93      christos  145: int    acpi_force_load;
1.1       thorpej   146:
                    147: /*
                    148:  * Pointer to the ACPI subsystem's state.  There can be only
                    149:  * one ACPI instance.
                    150:  */
                    151: struct acpi_softc *acpi_softc;
                    152:
1.32      tshiozak  153: /*
                    154:  * Locking stuff.
                    155:  */
1.100     xtraeme   156: static kmutex_t acpi_slock;
1.32      tshiozak  157: static int acpi_locked;
1.101     ad        158: extern kmutex_t acpi_interrupt_list_mtx;
1.32      tshiozak  159:
1.79      cube      160: /*
                    161:  * sysctl-related information
                    162:  */
                    163:
                    164: static int acpi_node = CTL_EOL;
                    165: static uint64_t acpi_root_pointer;     /* found as hw.acpi.root */
1.86      jmcneill  166: static int acpi_sleepstate = ACPI_STATE_S0;
1.78      cube      167:
1.32      tshiozak  168: /*
                    169:  * Prototypes.
                    170:  */
1.64      kochi     171: static void            acpi_shutdown(void *);
                    172: static void            acpi_build_tree(struct acpi_softc *);
                    173: static ACPI_STATUS     acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
1.1       thorpej   174:
1.64      kochi     175: static void            acpi_enable_fixed_events(struct acpi_softc *);
1.1       thorpej   176:
                    177: /*
                    178:  * acpi_probe:
                    179:  *
                    180:  *     Probe for ACPI support.  This is called by the
                    181:  *     machine-dependent ACPI front-end.  All of the
                    182:  *     actual work is done by ACPICA.
                    183:  *
                    184:  *     NOTE: This is not an autoconfiguration interface function.
                    185:  */
                    186: int
                    187: acpi_probe(void)
                    188: {
                    189:        static int beenhere;
                    190:        ACPI_STATUS rv;
                    191:
                    192:        if (beenhere != 0)
                    193:                panic("acpi_probe: ACPI has already been probed");
                    194:        beenhere = 1;
                    195:
1.103     ad        196:        mutex_init(&acpi_slock, MUTEX_DEFAULT, IPL_NONE);
                    197:        mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE);
1.32      tshiozak  198:        acpi_locked = 0;
                    199:
1.1       thorpej   200:        /*
                    201:         * Start up ACPICA.
                    202:         */
1.40      kochi     203: #ifdef ACPI_DEBUGGER
1.1       thorpej   204:        if (acpi_dbgr & ACPI_DBGR_INIT)
                    205:                acpi_osd_debugger();
                    206: #endif
                    207:
1.104     jmcneill  208:        AcpiGbl_AllMethodsSerialized = FALSE;
                    209:        AcpiGbl_EnableInterpreterSlack = TRUE;
                    210:
1.1       thorpej   211:        rv = AcpiInitializeSubsystem();
1.56      mycroft   212:        if (ACPI_FAILURE(rv)) {
1.55      mycroft   213:                printf("ACPI: unable to initialize ACPICA: %s\n",
                    214:                    AcpiFormatException(rv));
1.63      kochi     215:                return 0;
1.1       thorpej   216:        }
                    217:
1.104     jmcneill  218:        rv = AcpiInitializeTables(acpi_initial_tables, 128, 0);
                    219:        if (ACPI_FAILURE(rv)) {
                    220:                printf("ACPI: unable to initialize ACPI tables: %s\n",
                    221:                    AcpiFormatException(rv));
                    222:                return 0;
                    223:        }
                    224:
                    225:        rv = AcpiReallocateRootTable();
                    226:        if (ACPI_FAILURE(rv)) {
                    227:                printf("ACPI: unable to reallocate root table: %s\n",
                    228:                    AcpiFormatException(rv));
                    229:                return 0;
                    230:        }
                    231:
1.40      kochi     232: #ifdef ACPI_DEBUGGER
1.1       thorpej   233:        if (acpi_dbgr & ACPI_DBGR_TABLES)
                    234:                acpi_osd_debugger();
                    235: #endif
                    236:
                    237:        rv = AcpiLoadTables();
1.56      mycroft   238:        if (ACPI_FAILURE(rv)) {
1.55      mycroft   239:                printf("ACPI: unable to load tables: %s\n",
                    240:                    AcpiFormatException(rv));
1.63      kochi     241:                return 0;
1.1       thorpej   242:        }
                    243:
1.104     jmcneill  244: #if notyet
1.93      christos  245:        if (!acpi_force_load && (acpi_find_quirks() & ACPI_QUIRK_BROKEN)) {
                    246:                printf("ACPI: BIOS implementation in listed as broken:\n");
                    247:                printf("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, "
                    248:                       "AslId <%4.4s,%08x>\n",
                    249:                        AcpiGbl_XSDT->OemId, AcpiGbl_XSDT->OemTableId,
                    250:                        AcpiGbl_XSDT->OemRevision,
                    251:                        AcpiGbl_XSDT->AslCompilerId,
                    252:                        AcpiGbl_XSDT->AslCompilerRevision);
                    253:                printf("ACPI: not used. set acpi_force_load to use anyway.\n");
                    254:                return 0;
                    255:        }
                    256:
1.104     jmcneill  257:        /* Install the default address space handlers. */
                    258:        rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
                    259:            ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
                    260:        if (ACPI_FAILURE(rv)) {
                    261:                printf("ACPI: unable to initialise SystemMemory handler: %s\n",
                    262:                    AcpiFormatException(rv));
                    263:                return 0;
                    264:        }
                    265:        rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
                    266:            ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
                    267:        if (ACPI_FAILURE(rv)) {
                    268:                printf("ACPI: unable to initialise SystemIO handler: %s\n",
                    269:                     AcpiFormatException(rv));
                    270:                return 0;
                    271:        }
                    272:        rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
                    273:            ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
                    274:        if (ACPI_FAILURE(rv)) {
                    275:                printf("ACPI: unabled to initialise PciConfig handler: %s\n",
                    276:                    AcpiFormatException(rv));
                    277:                return 0;
                    278:        }
                    279: #endif
                    280:
                    281:        rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE));
                    282:        if (ACPI_FAILURE(rv)) {
                    283:                printf("ACPI: unable to enable: %s\n", AcpiFormatException(rv));
                    284:                return 0;
                    285:        }
                    286:
1.1       thorpej   287:        /*
                    288:         * Looks like we have ACPI!
                    289:         */
                    290:
1.63      kochi     291:        return 1;
1.1       thorpej   292: }
                    293:
1.98      cube      294: static int
                    295: acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
                    296: {
                    297:        struct cfattach *ca;
                    298:
                    299:        ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
                    300:        return (ca == &acpi_ca);
                    301: }
                    302:
                    303: int
                    304: acpi_check(device_t parent, const char *ifattr)
                    305: {
                    306:        return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL);
                    307: }
                    308:
1.104     jmcneill  309: ACPI_PHYSICAL_ADDRESS
                    310: acpi_OsGetRootPointer(void)
1.78      cube      311: {
1.104     jmcneill  312:        ACPI_PHYSICAL_ADDRESS PhysicalAddress;
1.78      cube      313:
                    314:        /*
                    315:         * IA-32: Use AcpiFindRootPointer() to locate the RSDP.
                    316:         *
                    317:         * IA-64: Use the EFI.
                    318:         *
                    319:         * We let MD code handle this since there are multiple
                    320:         * ways to do it.
                    321:         */
                    322:
1.104     jmcneill  323:        PhysicalAddress = acpi_md_OsGetRootPointer();
1.78      cube      324:
1.104     jmcneill  325:        if (acpi_root_pointer == 0)
                    326:                acpi_root_pointer = PhysicalAddress;
1.78      cube      327:
1.104     jmcneill  328:        return PhysicalAddress;
1.78      cube      329: }
                    330:
1.1       thorpej   331: /*
                    332:  * acpi_match:
                    333:  *
                    334:  *     Autoconfiguration `match' routine.
                    335:  */
1.64      kochi     336: static int
1.97      christos  337: acpi_match(struct device *parent, struct cfdata *match,
                    338:     void *aux)
1.1       thorpej   339: {
                    340:        /*
                    341:         * XXX Check other locators?  Hard to know -- machine
                    342:         * dependent code has already checked for the presence
                    343:         * of ACPI by calling acpi_probe(), so I suppose we
                    344:         * don't really have to do anything else.
                    345:         */
1.63      kochi     346:        return 1;
1.1       thorpej   347: }
                    348:
                    349: /*
                    350:  * acpi_attach:
                    351:  *
                    352:  *     Autoconfiguration `attach' routine.  Finish initializing
                    353:  *     ACPICA (some initialization was done in acpi_probe(),
                    354:  *     which was required to check for the presence of ACPI),
                    355:  *     and enable the ACPI subsystem.
                    356:  */
1.64      kochi     357: static void
1.97      christos  358: acpi_attach(struct device *parent, struct device *self, void *aux)
1.1       thorpej   359: {
                    360:        struct acpi_softc *sc = (void *) self;
                    361:        struct acpibus_attach_args *aa = aux;
                    362:        ACPI_STATUS rv;
                    363:
1.84      wiz       364:        aprint_naive(": Advanced Configuration and Power Interface\n");
                    365:        aprint_normal(": Advanced Configuration and Power Interface\n");
1.1       thorpej   366:
                    367:        if (acpi_softc != NULL)
                    368:                panic("acpi_attach: ACPI has already been attached");
1.29      fvdl      369:
1.35      thorpej   370:        sysmon_power_settype("acpi");
1.37      kochi     371:
1.83      kochi     372:        aprint_verbose("%s: using Intel ACPI CA subsystem version %08x\n",
1.37      kochi     373:            sc->sc_dev.dv_xname, ACPI_CA_VERSION);
1.35      thorpej   374:
1.104     jmcneill  375: #if 0
1.83      kochi     376:        aprint_verbose("%s: X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
1.29      fvdl      377:            sc->sc_dev.dv_xname,
1.48      mycroft   378:            AcpiGbl_XSDT->OemId, AcpiGbl_XSDT->OemTableId,
                    379:            AcpiGbl_XSDT->OemRevision,
                    380:            AcpiGbl_XSDT->AslCompilerId, AcpiGbl_XSDT->AslCompilerRevision);
1.104     jmcneill  381: #endif
1.1       thorpej   382:
1.36      fvdl      383:        sc->sc_quirks = acpi_find_quirks();
                    384:
1.1       thorpej   385:        sc->sc_iot = aa->aa_iot;
                    386:        sc->sc_memt = aa->aa_memt;
                    387:        sc->sc_pc = aa->aa_pc;
                    388:        sc->sc_pciflags = aa->aa_pciflags;
1.19      jmcneill  389:        sc->sc_ic = aa->aa_ic;
1.1       thorpej   390:
                    391:        acpi_softc = sc;
                    392:
                    393:        /*
1.104     jmcneill  394:         * Register null power management handler
                    395:         */
                    396:        if (!pmf_device_register(self, NULL, NULL))
                    397:                aprint_error_dev(self, "couldn't establish power handler\n");
                    398:
                    399:        /*
1.1       thorpej   400:         * Bring ACPI on-line.
                    401:         */
1.40      kochi     402: #ifdef ACPI_DEBUGGER
1.1       thorpej   403:        if (acpi_dbgr & ACPI_DBGR_ENABLE)
                    404:                acpi_osd_debugger();
                    405: #endif
1.47      mycroft   406:
1.104     jmcneill  407: #define ACPI_ENABLE_PHASE1 \
                    408:     (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
                    409: #define ACPI_ENABLE_PHASE2 \
                    410:     (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
                    411:      ACPI_NO_ADDRESS_SPACE_INIT)
                    412:
                    413:        rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
                    414:        if (ACPI_FAILURE(rv)) {
                    415:                aprint_error("%s: unable to enable ACPI: %s\n",
                    416:                    sc->sc_dev.dv_xname, AcpiFormatException(rv));
                    417:                return;
                    418:        }
                    419:
                    420:        acpi_md_callback();
                    421:
                    422:        rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
1.56      mycroft   423:        if (ACPI_FAILURE(rv)) {
1.83      kochi     424:                aprint_error("%s: unable to enable ACPI: %s\n",
1.55      mycroft   425:                    sc->sc_dev.dv_xname, AcpiFormatException(rv));
1.47      mycroft   426:                return;
                    427:        }
1.60      kochi     428:
                    429:        /* early EC handler initialization if ECDT table is available */
1.104     jmcneill  430:        config_found_ia(&sc->sc_dev, "acpiecdtbus", NULL, NULL);
1.60      kochi     431:
1.104     jmcneill  432:        rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
1.56      mycroft   433:        if (ACPI_FAILURE(rv)) {
1.83      kochi     434:                aprint_error("%s: unable to initialize ACPI objects: %s\n",
1.55      mycroft   435:                    sc->sc_dev.dv_xname, AcpiFormatException(rv));
1.1       thorpej   436:                return;
                    437:        }
                    438:        acpi_active = 1;
                    439:
                    440:        /* Our current state is "awake". */
                    441:        sc->sc_sleepstate = ACPI_STATE_S0;
                    442:
1.9       kanaoka   443:        /* Show SCI interrupt. */
1.104     jmcneill  444:        aprint_verbose("%s: SCI interrupting at int %d\n",
                    445:            sc->sc_dev.dv_xname, AcpiGbl_FADT.SciInterrupt);
                    446:
1.1       thorpej   447:        /*
                    448:         * Check for fixed-hardware features.
                    449:         */
                    450:        acpi_enable_fixed_events(sc);
1.90      drochner  451:        acpitimer_init();
1.1       thorpej   452:
                    453:        /*
                    454:         * Scan the namespace and build our device tree.
                    455:         */
1.40      kochi     456: #ifdef ACPI_DEBUGGER
1.1       thorpej   457:        if (acpi_dbgr & ACPI_DBGR_PROBE)
                    458:                acpi_osd_debugger();
                    459: #endif
                    460:        acpi_build_tree(sc);
                    461:
1.86      jmcneill  462:        if (acpi_root_pointer != 0 && acpi_node != CTL_EOL) {
1.78      cube      463:                (void)sysctl_createv(NULL, 0, NULL, NULL,
                    464:                    CTLFLAG_IMMEDIATE,
1.79      cube      465:                    CTLTYPE_QUAD, "root", NULL, NULL,
1.78      cube      466:                    acpi_root_pointer, NULL, 0,
1.79      cube      467:                    CTL_HW, acpi_node, CTL_CREATE, CTL_EOL);
1.86      jmcneill  468:        }
                    469:
1.78      cube      470:
1.1       thorpej   471:        /*
                    472:         * Register a shutdown hook that disables certain ACPI
                    473:         * events that might happen and confuse us while we're
                    474:         * trying to shut down.
                    475:         */
                    476:        sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
                    477:        if (sc->sc_sdhook == NULL)
1.83      kochi     478:                aprint_error("%s: WARNING: unable to register shutdown hook\n",
1.1       thorpej   479:                    sc->sc_dev.dv_xname);
                    480:
1.40      kochi     481: #ifdef ACPI_DEBUGGER
1.1       thorpej   482:        if (acpi_dbgr & ACPI_DBGR_RUNNING)
                    483:                acpi_osd_debugger();
                    484: #endif
                    485: }
                    486:
                    487: /*
                    488:  * acpi_shutdown:
                    489:  *
                    490:  *     Shutdown hook for ACPI -- disable some events that
                    491:  *     might confuse us.
                    492:  */
1.64      kochi     493: static void
1.97      christos  494: acpi_shutdown(void *arg)
1.1       thorpej   495: {
1.81      kochi     496:        /* nothing */
1.1       thorpej   497: }
                    498:
1.81      kochi     499: #if 0
1.1       thorpej   500: /*
                    501:  * acpi_disable:
                    502:  *
                    503:  *     Disable ACPI.
                    504:  */
1.64      kochi     505: static ACPI_STATUS
1.1       thorpej   506: acpi_disable(struct acpi_softc *sc)
                    507: {
                    508:        ACPI_STATUS rv = AE_OK;
                    509:
                    510:        if (acpi_active) {
                    511:                rv = AcpiDisable();
1.56      mycroft   512:                if (ACPI_SUCCESS(rv))
1.1       thorpej   513:                        acpi_active = 0;
                    514:        }
1.63      kochi     515:        return rv;
1.1       thorpej   516: }
1.81      kochi     517: #endif
1.1       thorpej   518:
                    519: struct acpi_make_devnode_state {
                    520:        struct acpi_softc *softc;
                    521:        struct acpi_scope *scope;
                    522: };
                    523:
                    524: /*
                    525:  * acpi_build_tree:
                    526:  *
                    527:  *     Scan relevant portions of the ACPI namespace and attach
                    528:  *     child devices.
                    529:  */
1.64      kochi     530: static void
1.1       thorpej   531: acpi_build_tree(struct acpi_softc *sc)
                    532: {
                    533:        static const char *scopes[] = {
                    534:                "\\_PR_",       /* ACPI 1.0 processor namespace */
                    535:                "\\_SB_",       /* system bus namespace */
1.91      tsarna    536:                "\\_SI_",       /* system indicator namespace */
1.1       thorpej   537:                "\\_TZ_",       /* ACPI 1.0 thermal zone namespace */
                    538:                NULL,
                    539:        };
                    540:        struct acpi_attach_args aa;
                    541:        struct acpi_make_devnode_state state;
                    542:        struct acpi_scope *as;
                    543:        struct acpi_devnode *ad;
                    544:        ACPI_HANDLE parent;
1.56      mycroft   545:        ACPI_STATUS rv;
1.1       thorpej   546:        int i;
                    547:
                    548:        TAILQ_INIT(&sc->sc_scopes);
                    549:
                    550:        state.softc = sc;
                    551:
                    552:        /*
                    553:         * Scan the namespace and build our tree.
                    554:         */
                    555:        for (i = 0; scopes[i] != NULL; i++) {
1.33      christos  556:                as = malloc(sizeof(*as), M_ACPI, M_WAITOK);
1.1       thorpej   557:                as->as_name = scopes[i];
                    558:                TAILQ_INIT(&as->as_devnodes);
                    559:
                    560:                TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
                    561:
                    562:                state.scope = as;
                    563:
1.70      christos  564:                rv = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i],
1.56      mycroft   565:                    &parent);
                    566:                if (ACPI_SUCCESS(rv)) {
1.1       thorpej   567:                        AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
                    568:                            acpi_make_devnode, &state, NULL);
                    569:                }
                    570:
                    571:                /* Now, for this namespace, try and attach the devices. */
                    572:                TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
                    573:                        aa.aa_node = ad;
                    574:                        aa.aa_iot = sc->sc_iot;
                    575:                        aa.aa_memt = sc->sc_memt;
                    576:                        aa.aa_pc = sc->sc_pc;
                    577:                        aa.aa_pciflags = sc->sc_pciflags;
1.19      jmcneill  578:                        aa.aa_ic = sc->sc_ic;
1.1       thorpej   579:
1.54      kochi     580:                        if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) {
1.25      jmcneill  581:                                /*
                    582:                                 * XXX We only attach devices which are:
                    583:                                 *
                    584:                                 *      - present
                    585:                                 *      - enabled
                    586:                                 *      - functioning properly
                    587:                                 *
                    588:                                 * However, if enabled, it's decoding resources,
                    589:                                 * so we should claim them, if possible.
                    590:                                 * Requires changes to bus_space(9).
                    591:                                 */
1.54      kochi     592:                                if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) ==
1.45      mycroft   593:                                    ACPI_VALID_STA &&
1.54      kochi     594:                                    (ad->ad_devinfo->CurrentStatus &
1.25      jmcneill  595:                                     (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
                    596:                                      ACPI_STA_DEV_OK)) !=
                    597:                                    (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
                    598:                                     ACPI_STA_DEV_OK))
                    599:                                        continue;
1.104     jmcneill  600:                        }
1.25      jmcneill  601:
1.104     jmcneill  602:                        /*
                    603:                         * XXX Same problem as above...
                    604:                         *
                    605:                         * Do this check only for devices, as e.g.
                    606:                         * a Thermal Zone doesn't have a HID.
                    607:                         */
                    608:                        if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE &&
                    609:                            (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
                    610:                                continue;
1.1       thorpej   611:
1.94      christos  612:                        ad->ad_device = config_found_ia(&sc->sc_dev,
                    613:                            "acpinodebus", &aa, acpi_print);
1.1       thorpej   614:                }
                    615:        }
1.94      christos  616:        config_found_ia(&sc->sc_dev, "acpiapmbus", NULL, NULL);
1.1       thorpej   617: }
                    618:
1.40      kochi     619: #ifdef ACPI_ACTIVATE_DEV
1.15      augustss  620: static void
1.54      kochi     621: acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
1.15      augustss  622: {
                    623:        ACPI_STATUS rv;
1.54      kochi     624:        ACPI_BUFFER buf;
                    625:
                    626:        buf.Pointer = NULL;
                    627:        buf.Length = ACPI_ALLOCATE_BUFFER;
1.15      augustss  628:
                    629: #ifdef ACPI_DEBUG
1.83      kochi     630:        aprint_normal("acpi_activate_device: %s, old status=%x\n",
1.54      kochi     631:               (*di)->HardwareId.Value, (*di)->CurrentStatus);
1.15      augustss  632: #endif
                    633:
                    634:        rv = acpi_allocate_resources(handle);
                    635:        if (ACPI_FAILURE(rv)) {
1.83      kochi     636:                aprint_error("acpi: activate failed for %s\n",
1.54      kochi     637:                       (*di)->HardwareId.Value);
1.23      augustss  638:        } else {
1.99      ad        639:                aprint_verbose("acpi: activated %s\n",
                    640:                    (*di)->HardwareId.Value);
1.15      augustss  641:        }
                    642:
1.54      kochi     643:        (void)AcpiGetObjectInfo(handle, &buf);
                    644:        AcpiOsFree(*di);
                    645:        *di = buf.Pointer;
                    646:
1.44      mycroft   647: #ifdef ACPI_DEBUG
1.83      kochi     648:        aprint_normal("acpi_activate_device: %s, new status=%x\n",
1.54      kochi     649:               (*di)->HardwareId.Value, (*di)->CurrentStatus);
1.15      augustss  650: #endif
                    651: }
                    652: #endif /* ACPI_ACTIVATE_DEV */
                    653:
1.1       thorpej   654: /*
                    655:  * acpi_make_devnode:
                    656:  *
                    657:  *     Make an ACPI devnode.
                    658:  */
1.64      kochi     659: static ACPI_STATUS
1.1       thorpej   660: acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
1.97      christos  661:     void **status)
1.1       thorpej   662: {
                    663:        struct acpi_make_devnode_state *state = context;
1.20      jmcneill  664: #if defined(ACPI_DEBUG) || defined(ACPI_EXTRA_DEBUG)
1.1       thorpej   665:        struct acpi_softc *sc = state->softc;
1.4       thorpej   666: #endif
1.1       thorpej   667:        struct acpi_scope *as = state->scope;
                    668:        struct acpi_devnode *ad;
1.48      mycroft   669:        ACPI_OBJECT_TYPE type;
                    670:        ACPI_BUFFER buf;
1.54      kochi     671:        ACPI_DEVICE_INFO *devinfo;
1.1       thorpej   672:        ACPI_STATUS rv;
1.102     cube      673:        ACPI_NAME_UNION *anu;
                    674:        int i, clear = 0;
1.1       thorpej   675:
1.56      mycroft   676:        rv = AcpiGetType(handle, &type);
                    677:        if (ACPI_SUCCESS(rv)) {
1.54      kochi     678:                buf.Pointer = NULL;
                    679:                buf.Length = ACPI_ALLOCATE_BUFFER;
1.48      mycroft   680:                rv = AcpiGetObjectInfo(handle, &buf);
1.56      mycroft   681:                if (ACPI_FAILURE(rv)) {
1.15      augustss  682: #ifdef ACPI_DEBUG
1.83      kochi     683:                        aprint_normal("%s: AcpiGetObjectInfo failed: %s\n",
1.55      mycroft   684:                            sc->sc_dev.dv_xname, AcpiFormatException(rv));
1.15      augustss  685: #endif
                    686:                        goto out; /* XXX why return OK */
                    687:                }
                    688:
1.54      kochi     689:                devinfo = buf.Pointer;
                    690:
1.1       thorpej   691:                switch (type) {
                    692:                case ACPI_TYPE_DEVICE:
1.40      kochi     693: #ifdef ACPI_ACTIVATE_DEV
1.54      kochi     694:                        if ((devinfo->Valid & (ACPI_VALID_STA|ACPI_VALID_HID)) ==
1.43      mycroft   695:                            (ACPI_VALID_STA|ACPI_VALID_HID) &&
1.54      kochi     696:                            (devinfo->CurrentStatus &
1.15      augustss  697:                             (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) ==
1.54      kochi     698:                            ACPI_STA_DEV_PRESENT)
1.15      augustss  699:                                acpi_activate_device(handle, &devinfo);
1.43      mycroft   700:
1.15      augustss  701:                        /* FALLTHROUGH */
                    702: #endif
                    703:
1.1       thorpej   704:                case ACPI_TYPE_PROCESSOR:
                    705:                case ACPI_TYPE_THERMAL:
                    706:                case ACPI_TYPE_POWER:
1.33      christos  707:                        ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT|M_ZERO);
1.1       thorpej   708:                        if (ad == NULL)
1.63      kochi     709:                                return AE_NO_MEMORY;
1.1       thorpej   710:
1.43      mycroft   711:                        ad->ad_devinfo = devinfo;
1.1       thorpej   712:                        ad->ad_handle = handle;
                    713:                        ad->ad_level = level;
                    714:                        ad->ad_scope = as;
                    715:                        ad->ad_type = type;
                    716:
1.102     cube      717:                        anu = (ACPI_NAME_UNION *)&devinfo->Name;
                    718:                        ad->ad_name[4] = '\0';
                    719:                        for (i = 3, clear = 0; i >= 0; i--) {
                    720:                                if (!clear && anu->Ascii[i] == '_')
                    721:                                        ad->ad_name[i] = '\0';
                    722:                                else {
                    723:                                        ad->ad_name[i] = anu->Ascii[i];
                    724:                                        clear = 1;
                    725:                                }
                    726:                        }
                    727:                        if (ad->ad_name[0] == '\0')
                    728:                                ad->ad_name[0] = '_';
                    729:
1.1       thorpej   730:                        TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
                    731:
1.104     jmcneill  732:                        if (type == ACPI_TYPE_DEVICE &&
                    733:                            (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
1.1       thorpej   734:                                goto out;
                    735:
1.14      augustss  736: #ifdef ACPI_EXTRA_DEBUG
1.83      kochi     737:                        aprint_normal("%s: HID %s found in scope %s level %d\n",
1.54      kochi     738:                            sc->sc_dev.dv_xname,
                    739:                            ad->ad_devinfo->HardwareId.Value,
1.1       thorpej   740:                            as->as_name, ad->ad_level);
1.54      kochi     741:                        if (ad->ad_devinfo->Valid & ACPI_VALID_UID)
1.83      kochi     742:                                aprint_normal("       UID %s\n",
1.54      kochi     743:                                    ad->ad_devinfo->UniqueId.Value);
                    744:                        if (ad->ad_devinfo->Valid & ACPI_VALID_ADR)
1.83      kochi     745:                                aprint_normal("       ADR 0x%016qx\n",
1.54      kochi     746:                                    ad->ad_devinfo->Address);
                    747:                        if (ad->ad_devinfo->Valid & ACPI_VALID_STA)
1.83      kochi     748:                                aprint_normal("       STA 0x%08x\n",
1.54      kochi     749:                                    ad->ad_devinfo->CurrentStatus);
1.1       thorpej   750: #endif
                    751:                }
                    752:        }
                    753:  out:
1.63      kochi     754:        return AE_OK;
1.1       thorpej   755: }
                    756:
                    757: /*
                    758:  * acpi_print:
                    759:  *
1.94      christos  760:  *     Autoconfiguration print routine for ACPI node bus.
1.1       thorpej   761:  */
1.64      kochi     762: static int
1.1       thorpej   763: acpi_print(void *aux, const char *pnp)
                    764: {
                    765:        struct acpi_attach_args *aa = aux;
1.56      mycroft   766:        ACPI_STATUS rv;
1.1       thorpej   767:
1.4       thorpej   768:        if (pnp) {
1.54      kochi     769:                if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
                    770:                        char *pnpstr =
                    771:                            aa->aa_node->ad_devinfo->HardwareId.Value;
1.27      christos  772:                        char *str;
                    773:
1.102     cube      774:                        aprint_normal("%s (%s) ", aa->aa_node->ad_name,
                    775:                            pnpstr);
1.56      mycroft   776:                        rv = acpi_eval_string(aa->aa_node->ad_handle,
                    777:                            "_STR", &str);
                    778:                        if (ACPI_SUCCESS(rv)) {
1.27      christos  779:                                aprint_normal("[%s] ", str);
                    780:                                AcpiOsFree(str);
                    781:                        }
                    782: #ifdef ACPIVERBOSE
                    783:                        else {
                    784:                                int i;
                    785:
                    786:                                for (i = 0; i < sizeof(acpi_knowndevs) /
                    787:                                    sizeof(acpi_knowndevs[0]); i++) {
                    788:                                        if (strcmp(acpi_knowndevs[i].pnp,
                    789:                                            pnpstr) == 0) {
1.83      kochi     790:                                                aprint_normal("[%s] ",
1.27      christos  791:                                                    acpi_knowndevs[i].str);
                    792:                                        }
                    793:                                }
                    794:                        }
1.62      kochi     795:
1.27      christos  796: #endif
1.104     jmcneill  797:                        aprint_normal("at %s", pnp);
                    798:                } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) {
1.102     cube      799:                        aprint_normal("%s (ACPI Object Type '%s' "
                    800:                            "[0x%02x]) ", aa->aa_node->ad_name,
                    801:                             AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
                    802:                             aa->aa_node->ad_devinfo->Type);
1.104     jmcneill  803:                        aprint_normal("at %s", pnp);
                    804:                } else
                    805:                        return 0;
1.21      matt      806:        } else {
1.102     cube      807:                aprint_normal(" (%s", aa->aa_node->ad_name);
1.54      kochi     808:                if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
1.102     cube      809:                        aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.Value);
1.54      kochi     810:                        if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
1.70      christos  811:                                const char *uid;
1.41      kochi     812:
1.54      kochi     813:                                uid = aa->aa_node->ad_devinfo->UniqueId.Value;
1.48      mycroft   814:                                if (uid[0] == '\0')
1.41      kochi     815:                                        uid = "<null>";
                    816:                                aprint_normal("-%s", uid);
                    817:                        }
1.22      jmcneill  818:                }
1.102     cube      819:                aprint_normal(")");
1.4       thorpej   820:        }
1.1       thorpej   821:
1.63      kochi     822:        return UNCONF;
1.1       thorpej   823: }
                    824:
                    825: /*****************************************************************************
                    826:  * ACPI fixed-hardware feature handlers
                    827:  *****************************************************************************/
                    828:
1.64      kochi     829: static UINT32  acpi_fixed_button_handler(void *);
                    830: static void    acpi_fixed_button_pressed(void *);
1.1       thorpej   831:
                    832: /*
                    833:  * acpi_enable_fixed_events:
                    834:  *
                    835:  *     Enable any fixed-hardware feature handlers.
                    836:  */
1.64      kochi     837: static void
1.1       thorpej   838: acpi_enable_fixed_events(struct acpi_softc *sc)
                    839: {
                    840:        static int beenhere;
                    841:        ACPI_STATUS rv;
                    842:
1.34      thorpej   843:        KASSERT(beenhere == 0);
                    844:        beenhere = 1;
                    845:
1.1       thorpej   846:        /*
                    847:         * Check for fixed-hardware buttons.
                    848:         */
                    849:
1.104     jmcneill  850:        if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
1.99      ad        851:                aprint_verbose("%s: fixed-feature power button present\n",
1.34      thorpej   852:                    sc->sc_dev.dv_xname);
                    853:                sc->sc_smpsw_power.smpsw_name = sc->sc_dev.dv_xname;
1.35      thorpej   854:                sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER;
1.34      thorpej   855:                if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
1.83      kochi     856:                        aprint_error("%s: unable to register fixed power "
                    857:                            "button with sysmon\n", sc->sc_dev.dv_xname);
1.34      thorpej   858:                } else {
                    859:                        rv = AcpiInstallFixedEventHandler(
                    860:                            ACPI_EVENT_POWER_BUTTON,
                    861:                            acpi_fixed_button_handler, &sc->sc_smpsw_power);
1.56      mycroft   862:                        if (ACPI_FAILURE(rv)) {
1.83      kochi     863:                                aprint_error("%s: unable to install handler "
                    864:                                    "for fixed power button: %s\n",
1.56      mycroft   865:                                    sc->sc_dev.dv_xname,
                    866:                                    AcpiFormatException(rv));
1.34      thorpej   867:                        }
                    868:                }
1.1       thorpej   869:        }
                    870:
1.104     jmcneill  871:        if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
1.99      ad        872:                aprint_verbose("%s: fixed-feature sleep button present\n",
1.34      thorpej   873:                    sc->sc_dev.dv_xname);
                    874:                sc->sc_smpsw_sleep.smpsw_name = sc->sc_dev.dv_xname;
1.35      thorpej   875:                sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP;
1.34      thorpej   876:                if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
1.83      kochi     877:                        aprint_error("%s: unable to register fixed sleep "
                    878:                            "button with sysmon\n", sc->sc_dev.dv_xname);
1.34      thorpej   879:                } else {
                    880:                        rv = AcpiInstallFixedEventHandler(
                    881:                            ACPI_EVENT_SLEEP_BUTTON,
                    882:                            acpi_fixed_button_handler, &sc->sc_smpsw_sleep);
1.56      mycroft   883:                        if (ACPI_FAILURE(rv)) {
1.83      kochi     884:                                aprint_error("%s: unable to install handler "
                    885:                                    "for fixed sleep button: %s\n",
1.56      mycroft   886:                                    sc->sc_dev.dv_xname,
                    887:                                    AcpiFormatException(rv));
1.34      thorpej   888:                        }
                    889:                }
1.1       thorpej   890:        }
                    891: }
                    892:
                    893: /*
1.34      thorpej   894:  * acpi_fixed_button_handler:
1.1       thorpej   895:  *
1.34      thorpej   896:  *     Event handler for the fixed buttons.
1.1       thorpej   897:  */
1.64      kochi     898: static UINT32
1.34      thorpej   899: acpi_fixed_button_handler(void *context)
1.1       thorpej   900: {
1.34      thorpej   901:        struct sysmon_pswitch *smpsw = context;
                    902:        int rv;
1.1       thorpej   903:
1.34      thorpej   904: #ifdef ACPI_BUT_DEBUG
                    905:        printf("%s: fixed button handler\n", smpsw->smpsw_name);
                    906: #endif
1.1       thorpej   907:
1.104     jmcneill  908:        rv = AcpiOsExecute(OSL_NOTIFY_HANDLER,
1.34      thorpej   909:            acpi_fixed_button_pressed, smpsw);
1.56      mycroft   910:        if (ACPI_FAILURE(rv))
1.34      thorpej   911:                printf("%s: WARNING: unable to queue fixed button pressed "
1.55      mycroft   912:                    "callback: %s\n", smpsw->smpsw_name,
                    913:                    AcpiFormatException(rv));
1.1       thorpej   914:
1.63      kochi     915:        return ACPI_INTERRUPT_HANDLED;
1.1       thorpej   916: }
                    917:
                    918: /*
1.34      thorpej   919:  * acpi_fixed_button_pressed:
1.1       thorpej   920:  *
1.34      thorpej   921:  *     Deal with a fixed button being pressed.
1.1       thorpej   922:  */
1.64      kochi     923: static void
1.34      thorpej   924: acpi_fixed_button_pressed(void *context)
1.1       thorpej   925: {
1.34      thorpej   926:        struct sysmon_pswitch *smpsw = context;
1.1       thorpej   927:
1.34      thorpej   928: #ifdef ACPI_BUT_DEBUG
                    929:        printf("%s: fixed button pressed, calling sysmon\n",
                    930:            smpsw->smpsw_name);
                    931: #endif
1.1       thorpej   932:
1.35      thorpej   933:        sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
1.1       thorpej   934: }
                    935:
                    936: /*****************************************************************************
                    937:  * ACPI utility routines.
                    938:  *****************************************************************************/
                    939:
1.2       thorpej   940: /*
                    941:  * acpi_eval_integer:
                    942:  *
                    943:  *     Evaluate an integer object.
                    944:  */
1.1       thorpej   945: ACPI_STATUS
1.70      christos  946: acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp)
1.1       thorpej   947: {
                    948:        ACPI_STATUS rv;
                    949:        ACPI_BUFFER buf;
                    950:        ACPI_OBJECT param;
                    951:
                    952:        if (handle == NULL)
                    953:                handle = ACPI_ROOT_OBJECT;
                    954:
                    955:        buf.Pointer = &param;
                    956:        buf.Length = sizeof(param);
                    957:
1.46      mycroft   958:        rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_INTEGER);
1.56      mycroft   959:        if (ACPI_SUCCESS(rv))
1.46      mycroft   960:                *valp = param.Integer.Value;
1.1       thorpej   961:
1.63      kochi     962:        return rv;
1.4       thorpej   963: }
                    964:
                    965: /*
                    966:  * acpi_eval_string:
                    967:  *
1.7       sommerfe  968:  *     Evaluate a (Unicode) string object.
1.4       thorpej   969:  */
                    970: ACPI_STATUS
1.70      christos  971: acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp)
1.4       thorpej   972: {
                    973:        ACPI_STATUS rv;
                    974:        ACPI_BUFFER buf;
                    975:
                    976:        if (handle == NULL)
                    977:                handle = ACPI_ROOT_OBJECT;
                    978:
                    979:        buf.Pointer = NULL;
1.32      tshiozak  980:        buf.Length = ACPI_ALLOCATE_BUFFER;
1.4       thorpej   981:
1.46      mycroft   982:        rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_STRING);
1.56      mycroft   983:        if (ACPI_SUCCESS(rv)) {
1.49      mycroft   984:                ACPI_OBJECT *param = buf.Pointer;
1.71      drochner  985:                const char *ptr = param->String.Pointer;
1.46      mycroft   986:                size_t len = param->String.Length;
                    987:                if ((*stringp = AcpiOsAllocate(len)) == NULL)
                    988:                        rv = AE_NO_MEMORY;
                    989:                else
                    990:                        (void)memcpy(*stringp, ptr, len);
                    991:                AcpiOsFree(param);
1.4       thorpej   992:        }
1.46      mycroft   993:
1.63      kochi     994:        return rv;
1.7       sommerfe  995: }
                    996:
                    997:
                    998: /*
                    999:  * acpi_eval_struct:
                   1000:  *
1.38      kochi    1001:  *     Evaluate a more complex structure.
                   1002:  *     Caller must free buf.Pointer by AcpiOsFree().
1.7       sommerfe 1003:  */
                   1004: ACPI_STATUS
1.70      christos 1005: acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp)
1.7       sommerfe 1006: {
                   1007:        ACPI_STATUS rv;
                   1008:
                   1009:        if (handle == NULL)
                   1010:                handle = ACPI_ROOT_OBJECT;
                   1011:
                   1012:        bufp->Pointer = NULL;
1.32      tshiozak 1013:        bufp->Length = ACPI_ALLOCATE_BUFFER;
1.7       sommerfe 1014:
                   1015:        rv = AcpiEvaluateObject(handle, path, NULL, bufp);
                   1016:
1.63      kochi    1017:        return rv;
1.2       thorpej  1018: }
                   1019:
                   1020: /*
1.65      kochi    1021:  * acpi_foreach_package_object:
                   1022:  *
                   1023:  *     Iterate over all objects in a in a packages and pass then all
                   1024:  *     to a function. If the called function returns non AE_OK, the
                   1025:  *     iteration is stopped and that value is returned.
                   1026:  */
                   1027:
                   1028: ACPI_STATUS
1.68      perry    1029: acpi_foreach_package_object(ACPI_OBJECT *pkg,
                   1030:     ACPI_STATUS (*func)(ACPI_OBJECT *, void *),
1.65      kochi    1031:     void *arg)
                   1032: {
                   1033:        ACPI_STATUS rv = AE_OK;
                   1034:        int i;
                   1035:
                   1036:        if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE)
                   1037:                return AE_BAD_PARAMETER;
                   1038:
                   1039:        for (i = 0; i < pkg->Package.Count; i++) {
                   1040:                rv = (*func)(&pkg->Package.Elements[i], arg);
                   1041:                if (ACPI_FAILURE(rv))
                   1042:                        break;
                   1043:        }
                   1044:
                   1045:        return rv;
                   1046: }
                   1047:
                   1048: const char *
                   1049: acpi_name(ACPI_HANDLE handle)
                   1050: {
                   1051:        static char buffer[80];
                   1052:        ACPI_BUFFER buf;
                   1053:        ACPI_STATUS rv;
                   1054:
                   1055:        buf.Length = sizeof(buffer);
                   1056:        buf.Pointer = buffer;
                   1057:
                   1058:        rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
                   1059:        if (ACPI_FAILURE(rv))
                   1060:                return "(unknown acpi path)";
                   1061:        return buffer;
                   1062: }
                   1063:
                   1064: /*
1.2       thorpej  1065:  * acpi_get:
                   1066:  *
                   1067:  *     Fetch data info the specified (empty) ACPI buffer.
1.38      kochi    1068:  *     Caller must free buf.Pointer by AcpiOsFree().
1.2       thorpej  1069:  */
                   1070: ACPI_STATUS
                   1071: acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
                   1072:     ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
                   1073: {
                   1074:        buf->Pointer = NULL;
1.38      kochi    1075:        buf->Length = ACPI_ALLOCATE_BUFFER;
1.2       thorpej  1076:
1.63      kochi    1077:        return (*getit)(handle, buf);
1.54      kochi    1078: }
                   1079:
                   1080:
                   1081: /*
                   1082:  * acpi_match_hid
                   1083:  *
                   1084:  *     Match given ids against _HID and _CIDs
                   1085:  */
                   1086: int
                   1087: acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
                   1088: {
                   1089:        int i;
                   1090:
                   1091:        while (*ids) {
1.57      mycroft  1092:                if (ad->Valid & ACPI_VALID_HID) {
                   1093:                        if (pmatch(ad->HardwareId.Value, *ids, NULL) == 2)
1.63      kochi    1094:                                return 1;
1.57      mycroft  1095:                }
1.54      kochi    1096:
                   1097:                if (ad->Valid & ACPI_VALID_CID) {
                   1098:                        for (i = 0; i < ad->CompatibilityId.Count; i++) {
1.57      mycroft  1099:                                if (pmatch(ad->CompatibilityId.Id[i].Value, *ids, NULL) == 2)
1.63      kochi    1100:                                        return 1;
1.54      kochi    1101:                        }
                   1102:                }
                   1103:                ids++;
                   1104:        }
                   1105:
1.63      kochi    1106:        return 0;
1.10      tshiozak 1107: }
                   1108:
1.69      kochi    1109: /*
                   1110:  * acpi_set_wake_gpe
                   1111:  *
                   1112:  *     Set GPE as both Runtime and Wake
                   1113:  */
                   1114: void
                   1115: acpi_set_wake_gpe(ACPI_HANDLE handle)
                   1116: {
                   1117:        ACPI_BUFFER buf;
                   1118:        ACPI_STATUS rv;
                   1119:        ACPI_OBJECT *p, *elt;
                   1120:
                   1121:        rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf);
                   1122:        if (ACPI_FAILURE(rv))
                   1123:                return;                 /* just ignore */
                   1124:
                   1125:        p = buf.Pointer;
                   1126:        if (p->Type != ACPI_TYPE_PACKAGE || p->Package.Count < 2)
                   1127:                goto out;               /* just ignore */
                   1128:
                   1129:        elt = p->Package.Elements;
                   1130:
                   1131:        /* TBD: package support */
                   1132:        AcpiSetGpeType(NULL, elt[0].Integer.Value, ACPI_GPE_TYPE_WAKE_RUN);
                   1133:        AcpiEnableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR);
                   1134:
                   1135:  out:
                   1136:        AcpiOsFree(buf.Pointer);
                   1137: }
                   1138:
1.10      tshiozak 1139:
                   1140: /*****************************************************************************
                   1141:  * ACPI sleep support.
                   1142:  *****************************************************************************/
                   1143:
                   1144: static int
1.97      christos 1145: is_available_state(struct acpi_softc *sc, int state)
1.10      tshiozak 1146: {
                   1147:        UINT8 type_a, type_b;
                   1148:
1.63      kochi    1149:        return ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
                   1150:                                &type_a, &type_b));
1.10      tshiozak 1151: }
                   1152:
                   1153: /*
                   1154:  * acpi_enter_sleep_state:
                   1155:  *
                   1156:  *     enter to the specified sleep state.
                   1157:  */
                   1158:
                   1159: ACPI_STATUS
                   1160: acpi_enter_sleep_state(struct acpi_softc *sc, int state)
                   1161: {
1.104     jmcneill 1162:        int err;
1.10      tshiozak 1163:        ACPI_STATUS ret = AE_OK;
                   1164:
1.92      christos 1165:        if (state == acpi_sleepstate)
                   1166:                return AE_OK;
                   1167:
                   1168:        aprint_normal("%s: entering state %d\n", sc->sc_dev.dv_xname, state);
                   1169:
1.10      tshiozak 1170:        switch (state) {
                   1171:        case ACPI_STATE_S0:
                   1172:                break;
                   1173:        case ACPI_STATE_S1:
                   1174:        case ACPI_STATE_S2:
                   1175:        case ACPI_STATE_S3:
                   1176:        case ACPI_STATE_S4:
                   1177:                if (!is_available_state(sc, state)) {
1.104.2.1! bouyer   1178:                        aprint_error("%s: cannot enter the sleep state (%d)\n",
1.92      christos 1179:                            sc->sc_dev.dv_xname, state);
1.10      tshiozak 1180:                        break;
                   1181:                }
1.104     jmcneill 1182:
                   1183:                if (state != ACPI_STATE_S1 && !pmf_system_suspend()) {
1.104.2.1! bouyer   1184:                        aprint_error_dev(&sc->sc_dev, "aborting suspend\n");
1.104     jmcneill 1185:                        break;
                   1186:                }
                   1187:
1.10      tshiozak 1188:                ret = AcpiEnterSleepStatePrep(state);
                   1189:                if (ACPI_FAILURE(ret)) {
1.92      christos 1190:                        aprint_error("%s: failed preparing to sleep (%s)\n",
                   1191:                            sc->sc_dev.dv_xname, AcpiFormatException(ret));
1.10      tshiozak 1192:                        break;
                   1193:                }
1.104     jmcneill 1194:
1.92      christos 1195:                acpi_sleepstate = state;
                   1196:                if (state == ACPI_STATE_S1) {
1.10      tshiozak 1197:                        /* just enter the state */
1.12      kanaoka  1198:                        acpi_md_OsDisableInterrupt();
1.10      tshiozak 1199:                        AcpiEnterSleepState((UINT8)state);
1.104     jmcneill 1200:                        AcpiLeaveSleepState((UINT8)state);
1.10      tshiozak 1201:                } else {
1.104     jmcneill 1202:                        err = acpi_md_sleep(state);
                   1203:                        if (state == ACPI_STATE_S4)
1.10      tshiozak 1204:                                AcpiEnable();
1.104     jmcneill 1205:                        AcpiLeaveSleepState((UINT8)state);
                   1206:                        pmf_system_resume();
1.10      tshiozak 1207:                }
1.104     jmcneill 1208:
1.10      tshiozak 1209:                break;
                   1210:        case ACPI_STATE_S5:
1.42      kochi    1211:                ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
                   1212:                if (ACPI_FAILURE(ret)) {
1.92      christos 1213:                        aprint_error("%s: failed preparing to sleep (%s)\n",
                   1214:                               sc->sc_dev.dv_xname, AcpiFormatException(ret));
1.42      kochi    1215:                        break;
                   1216:                }
1.104     jmcneill 1217:                DELAY(1000000);
1.92      christos 1218:                acpi_sleepstate = state;
1.12      kanaoka  1219:                acpi_md_OsDisableInterrupt();
1.10      tshiozak 1220:                AcpiEnterSleepState(ACPI_STATE_S5);
1.92      christos 1221:                aprint_error("%s: WARNING powerdown failed!\n",
                   1222:                    sc->sc_dev.dv_xname);
1.10      tshiozak 1223:                break;
                   1224:        }
                   1225:
1.92      christos 1226:        acpi_sleepstate = ACPI_STATE_S0;
1.63      kochi    1227:        return ret;
1.1       thorpej  1228: }
1.13      augustss 1229:
1.93      christos 1230: #if defined(ACPI_ACTIVATE_DEV)
                   1231: /* XXX This very incomplete */
1.13      augustss 1232: ACPI_STATUS
                   1233: acpi_allocate_resources(ACPI_HANDLE handle)
                   1234: {
                   1235:        ACPI_BUFFER bufp, bufc, bufn;
                   1236:        ACPI_RESOURCE *resp, *resc, *resn;
                   1237:        ACPI_RESOURCE_IRQ *irq;
1.93      christos 1238:        ACPI_RESOURCE_EXTENDED_IRQ *xirq;
1.13      augustss 1239:        ACPI_STATUS rv;
                   1240:        uint delta;
                   1241:
                   1242:        rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
                   1243:        if (ACPI_FAILURE(rv))
                   1244:                goto out;
                   1245:        rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
                   1246:        if (ACPI_FAILURE(rv)) {
                   1247:                goto out1;
                   1248:        }
                   1249:
                   1250:        bufn.Length = 1000;
1.33      christos 1251:        bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
1.13      augustss 1252:        resp = bufp.Pointer;
                   1253:        resc = bufc.Pointer;
1.85      cube     1254:        while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG &&
                   1255:               resp->Type != ACPI_RESOURCE_TYPE_END_TAG) {
                   1256:                while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG)
1.13      augustss 1257:                        resp = ACPI_NEXT_RESOURCE(resp);
1.85      cube     1258:                if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG)
1.13      augustss 1259:                        break;
                   1260:                /* Found identical Id */
1.80      kochi    1261:                resn->Type = resc->Type;
                   1262:                switch (resc->Type) {
                   1263:                case ACPI_RESOURCE_TYPE_IRQ:
1.13      augustss 1264:                        memcpy(&resn->Data, &resp->Data,
                   1265:                               sizeof(ACPI_RESOURCE_IRQ));
                   1266:                        irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
                   1267:                        irq->Interrupts[0] =
                   1268:                            ((ACPI_RESOURCE_IRQ *)&resp->Data)->
1.80      kochi    1269:                                Interrupts[irq->InterruptCount-1];
                   1270:                        irq->InterruptCount = 1;
                   1271:                        resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
1.13      augustss 1272:                        break;
1.93      christos 1273:                case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
                   1274:                        memcpy(&resn->Data, &resp->Data,
                   1275:                               sizeof(ACPI_RESOURCE_EXTENDED_IRQ));
                   1276:                        xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data;
                   1277: #if 0
                   1278:                        /*
                   1279:                         * XXX not duplicating the interrupt logic above
                   1280:                         * because its not clear what it accomplishes.
                   1281:                         */
                   1282:                        xirq->Interrupts[0] =
                   1283:                            ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)->
                   1284:                            Interrupts[irq->NumberOfInterrupts-1];
                   1285:                        xirq->NumberOfInterrupts = 1;
                   1286: #endif
                   1287:                        resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
                   1288:                        break;
1.80      kochi    1289:                case ACPI_RESOURCE_TYPE_IO:
1.13      augustss 1290:                        memcpy(&resn->Data, &resp->Data,
                   1291:                               sizeof(ACPI_RESOURCE_IO));
                   1292:                        resn->Length = resp->Length;
                   1293:                        break;
                   1294:                default:
1.80      kochi    1295:                        printf("acpi_allocate_resources: res=%d\n", resc->Type);
1.13      augustss 1296:                        rv = AE_BAD_DATA;
                   1297:                        goto out2;
                   1298:                }
                   1299:                resc = ACPI_NEXT_RESOURCE(resc);
                   1300:                resn = ACPI_NEXT_RESOURCE(resn);
1.89      cube     1301:                resp = ACPI_NEXT_RESOURCE(resp);
1.13      augustss 1302:                delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
1.62      kochi    1303:                if (delta >=
1.80      kochi    1304:                    bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) {
1.13      augustss 1305:                        bufn.Length *= 2;
                   1306:                        bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
1.33      christos 1307:                                               M_ACPI, M_WAITOK);
1.13      augustss 1308:                        resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
                   1309:                }
                   1310:        }
1.85      cube     1311:        if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1.13      augustss 1312:                printf("acpi_allocate_resources: resc not exhausted\n");
                   1313:                rv = AE_BAD_DATA;
                   1314:                goto out3;
                   1315:        }
                   1316:
1.85      cube     1317:        resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
1.13      augustss 1318:        rv = AcpiSetCurrentResources(handle, &bufn);
                   1319:        if (ACPI_FAILURE(rv)) {
                   1320:                printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n",
                   1321:                       AcpiFormatException(rv));
                   1322:        }
                   1323:
                   1324: out3:
1.33      christos 1325:        free(bufn.Pointer, M_ACPI);
1.13      augustss 1326: out2:
1.38      kochi    1327:        AcpiOsFree(bufc.Pointer);
1.13      augustss 1328: out1:
1.38      kochi    1329:        AcpiOsFree(bufp.Pointer);
1.13      augustss 1330: out:
                   1331:        return rv;
                   1332: }
1.93      christos 1333: #endif /* ACPI_ACTIVATE_DEV */
1.79      cube     1334:
                   1335: SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
                   1336: {
                   1337:        const struct sysctlnode *node;
1.86      jmcneill 1338:        const struct sysctlnode *ssnode;
1.79      cube     1339:
                   1340:        if (sysctl_createv(clog, 0, NULL, NULL,
                   1341:            CTLFLAG_PERMANENT,
                   1342:            CTLTYPE_NODE, "hw", NULL,
                   1343:            NULL, 0, NULL, 0,
                   1344:            CTL_HW, CTL_EOL) != 0)
                   1345:                return;
                   1346:
                   1347:        if (sysctl_createv(clog, 0, NULL, &node,
                   1348:            CTLFLAG_PERMANENT,
                   1349:            CTLTYPE_NODE, "acpi", NULL,
                   1350:            NULL, 0, NULL, 0,
                   1351:            CTL_HW, CTL_CREATE, CTL_EOL) != 0)
                   1352:                return;
                   1353:
                   1354:        acpi_node = node->sysctl_num;
1.86      jmcneill 1355:
                   1356:        /* ACPI sleepstate sysctl */
                   1357:        if (sysctl_createv(NULL, 0, NULL, &node,
                   1358:            CTLFLAG_PERMANENT,
                   1359:            CTLTYPE_NODE, "machdep", NULL,
                   1360:            NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL) != 0)
                   1361:                return;
                   1362:        if (sysctl_createv(NULL, 0, &node, &ssnode,
                   1363:            CTLFLAG_READWRITE, CTLTYPE_INT, "sleep_state",
                   1364:            NULL, sysctl_hw_acpi_sleepstate, 0, NULL, 0, CTL_CREATE,
                   1365:            CTL_EOL) != 0)
                   1366:                return;
                   1367: }
                   1368:
                   1369: static int
                   1370: sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
                   1371: {
                   1372:        int error, t;
                   1373:        struct sysctlnode node;
                   1374:
                   1375:        node = *rnode;
                   1376:        t = acpi_sleepstate;
                   1377:        node.sysctl_data = &t;
                   1378:        error = sysctl_lookup(SYSCTLFN_CALL(&node));
                   1379:        if (error || newp == NULL)
                   1380:                return error;
                   1381:
1.92      christos 1382:        if (acpi_softc == NULL)
                   1383:                return ENOSYS;
1.86      jmcneill 1384:
1.92      christos 1385:        acpi_enter_sleep_state(acpi_softc, t);
1.86      jmcneill 1386:
                   1387:        return 0;
1.79      cube     1388: }

CVSweb <webmaster@jp.NetBSD.org>