No empty .Rs/.Re
[netbsd-mini2440.git] / sys / dev / acpi / acpi.c
blob5260b70bcaefcec35e0fe4b2ebf0d93afe3a5ff1
1 /* $NetBSD: acpi.c,v 1.141 2010/01/08 00:09:44 dyoung Exp $ */
3 /*-
4 * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
5 * All rights reserved.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum of By Noon Software, Inc.
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.
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.
33 * Copyright 2001, 2003 Wasabi Systems, Inc.
34 * All rights reserved.
36 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
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.
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.
68 * Autoconfiguration support for the Intel ACPI Component Architecture
69 * ACPI reference implementation.
72 #include <sys/cdefs.h>
73 __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.141 2010/01/08 00:09:44 dyoung Exp $");
75 #include "opt_acpi.h"
76 #include "opt_pcifixup.h"
78 #include <sys/param.h>
79 #include <sys/systm.h>
80 #include <sys/device.h>
81 #include <sys/malloc.h>
82 #include <sys/mutex.h>
83 #include <sys/kernel.h>
84 #include <sys/proc.h>
85 #include <sys/sysctl.h>
87 #include <dev/acpi/acpica.h>
88 #include <dev/acpi/acpireg.h>
89 #include <dev/acpi/acpivar.h>
90 #include <dev/acpi/acpi_osd.h>
91 #include <dev/acpi/acpi_timer.h>
92 #include <dev/acpi/acpi_wakedev.h>
93 #include <dev/acpi/acpi_pci.h>
94 #ifdef ACPIVERBOSE
95 #include <dev/acpi/acpidevs_data.h>
96 #endif
98 #define _COMPONENT ACPI_TOOLS
99 ACPI_MODULE_NAME ("acpi")
101 #if defined(ACPI_PCI_FIXUP)
102 #error The option ACPI_PCI_FIXUP has been obsoleted by PCI_INTR_FIXUP_DISABLED. Please adjust your kernel configuration file.
103 #endif
105 #ifdef PCI_INTR_FIXUP_DISABLED
106 #include <dev/pci/pcidevs.h>
107 #endif
109 MALLOC_DECLARE(M_ACPI);
111 #include <machine/acpi_machdep.h>
113 #ifdef ACPI_DEBUGGER
114 #define ACPI_DBGR_INIT 0x01
115 #define ACPI_DBGR_TABLES 0x02
116 #define ACPI_DBGR_ENABLE 0x04
117 #define ACPI_DBGR_PROBE 0x08
118 #define ACPI_DBGR_RUNNING 0x10
120 static int acpi_dbgr = 0x00;
121 #endif
123 static ACPI_TABLE_DESC acpi_initial_tables[128];
125 static int acpi_match(device_t, cfdata_t, void *);
126 static void acpi_attach(device_t, device_t, void *);
127 static void acpi_childdet(device_t, device_t);
128 static int acpi_detach(device_t, int);
130 static int acpi_rescan(device_t, const char *, const int *);
131 static void acpi_rescan1(struct acpi_softc *, const char *, const int *);
132 static void acpi_rescan_nodes(struct acpi_softc *);
134 static int acpi_print(void *aux, const char *);
136 static int sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS);
138 extern struct cfdriver acpi_cd;
140 CFATTACH_DECL2_NEW(acpi, sizeof(struct acpi_softc),
141 acpi_match, acpi_attach, acpi_detach, NULL, acpi_rescan, acpi_childdet);
144 * This is a flag we set when the ACPI subsystem is active. Machine
145 * dependent code may wish to skip other steps (such as attaching
146 * subsystems that ACPI supercedes) when ACPI is active.
148 int acpi_active;
149 int acpi_force_load;
150 int acpi_suspended = 0;
153 * Pointer to the ACPI subsystem's state. There can be only
154 * one ACPI instance.
156 struct acpi_softc *acpi_softc;
159 * Locking stuff.
161 extern kmutex_t acpi_interrupt_list_mtx;
164 * Ignored HIDs
166 static const char * const acpi_ignored_ids[] = {
167 #if defined(i386) || defined(x86_64)
168 "PNP0000", /* AT interrupt controller is handled internally */
169 "PNP0200", /* AT DMA controller is handled internally */
170 "PNP0A??", /* PCI Busses are handled internally */
171 "PNP0B00", /* AT RTC is handled internally */
172 "PNP0C01", /* No "System Board" driver */
173 "PNP0C02", /* No "PnP motherboard register resources" driver */
174 "PNP0C0F", /* ACPI PCI link devices are handled internally */
175 "INT0800", /* Intel HW RNG is handled internally */
176 #endif
177 #if defined(x86_64)
178 "PNP0C04", /* FPU is handled internally */
179 #endif
180 NULL
184 * sysctl-related information
187 static uint64_t acpi_root_pointer; /* found as hw.acpi.root */
188 static int acpi_sleepstate = ACPI_STATE_S0;
189 static char acpi_supported_states[3 * 6 + 1] = "";
192 * Prototypes.
194 static void acpi_build_tree(struct acpi_softc *);
195 static ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
197 static void acpi_enable_fixed_events(struct acpi_softc *);
199 static ACPI_TABLE_HEADER *acpi_map_rsdt(void);
200 static void acpi_unmap_rsdt(ACPI_TABLE_HEADER *);
201 static int is_available_state(struct acpi_softc *, int);
203 static bool acpi_suspend(device_t, pmf_qual_t);
204 static bool acpi_resume(device_t, pmf_qual_t);
207 * acpi_probe:
209 * Probe for ACPI support. This is called by the
210 * machine-dependent ACPI front-end. All of the
211 * actual work is done by ACPICA.
213 * NOTE: This is not an autoconfiguration interface function.
216 acpi_probe(void)
218 static int beenhere;
219 ACPI_TABLE_HEADER *rsdt;
220 ACPI_STATUS rv;
222 if (beenhere != 0)
223 panic("acpi_probe: ACPI has already been probed");
224 beenhere = 1;
226 mutex_init(&acpi_interrupt_list_mtx, MUTEX_DEFAULT, IPL_NONE);
229 * Start up ACPICA.
231 #ifdef ACPI_DEBUGGER
232 if (acpi_dbgr & ACPI_DBGR_INIT)
233 acpi_osd_debugger();
234 #endif
236 AcpiGbl_AllMethodsSerialized = FALSE;
237 AcpiGbl_EnableInterpreterSlack = TRUE;
239 rv = AcpiInitializeSubsystem();
240 if (ACPI_FAILURE(rv)) {
241 printf("ACPI: unable to initialize ACPICA: %s\n",
242 AcpiFormatException(rv));
243 return 0;
246 rv = AcpiInitializeTables(acpi_initial_tables, 128, 0);
247 if (ACPI_FAILURE(rv)) {
248 #ifdef ACPI_DEBUG
249 printf("ACPI: unable to initialize ACPI tables: %s\n",
250 AcpiFormatException(rv));
251 #endif
252 AcpiTerminate();
253 return 0;
256 rv = AcpiReallocateRootTable();
257 if (ACPI_FAILURE(rv)) {
258 printf("ACPI: unable to reallocate root table: %s\n",
259 AcpiFormatException(rv));
260 AcpiTerminate();
261 return 0;
264 #ifdef ACPI_DEBUGGER
265 if (acpi_dbgr & ACPI_DBGR_TABLES)
266 acpi_osd_debugger();
267 #endif
269 rv = AcpiLoadTables();
270 if (ACPI_FAILURE(rv)) {
271 printf("ACPI: unable to load tables: %s\n",
272 AcpiFormatException(rv));
273 AcpiTerminate();
274 return 0;
277 rsdt = acpi_map_rsdt();
278 if (rsdt == NULL) {
279 printf("ACPI: unable to map RSDT\n");
280 AcpiTerminate();
281 return 0;
284 if (!acpi_force_load && (acpi_find_quirks() & ACPI_QUIRK_BROKEN)) {
285 printf("ACPI: BIOS implementation in listed as broken:\n");
286 printf("ACPI: X/RSDT: OemId <%6.6s,%8.8s,%08x>, "
287 "AslId <%4.4s,%08x>\n",
288 rsdt->OemId, rsdt->OemTableId,
289 rsdt->OemRevision,
290 rsdt->AslCompilerId,
291 rsdt->AslCompilerRevision);
292 printf("ACPI: not used. set acpi_force_load to use anyway.\n");
293 acpi_unmap_rsdt(rsdt);
294 AcpiTerminate();
295 return 0;
298 acpi_unmap_rsdt(rsdt);
300 #if notyet
301 /* Install the default address space handlers. */
302 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
303 ACPI_ADR_SPACE_SYSTEM_MEMORY, ACPI_DEFAULT_HANDLER, NULL, NULL);
304 if (ACPI_FAILURE(rv)) {
305 printf("ACPI: unable to initialize SystemMemory handler: %s\n",
306 AcpiFormatException(rv));
307 AcpiTerminate();
308 return 0;
310 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
311 ACPI_ADR_SPACE_SYSTEM_IO, ACPI_DEFAULT_HANDLER, NULL, NULL);
312 if (ACPI_FAILURE(rv)) {
313 printf("ACPI: unable to initialize SystemIO handler: %s\n",
314 AcpiFormatException(rv));
315 AcpiTerminate();
316 return 0;
318 rv = AcpiInstallAddressSpaceHandler(ACPI_ROOT_OBJECT,
319 ACPI_ADR_SPACE_PCI_CONFIG, ACPI_DEFAULT_HANDLER, NULL, NULL);
320 if (ACPI_FAILURE(rv)) {
321 printf("ACPI: unable to initialize PciConfig handler: %s\n",
322 AcpiFormatException(rv));
323 AcpiTerminate();
324 return 0;
326 #endif
328 rv = AcpiEnableSubsystem(~(ACPI_NO_HARDWARE_INIT|ACPI_NO_ACPI_ENABLE));
329 if (ACPI_FAILURE(rv)) {
330 printf("ACPI: unable to enable: %s\n", AcpiFormatException(rv));
331 AcpiTerminate();
332 return 0;
336 * Looks like we have ACPI!
339 return 1;
342 static int
343 acpi_submatch(device_t parent, cfdata_t cf, const int *locs, void *aux)
345 struct cfattach *ca;
347 ca = config_cfattach_lookup(cf->cf_name, cf->cf_atname);
348 return (ca == &acpi_ca);
352 acpi_check(device_t parent, const char *ifattr)
354 return (config_search_ia(acpi_submatch, parent, ifattr, NULL) != NULL);
357 ACPI_PHYSICAL_ADDRESS
358 acpi_OsGetRootPointer(void)
360 ACPI_PHYSICAL_ADDRESS PhysicalAddress;
363 * IA-32: Use AcpiFindRootPointer() to locate the RSDP.
365 * IA-64: Use the EFI.
367 * We let MD code handle this since there are multiple
368 * ways to do it.
371 PhysicalAddress = acpi_md_OsGetRootPointer();
373 if (acpi_root_pointer == 0)
374 acpi_root_pointer = PhysicalAddress;
376 return PhysicalAddress;
380 * acpi_match:
382 * Autoconfiguration `match' routine.
384 static int
385 acpi_match(device_t parent, cfdata_t match, void *aux)
388 * XXX Check other locators? Hard to know -- machine
389 * dependent code has already checked for the presence
390 * of ACPI by calling acpi_probe(), so I suppose we
391 * don't really have to do anything else.
393 return 1;
396 /* Remove references to child devices.
398 * XXX Need to reclaim any resources?
400 static void
401 acpi_childdet(device_t self, device_t child)
403 struct acpi_softc *sc = device_private(self);
404 struct acpi_scope *as;
405 struct acpi_devnode *ad;
407 if (sc->sc_apmbus == child)
408 sc->sc_apmbus = NULL;
410 TAILQ_FOREACH(as, &sc->sc_scopes, as_list) {
411 TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
412 if (ad->ad_device == child)
413 ad->ad_device = NULL;
419 * acpi_attach:
421 * Autoconfiguration `attach' routine. Finish initializing
422 * ACPICA (some initialization was done in acpi_probe(),
423 * which was required to check for the presence of ACPI),
424 * and enable the ACPI subsystem.
426 static void
427 acpi_attach(device_t parent, device_t self, void *aux)
429 struct acpi_softc *sc = device_private(self);
430 struct acpibus_attach_args *aa = aux;
431 ACPI_STATUS rv;
432 ACPI_TABLE_HEADER *rsdt;
434 aprint_naive("\n");
435 aprint_normal(": Intel ACPICA %08x\n", ACPI_CA_VERSION);
437 if (acpi_softc != NULL)
438 panic("acpi_attach: ACPI has already been attached");
440 sysmon_power_settype("acpi");
442 rsdt = acpi_map_rsdt();
443 if (rsdt) {
444 aprint_verbose_dev(
445 self,
446 "X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
447 rsdt->OemId, rsdt->OemTableId,
448 rsdt->OemRevision,
449 rsdt->AslCompilerId, rsdt->AslCompilerRevision);
450 } else
451 aprint_error_dev(self, "X/RSDT: Not found\n");
452 acpi_unmap_rsdt(rsdt);
454 sc->sc_dev = self;
455 sc->sc_quirks = acpi_find_quirks();
457 sc->sc_iot = aa->aa_iot;
458 sc->sc_memt = aa->aa_memt;
459 sc->sc_pc = aa->aa_pc;
460 sc->sc_pciflags = aa->aa_pciflags;
461 sc->sc_ic = aa->aa_ic;
463 acpi_softc = sc;
466 * Register null power management handler
468 if (!pmf_device_register(self, acpi_suspend, acpi_resume))
469 aprint_error_dev(self, "couldn't establish power handler\n");
472 * Bring ACPI on-line.
474 #ifdef ACPI_DEBUGGER
475 if (acpi_dbgr & ACPI_DBGR_ENABLE)
476 acpi_osd_debugger();
477 #endif
479 #define ACPI_ENABLE_PHASE1 \
480 (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
481 #define ACPI_ENABLE_PHASE2 \
482 (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
483 ACPI_NO_ADDRESS_SPACE_INIT)
485 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
486 if (ACPI_FAILURE(rv)) {
487 aprint_error_dev(self, "unable to enable ACPI: %s\n",
488 AcpiFormatException(rv));
489 return;
492 acpi_md_callback();
494 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
495 if (ACPI_FAILURE(rv)) {
496 aprint_error_dev(self, "unable to enable ACPI: %s\n",
497 AcpiFormatException(rv));
498 return;
501 /* early EC handler initialization if ECDT table is available */
502 config_found_ia(self, "acpiecdtbus", NULL, NULL);
504 rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
505 if (ACPI_FAILURE(rv)) {
506 aprint_error_dev(self,
507 "unable to initialize ACPI objects: %s\n",
508 AcpiFormatException(rv));
509 return;
511 acpi_active = 1;
513 /* Our current state is "awake". */
514 sc->sc_sleepstate = ACPI_STATE_S0;
516 /* Show SCI interrupt. */
517 aprint_verbose_dev(self, "SCI interrupting at int %d\n",
518 AcpiGbl_FADT.SciInterrupt);
521 * Check for fixed-hardware features.
523 acpi_enable_fixed_events(sc);
524 acpitimer_init();
527 * Scan the namespace and build our device tree.
529 #ifdef ACPI_DEBUGGER
530 if (acpi_dbgr & ACPI_DBGR_PROBE)
531 acpi_osd_debugger();
532 #endif
533 acpi_build_tree(sc);
535 snprintf(acpi_supported_states, sizeof(acpi_supported_states),
536 "%s%s%s%s%s%s",
537 is_available_state(sc, ACPI_STATE_S0) ? "S0 " : "",
538 is_available_state(sc, ACPI_STATE_S1) ? "S1 " : "",
539 is_available_state(sc, ACPI_STATE_S2) ? "S2 " : "",
540 is_available_state(sc, ACPI_STATE_S3) ? "S3 " : "",
541 is_available_state(sc, ACPI_STATE_S4) ? "S4 " : "",
542 is_available_state(sc, ACPI_STATE_S5) ? "S5 " : "");
544 #ifdef ACPI_DEBUGGER
545 if (acpi_dbgr & ACPI_DBGR_RUNNING)
546 acpi_osd_debugger();
547 #endif
550 static int
551 acpi_detach(device_t self, int flags)
553 int rc;
555 #ifdef ACPI_DEBUGGER
556 if (acpi_dbgr & ACPI_DBGR_RUNNING)
557 acpi_osd_debugger();
558 #endif
560 if ((rc = config_detach_children(self, flags)) != 0)
561 return rc;
563 #ifdef ACPI_DEBUGGER
564 if (acpi_dbgr & ACPI_DBGR_PROBE)
565 acpi_osd_debugger();
566 #endif
568 if ((rc = acpitimer_detach()) != 0)
569 return rc;
571 #if 0
573 * Bring ACPI on-line.
575 #ifdef ACPI_DEBUGGER
576 if (acpi_dbgr & ACPI_DBGR_ENABLE)
577 acpi_osd_debugger();
578 #endif
580 #define ACPI_ENABLE_PHASE1 \
581 (ACPI_NO_HANDLER_INIT | ACPI_NO_EVENT_INIT)
582 #define ACPI_ENABLE_PHASE2 \
583 (ACPI_NO_HARDWARE_INIT | ACPI_NO_ACPI_ENABLE | \
584 ACPI_NO_ADDRESS_SPACE_INIT)
586 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE1);
587 if (ACPI_FAILURE(rv)) {
588 aprint_error_dev(self, "unable to enable ACPI: %s\n",
589 AcpiFormatException(rv));
590 return;
593 rv = AcpiEnableSubsystem(ACPI_ENABLE_PHASE2);
594 if (ACPI_FAILURE(rv)) {
595 aprint_error_dev(self, "unable to enable ACPI: %s\n",
596 AcpiFormatException(rv));
597 return;
600 /* early EC handler initialization if ECDT table is available */
601 config_found_ia(self, "acpiecdtbus", NULL, NULL);
603 rv = AcpiInitializeObjects(ACPI_FULL_INITIALIZATION);
604 if (ACPI_FAILURE(rv)) {
605 aprint_error_dev(self,
606 "unable to initialize ACPI objects: %s\n",
607 AcpiFormatException(rv));
608 return;
610 acpi_active = 1;
612 acpi_enable_fixed_events(sc);
613 #endif
615 pmf_device_deregister(self);
617 #if 0
618 sysmon_power_settype("acpi");
619 #endif
620 acpi_softc = NULL;
622 return 0;
625 static bool
626 acpi_suspend(device_t dv, pmf_qual_t qual)
628 acpi_suspended = 1;
629 return true;
632 static bool
633 acpi_resume(device_t dv, pmf_qual_t qual)
635 acpi_suspended = 0;
636 return true;
639 #if 0
641 * acpi_disable:
643 * Disable ACPI.
645 static ACPI_STATUS
646 acpi_disable(struct acpi_softc *sc)
648 ACPI_STATUS rv = AE_OK;
650 if (acpi_active) {
651 rv = AcpiDisable();
652 if (ACPI_SUCCESS(rv))
653 acpi_active = 0;
655 return rv;
657 #endif
659 struct acpi_make_devnode_state {
660 struct acpi_softc *softc;
661 struct acpi_scope *scope;
665 * acpi_build_tree:
667 * Scan relevant portions of the ACPI namespace and attach
668 * child devices.
670 static void
671 acpi_build_tree(struct acpi_softc *sc)
673 static const char *scopes[] = {
674 "\\_PR_", /* ACPI 1.0 processor namespace */
675 "\\_SB_", /* system bus namespace */
676 "\\_SI_", /* system indicator namespace */
677 "\\_TZ_", /* ACPI 1.0 thermal zone namespace */
678 NULL,
680 struct acpi_make_devnode_state state;
681 struct acpi_scope *as;
682 ACPI_HANDLE parent;
683 ACPI_STATUS rv;
684 int i;
686 TAILQ_INIT(&sc->sc_scopes);
688 state.softc = sc;
691 * Scan the namespace and build our tree.
693 for (i = 0; scopes[i] != NULL; i++) {
694 as = malloc(sizeof(*as), M_ACPI, M_WAITOK);
695 as->as_name = scopes[i];
696 TAILQ_INIT(&as->as_devnodes);
698 TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
700 state.scope = as;
702 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i],
703 &parent);
704 if (ACPI_SUCCESS(rv)) {
705 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
706 acpi_make_devnode, &state, NULL);
710 acpi_rescan1(sc, NULL, NULL);
712 acpi_wakedev_scan(sc);
714 acpi_pcidev_scan(sc);
717 static int
718 acpi_rescan(device_t self, const char *ifattr, const int *locators)
720 struct acpi_softc *sc = device_private(self);
722 acpi_rescan1(sc, ifattr, locators);
723 return 0;
726 static void
727 acpi_rescan1(struct acpi_softc *sc, const char *ifattr, const int *locators)
729 if (ifattr_match(ifattr, "acpinodebus"))
730 acpi_rescan_nodes(sc);
732 if (ifattr_match(ifattr, "acpiapmbus") && sc->sc_apmbus == NULL) {
733 sc->sc_apmbus = config_found_ia(sc->sc_dev, "acpiapmbus", NULL,
734 NULL);
738 static void
739 acpi_rescan_nodes(struct acpi_softc *sc)
741 struct acpi_scope *as;
743 TAILQ_FOREACH(as, &sc->sc_scopes, as_list) {
744 struct acpi_devnode *ad;
746 /* Now, for this namespace, try to attach the devices. */
747 TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
748 struct acpi_attach_args aa;
750 if (ad->ad_device != NULL)
751 continue;
753 aa.aa_node = ad;
754 aa.aa_iot = sc->sc_iot;
755 aa.aa_memt = sc->sc_memt;
756 aa.aa_pc = sc->sc_pc;
757 aa.aa_pciflags = sc->sc_pciflags;
758 aa.aa_ic = sc->sc_ic;
760 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) {
762 * XXX We only attach devices which are:
764 * - present
765 * - enabled
766 * - functioning properly
768 * However, if enabled, it's decoding resources,
769 * so we should claim them, if possible.
770 * Requires changes to bus_space(9).
772 if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) ==
773 ACPI_VALID_STA &&
774 (ad->ad_devinfo->CurrentStatus &
775 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
776 ACPI_STA_DEV_OK)) !=
777 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
778 ACPI_STA_DEV_OK))
779 continue;
783 * XXX Same problem as above...
785 * Do this check only for devices, as e.g.
786 * a Thermal Zone doesn't have a HID.
788 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE &&
789 (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
790 continue;
793 * Handled internally
795 if (ad->ad_devinfo->Type == ACPI_TYPE_PROCESSOR ||
796 ad->ad_devinfo->Type == ACPI_TYPE_POWER)
797 continue;
800 * Skip ignored HIDs
802 if (acpi_match_hid(ad->ad_devinfo, acpi_ignored_ids))
803 continue;
805 ad->ad_device = config_found_ia(sc->sc_dev,
806 "acpinodebus", &aa, acpi_print);
811 #ifdef ACPI_ACTIVATE_DEV
812 static void
813 acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
815 ACPI_STATUS rv;
816 ACPI_DEVICE_INFO *newdi;
818 #ifdef ACPI_DEBUG
819 aprint_normal("acpi_activate_device: %s, old status=%x\n",
820 (*di)->HardwareId.Value, (*di)->CurrentStatus);
821 #endif
823 rv = acpi_allocate_resources(handle);
824 if (ACPI_FAILURE(rv)) {
825 aprint_error("acpi: activate failed for %s\n",
826 (*di)->HardwareId.String);
827 } else {
828 aprint_verbose("acpi: activated %s\n",
829 (*di)->HardwareId.String);
832 (void)AcpiGetObjectInfo(handle, &newdi);
833 ACPI_FREE(*di);
834 *di = newdi;
836 #ifdef ACPI_DEBUG
837 aprint_normal("acpi_activate_device: %s, new status=%x\n",
838 (*di)->HardwareId.Value, (*di)->CurrentStatus);
839 #endif
841 #endif /* ACPI_ACTIVATE_DEV */
844 * acpi_make_devnode:
846 * Make an ACPI devnode.
848 static ACPI_STATUS
849 acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
850 void **status)
852 struct acpi_make_devnode_state *state = context;
853 #if defined(ACPI_DEBUG) || defined(ACPI_EXTRA_DEBUG)
854 struct acpi_softc *sc = state->softc;
855 #endif
856 struct acpi_scope *as = state->scope;
857 struct acpi_devnode *ad;
858 ACPI_OBJECT_TYPE type;
859 ACPI_DEVICE_INFO *devinfo;
860 ACPI_STATUS rv;
861 ACPI_NAME_UNION *anu;
862 int i, clear = 0;
864 rv = AcpiGetType(handle, &type);
865 if (ACPI_SUCCESS(rv)) {
866 rv = AcpiGetObjectInfo(handle, &devinfo);
867 if (ACPI_FAILURE(rv)) {
868 #ifdef ACPI_DEBUG
869 aprint_normal_dev(sc->sc_dev,
870 "AcpiGetObjectInfo failed: %s\n",
871 AcpiFormatException(rv));
872 #endif
873 goto out; /* XXX why return OK */
876 switch (type) {
877 case ACPI_TYPE_DEVICE:
878 #ifdef ACPI_ACTIVATE_DEV
879 if ((devinfo->Valid & (ACPI_VALID_STA|ACPI_VALID_HID)) ==
880 (ACPI_VALID_STA|ACPI_VALID_HID) &&
881 (devinfo->CurrentStatus &
882 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) ==
883 ACPI_STA_DEV_PRESENT)
884 acpi_activate_device(handle, &devinfo);
886 /* FALLTHROUGH */
887 #endif
889 case ACPI_TYPE_PROCESSOR:
890 case ACPI_TYPE_THERMAL:
891 case ACPI_TYPE_POWER:
892 ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT|M_ZERO);
893 if (ad == NULL)
894 return AE_NO_MEMORY;
896 ad->ad_devinfo = devinfo;
897 ad->ad_handle = handle;
898 ad->ad_level = level;
899 ad->ad_scope = as;
900 ad->ad_type = type;
902 anu = (ACPI_NAME_UNION *)&devinfo->Name;
903 ad->ad_name[4] = '\0';
904 for (i = 3, clear = 0; i >= 0; i--) {
905 if (!clear && anu->Ascii[i] == '_')
906 ad->ad_name[i] = '\0';
907 else {
908 ad->ad_name[i] = anu->Ascii[i];
909 clear = 1;
912 if (ad->ad_name[0] == '\0')
913 ad->ad_name[0] = '_';
915 TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
917 if (type == ACPI_TYPE_DEVICE &&
918 (ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
919 goto out;
921 #ifdef ACPI_EXTRA_DEBUG
922 aprint_normal_dev(sc->sc_dev,
923 "HID %s found in scope %s level %d\n",
924 ad->ad_devinfo->HardwareId.String,
925 as->as_name, ad->ad_level);
926 if (ad->ad_devinfo->Valid & ACPI_VALID_UID)
927 aprint_normal(" UID %s\n",
928 ad->ad_devinfo->UniqueId.String);
929 if (ad->ad_devinfo->Valid & ACPI_VALID_ADR)
930 aprint_normal(" ADR 0x%016" PRIx64 "\n",
931 ad->ad_devinfo->Address);
932 if (ad->ad_devinfo->Valid & ACPI_VALID_STA)
933 aprint_normal(" STA 0x%08x\n",
934 ad->ad_devinfo->CurrentStatus);
935 #endif
938 out:
939 return AE_OK;
943 * acpi_print:
945 * Autoconfiguration print routine for ACPI node bus.
947 static int
948 acpi_print(void *aux, const char *pnp)
950 struct acpi_attach_args *aa = aux;
951 ACPI_STATUS rv;
953 if (pnp) {
954 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
955 char *pnpstr =
956 aa->aa_node->ad_devinfo->HardwareId.String;
957 ACPI_BUFFER buf;
959 aprint_normal("%s (%s) ", aa->aa_node->ad_name,
960 pnpstr);
962 rv = acpi_eval_struct(aa->aa_node->ad_handle,
963 "_STR", &buf);
964 if (ACPI_SUCCESS(rv)) {
965 ACPI_OBJECT *obj = buf.Pointer;
966 switch (obj->Type) {
967 case ACPI_TYPE_STRING:
968 aprint_normal("[%s] ", obj->String.Pointer);
969 break;
970 case ACPI_TYPE_BUFFER:
971 aprint_normal("buffer %p ", obj->Buffer.Pointer);
972 break;
973 default:
974 aprint_normal("type %d ",obj->Type);
975 break;
977 ACPI_FREE(buf.Pointer);
979 #ifdef ACPIVERBOSE
980 else {
981 int i;
983 for (i = 0; i < __arraycount(acpi_knowndevs);
984 i++) {
985 if (strcmp(acpi_knowndevs[i].pnp,
986 pnpstr) == 0) {
987 aprint_normal("[%s] ",
988 acpi_knowndevs[i].str);
993 #endif
994 aprint_normal("at %s", pnp);
995 } else if (aa->aa_node->ad_devinfo->Type != ACPI_TYPE_DEVICE) {
996 aprint_normal("%s (ACPI Object Type '%s' "
997 "[0x%02x]) ", aa->aa_node->ad_name,
998 AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
999 aa->aa_node->ad_devinfo->Type);
1000 aprint_normal("at %s", pnp);
1001 } else
1002 return 0;
1003 } else {
1004 aprint_normal(" (%s", aa->aa_node->ad_name);
1005 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
1006 aprint_normal(", %s", aa->aa_node->ad_devinfo->HardwareId.String);
1007 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
1008 const char *uid;
1010 uid = aa->aa_node->ad_devinfo->UniqueId.String;
1011 if (uid[0] == '\0')
1012 uid = "<null>";
1013 aprint_normal("-%s", uid);
1016 aprint_normal(")");
1019 return UNCONF;
1022 /*****************************************************************************
1023 * ACPI fixed-hardware feature handlers
1024 *****************************************************************************/
1026 static UINT32 acpi_fixed_button_handler(void *);
1027 static void acpi_fixed_button_pressed(void *);
1030 * acpi_enable_fixed_events:
1032 * Enable any fixed-hardware feature handlers.
1034 static void
1035 acpi_enable_fixed_events(struct acpi_softc *sc)
1037 static int beenhere;
1038 ACPI_STATUS rv;
1040 KASSERT(beenhere == 0);
1041 beenhere = 1;
1044 * Check for fixed-hardware buttons.
1047 if ((AcpiGbl_FADT.Flags & ACPI_FADT_POWER_BUTTON) == 0) {
1048 aprint_verbose_dev(sc->sc_dev,
1049 "fixed-feature power button present\n");
1050 sc->sc_smpsw_power.smpsw_name = device_xname(sc->sc_dev);
1051 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER;
1052 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
1053 aprint_error_dev(sc->sc_dev,
1054 "unable to register fixed power "
1055 "button with sysmon\n");
1056 } else {
1057 rv = AcpiInstallFixedEventHandler(
1058 ACPI_EVENT_POWER_BUTTON,
1059 acpi_fixed_button_handler, &sc->sc_smpsw_power);
1060 if (ACPI_FAILURE(rv)) {
1061 aprint_error_dev(sc->sc_dev,
1062 "unable to install handler "
1063 "for fixed power button: %s\n",
1064 AcpiFormatException(rv));
1069 if ((AcpiGbl_FADT.Flags & ACPI_FADT_SLEEP_BUTTON) == 0) {
1070 aprint_verbose_dev(sc->sc_dev,
1071 "fixed-feature sleep button present\n");
1072 sc->sc_smpsw_sleep.smpsw_name = device_xname(sc->sc_dev);
1073 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP;
1074 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
1075 aprint_error_dev(sc->sc_dev,
1076 "unable to register fixed sleep "
1077 "button with sysmon\n");
1078 } else {
1079 rv = AcpiInstallFixedEventHandler(
1080 ACPI_EVENT_SLEEP_BUTTON,
1081 acpi_fixed_button_handler, &sc->sc_smpsw_sleep);
1082 if (ACPI_FAILURE(rv)) {
1083 aprint_error_dev(sc->sc_dev,
1084 "unable to install handler "
1085 "for fixed sleep button: %s\n",
1086 AcpiFormatException(rv));
1093 * acpi_fixed_button_handler:
1095 * Event handler for the fixed buttons.
1097 static UINT32
1098 acpi_fixed_button_handler(void *context)
1100 struct sysmon_pswitch *smpsw = context;
1101 ACPI_STATUS rv;
1103 #ifdef ACPI_BUT_DEBUG
1104 printf("%s: fixed button handler\n", smpsw->smpsw_name);
1105 #endif
1107 rv = AcpiOsExecute(OSL_NOTIFY_HANDLER,
1108 acpi_fixed_button_pressed, smpsw);
1109 if (ACPI_FAILURE(rv))
1110 printf("%s: WARNING: unable to queue fixed button pressed "
1111 "callback: %s\n", smpsw->smpsw_name,
1112 AcpiFormatException(rv));
1114 return ACPI_INTERRUPT_HANDLED;
1118 * acpi_fixed_button_pressed:
1120 * Deal with a fixed button being pressed.
1122 static void
1123 acpi_fixed_button_pressed(void *context)
1125 struct sysmon_pswitch *smpsw = context;
1127 #ifdef ACPI_BUT_DEBUG
1128 printf("%s: fixed button pressed, calling sysmon\n",
1129 smpsw->smpsw_name);
1130 #endif
1132 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
1135 /*****************************************************************************
1136 * ACPI utility routines.
1137 *****************************************************************************/
1140 * acpi_eval_integer:
1142 * Evaluate an integer object.
1144 ACPI_STATUS
1145 acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp)
1147 ACPI_STATUS rv;
1148 ACPI_BUFFER buf;
1149 ACPI_OBJECT param;
1151 if (handle == NULL)
1152 handle = ACPI_ROOT_OBJECT;
1154 buf.Pointer = &param;
1155 buf.Length = sizeof(param);
1157 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf,
1158 ACPI_TYPE_INTEGER);
1159 if (ACPI_SUCCESS(rv))
1160 *valp = param.Integer.Value;
1162 return rv;
1165 ACPI_STATUS
1166 acpi_eval_set_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER arg)
1168 ACPI_OBJECT param_arg;
1169 ACPI_OBJECT_LIST param_args;
1171 if (handle == NULL)
1172 handle = ACPI_ROOT_OBJECT;
1174 param_arg.Type = ACPI_TYPE_INTEGER;
1175 param_arg.Integer.Value = arg;
1177 param_args.Count = 1;
1178 param_args.Pointer = &param_arg;
1180 return AcpiEvaluateObject(handle, path, &param_args, NULL);
1184 * acpi_eval_string:
1186 * Evaluate a (Unicode) string object.
1188 ACPI_STATUS
1189 acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp)
1191 ACPI_STATUS rv;
1192 ACPI_BUFFER buf;
1194 if (handle == NULL)
1195 handle = ACPI_ROOT_OBJECT;
1197 buf.Pointer = NULL;
1198 buf.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1200 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_STRING);
1201 if (ACPI_SUCCESS(rv)) {
1202 ACPI_OBJECT *param = buf.Pointer;
1203 const char *ptr = param->String.Pointer;
1204 size_t len = param->String.Length;
1205 if ((*stringp = ACPI_ALLOCATE(len)) == NULL)
1206 rv = AE_NO_MEMORY;
1207 else
1208 (void)memcpy(*stringp, ptr, len);
1209 ACPI_FREE(param);
1212 return rv;
1217 * acpi_eval_struct:
1219 * Evaluate a more complex structure.
1220 * Caller must free buf.Pointer by ACPI_FREE().
1222 ACPI_STATUS
1223 acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp)
1225 ACPI_STATUS rv;
1227 if (handle == NULL)
1228 handle = ACPI_ROOT_OBJECT;
1230 bufp->Pointer = NULL;
1231 bufp->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1233 rv = AcpiEvaluateObject(handle, path, NULL, bufp);
1235 return rv;
1239 * acpi_foreach_package_object:
1241 * Iterate over all objects in a in a packages and pass then all
1242 * to a function. If the called function returns non AE_OK, the
1243 * iteration is stopped and that value is returned.
1246 ACPI_STATUS
1247 acpi_foreach_package_object(ACPI_OBJECT *pkg,
1248 ACPI_STATUS (*func)(ACPI_OBJECT *, void *),
1249 void *arg)
1251 ACPI_STATUS rv = AE_OK;
1252 int i;
1254 if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE)
1255 return AE_BAD_PARAMETER;
1257 for (i = 0; i < pkg->Package.Count; i++) {
1258 rv = (*func)(&pkg->Package.Elements[i], arg);
1259 if (ACPI_FAILURE(rv))
1260 break;
1263 return rv;
1266 const char *
1267 acpi_name(ACPI_HANDLE handle)
1269 static char buffer[80];
1270 ACPI_BUFFER buf;
1271 ACPI_STATUS rv;
1273 buf.Length = sizeof(buffer);
1274 buf.Pointer = buffer;
1276 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
1277 if (ACPI_FAILURE(rv))
1278 return "(unknown acpi path)";
1279 return buffer;
1283 * acpi_get:
1285 * Fetch data info the specified (empty) ACPI buffer.
1286 * Caller must free buf.Pointer by ACPI_FREE().
1288 ACPI_STATUS
1289 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
1290 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
1292 buf->Pointer = NULL;
1293 buf->Length = ACPI_ALLOCATE_LOCAL_BUFFER;
1295 return (*getit)(handle, buf);
1300 * acpi_match_hid
1302 * Match given ids against _HID and _CIDs
1305 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
1307 int i;
1309 while (*ids) {
1310 if (ad->Valid & ACPI_VALID_HID) {
1311 if (pmatch(ad->HardwareId.String, *ids, NULL) == 2)
1312 return 1;
1315 if (ad->Valid & ACPI_VALID_CID) {
1316 for (i = 0; i < ad->CompatibleIdList.Count; i++) {
1317 if (pmatch(ad->CompatibleIdList.Ids[i].String, *ids, NULL) == 2)
1318 return 1;
1321 ids++;
1324 return 0;
1328 * acpi_wake_gpe_helper
1330 * Set/unset GPE as both Runtime and Wake
1332 static void
1333 acpi_wake_gpe_helper(ACPI_HANDLE handle, bool enable)
1335 ACPI_BUFFER buf;
1336 ACPI_STATUS rv;
1337 ACPI_OBJECT *p, *elt;
1339 rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf);
1340 if (ACPI_FAILURE(rv))
1341 return; /* just ignore */
1343 p = buf.Pointer;
1344 if (p->Type != ACPI_TYPE_PACKAGE || p->Package.Count < 2)
1345 goto out; /* just ignore */
1347 elt = p->Package.Elements;
1349 /* TBD: package support */
1350 if (enable) {
1351 AcpiSetGpeType(NULL, elt[0].Integer.Value,
1352 ACPI_GPE_TYPE_WAKE_RUN);
1353 AcpiEnableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR);
1354 } else
1355 AcpiDisableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR);
1357 out:
1358 ACPI_FREE(buf.Pointer);
1362 * acpi_clear_wake_gpe
1364 * Clear GPE as both Runtime and Wake
1366 void
1367 acpi_clear_wake_gpe(ACPI_HANDLE handle)
1369 acpi_wake_gpe_helper(handle, false);
1373 * acpi_set_wake_gpe
1375 * Set GPE as both Runtime and Wake
1377 void
1378 acpi_set_wake_gpe(ACPI_HANDLE handle)
1380 acpi_wake_gpe_helper(handle, true);
1384 /*****************************************************************************
1385 * ACPI sleep support.
1386 *****************************************************************************/
1388 static int
1389 is_available_state(struct acpi_softc *sc, int state)
1391 UINT8 type_a, type_b;
1393 return ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
1394 &type_a, &type_b));
1398 * acpi_enter_sleep_state:
1400 * enter to the specified sleep state.
1403 ACPI_STATUS
1404 acpi_enter_sleep_state(struct acpi_softc *sc, int state)
1406 int err;
1407 ACPI_STATUS ret = AE_OK;
1409 if (state == acpi_sleepstate)
1410 return AE_OK;
1412 aprint_normal_dev(sc->sc_dev, "entering state %d\n", state);
1414 switch (state) {
1415 case ACPI_STATE_S0:
1416 break;
1417 case ACPI_STATE_S1:
1418 case ACPI_STATE_S2:
1419 case ACPI_STATE_S3:
1420 case ACPI_STATE_S4:
1421 if (!is_available_state(sc, state)) {
1422 aprint_error_dev(sc->sc_dev,
1423 "ACPI S%d not available on this platform\n", state);
1424 break;
1427 acpi_wakedev_commit(sc);
1429 if (state != ACPI_STATE_S1 && !pmf_system_suspend(PMF_Q_NONE)) {
1430 aprint_error_dev(sc->sc_dev, "aborting suspend\n");
1431 break;
1434 ret = AcpiEnterSleepStatePrep(state);
1435 if (ACPI_FAILURE(ret)) {
1436 aprint_error_dev(sc->sc_dev,
1437 "failed preparing to sleep (%s)\n",
1438 AcpiFormatException(ret));
1439 break;
1442 acpi_sleepstate = state;
1443 if (state == ACPI_STATE_S1) {
1444 /* just enter the state */
1445 acpi_md_OsDisableInterrupt();
1446 ret = AcpiEnterSleepState((UINT8)state);
1447 if (ACPI_FAILURE(ret))
1448 aprint_error_dev(sc->sc_dev,
1449 "failed to enter sleep state S1: %s\n",
1450 AcpiFormatException(ret));
1451 AcpiLeaveSleepState((UINT8)state);
1452 } else {
1453 err = acpi_md_sleep(state);
1454 if (state == ACPI_STATE_S4)
1455 AcpiEnable();
1456 pmf_system_bus_resume(PMF_Q_NONE);
1457 AcpiLeaveSleepState((UINT8)state);
1458 pmf_system_resume(PMF_Q_NONE);
1461 break;
1462 case ACPI_STATE_S5:
1463 ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
1464 if (ACPI_FAILURE(ret)) {
1465 aprint_error_dev(sc->sc_dev,
1466 "failed preparing to sleep (%s)\n",
1467 AcpiFormatException(ret));
1468 break;
1470 DELAY(1000000);
1471 acpi_sleepstate = state;
1472 acpi_md_OsDisableInterrupt();
1473 AcpiEnterSleepState(ACPI_STATE_S5);
1474 aprint_error_dev(sc->sc_dev, "WARNING powerdown failed!\n");
1475 break;
1478 acpi_sleepstate = ACPI_STATE_S0;
1479 return ret;
1482 #if defined(ACPI_ACTIVATE_DEV)
1483 /* XXX This very incomplete */
1484 ACPI_STATUS
1485 acpi_allocate_resources(ACPI_HANDLE handle)
1487 ACPI_BUFFER bufp, bufc, bufn;
1488 ACPI_RESOURCE *resp, *resc, *resn;
1489 ACPI_RESOURCE_IRQ *irq;
1490 ACPI_RESOURCE_EXTENDED_IRQ *xirq;
1491 ACPI_STATUS rv;
1492 uint delta;
1494 rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
1495 if (ACPI_FAILURE(rv))
1496 goto out;
1497 rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
1498 if (ACPI_FAILURE(rv)) {
1499 goto out1;
1502 bufn.Length = 1000;
1503 bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
1504 resp = bufp.Pointer;
1505 resc = bufc.Pointer;
1506 while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG &&
1507 resp->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1508 while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG)
1509 resp = ACPI_NEXT_RESOURCE(resp);
1510 if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG)
1511 break;
1512 /* Found identical Id */
1513 resn->Type = resc->Type;
1514 switch (resc->Type) {
1515 case ACPI_RESOURCE_TYPE_IRQ:
1516 memcpy(&resn->Data, &resp->Data,
1517 sizeof(ACPI_RESOURCE_IRQ));
1518 irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
1519 irq->Interrupts[0] =
1520 ((ACPI_RESOURCE_IRQ *)&resp->Data)->
1521 Interrupts[irq->InterruptCount-1];
1522 irq->InterruptCount = 1;
1523 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
1524 break;
1525 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
1526 memcpy(&resn->Data, &resp->Data,
1527 sizeof(ACPI_RESOURCE_EXTENDED_IRQ));
1528 xirq = (ACPI_RESOURCE_EXTENDED_IRQ *)&resn->Data;
1529 #if 0
1531 * XXX not duplicating the interrupt logic above
1532 * because its not clear what it accomplishes.
1534 xirq->Interrupts[0] =
1535 ((ACPI_RESOURCE_EXT_IRQ *)&resp->Data)->
1536 Interrupts[irq->NumberOfInterrupts-1];
1537 xirq->NumberOfInterrupts = 1;
1538 #endif
1539 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_EXTENDED_IRQ);
1540 break;
1541 case ACPI_RESOURCE_TYPE_IO:
1542 memcpy(&resn->Data, &resp->Data,
1543 sizeof(ACPI_RESOURCE_IO));
1544 resn->Length = resp->Length;
1545 break;
1546 default:
1547 printf("acpi_allocate_resources: res=%d\n", resc->Type);
1548 rv = AE_BAD_DATA;
1549 goto out2;
1551 resc = ACPI_NEXT_RESOURCE(resc);
1552 resn = ACPI_NEXT_RESOURCE(resn);
1553 resp = ACPI_NEXT_RESOURCE(resp);
1554 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
1555 if (delta >=
1556 bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) {
1557 bufn.Length *= 2;
1558 bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
1559 M_ACPI, M_WAITOK);
1560 resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
1563 if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1564 printf("acpi_allocate_resources: resc not exhausted\n");
1565 rv = AE_BAD_DATA;
1566 goto out3;
1569 resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
1570 rv = AcpiSetCurrentResources(handle, &bufn);
1571 if (ACPI_FAILURE(rv)) {
1572 printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n",
1573 AcpiFormatException(rv));
1576 out3:
1577 free(bufn.Pointer, M_ACPI);
1578 out2:
1579 ACPI_FREE(bufc.Pointer);
1580 out1:
1581 ACPI_FREE(bufp.Pointer);
1582 out:
1583 return rv;
1585 #endif /* ACPI_ACTIVATE_DEV */
1587 SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
1589 const struct sysctlnode *node;
1590 const struct sysctlnode *ssnode;
1592 if (sysctl_createv(clog, 0, NULL, NULL,
1593 CTLFLAG_PERMANENT,
1594 CTLTYPE_NODE, "hw", NULL,
1595 NULL, 0, NULL, 0,
1596 CTL_HW, CTL_EOL) != 0)
1597 return;
1599 if (sysctl_createv(clog, 0, NULL, &node,
1600 CTLFLAG_PERMANENT,
1601 CTLTYPE_NODE, "acpi", NULL,
1602 NULL, 0, NULL, 0,
1603 CTL_HW, CTL_CREATE, CTL_EOL) != 0)
1604 return;
1606 sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY,
1607 CTLTYPE_QUAD, "root",
1608 SYSCTL_DESCR("ACPI root pointer"),
1609 NULL, 0, &acpi_root_pointer, sizeof(acpi_root_pointer),
1610 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
1611 sysctl_createv(NULL, 0, NULL, NULL, CTLFLAG_READONLY,
1612 CTLTYPE_STRING, "supported_states",
1613 SYSCTL_DESCR("Supported ACPI system states"),
1614 NULL, 0, acpi_supported_states, 0,
1615 CTL_HW, node->sysctl_num, CTL_CREATE, CTL_EOL);
1617 /* ACPI sleepstate sysctl */
1618 if (sysctl_createv(NULL, 0, NULL, &node,
1619 CTLFLAG_PERMANENT,
1620 CTLTYPE_NODE, "machdep", NULL,
1621 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL) != 0)
1622 return;
1623 if (sysctl_createv(NULL, 0, &node, &ssnode,
1624 CTLFLAG_READWRITE, CTLTYPE_INT, "sleep_state",
1625 NULL, sysctl_hw_acpi_sleepstate, 0, NULL, 0, CTL_CREATE,
1626 CTL_EOL) != 0)
1627 return;
1630 static int
1631 sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
1633 int error, t;
1634 struct sysctlnode node;
1636 node = *rnode;
1637 t = acpi_sleepstate;
1638 node.sysctl_data = &t;
1639 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1640 if (error || newp == NULL)
1641 return error;
1643 if (acpi_softc == NULL)
1644 return ENOSYS;
1646 acpi_enter_sleep_state(acpi_softc, t);
1648 return 0;
1651 static ACPI_TABLE_HEADER *
1652 acpi_map_rsdt(void)
1654 ACPI_PHYSICAL_ADDRESS paddr;
1655 ACPI_TABLE_RSDP *rsdp;
1657 paddr = AcpiOsGetRootPointer();
1658 if (paddr == 0) {
1659 printf("ACPI: couldn't get root pointer\n");
1660 return NULL;
1662 rsdp = AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_RSDP));
1663 if (rsdp == NULL) {
1664 printf("ACPI: couldn't map RSDP\n");
1665 return NULL;
1667 if (rsdp->Revision > 1 && rsdp->XsdtPhysicalAddress)
1668 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->XsdtPhysicalAddress;
1669 else
1670 paddr = (ACPI_PHYSICAL_ADDRESS)rsdp->RsdtPhysicalAddress;
1671 AcpiOsUnmapMemory(rsdp, sizeof(ACPI_TABLE_RSDP));
1673 return AcpiOsMapMemory(paddr, sizeof(ACPI_TABLE_HEADER));
1676 static void
1677 acpi_unmap_rsdt(ACPI_TABLE_HEADER *rsdt)
1679 if (rsdt == NULL)
1680 return;
1682 AcpiOsUnmapMemory(rsdt, sizeof(ACPI_TABLE_HEADER));