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

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

CVSweb <webmaster@jp.NetBSD.org>