acpi.c revision 1.166 1 /* $NetBSD: acpi.c,v 1.166 2010/04/12 18:55:27 jruoho Exp $ */
2
3 /*-
4 * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
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 */
31
32 /*
33 * Copyright 2001, 2003 Wasabi Systems, Inc.
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 */
71
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.166 2010/04/12 18:55:27 jruoho Exp $");
74
75 #include "opt_acpi.h"
76 #include "opt_pcifixup.h"
77
78 #include <sys/param.h>
79 #include <sys/device.h>
80 #include <sys/kernel.h>
81 #include <sys/malloc.h>
82 #include <sys/mutex.h>
83 #include <sys/sysctl.h>
84 #include <sys/systm.h>
85
86 #include <dev/acpi/acpireg.h>
87 #include <dev/acpi/acpivar.h>
88 #include <dev/acpi/acpi_osd.h>
89 #include <dev/acpi/acpi_pci.h>
90 #include <dev/acpi/acpi_timer.h>
91 #include <dev/acpi/acpi_wakedev.h>
92
93 #ifdef ACPIVERBOSE
94 #include <dev/acpi/acpidevs_data.h>
95 #endif
96
97 #define _COMPONENT ACPI_BUS_COMPONENT
98 ACPI_MODULE_NAME ("acpi")
99
100 #if defined(ACPI_PCI_FIXUP)
101 #error The option ACPI_PCI_FIXUP has been obsoleted by PCI_INTR_FIXUP_DISABLED. Please adjust your kernel configuration file.
102 #endif
103
104 #ifdef PCI_INTR_FIXUP_DISABLED
105 #include <dev/pci/pcidevs.h>
106 #endif
107
108 MALLOC_DECLARE(M_ACPI);
109
110 #include <machine/acpi_machdep.h>
111
112 #ifdef ACPI_DEBUGGER
113 #define ACPI_DBGR_INIT 0x01
114 #define ACPI_DBGR_TABLES 0x02
115 #define ACPI_DBGR_ENABLE 0x04
116 #define ACPI_DBGR_PROBE 0x08
117 #define ACPI_DBGR_RUNNING 0x10
118
119 static int acpi_dbgr = 0x00;
120 #endif
121
122 static ACPI_TABLE_DESC acpi_initial_tables[128];
123
124 static int acpi_match(device_t, cfdata_t, void *);
125 static void acpi_attach(device_t, device_t, void *);
126 static void acpi_childdet(device_t, device_t);
127 static int acpi_detach(device_t, int);
128
129 static int acpi_rescan(device_t, const char *, const int *);
130 static void acpi_rescan1(struct acpi_softc *, const char *, const int *);
131 static void acpi_rescan_nodes(struct acpi_softc *);
132 static void acpi_rescan_capabilities(struct acpi_softc *);
133
134 static int acpi_print(void *aux, const char *);
135
136 static int sysctl_hw_acpi_fixedstats(SYSCTLFN_ARGS);
137 static int sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS);
138 static int sysctl_hw_acpi_sleepstates(SYSCTLFN_ARGS);
139
140 extern struct cfdriver acpi_cd;
141
142 CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc),
143 acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet);
144
145 /*
146 * This is a flag we set when the ACPI subsystem is active. Machine
147 * dependent code may wish to skip other steps (such as attaching
148 * subsystems that ACPI supercedes) when ACPI is active.
149 */
150 int acpi_active;
151 int acpi_force_load;
152 int acpi_suspended = 0;
153
154 struct acpi_softc *acpi_softc;
155 static uint64_t acpi_root_pointer;
156 extern kmutex_t acpi_interrupt_list_mtx;
157
158 /*
159 * Ignored HIDs.
160 */
161 static const char * const acpi_ignored_ids[] = {
162 #if defined(i386) || defined(x86_64)
163 "PNP0000", /* AT interrupt controller is handled internally */
164 "PNP0200", /* AT DMA controller is handled internally */
165 "PNP0A??", /* PCI Busses are handled internally */
166 "PNP0B00", /* AT RTC is handled internally */
167 "PNP0C01", /* No "System Board" driver */
168 "PNP0C02", /* No "PnP motherboard register resources" driver */
169 "PNP0C0B", /* No need for "ACPI fan" driver */
170 "PNP0C0F", /* ACPI PCI link devices are handled internally */
171 "IFX0102", /* No driver for Infineon TPM */
172 "INT0800", /* No driver for Intel Firmware Hub device */
173 #endif
174 #if defined(x86_64)
175 "PNP0C04", /* FPU is handled internally */
176 #endif
177 NULL
178 };
179
180 /*
181 * Prototypes.
182 */
183 static void acpi_build_tree(struct acpi_softc *);
184 static ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, uint32_t,
185 void *, void **);
186
187 static void acpi_enable_fixed_events(struct acpi_softc *);
188 static void acpi_sleep_init(struct acpi_softc *);
189
190 static ACPI_TABLE_HEADER *acpi_map_rsdt(void);
191 static void acpi_unmap_rsdt(ACPI_TABLE_HEADER *);
192
193 static bool acpi_suspend(device_t, const pmf_qual_t *);
194 static bool acpi_resume(device_t, const pmf_qual_t *);
195
196 #ifdef ACPI_ACTIVATE_DEV
197 static void acpi_activate_device(ACPI_HANDLE, ACPI_DEVICE_INFO **);
198 static ACPI_STATUS acpi_allocate_resources(ACPI_HANDLE);
199 #endif
200
201 /*
202 * acpi_probe:
203 *
204 * Probe for ACPI support. This is called by the
205 * machine-dependent ACPI front-end. All of the
206 * actual work is done by ACPICA.
207 *
208 * NOTE: This is not an autoconfiguration interface function.
209 */
210 int
211 acpi_probe(void)
212 {
213 static int beenhere;
214 ACPI_TABLE_HEADER *rsdt;
215 ACPI_STATUS rv;
216
217 if (beenhere != 0)
218 panic("acpi_probe: ACPI has already been probed");
219 beenhere = 1;
220
221 mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE);
222
223 /*
224 * Start up ACPICA.
225 */
226 #ifdef ACPI_DEBUGGER
227 if (acpi_dbgr & ACPI_DBGR_INIT)
228 acpi_osd_debugger();
229 #endif
230
231 AcpiGbl_AllMethodsSerialized = FALSE;
232 AcpiGbl_EnableInterpreterSlack = TRUE;
233
234 rv = AcpiInitializeSubsystem();
235 if (ACPI_FAILURE(rv)) {
236 printf("ACPI: unable to initialize ACPICA: %s\n",
237 AcpiFormatException(rv));
238 return 0;
239 }
240
241 rv = AcpiInitializeTables(acpi_initial_tables, 128, 0);
242 if (ACPI_FAILURE(rv)) {
243 #ifdef ACPI_DEBUG
244 printf("ACPI: unable to initialize ACPI tables: %s\n",
245 AcpiFormatException(rv));
246 #endif
247 AcpiTerminate();
248 return 0;
249 }
250
251 rv = AcpiReallocateRootTable();
252 if (ACPI_FAILURE(rv)) {
253 printf("ACPI: unable to reallocate root table: %s\n",
254 AcpiFormatException(rv));
255 AcpiTerminate();
256 return 0;
257 }
258
259 #ifdef ACPI_DEBUGGER
260 if (acpi_dbgr & ACPI_DBGR_TABLES)
261 acpi_osd_debugger();
262 #endif
263
264 rv = AcpiLoadTables();
265 if (ACPI_FAILURE(rv)) {
266 printf("ACPI: unable to load tables: %s\n",
267 AcpiFormatException(rv));
268 AcpiTerminate();
269 return 0;
270 }
271
272 rsdt = acpi_map_rsdt();
273 if (rsdt == NULL) {
274 printf("ACPI: unable to map RSDT\n");
275 AcpiTerminate();
276 return 0;
277 }
278
279 if (!acpi_force_load && (acpi_find_quirks() & ACPI_QUIRK_BROKEN)) {
280 printf("ACPI: BIOS implementation in listed as broken:\n");
281 printf("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, "
282 "AslId <%4.4s,%08x>\n",
283 rsdt->OemId, rsdt->OemTableId,
284 rsdt->OemRevision,
285 rsdt->AslCompilerId,
286 rsdt->AslCompilerRevision);
287 printf("ACPI: not used. set acpi_force_load to use anyway.\n");
288 acpi_unmap_rsdt(rsdt);
289 AcpiTerminate();
290 return 0;
291 }
292
293 acpi_unmap_rsdt(rsdt);
294
295 #if notyet
296 /* Install the default address space handlers. */
297 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
298 ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
299 if (ACPI_FAILURE(rv)) {
300 printf("ACPI: unable to initialize SystemMemory handler: %s\n",
301 AcpiFormatException(rv));
302 AcpiTerminate();
303 return 0;
304 }
305 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
306 ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
307 if (ACPI_FAILURE(rv)) {
308 printf("ACPI: unable to initialize SystemIO handler: %s\n",
309 AcpiFormatException(rv));
310 AcpiTerminate();
311 return 0;
312 }
313 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
314 ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
315 if (ACPI_FAILURE(rv)) {
316 printf("ACPI: unable to initialize PciConfig handler: %s\n",
317 AcpiFormatException(rv));
318 AcpiTerminate();
319 return 0;
320 }
321 #endif
322
323 rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE));
324 if (ACPI_FAILURE(rv)) {
325 printf("ACPI: unable to enable: %s\n", AcpiFormatException(rv));
326 AcpiTerminate();
327 return 0;
328 }
329
330 /*
331 * Looks like we have ACPI!
332 */
333
334 return 1;
335 }
336
337 static int
338 acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
339 {
340 struct cfattach *ca;
341
342 ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
343 return (ca == &acpi_ca);
344 }
345
346 int
347 acpi_check(device_t parent, const char *ifattr)
348 {
349 return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL);
350 }
351
352 ACPI_PHYSICAL_ADDRESS
353 acpi_OsGetRootPointer(void)
354 {
355 ACPI_PHYSICAL_ADDRESS PhysicalAddress;
356
357 /*
358 * IA-32: Use AcpiFindRootPointer() to locate the RSDP.
359 *
360 * IA-64: Use the EFI.
361 *
362 * We let MD code handle this since there are multiple
363 * ways to do it.
364 */
365
366 PhysicalAddress = acpi_md_OsGetRootPointer();
367
368 if (acpi_root_pointer == 0)
369 acpi_root_pointer = PhysicalAddress;
370
371 return PhysicalAddress;
372 }
373
374 /*
375 * acpi_match:
376 *
377 * Autoconfiguration `match' routine.
378 */
379 static int
380 acpi_match(device_t parent, cfdata_t match, void *aux)
381 {
382 /*
383 * XXX Check other locators? Hard to know -- machine
384 * dependent code has already checked for the presence
385 * of ACPI by calling acpi_probe(), so I suppose we
386 * don't really have to do anything else.
387 */
388 return 1;
389 }
390
391 /* Remove references to child devices.
392 *
393 * XXX Need to reclaim any resources?
394 */
395 static void
396 acpi_childdet(device_t self, device_t child)
397 {
398 struct acpi_softc *sc = device_private(self);
399 struct acpi_devnode *ad;
400
401 if (sc->sc_apmbus == child)
402 sc->sc_apmbus = NULL;
403
404 SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) {
405
406 if (ad->ad_device == child)
407 ad->ad_device = NULL;
408 }
409 }
410
411 /*
412 * acpi_attach:
413 *
414 * Autoconfiguration `attach' routine. Finish initializing
415 * ACPICA (some initialization was done in acpi_probe(),
416 * which was required to check for the presence of ACPI),
417 * and enable the ACPI subsystem.
418 */
419 static void
420 acpi_attach(device_t parent, device_t self, void *aux)
421 {
422 struct acpi_softc *sc = device_private(self);
423 struct acpibus_attach_args *aa = aux;
424 ACPI_TABLE_HEADER *rsdt;
425 ACPI_STATUS rv;
426
427 aprint_naive("\n");
428 aprint_normal(": Intel ACPICA %08x\n", ACPI_CA_VERSION);
429
430 if (acpi_softc != NULL)
431 panic("acpi_attach: ACPI has already been attached");
432
433 sysmon_power_settype("acpi");
434
435 rsdt = acpi_map_rsdt();
436 if (rsdt) {
437 aprint_verbose_dev(
438 self,
439 "X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
440 rsdt->OemId, rsdt->OemTableId,
441 rsdt->OemRevision,
442 rsdt->AslCompilerId, rsdt->AslCompilerRevision);
443 } else
444 aprint_error_dev(self, "X/RSDT: Not found\n");
445
446 acpi_unmap_rsdt(rsdt);
447
448 sc->sc_dev = self;
449 sc->sc_quirks = acpi_find_quirks();
450 sc->sc_sleepstate = ACPI_STATE_S0;
451
452 sc->sc_iot = aa->aa_iot;
453 sc->sc_memt = aa->aa_memt;
454 sc->sc_pc = aa->aa_pc;
455 sc->sc_pciflags = aa->aa_pciflags;
456 sc->sc_ic = aa->aa_ic;
457
458 SIMPLEQ_INIT(&sc->sc_devnodes);
459
460 acpi_softc = sc;
461
462 /*
463 * Register null power management handler.
464 */
465 if (!pmf_device_register(self, acpi_suspend, acpi_resume))
466 aprint_error_dev(self, "couldn't establish power handler\n");
467
468 /*
469 * Bring ACPI on-line.
470 */
471 #ifdef ACPI_DEBUGGER
472 if (acpi_dbgr & ACPI_DBGR_ENABLE)
473 acpi_osd_debugger();
474 #endif
475
476 #define ACPI_ENABLE_PHASE1 \
477 (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
478 #define ACPI_ENABLE_PHASE2 \
479 (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
480 ACPI_NO_ADDRESS_SPACE_INIT)
481
482 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
483 if (ACPI_FAILURE(rv)) {
484 aprint_error_dev(self, "unable to enable ACPI: %s\n",
485 AcpiFormatException(rv));
486 return;
487 }
488
489 acpi_md_callback();
490
491 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
492 if (ACPI_FAILURE(rv)) {
493 aprint_error_dev(self, "unable to enable ACPI: %s\n",
494 AcpiFormatException(rv));
495 return;
496 }
497
498 /* Early EC handler initialization if ECDT table is available. */
499 config_found_ia(self, "acpiecdtbus", aa, NULL);
500
501 rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
502 if (ACPI_FAILURE(rv)) {
503 aprint_error_dev(self,
504 "unable to initialize ACPI objects: %s\n",
505 AcpiFormatException(rv));
506 return;
507 }
508 acpi_active = 1;
509
510 /* Our current state is "awake". */
511 sc->sc_sleepstate = ACPI_STATE_S0;
512
513 /* Show SCI interrupt. */
514 aprint_verbose_dev(self, "SCI interrupting at int %u\n",
515 AcpiGbl_FADT.SciInterrupt);
516
517 /*
518 * Check for fixed-hardware features.
519 */
520 acpi_enable_fixed_events(sc);
521 acpitimer_init();
522
523 /*
524 * Scan the namespace and build our device tree.
525 */
526 #ifdef ACPI_DEBUGGER
527 if (acpi_dbgr & ACPI_DBGR_PROBE)
528 acpi_osd_debugger();
529 #endif
530
531 acpi_build_tree(sc);
532 acpi_sleep_init(sc);
533
534 #ifdef ACPI_DEBUGGER
535 if (acpi_dbgr & ACPI_DBGR_RUNNING)
536 acpi_osd_debugger();
537 #endif
538
539 #ifdef ACPI_DEBUG
540 acpi_debug_init();
541 #endif
542 }
543
544 static int
545 acpi_detach(device_t self, int flags)
546 {
547 int rc;
548
549 #ifdef ACPI_DEBUGGER
550 if (acpi_dbgr & ACPI_DBGR_RUNNING)
551 acpi_osd_debugger();
552 #endif
553
554 if ((rc = config_detach_children(self, flags)) != 0)
555 return rc;
556
557 #ifdef ACPI_DEBUGGER
558 if (acpi_dbgr & ACPI_DBGR_PROBE)
559 acpi_osd_debugger();
560 #endif
561
562 if ((rc = acpitimer_detach()) != 0)
563 return rc;
564
565 #if 0
566 /*
567 * Bring ACPI on-line.
568 */
569 #ifdef ACPI_DEBUGGER
570 if (acpi_dbgr & ACPI_DBGR_ENABLE)
571 acpi_osd_debugger();
572 #endif
573
574 #define ACPI_ENABLE_PHASE1 \
575 (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
576 #define ACPI_ENABLE_PHASE2 \
577 (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
578 ACPI_NO_ADDRESS_SPACE_INIT)
579
580 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
581 if (ACPI_FAILURE(rv)) {
582 aprint_error_dev(self, "unable to enable ACPI: %s\n",
583 AcpiFormatException(rv));
584 return;
585 }
586
587 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
588 if (ACPI_FAILURE(rv)) {
589 aprint_error_dev(self, "unable to enable ACPI: %s\n",
590 AcpiFormatException(rv));
591 return;
592 }
593
594 /* Early EC handler initialization if ECDT table is available. */
595 config_found_ia(self, "acpiecdtbus", aa, NULL);
596
597 rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
598 if (ACPI_FAILURE(rv)) {
599 aprint_error_dev(self,
600 "unable to initialize ACPI objects: %s\n",
601 AcpiFormatException(rv));
602 return;
603 }
604 acpi_active = 1;
605
606 acpi_enable_fixed_events(sc);
607 #endif
608
609 pmf_device_deregister(self);
610
611 #if 0
612 sysmon_power_settype("acpi");
613 #endif
614 acpi_softc = NULL;
615
616 return 0;
617 }
618
619 static bool
620 acpi_suspend(device_t dv, const pmf_qual_t *qual)
621 {
622 acpi_suspended = 1;
623 return true;
624 }
625
626 static bool
627 acpi_resume(device_t dv, const pmf_qual_t *qual)
628 {
629 acpi_suspended = 0;
630 return true;
631 }
632
633 #if 0
634 /*
635 * acpi_disable:
636 *
637 * Disable ACPI.
638 */
639 static ACPI_STATUS
640 acpi_disable(struct acpi_softc *sc)
641 {
642 ACPI_STATUS rv = AE_OK;
643
644 if (acpi_active) {
645 rv = AcpiDisable();
646 if (ACPI_SUCCESS(rv))
647 acpi_active = 0;
648 }
649 return rv;
650 }
651 #endif
652
653 /*
654 * acpi_build_tree:
655 *
656 * Scan relevant portions of the ACPI namespace and attach
657 * child devices.
658 */
659 static void
660 acpi_build_tree(struct acpi_softc *sc)
661 {
662 static const char *scopes[] = {
663 "\\_PR_", "\\_SB_", "\\_SI_", "\\_TZ_", NULL
664 };
665
666 ACPI_HANDLE parent;
667 ACPI_STATUS rv;
668 int i;
669
670 /*
671 * Scan the namespace and build our device tree.
672 */
673 for (i = 0; scopes[i] != NULL; i++) {
674
675 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i], &parent);
676
677 if (ACPI_SUCCESS(rv))
678 (void)AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
679 acpi_make_devnode, NULL, sc, NULL);
680 }
681
682 acpi_rescan1(sc, NULL, NULL);
683 acpi_rescan_capabilities(sc);
684
685 acpi_pcidev_scan(sc);
686 }
687
688 static int
689 acpi_rescan(device_t self, const char *ifattr, const int *locators)
690 {
691 struct acpi_softc *sc = device_private(self);
692
693 acpi_rescan1(sc, ifattr, locators);
694 return 0;
695 }
696
697 static void
698 acpi_rescan1(struct acpi_softc *sc, const char *ifattr, const int *locators)
699 {
700 if (ifattr_match(ifattr, "acpinodebus"))
701 acpi_rescan_nodes(sc);
702
703 if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL) {
704 sc->sc_apmbus = config_found_ia(sc->sc_dev, "acpiapmbus", NULL,
705 NULL);
706 }
707 }
708
709 static void
710 acpi_rescan_nodes(struct acpi_softc *sc)
711 {
712 struct acpi_attach_args aa;
713 struct acpi_devnode *ad;
714
715 SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) {
716
717 if (ad->ad_device != NULL)
718 continue;
719
720 aa.aa_node = ad;
721 aa.aa_iot = sc->sc_iot;
722 aa.aa_memt = sc->sc_memt;
723 aa.aa_pc = sc->sc_pc;
724 aa.aa_pciflags = sc->sc_pciflags;
725 aa.aa_ic = sc->sc_ic;
726
727 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) {
728 /*
729 * XXX We only attach devices which are:
730 *
731 * - present
732 * - enabled
733 * - functioning properly
734 *
735 * However, if enabled, it's decoding resources,
736 * so we should claim them, if possible.
737 * Requires changes to bus_space(9).
738 */
739 if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) ==
740 ACPI_VALID_STA &&
741 (ad->ad_devinfo->CurrentStatus &
742 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
743 ACPI_STA_DEV_OK)) !=
744 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
745 ACPI_STA_DEV_OK))
746 continue;
747 }
748
749 /*
750 * XXX Same problem as above...
751 *
752 * Do this check only for devices, as e.g.
753 * a Thermal Zone doesn't have a HID.
754 */
755 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE &&
756 (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
757 continue;
758
759 /*
760 * Handled internally.
761 */
762 if (ad->ad_devinfo->Type == ACPI_TYPE_PROCESSOR ||
763 ad->ad_devinfo->Type == ACPI_TYPE_POWER)
764 continue;
765
766 /*
767 * Skip ignored HIDs.
768 */
769 if (acpi_match_hid(ad->ad_devinfo, acpi_ignored_ids))
770 continue;
771
772 ad->ad_device = config_found_ia(sc->sc_dev,
773 "acpinodebus", &aa, acpi_print);
774 }
775 }
776
777 #define ACPI_STA_DEV_VALID \
778 (ACPI_STA_DEV_PRESENT | ACPI_STA_DEV_ENABLED | ACPI_STA_DEV_OK)
779
780 /*
781 * acpi_rescan_capabilities:
782 *
783 * Scan device capabilities.
784 */
785 static void
786 acpi_rescan_capabilities(struct acpi_softc *sc)
787 {
788 struct acpi_devnode *ad;
789 ACPI_DEVICE_INFO *di;
790 ACPI_HANDLE tmp;
791 ACPI_STATUS rv;
792
793 SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) {
794
795 di = ad->ad_devinfo;
796
797 if (di->Type != ACPI_TYPE_DEVICE)
798 continue;
799
800 if ((di->Valid & ACPI_VALID_STA) != 0 &&
801 (di->CurrentStatus & ACPI_STA_DEV_VALID) !=
802 ACPI_STA_DEV_VALID)
803 continue;
804
805 /*
806 * Scan power resource capabilities.
807 */
808 rv = AcpiGetHandle(ad->ad_handle, "_PR0", &tmp);
809
810 if (ACPI_FAILURE(rv))
811 rv = AcpiGetHandle(ad->ad_handle, "_PSC", &tmp);
812
813 if (ACPI_SUCCESS(rv))
814 ad->ad_flags |= ACPI_DEVICE_POWER;
815
816 /*
817 * Scan wake-up capabilities.
818 */
819 rv = AcpiGetHandle(ad->ad_handle, "_PRW", &tmp);
820
821 if (ACPI_SUCCESS(rv)) {
822 ad->ad_flags |= ACPI_DEVICE_WAKEUP;
823 acpi_wakedev_add(ad);
824 }
825
826 if (ad->ad_flags != 0) {
827 aprint_debug_dev(sc->sc_dev, "%-5s ", ad->ad_name);
828
829 if ((ad->ad_flags & ACPI_DEVICE_POWER) != 0)
830 aprint_debug("power ");
831
832 if ((ad->ad_flags & ACPI_DEVICE_WAKEUP) != 0)
833 aprint_debug("wake-up ");
834
835 aprint_debug("\n");
836 }
837 }
838 }
839
840 #undef ACPI_STA_DEV_VALID
841
842 /*
843 * acpi_make_devnode:
844 *
845 * Make an ACPI devnode.
846 */
847 static ACPI_STATUS
848 acpi_make_devnode(ACPI_HANDLE handle, uint32_t level,
849 void *context, void **status)
850 {
851 struct acpi_softc *sc = context;
852 struct acpi_devnode *ad;
853 ACPI_DEVICE_INFO *devinfo;
854 ACPI_OBJECT_TYPE type;
855 ACPI_NAME_UNION *anu;
856 ACPI_STATUS rv;
857 int clear, i;
858
859 rv = AcpiGetObjectInfo(handle, &devinfo);
860
861 if (ACPI_FAILURE(rv))
862 return AE_OK; /* Do not terminate the walk. */
863
864 type = devinfo->Type;
865
866 switch (type) {
867
868 case ACPI_TYPE_DEVICE:
869
870 #ifdef ACPI_ACTIVATE_DEV
871 acpi_activate_device(handle, &devinfo);
872 #endif
873
874 case ACPI_TYPE_PROCESSOR:
875 case ACPI_TYPE_THERMAL:
876 case ACPI_TYPE_POWER:
877
878 ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT | M_ZERO);
879
880 if (ad == NULL)
881 return AE_NO_MEMORY;
882
883 ad->ad_parent = sc->sc_dev;
884 ad->ad_devinfo = devinfo;
885 ad->ad_handle = handle;
886 ad->ad_type = type;
887
888 anu = (ACPI_NAME_UNION *)&devinfo->Name;
889 ad->ad_name[4] = '\0';
890
891 for (i = 3, clear = 0; i >= 0; i--) {
892
893 if (clear == 0 && anu->Ascii[i] == '_')
894 ad->ad_name[i] = '\0';
895 else {
896 ad->ad_name[i] = anu->Ascii[i];
897 clear = 1;
898 }
899 }
900
901 if (ad->ad_name[0] == '\0')
902 ad->ad_name[0] = '_';
903
904 SIMPLEQ_INSERT_TAIL(&sc->sc_devnodes, ad, ad_list);
905
906 #ifdef ACPIVERBOSE
907
908 if (type != ACPI_TYPE_DEVICE)
909 return AE_OK;
910
911 aprint_normal_dev(sc->sc_dev, "%-5s ", ad->ad_name);
912
913 aprint_normal("HID %-10s ",
914 ((devinfo->Valid & ACPI_VALID_HID) != 0) ?
915 devinfo->HardwareId.String: "-");
916
917 aprint_normal("UID %-4s ",
918 ((devinfo->Valid & ACPI_VALID_UID) != 0) ?
919 devinfo->UniqueId.String : "-");
920
921 if ((devinfo->Valid & ACPI_VALID_STA) != 0)
922 aprint_normal("STA 0x%08X ", devinfo->CurrentStatus);
923 else
924 aprint_normal("STA %10s ", "-");
925
926 if ((devinfo->Valid & ACPI_VALID_ADR) != 0)
927 aprint_normal("ADR 0x%016" PRIX64"",
928 devinfo->Address);
929
930 aprint_normal("\n");
931 #endif
932 }
933
934 return AE_OK;
935 }
936
937 /*
938 * acpi_print:
939 *
940 * Autoconfiguration print routine for ACPI node bus.
941 */
942 static int
943 acpi_print(void *aux, const char *pnp)
944 {
945 struct acpi_attach_args *aa = aux;
946 ACPI_STATUS rv;
947
948 if (pnp) {
949 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
950 char *pnpstr =
951 aa->aa_node->ad_devinfo->HardwareId.String;
952 ACPI_BUFFER buf;
953
954 aprint_normal("%s (%s) ", aa->aa_node->ad_name,
955 pnpstr);
956
957 rv = acpi_eval_struct(aa->aa_node->ad_handle,
958 "_STR", &buf);
959 if (ACPI_SUCCESS(rv)) {
960 ACPI_OBJECT *obj = buf.Pointer;
961 switch (obj->Type) {
962 case ACPI_TYPE_STRING:
963 aprint_normal("[%s] ", obj->String.Pointer);
964 break;
965 case ACPI_TYPE_BUFFER:
966 aprint_normal("buffer %p ", obj->Buffer.Pointer);
967 break;
968 default:
969 aprint_normal("type %u ",obj->Type);
970 break;
971 }
972 ACPI_FREE(buf.Pointer);
973 }
974 #ifdef ACPIVERBOSE
975 else {
976 int i;
977
978 for (i = 0; i < __arraycount(acpi_knowndevs);
979 i++) {
980 if (strcmp(acpi_knowndevs[i].pnp,
981 pnpstr) == 0) {
982 aprint_normal("[%s] ",
983 acpi_knowndevs[i].str);
984 }
985 }
986 }
987
988 #endif
989 aprint_normal("at %s", pnp);
990 } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) {
991 aprint_normal("%s (ACPI Object Type '%s' "
992 "[0x%02x]) ", aa->aa_node->ad_name,
993 AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
994 aa->aa_node->ad_devinfo->Type);
995 aprint_normal("at %s", pnp);
996 } else
997 return 0;
998 } else {
999 aprint_normal(" (%s", aa->aa_node->ad_name);
1000 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
1001 aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.String);
1002 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
1003 const char *uid;
1004
1005 uid = aa->aa_node->ad_devinfo->UniqueId.String;
1006 if (uid[0] == '\0')
1007 uid = "<null>";
1008 aprint_normal("-%s", uid);
1009 }
1010 }
1011 aprint_normal(")");
1012 }
1013
1014 return UNCONF;
1015 }
1016
1017 /*****************************************************************************
1018 * ACPI fixed-hardware feature handlers
1019 *****************************************************************************/
1020
1021 static UINT32 acpi_fixed_button_handler(void *);
1022 static void acpi_fixed_button_pressed(void *);
1023
1024 /*
1025 * acpi_enable_fixed_events:
1026 *
1027 * Enable any fixed-hardware feature handlers.
1028 */
1029 static void
1030 acpi_enable_fixed_events(struct acpi_softc *sc)
1031 {
1032 static int beenhere;
1033 ACPI_STATUS rv;
1034
1035 KASSERT(beenhere == 0);
1036 beenhere = 1;
1037
1038 /*
1039 * Check for fixed-hardware buttons.
1040 */
1041 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
1042 aprint_verbose_dev(sc->sc_dev,
1043 "fixed-feature power button present\n");
1044 sc->sc_smpsw_power.smpsw_name = device_xname(sc->sc_dev);
1045 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER;
1046 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
1047 aprint_error_dev(sc->sc_dev,
1048 "unable to register fixed power "
1049 "button with sysmon\n");
1050 } else {
1051 rv = AcpiInstallFixedEventHandler(
1052 ACPI_EVENT_POWER_BUTTON,
1053 acpi_fixed_button_handler, &sc->sc_smpsw_power);
1054 if (ACPI_FAILURE(rv)) {
1055 aprint_error_dev(sc->sc_dev,
1056 "unable to install handler "
1057 "for fixed power button: %s\n",
1058 AcpiFormatException(rv));
1059 }
1060 }
1061 }
1062
1063 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
1064 aprint_verbose_dev(sc->sc_dev,
1065 "fixed-feature sleep button present\n");
1066 sc->sc_smpsw_sleep.smpsw_name = device_xname(sc->sc_dev);
1067 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP;
1068 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
1069 aprint_error_dev(sc->sc_dev,
1070 "unable to register fixed sleep "
1071 "button with sysmon\n");
1072 } else {
1073 rv = AcpiInstallFixedEventHandler(
1074 ACPI_EVENT_SLEEP_BUTTON,
1075 acpi_fixed_button_handler, &sc->sc_smpsw_sleep);
1076 if (ACPI_FAILURE(rv)) {
1077 aprint_error_dev(sc->sc_dev,
1078 "unable to install handler "
1079 "for fixed sleep button: %s\n",
1080 AcpiFormatException(rv));
1081 }
1082 }
1083 }
1084 }
1085
1086 /*
1087 * acpi_fixed_button_handler:
1088 *
1089 * Event handler for the fixed buttons.
1090 */
1091 static UINT32
1092 acpi_fixed_button_handler(void *context)
1093 {
1094 static const int handler = OSL_NOTIFY_HANDLER;
1095 struct sysmon_pswitch *smpsw = context;
1096
1097 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s\n", __func__));
1098
1099 (void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw);
1100
1101 return ACPI_INTERRUPT_HANDLED;
1102 }
1103
1104 /*
1105 * acpi_fixed_button_pressed:
1106 *
1107 * Deal with a fixed button being pressed.
1108 */
1109 static void
1110 acpi_fixed_button_pressed(void *context)
1111 {
1112 struct sysmon_pswitch *smpsw = context;
1113
1114 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: %s fixed button pressed\n",
1115 __func__, smpsw->smpsw_name));
1116
1117 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
1118 }
1119
1120 /*****************************************************************************
1121 * ACPI utility routines.
1122 *****************************************************************************/
1123
1124 /*
1125 * acpi_eval_integer:
1126 *
1127 * Evaluate an integer object.
1128 */
1129 ACPI_STATUS
1130 acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp)
1131 {
1132 ACPI_STATUS rv;
1133 ACPI_BUFFER buf;
1134 ACPI_OBJECT param;
1135
1136 if (handle == NULL)
1137 handle = ACPI_ROOT_OBJECT;
1138
1139 buf.Pointer = ¶m;
1140 buf.Length = sizeof(param);
1141
1142 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf,
1143 ACPI_TYPE_INTEGER);
1144 if (ACPI_SUCCESS(rv))
1145 *valp = param.Integer.Value;
1146
1147 return rv;
1148 }
1149
1150 /*
1151 * acpi_eval_set_integer:
1152 *
1153 * Evaluate an integer object with a single integer input parameter.
1154 */
1155 ACPI_STATUS
1156 acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER arg)
1157 {
1158 ACPI_OBJECT param_arg;
1159 ACPI_OBJECT_LIST param_args;
1160
1161 if (handle == NULL)
1162 handle = ACPI_ROOT_OBJECT;
1163
1164 param_arg.Type = ACPI_TYPE_INTEGER;
1165 param_arg.Integer.Value = arg;
1166
1167 param_args.Count = 1;
1168 param_args.Pointer = ¶m_arg;
1169
1170 return AcpiEvaluateObject(handle, path, ¶m_args, NULL);
1171 }
1172
1173 /*
1174 * acpi_eval_string:
1175 *
1176 * Evaluate a (Unicode) string object.
1177 */
1178 ACPI_STATUS
1179 acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp)
1180 {
1181 ACPI_OBJECT *obj;
1182 ACPI_BUFFER buf;
1183 ACPI_STATUS rv;
1184
1185 rv = acpi_eval_struct(handle, path, &buf);
1186
1187 if (ACPI_FAILURE(rv))
1188 return rv;
1189
1190 obj = buf.Pointer;
1191
1192 if (obj->Type != ACPI_TYPE_STRING) {
1193 rv = AE_TYPE;
1194 goto out;
1195 }
1196
1197 if (obj->String.Length == 0) {
1198 rv = AE_BAD_DATA;
1199 goto out;
1200 }
1201
1202 *stringp = ACPI_ALLOCATE(obj->String.Length + 1);
1203
1204 if (*stringp == NULL) {
1205 rv = AE_NO_MEMORY;
1206 goto out;
1207 }
1208
1209 (void)memcpy(*stringp, obj->String.Pointer, obj->String.Length);
1210
1211 (*stringp)[obj->String.Length] = '\0';
1212
1213 out:
1214 ACPI_FREE(buf.Pointer);
1215
1216 return rv;
1217 }
1218
1219 /*
1220 * acpi_eval_struct:
1221 *
1222 * Evaluate a more complex structure.
1223 * Caller must free buf.Pointer by ACPI_FREE().
1224 */
1225 ACPI_STATUS
1226 acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp)
1227 {
1228 ACPI_STATUS rv;
1229
1230 if (handle == NULL)
1231 handle = ACPI_ROOT_OBJECT;
1232
1233 bufp->Pointer = NULL;
1234 bufp->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1235
1236 rv = AcpiEvaluateObject(handle, path, NULL, bufp);
1237
1238 return rv;
1239 }
1240
1241 /*
1242 * acpi_eval_reference_handle:
1243 *
1244 * Evaluate a reference handle from an element in a package.
1245 */
1246 ACPI_STATUS
1247 acpi_eval_reference_handle(ACPI_OBJECT *elm, ACPI_HANDLE *handle)
1248 {
1249
1250 if (elm == NULL || handle == NULL)
1251 return AE_BAD_PARAMETER;
1252
1253 switch (elm->Type) {
1254
1255 case ACPI_TYPE_ANY:
1256 case ACPI_TYPE_LOCAL_REFERENCE:
1257
1258 if (elm->Reference.Handle == NULL)
1259 return AE_NULL_ENTRY;
1260
1261 *handle = elm->Reference.Handle;
1262
1263 return AE_OK;
1264
1265 case ACPI_TYPE_STRING:
1266 return AcpiGetHandle(NULL, elm->String.Pointer, handle);
1267
1268 default:
1269 return AE_TYPE;
1270 }
1271 }
1272
1273 /*
1274 * acpi_foreach_package_object:
1275 *
1276 * Iterate over all objects in a package, and pass them all
1277 * to a function. If the called function returns non AE_OK, the
1278 * iteration is stopped and that value is returned.
1279 */
1280 ACPI_STATUS
1281 acpi_foreach_package_object(ACPI_OBJECT *pkg,
1282 ACPI_STATUS (*func)(ACPI_OBJECT *, void *),
1283 void *arg)
1284 {
1285 ACPI_STATUS rv = AE_OK;
1286 int i;
1287
1288 if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE)
1289 return AE_BAD_PARAMETER;
1290
1291 for (i = 0; i < pkg->Package.Count; i++) {
1292 rv = (*func)(&pkg->Package.Elements[i], arg);
1293 if (ACPI_FAILURE(rv))
1294 break;
1295 }
1296
1297 return rv;
1298 }
1299
1300 /*
1301 * acpi_name:
1302 *
1303 * Return a complete pathname from a handle.
1304 *
1305 * Note that the function uses static data storage;
1306 * if the data is needed for future use, it should be
1307 * copied before any subsequent calls overwrite it.
1308 */
1309 const char *
1310 acpi_name(ACPI_HANDLE handle)
1311 {
1312 static char buffer[80];
1313 ACPI_BUFFER buf;
1314 ACPI_STATUS rv;
1315
1316 buf.Length = sizeof(buffer);
1317 buf.Pointer = buffer;
1318
1319 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
1320 if (ACPI_FAILURE(rv))
1321 return "(unknown acpi path)";
1322 return buffer;
1323 }
1324
1325 /*
1326 * acpi_get:
1327 *
1328 * Fetch data info the specified (empty) ACPI buffer.
1329 * Caller must free buf.Pointer by ACPI_FREE().
1330 */
1331 ACPI_STATUS
1332 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
1333 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
1334 {
1335 buf->Pointer = NULL;
1336 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1337
1338 return (*getit)(handle, buf);
1339 }
1340
1341
1342 /*
1343 * acpi_match_hid
1344 *
1345 * Match given ids against _HID and _CIDs.
1346 */
1347 int
1348 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
1349 {
1350 int i;
1351
1352 while (*ids) {
1353 if (ad->Valid & ACPI_VALID_HID) {
1354 if (pmatch(ad->HardwareId.String, *ids, NULL) == 2)
1355 return 1;
1356 }
1357
1358 if (ad->Valid & ACPI_VALID_CID) {
1359 for (i = 0; i < ad->CompatibleIdList.Count; i++) {
1360 if (pmatch(ad->CompatibleIdList.Ids[i].String, *ids, NULL) == 2)
1361 return 1;
1362 }
1363 }
1364 ids++;
1365 }
1366
1367 return 0;
1368 }
1369
1370 /*
1371 * acpi_wake_gpe_helper
1372 *
1373 * Set/unset GPE as both Runtime and Wake.
1374 */
1375 static void
1376 acpi_wake_gpe_helper(ACPI_HANDLE handle, bool enable)
1377 {
1378 ACPI_OBJECT *elm, *obj;
1379 ACPI_INTEGER val;
1380 ACPI_BUFFER buf;
1381 ACPI_STATUS rv;
1382
1383 rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf);
1384
1385 if (ACPI_FAILURE(rv))
1386 return;
1387
1388 obj = buf.Pointer;
1389
1390 if (obj->Type != ACPI_TYPE_PACKAGE || obj->Package.Count < 2)
1391 goto out;
1392
1393 /*
1394 * As noted in ACPI 3.0 (section 7.2.10), the _PRW object is
1395 * a package in which the first element is either an integer
1396 * or again a package. In the latter case the package inside
1397 * the package element has two elements, a reference handle
1398 * and the GPE number.
1399 */
1400 elm = &obj->Package.Elements[0];
1401
1402 switch (elm->Type) {
1403
1404 case ACPI_TYPE_INTEGER:
1405 val = elm->Integer.Value;
1406 break;
1407
1408 case ACPI_TYPE_PACKAGE:
1409
1410 if (elm->Package.Count < 2)
1411 goto out;
1412
1413 if (elm->Package.Elements[0].Type != ACPI_TYPE_LOCAL_REFERENCE)
1414 goto out;
1415
1416 if (elm->Package.Elements[1].Type != ACPI_TYPE_INTEGER)
1417 goto out;
1418
1419 val = elm->Package.Elements[1].Integer.Value;
1420 break;
1421
1422 default:
1423 goto out;
1424 }
1425
1426 if (enable) {
1427 (void)AcpiSetGpeType(NULL, val, ACPI_GPE_TYPE_WAKE_RUN);
1428 (void)AcpiEnableGpe(NULL, val, ACPI_NOT_ISR);
1429 } else
1430 (void)AcpiDisableGpe(NULL, val, ACPI_NOT_ISR);
1431
1432 out:
1433 ACPI_FREE(buf.Pointer);
1434 }
1435
1436 /*
1437 * acpi_clear_wake_gpe
1438 *
1439 * Clear GPE as both Runtime and Wake.
1440 */
1441 void
1442 acpi_clear_wake_gpe(ACPI_HANDLE handle)
1443 {
1444 acpi_wake_gpe_helper(handle, false);
1445 }
1446
1447 /*
1448 * acpi_set_wake_gpe
1449 *
1450 * Set GPE as both Runtime and Wake.
1451 */
1452 void
1453 acpi_set_wake_gpe(ACPI_HANDLE handle)
1454 {
1455 acpi_wake_gpe_helper(handle, true);
1456 }
1457
1458
1459 /*****************************************************************************
1460 * ACPI sleep support.
1461 *****************************************************************************/
1462
1463 /*
1464 * acpi_sleep_init:
1465 *
1466 * Evaluate supported sleep states.
1467 */
1468 static void
1469 acpi_sleep_init(struct acpi_softc *sc)
1470 {
1471 uint8_t a, b, i;
1472 ACPI_STATUS rv;
1473
1474 CTASSERT(ACPI_STATE_S0 == 0 && ACPI_STATE_S1 == 1);
1475 CTASSERT(ACPI_STATE_S2 == 2 && ACPI_STATE_S3 == 3);
1476 CTASSERT(ACPI_STATE_S4 == 4 && ACPI_STATE_S5 == 5);
1477
1478 for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) {
1479
1480 rv = AcpiGetSleepTypeData(i, &a, &b);
1481
1482 if (ACPI_SUCCESS(rv))
1483 sc->sc_sleepstates |= __BIT(i);
1484 }
1485 }
1486
1487 /*
1488 * acpi_enter_sleep_state:
1489 *
1490 * Enter to the specified sleep state.
1491 */
1492 ACPI_STATUS
1493 acpi_enter_sleep_state(struct acpi_softc *sc, int state)
1494 {
1495 ACPI_STATUS rv = AE_OK;
1496 int err;
1497
1498 if (state == sc->sc_sleepstate)
1499 return AE_OK;
1500
1501 aprint_normal_dev(sc->sc_dev, "entering state S%d\n", state);
1502
1503 switch (state) {
1504
1505 case ACPI_STATE_S0:
1506 break;
1507
1508 case ACPI_STATE_S1:
1509 case ACPI_STATE_S2:
1510 case ACPI_STATE_S3:
1511 case ACPI_STATE_S4:
1512
1513 if ((sc->sc_sleepstates & __BIT(state)) == 0) {
1514 aprint_error_dev(sc->sc_dev, "sleep state "
1515 "S%d is not available\n", state);
1516 break;
1517 }
1518
1519 acpi_wakedev_commit(sc, state);
1520
1521 if (state != ACPI_STATE_S1 &&
1522 pmf_system_suspend(PMF_Q_NONE) != true) {
1523 aprint_error_dev(sc->sc_dev, "aborting suspend\n");
1524 break;
1525 }
1526
1527 rv = AcpiEnterSleepStatePrep(state);
1528
1529 if (ACPI_FAILURE(rv)) {
1530 aprint_error_dev(sc->sc_dev, "failed to prepare "
1531 "S%d: %s\n", state, AcpiFormatException(rv));
1532 break;
1533 }
1534
1535 sc->sc_sleepstate = state;
1536
1537 if (state == ACPI_STATE_S1) {
1538
1539 /* Just enter the state. */
1540 acpi_md_OsDisableInterrupt();
1541 rv = AcpiEnterSleepState(state);
1542
1543 if (ACPI_FAILURE(rv))
1544 aprint_error_dev(sc->sc_dev, "failed to "
1545 "enter S1: %s\n", AcpiFormatException(rv));
1546
1547 (void)AcpiLeaveSleepState(state);
1548
1549 } else {
1550
1551 err = acpi_md_sleep(state);
1552
1553 if (state == ACPI_STATE_S4)
1554 AcpiEnable();
1555
1556 pmf_system_bus_resume(PMF_Q_NONE);
1557 (void)AcpiLeaveSleepState(state);
1558 pmf_system_resume(PMF_Q_NONE);
1559 }
1560
1561 break;
1562 case ACPI_STATE_S5:
1563
1564 rv = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
1565
1566 if (ACPI_FAILURE(rv)) {
1567 aprint_error_dev(sc->sc_dev, "failed to prepare "
1568 "S%d: %s\n", state, AcpiFormatException(rv));
1569 break;
1570 }
1571
1572 DELAY(1000000);
1573
1574 sc->sc_sleepstate = state;
1575 acpi_md_OsDisableInterrupt();
1576
1577 (void)AcpiEnterSleepState(ACPI_STATE_S5);
1578
1579 aprint_error_dev(sc->sc_dev, "WARNING: powerdown failed!\n");
1580 break;
1581 }
1582
1583 sc->sc_sleepstate = ACPI_STATE_S0;
1584
1585 return rv;
1586 }
1587
1588 #ifdef ACPI_ACTIVATE_DEV
1589
1590 #define ACPI_DEV_VALID (ACPI_VALID_STA | ACPI_VALID_HID)
1591 #define ACPI_DEV_STATUS (ACPI_STA_DEV_PRESENT | ACPI_STA_DEV_ENABLED)
1592
1593 static void
1594 acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
1595 {
1596 ACPI_DEVICE_INFO *newdi;
1597 ACPI_STATUS rv;
1598 uint32_t old;
1599
1600 /*
1601 * If the device is valid and present,
1602 * but not enabled, try to activate it.
1603 */
1604 if (((*di)->Valid & ACPI_DEV_VALID) != ACPI_DEV_VALID)
1605 return;
1606
1607 old = (*di)->CurrentStatus;
1608
1609 if ((old & ACPI_DEV_STATUS) != ACPI_STA_DEV_PRESENT)
1610 return;
1611
1612 rv = acpi_allocate_resources(handle);
1613
1614 if (ACPI_FAILURE(rv))
1615 goto fail;
1616
1617 rv = AcpiGetObjectInfo(handle, &newdi);
1618
1619 if (ACPI_FAILURE(rv))
1620 goto fail;
1621
1622 ACPI_FREE(*di);
1623 *di = newdi;
1624
1625 aprint_verbose_dev(acpi_softc->sc_dev,
1626 "%s activated, STA 0x%08X -> STA 0x%08X\n",
1627 (*di)->HardwareId.String, old, (*di)->CurrentStatus);
1628
1629 return;
1630
1631 fail:
1632 aprint_error_dev(acpi_softc->sc_dev, "failed to "
1633 "activate %s\n", (*di)->HardwareId.String);
1634 }
1635
1636 /*
1637 * XXX: This very incomplete.
1638 */
1639 ACPI_STATUS
1640 acpi_allocate_resources(ACPI_HANDLE handle)
1641 {
1642 ACPI_BUFFER bufp, bufc, bufn;
1643 ACPI_RESOURCE *resp, *resc, *resn;
1644 ACPI_RESOURCE_IRQ *irq;
1645 ACPI_RESOURCE_EXTENDED_IRQ *xirq;
1646 ACPI_STATUS rv;
1647 uint delta;
1648
1649 rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
1650 if (ACPI_FAILURE(rv))
1651 goto out;
1652 rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
1653 if (ACPI_FAILURE(rv)) {
1654 goto out1;
1655 }
1656
1657 bufn.Length = 1000;
1658 bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
1659 resp = bufp.Pointer;
1660 resc = bufc.Pointer;
1661 while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG &&
1662 resp->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1663 while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG)
1664 resp = ACPI_NEXT_RESOURCE(resp);
1665 if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG)
1666 break;
1667 /* Found identical Id */
1668 resn->Type = resc->Type;
1669 switch (resc->Type) {
1670 case ACPI_RESOURCE_TYPE_IRQ:
1671 memcpy(&resn->Data, &resp->Data,
1672 sizeof(ACPI_RESOURCE_IRQ));
1673 irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
1674 irq->Interrupts[0] =
1675 ((ACPI_RESOURCE_IRQ *)&resp->Data)->
1676 Interrupts[irq->InterruptCount-1];
1677 irq->InterruptCount = 1;
1678 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
1679 break;
1680 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1681 memcpy(&resn->Data, &resp->Data,
1682 sizeof(ACPI_RESOURCE_EXTENDED_IRQ));
1683 xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data;
1684 #if 0
1685 /*
1686 * XXX not duplicating the interrupt logic above
1687 * because its not clear what it accomplishes.
1688 */
1689 xirq->Interrupts[0] =
1690 ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)->
1691 Interrupts[irq->NumberOfInterrupts-1];
1692 xirq->NumberOfInterrupts = 1;
1693 #endif
1694 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
1695 break;
1696 case ACPI_RESOURCE_TYPE_IO:
1697 memcpy(&resn->Data, &resp->Data,
1698 sizeof(ACPI_RESOURCE_IO));
1699 resn->Length = resp->Length;
1700 break;
1701 default:
1702 aprint_error_dev(acpi_softc->sc_dev,
1703 "%s: invalid type %u\n", __func__, resc->Type);
1704 rv = AE_BAD_DATA;
1705 goto out2;
1706 }
1707 resc = ACPI_NEXT_RESOURCE(resc);
1708 resn = ACPI_NEXT_RESOURCE(resn);
1709 resp = ACPI_NEXT_RESOURCE(resp);
1710 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
1711 if (delta >=
1712 bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) {
1713 bufn.Length *= 2;
1714 bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
1715 M_ACPI, M_WAITOK);
1716 resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
1717 }
1718 }
1719
1720 if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1721 aprint_error_dev(acpi_softc->sc_dev,
1722 "%s: resc not exhausted\n", __func__);
1723 rv = AE_BAD_DATA;
1724 goto out3;
1725 }
1726
1727 resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
1728 rv = AcpiSetCurrentResources(handle, &bufn);
1729
1730 if (ACPI_FAILURE(rv))
1731 aprint_error_dev(acpi_softc->sc_dev, "%s: failed to set "
1732 "resources: %s\n", __func__, AcpiFormatException(rv));
1733
1734 out3:
1735 free(bufn.Pointer, M_ACPI);
1736 out2:
1737 ACPI_FREE(bufc.Pointer);
1738 out1:
1739 ACPI_FREE(bufp.Pointer);
1740 out:
1741 return rv;
1742 }
1743
1744 #undef ACPI_DEV_VALID
1745 #undef ACPI_DEV_STATUS
1746
1747 #endif /* ACPI_ACTIVATE_DEV */
1748
1749 SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
1750 {
1751 const struct sysctlnode *mnode, *rnode;
1752 int err;
1753
1754 err = sysctl_createv(clog, 0, NULL, &rnode,
1755 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw",
1756 NULL, NULL, 0, NULL, 0,
1757 CTL_HW, CTL_EOL);
1758
1759 if (err != 0)
1760 return;
1761
1762 err = sysctl_createv(clog, 0, &rnode, &rnode,
1763 CTLFLAG_PERMANENT, CTLTYPE_NODE,
1764 "acpi", SYSCTL_DESCR("ACPI subsystem parameters"),
1765 NULL, 0, NULL, 0,
1766 CTL_CREATE, CTL_EOL);
1767
1768 if (err != 0)
1769 return;
1770
1771 (void)sysctl_createv(NULL, 0, &rnode, NULL,
1772 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1773 "root", SYSCTL_DESCR("ACPI root pointer"),
1774 NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer),
1775 CTL_CREATE, CTL_EOL);
1776
1777 (void)sysctl_createv(NULL, 0, &rnode, NULL,
1778 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_STRING,
1779 "supported_states", SYSCTL_DESCR("Supported system states"),
1780 sysctl_hw_acpi_sleepstates, 0, NULL, 0,
1781 CTL_CREATE, CTL_EOL);
1782
1783 err = sysctl_createv(NULL, 0, NULL, &mnode,
1784 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep",
1785 NULL, NULL, 0, NULL, 0,
1786 CTL_MACHDEP, CTL_EOL);
1787
1788 if (err == 0) {
1789
1790 (void)sysctl_createv(NULL, 0, &mnode, NULL,
1791 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
1792 "sleep_state", SYSCTL_DESCR("System sleep state"),
1793 sysctl_hw_acpi_sleepstate, 0, NULL, 0,
1794 CTL_CREATE, CTL_EOL);
1795 }
1796
1797 err = sysctl_createv(clog, 0, &rnode, &rnode,
1798 CTLFLAG_PERMANENT, CTLTYPE_NODE,
1799 "stat", SYSCTL_DESCR("ACPI statistics"),
1800 NULL, 0, NULL, 0,
1801 CTL_CREATE, CTL_EOL);
1802
1803 if (err != 0)
1804 return;
1805
1806 (void)sysctl_createv(clog, 0, &rnode, NULL,
1807 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1808 "gpe", SYSCTL_DESCR("Number of dispatched GPEs"),
1809 NULL, 0, &AcpiGpeCount, sizeof(AcpiGpeCount),
1810 CTL_CREATE, CTL_EOL);
1811
1812 (void)sysctl_createv(clog, 0, &rnode, NULL,
1813 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1814 "sci", SYSCTL_DESCR("Number of SCI interrupts"),
1815 NULL, 0, &AcpiSciCount, sizeof(AcpiSciCount),
1816 CTL_CREATE, CTL_EOL);
1817
1818 (void)sysctl_createv(clog, 0, &rnode, NULL,
1819 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1820 "fixed", SYSCTL_DESCR("Number of fixed events"),
1821 sysctl_hw_acpi_fixedstats, 0, NULL, 0,
1822 CTL_CREATE, CTL_EOL);
1823
1824 (void)sysctl_createv(clog, 0, &rnode, NULL,
1825 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1826 "method", SYSCTL_DESCR("Number of methods executed"),
1827 NULL, 0, &AcpiMethodCount, sizeof(AcpiMethodCount),
1828 CTL_CREATE, CTL_EOL);
1829
1830 CTASSERT(sizeof(AcpiGpeCount) == sizeof(uint64_t));
1831 CTASSERT(sizeof(AcpiSciCount) == sizeof(uint64_t));
1832 }
1833
1834 static int
1835 sysctl_hw_acpi_fixedstats(SYSCTLFN_ARGS)
1836 {
1837 struct sysctlnode node;
1838 uint64_t t;
1839 int err, i;
1840
1841 for (i = t = 0; i < __arraycount(AcpiFixedEventCount); i++)
1842 t += AcpiFixedEventCount[i];
1843
1844 node = *rnode;
1845 node.sysctl_data = &t;
1846
1847 err = sysctl_lookup(SYSCTLFN_CALL(&node));
1848
1849 if (err || newp == NULL)
1850 return err;
1851
1852 return 0;
1853 }
1854
1855 static int
1856 sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
1857 {
1858 struct acpi_softc *sc = acpi_softc;
1859 struct sysctlnode node;
1860 int err, t;
1861
1862 if (acpi_softc == NULL)
1863 return ENOSYS;
1864
1865 node = *rnode;
1866 t = sc->sc_sleepstate;
1867 node.sysctl_data = &t;
1868
1869 err = sysctl_lookup(SYSCTLFN_CALL(&node));
1870
1871 if (err || newp == NULL)
1872 return err;
1873
1874 if (t < ACPI_STATE_S0 || t > ACPI_STATE_S5)
1875 return EINVAL;
1876
1877 acpi_enter_sleep_state(sc, t);
1878
1879 return 0;
1880 }
1881
1882 static int
1883 sysctl_hw_acpi_sleepstates(SYSCTLFN_ARGS)
1884 {
1885 struct acpi_softc *sc = acpi_softc;
1886 struct sysctlnode node;
1887 char t[3 * 6 + 1];
1888 int err;
1889
1890 if (acpi_softc == NULL)
1891 return ENOSYS;
1892
1893 (void)memset(t, '\0', sizeof(t));
1894
1895 (void)snprintf(t, sizeof(t), "%s%s%s%s%s%s",
1896 ((sc->sc_sleepstates & __BIT(0)) != 0) ? "S0 " : "",
1897 ((sc->sc_sleepstates & __BIT(1)) != 0) ? "S1 " : "",
1898 ((sc->sc_sleepstates & __BIT(2)) != 0) ? "S2 " : "",
1899 ((sc->sc_sleepstates & __BIT(3)) != 0) ? "S3 " : "",
1900 ((sc->sc_sleepstates & __BIT(4)) != 0) ? "S4 " : "",
1901 ((sc->sc_sleepstates & __BIT(5)) != 0) ? "S5 " : "");
1902
1903 node = *rnode;
1904 node.sysctl_data = &t;
1905
1906 err = sysctl_lookup(SYSCTLFN_CALL(&node));
1907
1908 if (err || newp == NULL)
1909 return err;
1910
1911 return 0;
1912 }
1913
1914 static ACPI_TABLE_HEADER *
1915 acpi_map_rsdt(void)
1916 {
1917 ACPI_PHYSICAL_ADDRESS paddr;
1918 ACPI_TABLE_RSDP *rsdp;
1919
1920 paddr = AcpiOsGetRootPointer();
1921 if (paddr == 0) {
1922 printf("ACPI: couldn't get root pointer\n");
1923 return NULL;
1924 }
1925 rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP));
1926 if (rsdp == NULL) {
1927 printf("ACPI: couldn't map RSDP\n");
1928 return NULL;
1929 }
1930 if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress)
1931 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->XsdtPhysicalAddress;
1932 else
1933 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->RsdtPhysicalAddress;
1934 AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP));
1935
1936 return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER));
1937 }
1938
1939 static void
1940 acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt)
1941 {
1942 if (rsdt == NULL)
1943 return;
1944
1945 AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER));
1946 }
1947