acpi.c revision 1.172 1 /* $NetBSD: acpi.c,v 1.172 2010/04/14 18:39:56 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.172 2010/04/14 18:39:56 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 *)resn - (UINT8 *)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 *)bufn.Pointer + delta);
794 }
795 }
796
797 if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
798 aprint_error_dev(acpi_softc->sc_dev,
799 "%s: resc not exhausted\n", __func__);
800 rv = AE_BAD_DATA;
801 goto out3;
802 }
803
804 resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
805 rv = AcpiSetCurrentResources(handle, &bufn);
806
807 if (ACPI_FAILURE(rv))
808 aprint_error_dev(acpi_softc->sc_dev, "%s: failed to set "
809 "resources: %s\n", __func__, AcpiFormatException(rv));
810
811 out3:
812 free(bufn.Pointer, M_ACPI);
813 out2:
814 ACPI_FREE(bufc.Pointer);
815 out1:
816 ACPI_FREE(bufp.Pointer);
817 out:
818 return rv;
819 }
820
821 #undef ACPI_DEV_VALID
822 #undef ACPI_DEV_STATUS
823
824 #endif /* ACPI_ACTIVATE_DEV */
825
826 /*
827 * Device attachment.
828 */
829 static int
830 acpi_rescan(device_t self, const char *ifattr, const int *locators)
831 {
832 struct acpi_softc *sc = device_private(self);
833
834 acpi_rescan1(sc, ifattr, locators);
835
836 return 0;
837 }
838
839 static void
840 acpi_rescan1(struct acpi_softc *sc, const char *ifattr, const int *locators)
841 {
842
843 if (ifattr_match(ifattr, "acpinodebus"))
844 acpi_rescan_nodes(sc);
845
846 if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL)
847 sc->sc_apmbus = config_found_ia(sc->sc_dev,
848 "acpiapmbus", NULL, NULL);
849 }
850
851 static void
852 acpi_rescan_nodes(struct acpi_softc *sc)
853 {
854 struct acpi_attach_args aa;
855 struct acpi_devnode *ad;
856
857 SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) {
858
859 if (ad->ad_device != NULL)
860 continue;
861
862 aa.aa_node = ad;
863 aa.aa_iot = sc->sc_iot;
864 aa.aa_memt = sc->sc_memt;
865 aa.aa_pc = sc->sc_pc;
866 aa.aa_pciflags = sc->sc_pciflags;
867 aa.aa_ic = sc->sc_ic;
868
869 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) {
870 /*
871 * XXX We only attach devices which are:
872 *
873 * - present
874 * - enabled
875 * - functioning properly
876 *
877 * However, if enabled, it's decoding resources,
878 * so we should claim them, if possible.
879 * Requires changes to bus_space(9).
880 */
881 if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) ==
882 ACPI_VALID_STA &&
883 (ad->ad_devinfo->CurrentStatus &
884 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
885 ACPI_STA_DEV_OK)) !=
886 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
887 ACPI_STA_DEV_OK))
888 continue;
889 }
890
891 /*
892 * XXX Same problem as above...
893 *
894 * Do this check only for devices, as e.g.
895 * a Thermal Zone doesn't have a HID.
896 */
897 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE &&
898 (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
899 continue;
900
901 /*
902 * Handled internally.
903 */
904 if (ad->ad_devinfo->Type == ACPI_TYPE_PROCESSOR ||
905 ad->ad_devinfo->Type == ACPI_TYPE_POWER)
906 continue;
907
908 /*
909 * Skip ignored HIDs.
910 */
911 if (acpi_match_hid(ad->ad_devinfo, acpi_ignored_ids))
912 continue;
913
914 ad->ad_device = config_found_ia(sc->sc_dev,
915 "acpinodebus", &aa, acpi_print);
916 }
917 }
918
919 #define ACPI_STA_DEV_VALID \
920 (ACPI_STA_DEV_PRESENT | ACPI_STA_DEV_ENABLED | ACPI_STA_DEV_OK)
921
922 static void
923 acpi_rescan_capabilities(struct acpi_softc *sc)
924 {
925 struct acpi_devnode *ad;
926 ACPI_DEVICE_INFO *di;
927 ACPI_HANDLE tmp;
928 ACPI_STATUS rv;
929
930 SIMPLEQ_FOREACH(ad, &sc->sc_devnodes, ad_list) {
931
932 di = ad->ad_devinfo;
933
934 if (di->Type != ACPI_TYPE_DEVICE)
935 continue;
936
937 if ((di->Valid & ACPI_VALID_STA) != 0 &&
938 (di->CurrentStatus & ACPI_STA_DEV_VALID) !=
939 ACPI_STA_DEV_VALID)
940 continue;
941
942 /*
943 * Scan power resource capabilities.
944 */
945 rv = AcpiGetHandle(ad->ad_handle, "_PR0", &tmp);
946
947 if (ACPI_FAILURE(rv))
948 rv = AcpiGetHandle(ad->ad_handle, "_PSC", &tmp);
949
950 if (ACPI_SUCCESS(rv))
951 ad->ad_flags |= ACPI_DEVICE_POWER;
952
953 /*
954 * Scan wake-up capabilities.
955 */
956 rv = AcpiGetHandle(ad->ad_handle, "_PRW", &tmp);
957
958 if (ACPI_SUCCESS(rv)) {
959 ad->ad_flags |= ACPI_DEVICE_WAKEUP;
960 acpi_wakedev_add(ad);
961 }
962
963 if (ad->ad_flags != 0) {
964 aprint_debug_dev(sc->sc_dev, "%-5s ", ad->ad_name);
965
966 if ((ad->ad_flags & ACPI_DEVICE_POWER) != 0)
967 aprint_debug("power ");
968
969 if ((ad->ad_flags & ACPI_DEVICE_WAKEUP) != 0)
970 aprint_debug("wake-up ");
971
972 aprint_debug("\n");
973 }
974 }
975 }
976
977 #undef ACPI_STA_DEV_VALID
978
979 static int
980 acpi_print(void *aux, const char *pnp)
981 {
982 struct acpi_attach_args *aa = aux;
983 ACPI_STATUS rv;
984
985 if (pnp) {
986 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
987 char *pnpstr =
988 aa->aa_node->ad_devinfo->HardwareId.String;
989 ACPI_BUFFER buf;
990
991 aprint_normal("%s (%s) ", aa->aa_node->ad_name,
992 pnpstr);
993
994 rv = acpi_eval_struct(aa->aa_node->ad_handle,
995 "_STR", &buf);
996 if (ACPI_SUCCESS(rv)) {
997 ACPI_OBJECT *obj = buf.Pointer;
998 switch (obj->Type) {
999 case ACPI_TYPE_STRING:
1000 aprint_normal("[%s] ", obj->String.Pointer);
1001 break;
1002 case ACPI_TYPE_BUFFER:
1003 aprint_normal("buffer %p ", obj->Buffer.Pointer);
1004 break;
1005 default:
1006 aprint_normal("type %u ",obj->Type);
1007 break;
1008 }
1009 ACPI_FREE(buf.Pointer);
1010 }
1011 #ifdef ACPIVERBOSE
1012 else {
1013 int i;
1014
1015 for (i = 0; i < __arraycount(acpi_knowndevs);
1016 i++) {
1017 if (strcmp(acpi_knowndevs[i].pnp,
1018 pnpstr) == 0) {
1019 aprint_normal("[%s] ",
1020 acpi_knowndevs[i].str);
1021 }
1022 }
1023 }
1024
1025 #endif
1026 aprint_normal("at %s", pnp);
1027 } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) {
1028 aprint_normal("%s (ACPI Object Type '%s' "
1029 "[0x%02x]) ", aa->aa_node->ad_name,
1030 AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
1031 aa->aa_node->ad_devinfo->Type);
1032 aprint_normal("at %s", pnp);
1033 } else
1034 return 0;
1035 } else {
1036 aprint_normal(" (%s", aa->aa_node->ad_name);
1037 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
1038 aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.String);
1039 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
1040 const char *uid;
1041
1042 uid = aa->aa_node->ad_devinfo->UniqueId.String;
1043 if (uid[0] == '\0')
1044 uid = "<null>";
1045 aprint_normal("-%s", uid);
1046 }
1047 }
1048 aprint_normal(")");
1049 }
1050
1051 return UNCONF;
1052 }
1053
1054 /*
1055 * Fixed buttons.
1056 */
1057 static void
1058 acpi_register_fixed_button(struct acpi_softc *sc, int event)
1059 {
1060 struct sysmon_pswitch *smpsw;
1061 ACPI_STATUS rv;
1062 int type;
1063
1064 switch (event) {
1065
1066 case ACPI_EVENT_POWER_BUTTON:
1067
1068 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0)
1069 return;
1070
1071 type = PSWITCH_TYPE_POWER;
1072 smpsw = &sc->sc_smpsw_power;
1073 break;
1074
1075 case ACPI_EVENT_SLEEP_BUTTON:
1076
1077 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0)
1078 return;
1079
1080 type = PSWITCH_TYPE_SLEEP;
1081 smpsw = &sc->sc_smpsw_sleep;
1082 break;
1083
1084 default:
1085 rv = AE_TYPE;
1086 goto fail;
1087 }
1088
1089 smpsw->smpsw_type = type;
1090 smpsw->smpsw_name = device_xname(sc->sc_dev);
1091
1092 if (sysmon_pswitch_register(smpsw) != 0) {
1093 rv = AE_ERROR;
1094 goto fail;
1095 }
1096
1097 rv = AcpiInstallFixedEventHandler(event,
1098 acpi_fixed_button_handler, smpsw);
1099
1100 if (ACPI_FAILURE(rv))
1101 goto fail;
1102
1103 aprint_debug_dev(sc->sc_dev, "fixed %s button present\n",
1104 (type != ACPI_EVENT_SLEEP_BUTTON) ? "power" : "sleep");
1105
1106 return;
1107
1108 fail:
1109 aprint_error_dev(sc->sc_dev, "failed to register "
1110 "fixed event: %s\n", AcpiFormatException(rv));
1111 }
1112
1113 static void
1114 acpi_deregister_fixed_button(struct acpi_softc *sc, int event)
1115 {
1116 struct sysmon_pswitch *smpsw;
1117 ACPI_STATUS rv;
1118
1119 switch (event) {
1120
1121 case ACPI_EVENT_POWER_BUTTON:
1122 smpsw = &sc->sc_smpsw_power;
1123
1124 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) != 0) {
1125 KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_POWER);
1126 return;
1127 }
1128
1129 break;
1130
1131 case ACPI_EVENT_SLEEP_BUTTON:
1132 smpsw = &sc->sc_smpsw_sleep;
1133
1134 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) != 0) {
1135 KASSERT(smpsw->smpsw_type != PSWITCH_TYPE_SLEEP);
1136 return;
1137 }
1138
1139 break;
1140
1141 default:
1142 rv = AE_TYPE;
1143 goto fail;
1144 }
1145
1146 rv = AcpiRemoveFixedEventHandler(event, acpi_fixed_button_handler);
1147
1148 if (ACPI_SUCCESS(rv)) {
1149 sysmon_pswitch_unregister(smpsw);
1150 return;
1151 }
1152
1153 fail:
1154 aprint_error_dev(sc->sc_dev, "failed to deregister "
1155 "fixed event: %s\n", AcpiFormatException(rv));
1156 }
1157
1158 static uint32_t
1159 acpi_fixed_button_handler(void *context)
1160 {
1161 static const int handler = OSL_NOTIFY_HANDLER;
1162 struct sysmon_pswitch *smpsw = context;
1163
1164 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: fixed event\n", __func__));
1165
1166 (void)AcpiOsExecute(handler, acpi_fixed_button_pressed, smpsw);
1167
1168 return ACPI_INTERRUPT_HANDLED;
1169 }
1170
1171 static void
1172 acpi_fixed_button_pressed(void *context)
1173 {
1174 struct sysmon_pswitch *smpsw = context;
1175
1176 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "%s: %s fixed button pressed\n",
1177 __func__, smpsw->smpsw_name));
1178
1179 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
1180 }
1181
1182 /*
1183 * Sleep.
1184 */
1185 static void
1186 acpi_sleep_init(struct acpi_softc *sc)
1187 {
1188 uint8_t a, b, i;
1189 ACPI_STATUS rv;
1190
1191 CTASSERT(ACPI_STATE_S0 == 0 && ACPI_STATE_S1 == 1);
1192 CTASSERT(ACPI_STATE_S2 == 2 && ACPI_STATE_S3 == 3);
1193 CTASSERT(ACPI_STATE_S4 == 4 && ACPI_STATE_S5 == 5);
1194
1195 /*
1196 * Evaluate supported sleep states.
1197 */
1198 for (i = ACPI_STATE_S0; i <= ACPI_STATE_S5; i++) {
1199
1200 rv = AcpiGetSleepTypeData(i, &a, &b);
1201
1202 if (ACPI_SUCCESS(rv))
1203 sc->sc_sleepstates |= __BIT(i);
1204 }
1205 }
1206
1207 ACPI_STATUS
1208 acpi_enter_sleep_state(struct acpi_softc *sc, int state)
1209 {
1210 ACPI_STATUS rv = AE_OK;
1211 int err;
1212
1213 if (state == sc->sc_sleepstate)
1214 return AE_OK;
1215
1216 aprint_normal_dev(sc->sc_dev, "entering state S%d\n", state);
1217
1218 switch (state) {
1219
1220 case ACPI_STATE_S0:
1221 break;
1222
1223 case ACPI_STATE_S1:
1224 case ACPI_STATE_S2:
1225 case ACPI_STATE_S3:
1226 case ACPI_STATE_S4:
1227
1228 if ((sc->sc_sleepstates & __BIT(state)) == 0) {
1229 aprint_error_dev(sc->sc_dev, "sleep state "
1230 "S%d is not available\n", state);
1231 break;
1232 }
1233
1234 acpi_wakedev_commit(sc, state);
1235
1236 if (state != ACPI_STATE_S1 &&
1237 pmf_system_suspend(PMF_Q_NONE) != true) {
1238 aprint_error_dev(sc->sc_dev, "aborting suspend\n");
1239 break;
1240 }
1241
1242 rv = AcpiEnterSleepStatePrep(state);
1243
1244 if (ACPI_FAILURE(rv)) {
1245 aprint_error_dev(sc->sc_dev, "failed to prepare "
1246 "S%d: %s\n", state, AcpiFormatException(rv));
1247 break;
1248 }
1249
1250 sc->sc_sleepstate = state;
1251
1252 if (state == ACPI_STATE_S1) {
1253
1254 /* Just enter the state. */
1255 acpi_md_OsDisableInterrupt();
1256 rv = AcpiEnterSleepState(state);
1257
1258 if (ACPI_FAILURE(rv))
1259 aprint_error_dev(sc->sc_dev, "failed to "
1260 "enter S1: %s\n", AcpiFormatException(rv));
1261
1262 (void)AcpiLeaveSleepState(state);
1263
1264 } else {
1265
1266 err = acpi_md_sleep(state);
1267
1268 if (state == ACPI_STATE_S4)
1269 AcpiEnable();
1270
1271 pmf_system_bus_resume(PMF_Q_NONE);
1272 (void)AcpiLeaveSleepState(state);
1273 pmf_system_resume(PMF_Q_NONE);
1274 }
1275
1276 break;
1277 case ACPI_STATE_S5:
1278
1279 rv = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
1280
1281 if (ACPI_FAILURE(rv)) {
1282 aprint_error_dev(sc->sc_dev, "failed to prepare "
1283 "S%d: %s\n", state, AcpiFormatException(rv));
1284 break;
1285 }
1286
1287 DELAY(1000000);
1288
1289 sc->sc_sleepstate = state;
1290 acpi_md_OsDisableInterrupt();
1291
1292 (void)AcpiEnterSleepState(ACPI_STATE_S5);
1293
1294 aprint_error_dev(sc->sc_dev, "WARNING: powerdown failed!\n");
1295 break;
1296 }
1297
1298 sc->sc_sleepstate = ACPI_STATE_S0;
1299
1300 return rv;
1301 }
1302
1303 /*
1304 * Sysctl.
1305 */
1306 SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
1307 {
1308 const struct sysctlnode *mnode, *rnode;
1309 int err;
1310
1311 err = sysctl_createv(clog, 0, NULL, &rnode,
1312 CTLFLAG_PERMANENT, CTLTYPE_NODE, "hw",
1313 NULL, NULL, 0, NULL, 0,
1314 CTL_HW, CTL_EOL);
1315
1316 if (err != 0)
1317 return;
1318
1319 err = sysctl_createv(clog, 0, &rnode, &rnode,
1320 CTLFLAG_PERMANENT, CTLTYPE_NODE,
1321 "acpi", SYSCTL_DESCR("ACPI subsystem parameters"),
1322 NULL, 0, NULL, 0,
1323 CTL_CREATE, CTL_EOL);
1324
1325 if (err != 0)
1326 return;
1327
1328 (void)sysctl_createv(NULL, 0, &rnode, NULL,
1329 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1330 "root", SYSCTL_DESCR("ACPI root pointer"),
1331 NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer),
1332 CTL_CREATE, CTL_EOL);
1333
1334 (void)sysctl_createv(NULL, 0, &rnode, NULL,
1335 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_STRING,
1336 "supported_states", SYSCTL_DESCR("Supported system states"),
1337 sysctl_hw_acpi_sleepstates, 0, NULL, 0,
1338 CTL_CREATE, CTL_EOL);
1339
1340 err = sysctl_createv(NULL, 0, NULL, &mnode,
1341 CTLFLAG_PERMANENT, CTLTYPE_NODE, "machdep",
1342 NULL, NULL, 0, NULL, 0,
1343 CTL_MACHDEP, CTL_EOL);
1344
1345 if (err == 0) {
1346
1347 (void)sysctl_createv(NULL, 0, &mnode, NULL,
1348 CTLFLAG_PERMANENT | CTLFLAG_READWRITE, CTLTYPE_INT,
1349 "sleep_state", SYSCTL_DESCR("System sleep state"),
1350 sysctl_hw_acpi_sleepstate, 0, NULL, 0,
1351 CTL_CREATE, CTL_EOL);
1352 }
1353
1354 err = sysctl_createv(clog, 0, &rnode, &rnode,
1355 CTLFLAG_PERMANENT, CTLTYPE_NODE,
1356 "stat", SYSCTL_DESCR("ACPI statistics"),
1357 NULL, 0, NULL, 0,
1358 CTL_CREATE, CTL_EOL);
1359
1360 if (err != 0)
1361 return;
1362
1363 (void)sysctl_createv(clog, 0, &rnode, NULL,
1364 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1365 "gpe", SYSCTL_DESCR("Number of dispatched GPEs"),
1366 NULL, 0, &AcpiGpeCount, sizeof(AcpiGpeCount),
1367 CTL_CREATE, CTL_EOL);
1368
1369 (void)sysctl_createv(clog, 0, &rnode, NULL,
1370 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1371 "sci", SYSCTL_DESCR("Number of SCI interrupts"),
1372 NULL, 0, &AcpiSciCount, sizeof(AcpiSciCount),
1373 CTL_CREATE, CTL_EOL);
1374
1375 (void)sysctl_createv(clog, 0, &rnode, NULL,
1376 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1377 "fixed", SYSCTL_DESCR("Number of fixed events"),
1378 sysctl_hw_acpi_fixedstats, 0, NULL, 0,
1379 CTL_CREATE, CTL_EOL);
1380
1381 (void)sysctl_createv(clog, 0, &rnode, NULL,
1382 CTLFLAG_PERMANENT | CTLFLAG_READONLY, CTLTYPE_QUAD,
1383 "method", SYSCTL_DESCR("Number of methods executed"),
1384 NULL, 0, &AcpiMethodCount, sizeof(AcpiMethodCount),
1385 CTL_CREATE, CTL_EOL);
1386
1387 CTASSERT(sizeof(AcpiGpeCount) == sizeof(uint64_t));
1388 CTASSERT(sizeof(AcpiSciCount) == sizeof(uint64_t));
1389 }
1390
1391 static int
1392 sysctl_hw_acpi_fixedstats(SYSCTLFN_ARGS)
1393 {
1394 struct sysctlnode node;
1395 uint64_t t;
1396 int err, i;
1397
1398 for (i = t = 0; i < __arraycount(AcpiFixedEventCount); i++)
1399 t += AcpiFixedEventCount[i];
1400
1401 node = *rnode;
1402 node.sysctl_data = &t;
1403
1404 err = sysctl_lookup(SYSCTLFN_CALL(&node));
1405
1406 if (err || newp == NULL)
1407 return err;
1408
1409 return 0;
1410 }
1411
1412 static int
1413 sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
1414 {
1415 struct acpi_softc *sc = acpi_softc;
1416 struct sysctlnode node;
1417 int err, t;
1418
1419 if (acpi_softc == NULL)
1420 return ENOSYS;
1421
1422 node = *rnode;
1423 t = sc->sc_sleepstate;
1424 node.sysctl_data = &t;
1425
1426 err = sysctl_lookup(SYSCTLFN_CALL(&node));
1427
1428 if (err || newp == NULL)
1429 return err;
1430
1431 if (t < ACPI_STATE_S0 || t > ACPI_STATE_S5)
1432 return EINVAL;
1433
1434 acpi_enter_sleep_state(sc, t);
1435
1436 return 0;
1437 }
1438
1439 static int
1440 sysctl_hw_acpi_sleepstates(SYSCTLFN_ARGS)
1441 {
1442 struct acpi_softc *sc = acpi_softc;
1443 struct sysctlnode node;
1444 char t[3 * 6 + 1];
1445 int err;
1446
1447 if (acpi_softc == NULL)
1448 return ENOSYS;
1449
1450 (void)memset(t, '\0', sizeof(t));
1451
1452 (void)snprintf(t, sizeof(t), "%s%s%s%s%s%s",
1453 ((sc->sc_sleepstates & __BIT(0)) != 0) ? "S0 " : "",
1454 ((sc->sc_sleepstates & __BIT(1)) != 0) ? "S1 " : "",
1455 ((sc->sc_sleepstates & __BIT(2)) != 0) ? "S2 " : "",
1456 ((sc->sc_sleepstates & __BIT(3)) != 0) ? "S3 " : "",
1457 ((sc->sc_sleepstates & __BIT(4)) != 0) ? "S4 " : "",
1458 ((sc->sc_sleepstates & __BIT(5)) != 0) ? "S5 " : "");
1459
1460 node = *rnode;
1461 node.sysctl_data = &t;
1462
1463 err = sysctl_lookup(SYSCTLFN_CALL(&node));
1464
1465 if (err || newp == NULL)
1466 return err;
1467
1468 return 0;
1469 }
1470
1471 /*
1472 * Miscellaneous.
1473 */
1474 ACPI_PHYSICAL_ADDRESS
1475 acpi_OsGetRootPointer(void)
1476 {
1477 ACPI_PHYSICAL_ADDRESS PhysicalAddress;
1478
1479 /*
1480 * We let MD code handle this since there are multiple ways to do it:
1481 *
1482 * IA-32: Use AcpiFindRootPointer() to locate the RSDP.
1483 *
1484 * IA-64: Use the EFI.
1485 */
1486 PhysicalAddress = acpi_md_OsGetRootPointer();
1487
1488 if (acpi_root_pointer == 0)
1489 acpi_root_pointer = PhysicalAddress;
1490
1491 return PhysicalAddress;
1492 }
1493
1494 static ACPI_TABLE_HEADER *
1495 acpi_map_rsdt(void)
1496 {
1497 ACPI_PHYSICAL_ADDRESS paddr;
1498 ACPI_TABLE_RSDP *rsdp;
1499
1500 paddr = AcpiOsGetRootPointer();
1501
1502 if (paddr == 0)
1503 return NULL;
1504
1505 rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP));
1506
1507 if (rsdp == NULL)
1508 return NULL;
1509
1510 if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress)
1511 paddr = rsdp->XsdtPhysicalAddress;
1512 else
1513 paddr = rsdp->RsdtPhysicalAddress;
1514
1515 AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP));
1516
1517 return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER));
1518 }
1519
1520 static void
1521 acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt)
1522 {
1523
1524 if (rsdt == NULL)
1525 return;
1526
1527 AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER));
1528 }
1529