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