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