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