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