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