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