Annotation of src/sys/dev/acpi/acpi.c, Revision 1.215
1.215 ! gsutre 1: /* $NetBSD: acpi.c,v 1.214 2010/08/07 20:07:25 jruoho 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.212 jruoho 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.215 ! gsutre 103: __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.214 2010/08/07 20:07:25 jruoho Exp $");
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.155 jruoho 110: #include <sys/kernel.h>
1.1 thorpej 111: #include <sys/malloc.h>
1.197 pgoyette 112: #include <sys/module.h>
1.100 xtraeme 113: #include <sys/mutex.h>
1.78 cube 114: #include <sys/sysctl.h>
1.155 jruoho 115: #include <sys/systm.h>
1.206 jruoho 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.155 jruoho 121: #include <dev/acpi/acpi_pci.h>
1.181 jruoho 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.155 jruoho 125:
1.169 jruoho 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.211 jruoho 159: int acpi_verbose_loaded = 0;
1.1 thorpej 160:
1.211 jruoho 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];
1.213 jruoho 166: ACPI_TABLE_HEADER *madt_header;
1.32 tshiozak 167:
1.79 cube 168: /*
1.176 jruoho 169: * This structure provides a context for the ACPI
170: * namespace walk performed in acpi_build_tree().
171: */
172: struct acpi_walkcontext {
173: struct acpi_softc *aw_sc;
174: struct acpi_devnode *aw_parent;
175: };
176:
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.162 jruoho 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.169 jruoho 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 *);
204:
1.64 kochi 205: static void acpi_build_tree(struct acpi_softc *);
1.151 jruoho 206: static ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, uint32_t,
207: void *, void **);
1.176 jruoho 208: static ACPI_STATUS acpi_make_devnode_post(ACPI_HANDLE, uint32_t,
209: void *, void **);
1.1 thorpej 210:
1.169 jruoho 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:
1.175 jruoho 221: static void acpi_notify_handler(ACPI_HANDLE, uint32_t, void *);
222:
1.168 jruoho 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:
1.166 jruoho 228: static void acpi_sleep_init(struct acpi_softc *);
1.1 thorpej 229:
1.209 jruoho 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.169 jruoho 233:
1.185 jruoho 234: static bool acpi_is_scope(struct acpi_devnode *);
1.108 jmcneill 235: static ACPI_TABLE_HEADER *acpi_map_rsdt(void);
1.185 jruoho 236: static void acpi_unmap_rsdt(ACPI_TABLE_HEADER *);
1.108 jmcneill 237:
1.211 jruoho 238: void acpi_print_verbose_stub(struct acpi_softc *);
239: void acpi_print_dev_stub(const char *);
1.123 jmcneill 240:
1.211 jruoho 241: void (*acpi_print_verbose)(struct acpi_softc *) = acpi_print_verbose_stub;
1.200 pgoyette 242: void (*acpi_print_dev)(const char *) = acpi_print_dev_stub;
1.197 pgoyette 243:
1.169 jruoho 244: CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc),
245: acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet);
1.159 jruoho 246:
1.1 thorpej 247: /*
1.169 jruoho 248: * Probe for ACPI support.
1.1 thorpej 249: *
1.169 jruoho 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.172 jruoho 257: const char *func;
258: static int once;
259: bool initialized;
1.1 thorpej 260: ACPI_STATUS rv;
1.169 jruoho 261:
262: if (once != 0)
263: panic("%s: already probed", __func__);
1.1 thorpej 264:
1.169 jruoho 265: once = 1;
1.172 jruoho 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.178 jruoho 279: CTASSERT(TRUE == true);
280: CTASSERT(FALSE == false);
281:
1.172 jruoho 282: AcpiGbl_AllMethodsSerialized = false;
283: AcpiGbl_EnableInterpreterSlack = true;
1.104 jmcneill 284:
1.1 thorpej 285: rv = AcpiInitializeSubsystem();
1.172 jruoho 286:
287: if (ACPI_SUCCESS(rv))
288: initialized = true;
289: else {
290: func = "AcpiInitializeSubsystem()";
291: goto fail;
1.1 thorpej 292: }
293:
1.178 jruoho 294: /*
295: * Allocate space for RSDT/XSDT and DSDT,
296: * but allow resizing if more tables exist.
297: */
298: rv = AcpiInitializeTables(NULL, 2, true);
1.172 jruoho 299:
1.104 jmcneill 300: if (ACPI_FAILURE(rv)) {
1.172 jruoho 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.172 jruoho 311:
1.56 mycroft 312: if (ACPI_FAILURE(rv)) {
1.172 jruoho 313: func = "AcpiLoadTables()";
314: goto fail;
1.1 thorpej 315: }
316:
1.108 jmcneill 317: rsdt = acpi_map_rsdt();
1.172 jruoho 318:
1.108 jmcneill 319: if (rsdt == NULL) {
1.172 jruoho 320: func = "acpi_map_rsdt()";
321: rv = AE_ERROR;
322: goto fail;
1.108 jmcneill 323: }
1.107 jmcneill 324:
1.172 jruoho 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.172 jruoho 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.172 jruoho 342:
1.104 jmcneill 343: if (ACPI_FAILURE(rv)) {
1.172 jruoho 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.172 jruoho 352:
353: fail:
354: KASSERT(rv != AE_OK);
355: KASSERT(func != NULL);
356:
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.1 thorpej 364: }
365:
1.214 jruoho 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.174 jruoho 380: /*
381: * Autoconfiguration.
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.169 jruoho 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.169 jruoho 392: static int
393: acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
1.111 dyoung 394: {
1.169 jruoho 395: struct cfattach *ca;
1.111 dyoung 396:
1.169 jruoho 397: ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
1.124 dyoung 398:
1.169 jruoho 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.166 jruoho 407: ACPI_TABLE_HEADER *rsdt;
1.1 thorpej 408: ACPI_STATUS rv;
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.172 jruoho 414: panic("%s: already attached", __func__);
1.29 fvdl 415:
1.172 jruoho 416: rsdt = acpi_map_rsdt();
1.37 kochi 417:
1.172 jruoho 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.172 jruoho 426: }
1.157 jruoho 427:
1.108 jmcneill 428: acpi_unmap_rsdt(rsdt);
1.1 thorpej 429:
1.113 jmcneill 430: sc->sc_dev = self;
1.176 jruoho 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.172 jruoho 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.176 jruoho 444: SIMPLEQ_INIT(&sc->ad_head);
1.157 jruoho 445:
1.1 thorpej 446: acpi_softc = sc;
447:
1.172 jruoho 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.172 jruoho 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.172 jruoho 473:
474: if (ACPI_FAILURE(rv))
475: goto fail;
1.60 kochi 476:
1.174 jruoho 477: /*
478: * Early EC handler initialization if ECDT table is available.
479: */
1.163 dyoung 480: config_found_ia(self, "acpiecdtbus", aa, NULL);
1.60 kochi 481:
1.104 jmcneill 482: rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
1.172 jruoho 483:
484: if (ACPI_FAILURE(rv))
485: goto fail;
486:
1.175 jruoho 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:
1.1 thorpej 502: acpi_active = 1;
503:
1.9 kanaoka 504: /* Show SCI interrupt. */
1.150 jruoho 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.168 jruoho 509: * Install fixed-event handlers.
1.1 thorpej 510: */
1.168 jruoho 511: acpi_register_fixed_button(sc, ACPI_EVENT_POWER_BUTTON);
512: acpi_register_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON);
513:
1.206 jruoho 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
1.166 jruoho 520:
1.168 jruoho 521: /*
522: * Scan the namespace and build our device tree.
523: */
1.1 thorpej 524: acpi_build_tree(sc);
1.166 jruoho 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.172 jruoho 535:
1.211 jruoho 536: /*
537: * Print debug information.
538: */
539: acpi_print_verbose(sc);
540:
1.172 jruoho 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.171 jruoho 548: /*
549: * XXX: This is incomplete.
550: */
1.124 dyoung 551: static int
552: acpi_detach(device_t self, int flags)
553: {
1.168 jruoho 554: struct acpi_softc *sc = device_private(self);
1.175 jruoho 555: ACPI_STATUS rv;
1.124 dyoung 556: int rc;
557:
1.175 jruoho 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;
569:
1.124 dyoung 570: if ((rc = config_detach_children(self, flags)) != 0)
571: return rc;
572:
573: if ((rc = acpitimer_detach()) != 0)
574: return rc;
575:
1.168 jruoho 576: acpi_deregister_fixed_button(sc, ACPI_EVENT_POWER_BUTTON);
577: acpi_deregister_fixed_button(sc, ACPI_EVENT_SLEEP_BUTTON);
1.124 dyoung 578:
579: pmf_device_deregister(self);
580:
581: acpi_softc = NULL;
582:
583: return 0;
584: }
585:
1.169 jruoho 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;
594:
595: if (sc->sc_apmbus == child)
596: sc->sc_apmbus = NULL;
597:
1.176 jruoho 598: SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1.169 jruoho 599:
600: if (ad->ad_device == child)
601: ad->ad_device = NULL;
602: }
603: }
604:
1.123 jmcneill 605: static bool
1.149 dyoung 606: acpi_suspend(device_t dv, const pmf_qual_t *qual)
1.123 jmcneill 607: {
1.169 jruoho 608:
1.123 jmcneill 609: acpi_suspended = 1;
1.169 jruoho 610:
1.123 jmcneill 611: return true;
612: }
613:
614: static bool
1.149 dyoung 615: acpi_resume(device_t dv, const pmf_qual_t *qual)
1.123 jmcneill 616: {
1.169 jruoho 617:
1.123 jmcneill 618: acpi_suspended = 0;
1.169 jruoho 619:
1.123 jmcneill 620: return true;
621: }
622:
1.1 thorpej 623: /*
1.169 jruoho 624: * Namespace scan.
1.1 thorpej 625: */
1.64 kochi 626: static void
1.1 thorpej 627: acpi_build_tree(struct acpi_softc *sc)
628: {
1.176 jruoho 629: struct acpi_walkcontext awc;
1.157 jruoho 630:
1.185 jruoho 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]);
1.187 jruoho 637: (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &acpi_scopes[1]);
638: (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SI_", &acpi_scopes[2]);
1.185 jruoho 639: (void)AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_TZ_", &acpi_scopes[3]);
640:
641: /*
642: * Make the root node.
643: */
1.176 jruoho 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:
1.185 jruoho 654: /*
655: * Build the internal namespace.
656: */
1.176 jruoho 657: (void)AcpiWalkNamespace(ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, UINT32_MAX,
658: acpi_make_devnode, acpi_make_devnode_post, &awc, NULL);
659:
1.185 jruoho 660: /*
661: * Scan the internal namespace.
662: */
1.204 jruoho 663: (void)acpi_rescan(sc->sc_dev, NULL, NULL);
664:
1.160 jruoho 665: acpi_rescan_capabilities(sc);
666:
1.182 jruoho 667: (void)acpi_pcidev_scan(sc->sc_root);
1.124 dyoung 668: }
1.1 thorpej 669:
1.169 jruoho 670: static ACPI_STATUS
671: acpi_make_devnode(ACPI_HANDLE handle, uint32_t level,
672: void *context, void **status)
1.124 dyoung 673: {
1.176 jruoho 674: struct acpi_walkcontext *awc = context;
675: struct acpi_softc *sc = awc->aw_sc;
1.169 jruoho 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;
682:
683: rv = AcpiGetObjectInfo(handle, &devinfo);
1.124 dyoung 684:
1.169 jruoho 685: if (ACPI_FAILURE(rv))
686: return AE_OK; /* Do not terminate the walk. */
1.124 dyoung 687:
1.169 jruoho 688: type = devinfo->Type;
1.124 dyoung 689:
1.169 jruoho 690: switch (type) {
1.124 dyoung 691:
1.169 jruoho 692: case ACPI_TYPE_DEVICE:
1.124 dyoung 693:
1.169 jruoho 694: #ifdef ACPI_ACTIVATE_DEV
695: acpi_activate_device(handle, &devinfo);
696: #endif
1.124 dyoung 697:
1.169 jruoho 698: case ACPI_TYPE_PROCESSOR:
699: case ACPI_TYPE_THERMAL:
700: case ACPI_TYPE_POWER:
1.124 dyoung 701:
1.169 jruoho 702: ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT | M_ZERO);
1.25 jmcneill 703:
1.169 jruoho 704: if (ad == NULL)
705: return AE_NO_MEMORY;
1.1 thorpej 706:
1.175 jruoho 707: ad->ad_device = NULL;
1.176 jruoho 708: ad->ad_notify = NULL;
1.180 jruoho 709: ad->ad_pciinfo = NULL;
1.175 jruoho 710:
711: ad->ad_type = type;
712: ad->ad_handle = handle;
1.169 jruoho 713: ad->ad_devinfo = devinfo;
1.157 jruoho 714:
1.176 jruoho 715: ad->ad_root = sc->sc_dev;
716: ad->ad_parent = awc->aw_parent;
717:
1.169 jruoho 718: anu = (ACPI_NAME_UNION *)&devinfo->Name;
719: ad->ad_name[4] = '\0';
1.157 jruoho 720:
1.169 jruoho 721: for (i = 3, clear = 0; i >= 0; i--) {
1.116 jmcneill 722:
1.169 jruoho 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: }
1.1 thorpej 730:
1.169 jruoho 731: if (ad->ad_name[0] == '\0')
732: ad->ad_name[0] = '_';
1.160 jruoho 733:
1.176 jruoho 734: SIMPLEQ_INIT(&ad->ad_child_head);
735: SIMPLEQ_INSERT_TAIL(&sc->ad_head, ad, ad_list);
736:
1.202 jruoho 737: acpi_set_node(ad);
738:
1.176 jruoho 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.169 jruoho 746: }
747:
748: return AE_OK;
749: }
750:
1.176 jruoho 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;
756:
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:
1.169 jruoho 766: #ifdef ACPI_ACTIVATE_DEV
767: static void
768: acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
769: {
1.193 jruoho 770: static const int valid = ACPI_VALID_STA | ACPI_VALID_HID;
1.169 jruoho 771: ACPI_DEVICE_INFO *newdi;
772: ACPI_STATUS rv;
773: uint32_t old;
774:
775: /*
776: * If the device is valid and present,
777: * but not enabled, try to activate it.
778: */
1.193 jruoho 779: if (((*di)->Valid & valid) != valid)
1.169 jruoho 780: return;
781:
782: old = (*di)->CurrentStatus;
783:
1.193 jruoho 784: if ((old & (ACPI_STA_DEVICE_PRESENT | ACPI_STA_DEVICE_ENABLED)) !=
785: ACPI_STA_DEVICE_PRESENT)
1.169 jruoho 786: return;
787:
788: rv = acpi_allocate_resources(handle);
789:
790: if (ACPI_FAILURE(rv))
791: goto fail;
792:
793: rv = AcpiGetObjectInfo(handle, &newdi);
1.160 jruoho 794:
1.169 jruoho 795: if (ACPI_FAILURE(rv))
796: goto fail;
1.160 jruoho 797:
1.169 jruoho 798: ACPI_FREE(*di);
799: *di = newdi;
1.160 jruoho 800:
1.169 jruoho 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);
1.160 jruoho 804:
1.169 jruoho 805: return;
1.160 jruoho 806:
1.169 jruoho 807: fail:
808: aprint_error_dev(acpi_softc->sc_dev, "failed to "
809: "activate %s\n", (*di)->HardwareId.String);
810: }
1.160 jruoho 811:
1.169 jruoho 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;
1.160 jruoho 824:
1.169 jruoho 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: }
1.160 jruoho 832:
1.169 jruoho 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: /*
1.174 jruoho 862: * XXX: Not duplicating the interrupt logic above
863: * because its not clear what it accomplishes.
1.169 jruoho 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);
1.173 jruoho 886: delta = (uint8_t *)resn - (uint8_t *)bufn.Pointer;
1.169 jruoho 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);
1.173 jruoho 892: resn = (ACPI_RESOURCE *)((uint8_t *)bufn.Pointer +
893: delta);
1.160 jruoho 894: }
895: }
1.169 jruoho 896:
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: }
903:
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));
910:
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.160 jruoho 919: }
1.169 jruoho 920: #endif /* ACPI_ACTIVATE_DEV */
1.160 jruoho 921:
1.1 thorpej 922: /*
1.169 jruoho 923: * Device attachment.
1.1 thorpej 924: */
1.169 jruoho 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:
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.204 jruoho 936:
937: return 0;
1.169 jruoho 938: }
939:
940: static void
941: acpi_rescan_nodes(struct acpi_softc *sc)
1.1 thorpej 942: {
1.169 jruoho 943: struct acpi_attach_args aa;
1.1 thorpej 944: struct acpi_devnode *ad;
1.193 jruoho 945: ACPI_DEVICE_INFO *di;
1.1 thorpej 946:
1.176 jruoho 947: SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1.15 augustss 948:
1.169 jruoho 949: if (ad->ad_device != NULL)
950: continue;
1.151 jruoho 951:
1.185 jruoho 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;
1.151 jruoho 958:
1.193 jruoho 959: di = ad->ad_devinfo;
960:
1.174 jruoho 961: /*
1.185 jruoho 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.215 ! gsutre 966: * Note: there is a possible race condition, because _STA
! 967: * may have changed since di->CurrentStatus was set.
1.174 jruoho 968: */
1.193 jruoho 969: if (di->Type == ACPI_TYPE_DEVICE) {
1.174 jruoho 970:
1.193 jruoho 971: if ((di->Valid & ACPI_VALID_STA) != 0 &&
972: (di->CurrentStatus & ACPI_STA_OK) != ACPI_STA_OK)
1.169 jruoho 973: continue;
974: }
1.151 jruoho 975:
1.169 jruoho 976: /*
1.185 jruoho 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.
1.169 jruoho 980: */
1.193 jruoho 981: if (di->Type == ACPI_TYPE_DEVICE &&
982: (di->Valid & ACPI_VALID_HID) == 0)
1.169 jruoho 983: continue;
1.151 jruoho 984:
1.169 jruoho 985: /*
986: * Handled internally.
987: */
1.207 jruoho 988: if (di->Type == ACPI_TYPE_POWER)
1.169 jruoho 989: continue;
1.15 augustss 990:
1.169 jruoho 991: /*
992: * Skip ignored HIDs.
993: */
1.193 jruoho 994: if (acpi_match_hid(di, acpi_ignored_ids))
1.169 jruoho 995: continue;
1.151 jruoho 996:
1.185 jruoho 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;
1003:
1.169 jruoho 1004: ad->ad_device = config_found_ia(sc->sc_dev,
1005: "acpinodebus", &aa, acpi_print);
1006: }
1007: }
1.151 jruoho 1008:
1.169 jruoho 1009: static void
1010: acpi_rescan_capabilities(struct acpi_softc *sc)
1011: {
1012: struct acpi_devnode *ad;
1013: ACPI_HANDLE tmp;
1014: ACPI_STATUS rv;
1.151 jruoho 1015:
1.176 jruoho 1016: SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1.151 jruoho 1017:
1.195 jruoho 1018: if (ad->ad_devinfo->Type != ACPI_TYPE_DEVICE)
1.169 jruoho 1019: continue;
1.151 jruoho 1020:
1.169 jruoho 1021: /*
1022: * Scan power resource capabilities.
1.181 jruoho 1023: *
1024: * If any power states are supported,
1025: * at least _PR0 and _PR3 must be present.
1.169 jruoho 1026: */
1027: rv = AcpiGetHandle(ad->ad_handle, "_PR0", &tmp);
1.102 cube 1028:
1.181 jruoho 1029: if (ACPI_SUCCESS(rv)) {
1.169 jruoho 1030: ad->ad_flags |= ACPI_DEVICE_POWER;
1.184 jruoho 1031: acpi_power_add(ad);
1.181 jruoho 1032: }
1.1 thorpej 1033:
1.169 jruoho 1034: /*
1035: * Scan wake-up capabilities.
1036: */
1037: rv = AcpiGetHandle(ad->ad_handle, "_PRW", &tmp);
1.1 thorpej 1038:
1.169 jruoho 1039: if (ACPI_SUCCESS(rv)) {
1040: ad->ad_flags |= ACPI_DEVICE_WAKEUP;
1041: acpi_wakedev_add(ad);
1042: }
1.1 thorpej 1043: }
1.169 jruoho 1044: }
1.151 jruoho 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.150 jruoho 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.197 pgoyette 1078: else
1079: acpi_print_dev(pnpstr);
1.27 christos 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.168 jruoho 1109: /*
1.175 jruoho 1110: * Notify.
1111: */
1112: static void
1113: acpi_notify_handler(ACPI_HANDLE handle, uint32_t event, void *aux)
1114: {
1115: struct acpi_softc *sc = acpi_softc;
1116: struct acpi_devnode *ad;
1117:
1118: KASSERT(sc != NULL);
1119: KASSERT(aux == NULL);
1120: KASSERT(acpi_active != 0);
1121:
1122: if (acpi_suspended != 0)
1123: return;
1124:
1125: /*
1126: * System: 0x00 - 0x7F.
1127: * Device: 0x80 - 0xFF.
1128: */
1129: switch (event) {
1130:
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: }
1145:
1146: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "notification 0x%02X for "
1147: "%s (%p)\n", event, acpi_name(handle), handle));
1148:
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: */
1.176 jruoho 1155: SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
1.175 jruoho 1156:
1157: if (ad->ad_device == NULL)
1158: continue;
1159:
1160: if (ad->ad_notify == NULL)
1161: continue;
1162:
1163: if (ad->ad_handle != handle)
1164: continue;
1165:
1166: (*ad->ad_notify)(ad->ad_handle, event, ad->ad_device);
1167:
1168: return;
1169: }
1170:
1171: aprint_debug_dev(sc->sc_dev, "unhandled notify 0x%02X "
1172: "for %s (%p)\n", event, acpi_name(handle), handle);
1173: }
1174:
1175: bool
1176: acpi_register_notify(struct acpi_devnode *ad, ACPI_NOTIFY_HANDLER notify)
1177: {
1178: struct acpi_softc *sc = acpi_softc;
1179:
1180: KASSERT(sc != NULL);
1181: KASSERT(acpi_active != 0);
1182:
1183: if (acpi_suspended != 0)
1184: goto fail;
1185:
1186: if (ad == NULL || notify == NULL)
1187: goto fail;
1188:
1189: ad->ad_notify = notify;
1190:
1191: return true;
1192:
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);
1196:
1197: return false;
1198: }
1199:
1200: void
1201: acpi_deregister_notify(struct acpi_devnode *ad)
1202: {
1203:
1204: ad->ad_notify = NULL;
1205: }
1206:
1207: /*
1.168 jruoho 1208: * Fixed buttons.
1209: */
1210: static void
1211: acpi_register_fixed_button(struct acpi_softc *sc, int event)
1212: {
1213: struct sysmon_pswitch *smpsw;
1214: ACPI_STATUS rv;
1215: int type;
1216:
1217: switch (event) {
1218:
1219: case ACPI_EVENT_POWER_BUTTON:
1220:
1221: if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0)
1222: return;
1223:
1224: type = PSWITCH_TYPE_POWER;
1225: smpsw = &sc->sc_smpsw_power;
1226: break;
1227:
1228: case ACPI_EVENT_SLEEP_BUTTON:
1229:
1230: if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0)
1231: return;
1232:
1233: type = PSWITCH_TYPE_SLEEP;
1234: smpsw = &sc->sc_smpsw_sleep;
1235: break;
1236:
1237: default:
1238: rv = AE_TYPE;
1239: goto fail;
1240: }
1241:
1242: smpsw->smpsw_type = type;
1243: smpsw->smpsw_name = device_xname(sc->sc_dev);
1244:
1245: if (sysmon_pswitch_register(smpsw) != 0) {
1246: rv = AE_ERROR;
1247: goto fail;
1248: }
1249:
1250: rv = AcpiInstallFixedEventHandler(event,
1251: acpi_fixed_button_handler, smpsw);
1252:
1.199 jruoho 1253: if (ACPI_FAILURE(rv)) {
1254: sysmon_pswitch_unregister(smpsw);
1.168 jruoho 1255: goto fail;
1.199 jruoho 1256: }
1.168 jruoho 1257:
1258: aprint_debug_dev(sc->sc_dev, "fixed %s button present\n",
1259: (type != ACPI_EVENT_SLEEP_BUTTON) ? "power" : "sleep");
1260:
1261: return;
1.1 thorpej 1262:
1.168 jruoho 1263: fail:
1264: aprint_error_dev(sc->sc_dev, "failed to register "
1265: "fixed event: %s\n", AcpiFormatException(rv));
1266: }
1.1 thorpej 1267:
1.64 kochi 1268: static void
1.169 jruoho 1269: acpi_deregister_fixed_button(struct acpi_softc *sc, int event)
1.69 kochi 1270: {
1.169 jruoho 1271: struct sysmon_pswitch *smpsw;
1.69 kochi 1272: ACPI_STATUS rv;
1273:
1.169 jruoho 1274: switch (event) {
1.144 jruoho 1275:
1.169 jruoho 1276: case ACPI_EVENT_POWER_BUTTON:
1277: smpsw = &sc->sc_smpsw_power;
1.144 jruoho 1278:
1.169 jruoho 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:
1284: break;
1285:
1.169 jruoho 1286: case ACPI_EVENT_SLEEP_BUTTON:
1287: smpsw = &sc->sc_smpsw_sleep;
1.144 jruoho 1288:
1.169 jruoho 1289: if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0) {
1290: KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_SLEEP);
1291: return;
1292: }
1.144 jruoho 1293:
1294: break;
1.69 kochi 1295:
1.144 jruoho 1296: default:
1.169 jruoho 1297: rv = AE_TYPE;
1298: goto fail;
1.144 jruoho 1299: }
1.69 kochi 1300:
1.169 jruoho 1301: rv = AcpiRemoveFixedEventHandler(event, acpi_fixed_button_handler);
1302:
1303: if (ACPI_SUCCESS(rv)) {
1304: sysmon_pswitch_unregister(smpsw);
1305: return;
1306: }
1.69 kochi 1307:
1.169 jruoho 1308: fail:
1309: aprint_error_dev(sc->sc_dev, "failed to deregister "
1310: "fixed event: %s\n", AcpiFormatException(rv));
1.69 kochi 1311: }
1312:
1.169 jruoho 1313: static uint32_t
1314: acpi_fixed_button_handler(void *context)
1.118 dyoung 1315: {
1.169 jruoho 1316: static const int handler = OSL_NOTIFY_HANDLER;
1317: struct sysmon_pswitch *smpsw = context;
1318:
1319: (void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw);
1320:
1321: return ACPI_INTERRUPT_HANDLED;
1.118 dyoung 1322: }
1323:
1.169 jruoho 1324: static void
1325: acpi_fixed_button_pressed(void *context)
1.118 dyoung 1326: {
1.169 jruoho 1327: struct sysmon_pswitch *smpsw = context;
1.118 dyoung 1328:
1.199 jruoho 1329: ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s fixed button pressed\n",
1330: (smpsw->smpsw_type != ACPI_EVENT_SLEEP_BUTTON) ?
1331: "power" : "sleep"));
1.10 tshiozak 1332:
1.169 jruoho 1333: sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
1334: }
1.10 tshiozak 1335:
1.166 jruoho 1336: /*
1.169 jruoho 1337: * Sleep.
1.166 jruoho 1338: */
1339: static void
1340: acpi_sleep_init(struct acpi_softc *sc)
1.10 tshiozak 1341: {
1.166 jruoho 1342: uint8_t a, b, i;
1343: ACPI_STATUS rv;
1.10 tshiozak 1344:
1.166 jruoho 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:
1.169 jruoho 1349: /*
1350: * Evaluate supported sleep states.
1351: */
1.166 jruoho 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: }
1.10 tshiozak 1359: }
1360:
1.194 jruoho 1361: void
1.10 tshiozak 1362: acpi_enter_sleep_state(struct acpi_softc *sc, int state)
1363: {
1.194 jruoho 1364: ACPI_STATUS rv;
1.104 jmcneill 1365: int err;
1.10 tshiozak 1366:
1.166 jruoho 1367: if (state == sc->sc_sleepstate)
1.194 jruoho 1368: return;
1.92 christos 1369:
1.166 jruoho 1370: aprint_normal_dev(sc->sc_dev, "entering state S%d\n", state);
1.92 christos 1371:
1.10 tshiozak 1372: switch (state) {
1.166 jruoho 1373:
1.10 tshiozak 1374: case ACPI_STATE_S0:
1.194 jruoho 1375: sc->sc_sleepstate = ACPI_STATE_S0;
1376: return;
1.166 jruoho 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.166 jruoho 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);
1.194 jruoho 1386: return;
1.10 tshiozak 1387: }
1.104 jmcneill 1388:
1.188 jruoho 1389: /*
1.190 jruoho 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.
1.189 jruoho 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:
1.190 jruoho 1402: if (state != ACPI_STATE_S1 &&
1403: pmf_system_suspend(PMF_Q_NONE) != true) {
1404: aprint_error_dev(sc->sc_dev, "aborting suspend\n");
1405: break;
1406: }
1407:
1.189 jruoho 1408: /*
1.188 jruoho 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: */
1.166 jruoho 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.203 jruoho 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.166 jruoho 1428: sc->sc_sleepstate = state;
1429:
1.92 christos 1430: if (state == ACPI_STATE_S1) {
1.166 jruoho 1431:
1432: /* Just enter the state. */
1.12 kanaoka 1433: acpi_md_OsDisableInterrupt();
1.166 jruoho 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.166 jruoho 1443:
1.104 jmcneill 1444: err = acpi_md_sleep(state);
1.166 jruoho 1445:
1.104 jmcneill 1446: if (state == ACPI_STATE_S4)
1.10 tshiozak 1447: AcpiEnable();
1.166 jruoho 1448:
1.133 dyoung 1449: pmf_system_bus_resume(PMF_Q_NONE);
1.166 jruoho 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.189 jruoho 1455:
1.10 tshiozak 1456: case ACPI_STATE_S5:
1.166 jruoho 1457:
1.190 jruoho 1458: (void)acpi_eval_set_integer(NULL, "\\_TTS", ACPI_STATE_S5);
1.189 jruoho 1459:
1.166 jruoho 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.166 jruoho 1467:
1.104 jmcneill 1468: DELAY(1000000);
1.166 jruoho 1469:
1470: sc->sc_sleepstate = state;
1.12 kanaoka 1471: acpi_md_OsDisableInterrupt();
1.166 jruoho 1472:
1473: (void)AcpiEnterSleepState(ACPI_STATE_S5);
1474:
1475: aprint_error_dev(sc->sc_dev, "WARNING: powerdown failed!\n");
1.189 jruoho 1476:
1.10 tshiozak 1477: break;
1478: }
1479:
1.166 jruoho 1480: sc->sc_sleepstate = ACPI_STATE_S0;
1481:
1.189 jruoho 1482: (void)acpi_eval_set_integer(NULL, "\\_TTS", ACPI_STATE_S0);
1.1 thorpej 1483: }
1.13 augustss 1484:
1.159 jruoho 1485: /*
1.169 jruoho 1486: * Sysctl.
1.159 jruoho 1487: */
1.79 cube 1488: SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
1489: {
1.165 jruoho 1490: const struct sysctlnode *mnode, *rnode;
1491: int err;
1492:
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);
1.79 cube 1497:
1.165 jruoho 1498: if (err != 0)
1.79 cube 1499: return;
1500:
1.165 jruoho 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.165 jruoho 1505: CTL_CREATE, CTL_EOL);
1506:
1507: if (err != 0)
1.79 cube 1508: return;
1509:
1.165 jruoho 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.165 jruoho 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"),
1.166 jruoho 1519: sysctl_hw_acpi_sleepstates, 0, NULL, 0,
1.165 jruoho 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);
1.86 jmcneill 1526:
1.165 jruoho 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.165 jruoho 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.166 jruoho 1597: struct acpi_softc *sc = acpi_softc;
1.86 jmcneill 1598: struct sysctlnode node;
1.165 jruoho 1599: int err, t;
1.86 jmcneill 1600:
1.166 jruoho 1601: if (acpi_softc == NULL)
1602: return ENOSYS;
1603:
1.86 jmcneill 1604: node = *rnode;
1.166 jruoho 1605: t = sc->sc_sleepstate;
1.86 jmcneill 1606: node.sysctl_data = &t;
1.165 jruoho 1607:
1608: err = sysctl_lookup(SYSCTLFN_CALL(&node));
1609:
1610: if (err || newp == NULL)
1611: return err;
1.86 jmcneill 1612:
1.166 jruoho 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;
1628:
1.92 christos 1629: if (acpi_softc == NULL)
1630: return ENOSYS;
1.86 jmcneill 1631:
1.166 jruoho 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));
1.165 jruoho 1646:
1.166 jruoho 1647: if (err || newp == NULL)
1648: return err;
1.86 jmcneill 1649:
1650: return 0;
1.79 cube 1651: }
1.108 jmcneill 1652:
1.169 jruoho 1653: /*
1.212 jruoho 1654: * Tables.
1.169 jruoho 1655: */
1656: ACPI_PHYSICAL_ADDRESS
1657: acpi_OsGetRootPointer(void)
1658: {
1659: ACPI_PHYSICAL_ADDRESS PhysicalAddress;
1660:
1661: /*
1.172 jruoho 1662: * We let MD code handle this since there are multiple ways to do it:
1.169 jruoho 1663: *
1.172 jruoho 1664: * IA-32: Use AcpiFindRootPointer() to locate the RSDP.
1.169 jruoho 1665: *
1.172 jruoho 1666: * IA-64: Use the EFI.
1.169 jruoho 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.172 jruoho 1683:
1684: if (paddr == 0)
1.108 jmcneill 1685: return NULL;
1.172 jruoho 1686:
1.108 jmcneill 1687: rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP));
1.172 jruoho 1688:
1689: if (rsdp == NULL)
1.108 jmcneill 1690: return NULL;
1.172 jruoho 1691:
1.108 jmcneill 1692: if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress)
1.172 jruoho 1693: paddr = rsdp->XsdtPhysicalAddress;
1.108 jmcneill 1694: else
1.172 jruoho 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.172 jruoho 1705:
1.108 jmcneill 1706: if (rsdt == NULL)
1707: return;
1708:
1709: AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER));
1710: }
1.211 jruoho 1711:
1712: /*
1.212 jruoho 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: /*
1.211 jruoho 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>