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