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