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