acpi.c revision 1.90 1 /* $NetBSD: acpi.c,v 1.90 2006/06/21 17:47:23 drochner Exp $ */
2
3 /*-
4 * Copyright (c) 2003 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 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Copyright 2001, 2003 Wasabi Systems, Inc.
41 * All rights reserved.
42 *
43 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
44 *
45 * Redistribution and use in source and binary forms, with or without
46 * modification, are permitted provided that the following conditions
47 * are met:
48 * 1. Redistributions of source code must retain the above copyright
49 * notice, this list of conditions and the following disclaimer.
50 * 2. Redistributions in binary form must reproduce the above copyright
51 * notice, this list of conditions and the following disclaimer in the
52 * documentation and/or other materials provided with the distribution.
53 * 3. All advertising materials mentioning features or use of this software
54 * must display the following acknowledgement:
55 * This product includes software developed for the NetBSD Project by
56 * Wasabi Systems, Inc.
57 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
58 * or promote products derived from this software without specific prior
59 * written permission.
60 *
61 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
62 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
63 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
64 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
65 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
66 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
67 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
68 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
69 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
70 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
71 * POSSIBILITY OF SUCH DAMAGE.
72 */
73
74 /*
75 * Autoconfiguration support for the Intel ACPI Component Architecture
76 * ACPI reference implementation.
77 */
78
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.90 2006/06/21 17:47:23 drochner Exp $");
81
82 #include "opt_acpi.h"
83 #include "opt_pcifixup.h"
84
85 #include <sys/param.h>
86 #include <sys/systm.h>
87 #include <sys/device.h>
88 #include <sys/malloc.h>
89 #include <sys/kernel.h>
90 #include <sys/proc.h>
91 #include <sys/sysctl.h>
92
93 #include <dev/acpi/acpica.h>
94 #include <dev/acpi/acpireg.h>
95 #include <dev/acpi/acpivar.h>
96 #include <dev/acpi/acpi_osd.h>
97 #include <dev/acpi/acpi_timer.h>
98 #ifdef ACPIVERBOSE
99 #include <dev/acpi/acpidevs_data.h>
100 #endif
101
102 #if defined(ACPI_PCI_FIXUP)
103 #error The option ACPI_PCI_FIXUP has been obsoleted by PCI_INTR_FIXUP. Please adjust your kernel configuration file.
104 #endif
105
106 #ifdef PCI_INTR_FIXUP
107 #include <dev/pci/pcidevs.h>
108 #endif
109
110 MALLOC_DECLARE(M_ACPI);
111
112 #include <machine/acpi_machdep.h>
113
114 #ifdef ACPI_DEBUGGER
115 #define ACPI_DBGR_INIT 0x01
116 #define ACPI_DBGR_TABLES 0x02
117 #define ACPI_DBGR_ENABLE 0x04
118 #define ACPI_DBGR_PROBE 0x08
119 #define ACPI_DBGR_RUNNING 0x10
120
121 static int acpi_dbgr = 0x00;
122 #endif
123
124 static int acpi_match(struct device *, struct cfdata *, void *);
125 static void acpi_attach(struct device *, struct device *, void *);
126
127 static int acpi_print(void *aux, const char *);
128
129 static int sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS);
130
131 extern struct cfdriver acpi_cd;
132
133 CFATTACH_DECL(acpi, sizeof(struct acpi_softc),
134 acpi_match, acpi_attach, NULL, NULL);
135
136 /*
137 * This is a flag we set when the ACPI subsystem is active. Machine
138 * dependent code may wish to skip other steps (such as attaching
139 * subsystems that ACPI supercedes) when ACPI is active.
140 */
141 int acpi_active;
142
143 /*
144 * Pointer to the ACPI subsystem's state. There can be only
145 * one ACPI instance.
146 */
147 struct acpi_softc *acpi_softc;
148
149 /*
150 * Locking stuff.
151 */
152 static struct simplelock acpi_slock;
153 static int acpi_locked;
154
155 /*
156 * sysctl-related information
157 */
158
159 static int acpi_node = CTL_EOL;
160 static uint64_t acpi_root_pointer; /* found as hw.acpi.root */
161 static int acpi_sleepstate = ACPI_STATE_S0;
162
163 /*
164 * Prototypes.
165 */
166 static void acpi_shutdown(void *);
167 static void acpi_build_tree(struct acpi_softc *);
168 static ACPI_STATUS acpi_make_devnode(ACPI_HANDLE, UINT32, void *, void **);
169
170 static void acpi_enable_fixed_events(struct acpi_softc *);
171 #ifdef PCI_INTR_FIXUP
172 void acpi_pci_fixup(struct acpi_softc *);
173 #endif
174 #if defined(PCI_INTR_FIXUP) || defined(ACPI_ACTIVATE_DEV)
175 static ACPI_STATUS acpi_allocate_resources(ACPI_HANDLE handle);
176 #endif
177
178 /*
179 * acpi_probe:
180 *
181 * Probe for ACPI support. This is called by the
182 * machine-dependent ACPI front-end. All of the
183 * actual work is done by ACPICA.
184 *
185 * NOTE: This is not an autoconfiguration interface function.
186 */
187 int
188 acpi_probe(void)
189 {
190 static int beenhere;
191 ACPI_STATUS rv;
192
193 if (beenhere != 0)
194 panic("acpi_probe: ACPI has already been probed");
195 beenhere = 1;
196
197 simple_lock_init(&acpi_slock);
198 acpi_locked = 0;
199
200 /*
201 * Start up ACPICA.
202 */
203 #ifdef ACPI_DEBUGGER
204 if (acpi_dbgr & ACPI_DBGR_INIT)
205 acpi_osd_debugger();
206 #endif
207
208 rv = AcpiInitializeSubsystem();
209 if (ACPI_FAILURE(rv)) {
210 printf("ACPI: unable to initialize ACPICA: %s\n",
211 AcpiFormatException(rv));
212 return 0;
213 }
214
215 #ifdef ACPI_DEBUGGER
216 if (acpi_dbgr & ACPI_DBGR_TABLES)
217 acpi_osd_debugger();
218 #endif
219
220 rv = AcpiLoadTables();
221 if (ACPI_FAILURE(rv)) {
222 printf("ACPI: unable to load tables: %s\n",
223 AcpiFormatException(rv));
224 return 0;
225 }
226
227 /*
228 * Looks like we have ACPI!
229 */
230
231 return 1;
232 }
233
234 ACPI_STATUS
235 acpi_OsGetRootPointer(UINT32 Flags, ACPI_POINTER *PhysicalAddress)
236 {
237 ACPI_STATUS rv;
238
239 /*
240 * IA-32: Use AcpiFindRootPointer() to locate the RSDP.
241 *
242 * IA-64: Use the EFI.
243 *
244 * We let MD code handle this since there are multiple
245 * ways to do it.
246 */
247
248 rv = acpi_md_OsGetRootPointer(Flags, PhysicalAddress);
249
250 if (acpi_root_pointer == 0 && ACPI_SUCCESS(rv))
251 acpi_root_pointer =
252 (uint64_t)PhysicalAddress->Pointer.Physical;
253
254 return rv;
255 }
256
257 /*
258 * acpi_match:
259 *
260 * Autoconfiguration `match' routine.
261 */
262 static int
263 acpi_match(struct device *parent, struct cfdata *match, void *aux)
264 {
265 /*
266 * XXX Check other locators? Hard to know -- machine
267 * dependent code has already checked for the presence
268 * of ACPI by calling acpi_probe(), so I suppose we
269 * don't really have to do anything else.
270 */
271 return 1;
272 }
273
274 /*
275 * acpi_attach:
276 *
277 * Autoconfiguration `attach' routine. Finish initializing
278 * ACPICA (some initialization was done in acpi_probe(),
279 * which was required to check for the presence of ACPI),
280 * and enable the ACPI subsystem.
281 */
282 static void
283 acpi_attach(struct device *parent, struct device *self, void *aux)
284 {
285 struct acpi_softc *sc = (void *) self;
286 struct acpibus_attach_args *aa = aux;
287 ACPI_STATUS rv;
288
289 aprint_naive(": Advanced Configuration and Power Interface\n");
290 aprint_normal(": Advanced Configuration and Power Interface\n");
291
292 if (acpi_softc != NULL)
293 panic("acpi_attach: ACPI has already been attached");
294
295 sysmon_power_settype("acpi");
296
297 aprint_verbose("%s: using Intel ACPI CA subsystem version %08x\n",
298 sc->sc_dev.dv_xname, ACPI_CA_VERSION);
299
300 aprint_verbose("%s: X/RSDT: OemId <%6.6s,%8.8s,%08x>, AslId <%4.4s,%08x>\n",
301 sc->sc_dev.dv_xname,
302 AcpiGbl_XSDT->OemId, AcpiGbl_XSDT->OemTableId,
303 AcpiGbl_XSDT->OemRevision,
304 AcpiGbl_XSDT->AslCompilerId, AcpiGbl_XSDT->AslCompilerRevision);
305
306 sc->sc_quirks = acpi_find_quirks();
307
308 sc->sc_iot = aa->aa_iot;
309 sc->sc_memt = aa->aa_memt;
310 sc->sc_pc = aa->aa_pc;
311 sc->sc_pciflags = aa->aa_pciflags;
312 sc->sc_ic = aa->aa_ic;
313
314 acpi_softc = sc;
315
316 /*
317 * Bring ACPI on-line.
318 */
319 #ifdef ACPI_DEBUGGER
320 if (acpi_dbgr & ACPI_DBGR_ENABLE)
321 acpi_osd_debugger();
322 #endif
323
324 rv = AcpiEnableSubsystem(0);
325 if (ACPI_FAILURE(rv)) {
326 aprint_error("%s: unable to enable ACPI: %s\n",
327 sc->sc_dev.dv_xname, AcpiFormatException(rv));
328 return;
329 }
330
331 /* early EC handler initialization if ECDT table is available */
332 #if NACPIEC > 0
333 acpiec_early_attach(&sc->sc_dev);
334 #endif
335
336 rv = AcpiInitializeObjects(0);
337 if (ACPI_FAILURE(rv)) {
338 aprint_error("%s: unable to initialize ACPI objects: %s\n",
339 sc->sc_dev.dv_xname, AcpiFormatException(rv));
340 return;
341 }
342 acpi_active = 1;
343
344 /* Our current state is "awake". */
345 sc->sc_sleepstate = ACPI_STATE_S0;
346
347 /* Show SCI interrupt. */
348 if (AcpiGbl_FADT != NULL)
349 aprint_verbose("%s: SCI interrupting at int %d\n",
350 sc->sc_dev.dv_xname, AcpiGbl_FADT->SciInt);
351 /*
352 * Check for fixed-hardware features.
353 */
354 acpi_enable_fixed_events(sc);
355 acpitimer_init();
356
357 /*
358 * Fix up PCI devices.
359 */
360 #ifdef PCI_INTR_FIXUP
361 if ((sc->sc_quirks & (ACPI_QUIRK_BADPCI | ACPI_QUIRK_BADIRQ)) == 0)
362 acpi_pci_fixup(sc);
363 #endif
364
365 /*
366 * Scan the namespace and build our device tree.
367 */
368 #ifdef ACPI_DEBUGGER
369 if (acpi_dbgr & ACPI_DBGR_PROBE)
370 acpi_osd_debugger();
371 #endif
372 acpi_md_callback((struct device *)sc);
373 acpi_build_tree(sc);
374
375 if (acpi_root_pointer != 0 && acpi_node != CTL_EOL) {
376 (void)sysctl_createv(NULL, 0, NULL, NULL,
377 CTLFLAG_IMMEDIATE,
378 CTLTYPE_QUAD, "root", NULL, NULL,
379 acpi_root_pointer, NULL, 0,
380 CTL_HW, acpi_node, CTL_CREATE, CTL_EOL);
381 }
382
383
384 /*
385 * Register a shutdown hook that disables certain ACPI
386 * events that might happen and confuse us while we're
387 * trying to shut down.
388 */
389 sc->sc_sdhook = shutdownhook_establish(acpi_shutdown, sc);
390 if (sc->sc_sdhook == NULL)
391 aprint_error("%s: WARNING: unable to register shutdown hook\n",
392 sc->sc_dev.dv_xname);
393
394 #ifdef ACPI_DEBUGGER
395 if (acpi_dbgr & ACPI_DBGR_RUNNING)
396 acpi_osd_debugger();
397 #endif
398 }
399
400 /*
401 * acpi_shutdown:
402 *
403 * Shutdown hook for ACPI -- disable some events that
404 * might confuse us.
405 */
406 static void
407 acpi_shutdown(void *arg)
408 {
409 /* nothing */
410 }
411
412 #if 0
413 /*
414 * acpi_disable:
415 *
416 * Disable ACPI.
417 */
418 static ACPI_STATUS
419 acpi_disable(struct acpi_softc *sc)
420 {
421 ACPI_STATUS rv = AE_OK;
422
423 if (acpi_active) {
424 rv = AcpiDisable();
425 if (ACPI_SUCCESS(rv))
426 acpi_active = 0;
427 }
428 return rv;
429 }
430 #endif
431
432 struct acpi_make_devnode_state {
433 struct acpi_softc *softc;
434 struct acpi_scope *scope;
435 };
436
437 /*
438 * acpi_build_tree:
439 *
440 * Scan relevant portions of the ACPI namespace and attach
441 * child devices.
442 */
443 static void
444 acpi_build_tree(struct acpi_softc *sc)
445 {
446 static const char *scopes[] = {
447 "\\_PR_", /* ACPI 1.0 processor namespace */
448 "\\_SB_", /* system bus namespace */
449 "\\_SI_", /* system idicator namespace */
450 "\\_TZ_", /* ACPI 1.0 thermal zone namespace */
451 NULL,
452 };
453 struct acpi_attach_args aa;
454 struct acpi_make_devnode_state state;
455 struct acpi_scope *as;
456 struct acpi_devnode *ad;
457 ACPI_HANDLE parent;
458 ACPI_STATUS rv;
459 int i;
460
461 TAILQ_INIT(&sc->sc_scopes);
462
463 state.softc = sc;
464
465 /*
466 * Scan the namespace and build our tree.
467 */
468 for (i = 0; scopes[i] != NULL; i++) {
469 as = malloc(sizeof(*as), M_ACPI, M_WAITOK);
470 as->as_name = scopes[i];
471 TAILQ_INIT(&as->as_devnodes);
472
473 TAILQ_INSERT_TAIL(&sc->sc_scopes, as, as_list);
474
475 state.scope = as;
476
477 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, scopes[i],
478 &parent);
479 if (ACPI_SUCCESS(rv)) {
480 AcpiWalkNamespace(ACPI_TYPE_ANY, parent, 100,
481 acpi_make_devnode, &state, NULL);
482 }
483
484 /* Now, for this namespace, try and attach the devices. */
485 TAILQ_FOREACH(ad, &as->as_devnodes, ad_list) {
486 aa.aa_node = ad;
487 aa.aa_iot = sc->sc_iot;
488 aa.aa_memt = sc->sc_memt;
489 aa.aa_pc = sc->sc_pc;
490 aa.aa_pciflags = sc->sc_pciflags;
491 aa.aa_ic = sc->sc_ic;
492
493 if (ad->ad_devinfo->Type == ACPI_TYPE_DEVICE) {
494 /*
495 * XXX We only attach devices which are:
496 *
497 * - present
498 * - enabled
499 * - functioning properly
500 *
501 * However, if enabled, it's decoding resources,
502 * so we should claim them, if possible.
503 * Requires changes to bus_space(9).
504 */
505 if ((ad->ad_devinfo->Valid & ACPI_VALID_STA) ==
506 ACPI_VALID_STA &&
507 (ad->ad_devinfo->CurrentStatus &
508 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
509 ACPI_STA_DEV_OK)) !=
510 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED|
511 ACPI_STA_DEV_OK))
512 continue;
513
514 /*
515 * XXX Same problem as above...
516 */
517 if ((ad->ad_devinfo->Valid & ACPI_VALID_HID)
518 == 0)
519 continue;
520 }
521
522 ad->ad_device = config_found(&sc->sc_dev,
523 &aa, acpi_print);
524 }
525 }
526 }
527
528 #ifdef ACPI_ACTIVATE_DEV
529 static void
530 acpi_activate_device(ACPI_HANDLE handle, ACPI_DEVICE_INFO **di)
531 {
532 ACPI_STATUS rv;
533 ACPI_BUFFER buf;
534
535 buf.Pointer = NULL;
536 buf.Length = ACPI_ALLOCATE_BUFFER;
537
538 #ifdef ACPI_DEBUG
539 aprint_normal("acpi_activate_device: %s, old status=%x\n",
540 (*di)->HardwareId.Value, (*di)->CurrentStatus);
541 #endif
542
543 rv = acpi_allocate_resources(handle);
544 if (ACPI_FAILURE(rv)) {
545 aprint_error("acpi: activate failed for %s\n",
546 (*di)->HardwareId.Value);
547 } else {
548 aprint_normal("acpi: activated %s\n", (*di)->HardwareId.Value);
549 }
550
551 (void)AcpiGetObjectInfo(handle, &buf);
552 AcpiOsFree(*di);
553 *di = buf.Pointer;
554
555 #ifdef ACPI_DEBUG
556 aprint_normal("acpi_activate_device: %s, new status=%x\n",
557 (*di)->HardwareId.Value, (*di)->CurrentStatus);
558 #endif
559 }
560 #endif /* ACPI_ACTIVATE_DEV */
561
562 /*
563 * acpi_make_devnode:
564 *
565 * Make an ACPI devnode.
566 */
567 static ACPI_STATUS
568 acpi_make_devnode(ACPI_HANDLE handle, UINT32 level, void *context,
569 void **status)
570 {
571 struct acpi_make_devnode_state *state = context;
572 #if defined(ACPI_DEBUG) || defined(ACPI_EXTRA_DEBUG)
573 struct acpi_softc *sc = state->softc;
574 #endif
575 struct acpi_scope *as = state->scope;
576 struct acpi_devnode *ad;
577 ACPI_OBJECT_TYPE type;
578 ACPI_BUFFER buf;
579 ACPI_DEVICE_INFO *devinfo;
580 ACPI_STATUS rv;
581
582 rv = AcpiGetType(handle, &type);
583 if (ACPI_SUCCESS(rv)) {
584 buf.Pointer = NULL;
585 buf.Length = ACPI_ALLOCATE_BUFFER;
586 rv = AcpiGetObjectInfo(handle, &buf);
587 if (ACPI_FAILURE(rv)) {
588 #ifdef ACPI_DEBUG
589 aprint_normal("%s: AcpiGetObjectInfo failed: %s\n",
590 sc->sc_dev.dv_xname, AcpiFormatException(rv));
591 #endif
592 goto out; /* XXX why return OK */
593 }
594
595 devinfo = buf.Pointer;
596
597 switch (type) {
598 case ACPI_TYPE_DEVICE:
599 #ifdef ACPI_ACTIVATE_DEV
600 if ((devinfo->Valid & (ACPI_VALID_STA|ACPI_VALID_HID)) ==
601 (ACPI_VALID_STA|ACPI_VALID_HID) &&
602 (devinfo->CurrentStatus &
603 (ACPI_STA_DEV_PRESENT|ACPI_STA_DEV_ENABLED)) ==
604 ACPI_STA_DEV_PRESENT)
605 acpi_activate_device(handle, &devinfo);
606
607 /* FALLTHROUGH */
608 #endif
609
610 case ACPI_TYPE_PROCESSOR:
611 case ACPI_TYPE_THERMAL:
612 case ACPI_TYPE_POWER:
613 ad = malloc(sizeof(*ad), M_ACPI, M_NOWAIT|M_ZERO);
614 if (ad == NULL)
615 return AE_NO_MEMORY;
616
617 ad->ad_devinfo = devinfo;
618 ad->ad_handle = handle;
619 ad->ad_level = level;
620 ad->ad_scope = as;
621 ad->ad_type = type;
622
623 TAILQ_INSERT_TAIL(&as->as_devnodes, ad, ad_list);
624
625 if ((ad->ad_devinfo->Valid & ACPI_VALID_HID) == 0)
626 goto out;
627
628 #ifdef ACPI_EXTRA_DEBUG
629 aprint_normal("%s: HID %s found in scope %s level %d\n",
630 sc->sc_dev.dv_xname,
631 ad->ad_devinfo->HardwareId.Value,
632 as->as_name, ad->ad_level);
633 if (ad->ad_devinfo->Valid & ACPI_VALID_UID)
634 aprint_normal(" UID %s\n",
635 ad->ad_devinfo->UniqueId.Value);
636 if (ad->ad_devinfo->Valid & ACPI_VALID_ADR)
637 aprint_normal(" ADR 0x%016qx\n",
638 ad->ad_devinfo->Address);
639 if (ad->ad_devinfo->Valid & ACPI_VALID_STA)
640 aprint_normal(" STA 0x%08x\n",
641 ad->ad_devinfo->CurrentStatus);
642 #endif
643 }
644 }
645 out:
646 return AE_OK;
647 }
648
649 /*
650 * acpi_print:
651 *
652 * Autoconfiguration print routine.
653 */
654 static int
655 acpi_print(void *aux, const char *pnp)
656 {
657 struct acpi_attach_args *aa = aux;
658 ACPI_STATUS rv;
659
660 if (pnp) {
661 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
662 char *pnpstr =
663 aa->aa_node->ad_devinfo->HardwareId.Value;
664 char *str;
665
666 aprint_normal("%s ", pnpstr);
667 rv = acpi_eval_string(aa->aa_node->ad_handle,
668 "_STR", &str);
669 if (ACPI_SUCCESS(rv)) {
670 aprint_normal("[%s] ", str);
671 AcpiOsFree(str);
672 }
673 #ifdef ACPIVERBOSE
674 else {
675 int i;
676
677 for (i = 0; i < sizeof(acpi_knowndevs) /
678 sizeof(acpi_knowndevs[0]); i++) {
679 if (strcmp(acpi_knowndevs[i].pnp,
680 pnpstr) == 0) {
681 aprint_normal("[%s] ",
682 acpi_knowndevs[i].str);
683 }
684 }
685 }
686
687 #endif
688 } else {
689 aprint_normal("ACPI Object Type '%s' (0x%02x) ",
690 AcpiUtGetTypeName(aa->aa_node->ad_devinfo->Type),
691 aa->aa_node->ad_devinfo->Type);
692 }
693 aprint_normal("at %s", pnp);
694 } else {
695 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_HID) {
696 aprint_normal(" (%s", aa->aa_node->ad_devinfo->HardwareId.Value);
697 if (aa->aa_node->ad_devinfo->Valid & ACPI_VALID_UID) {
698 const char *uid;
699
700 uid = aa->aa_node->ad_devinfo->UniqueId.Value;
701 if (uid[0] == '\0')
702 uid = "<null>";
703 aprint_normal("-%s", uid);
704 }
705 aprint_normal(")");
706 }
707 }
708
709 return UNCONF;
710 }
711
712 /*****************************************************************************
713 * ACPI fixed-hardware feature handlers
714 *****************************************************************************/
715
716 static UINT32 acpi_fixed_button_handler(void *);
717 static void acpi_fixed_button_pressed(void *);
718
719 /*
720 * acpi_enable_fixed_events:
721 *
722 * Enable any fixed-hardware feature handlers.
723 */
724 static void
725 acpi_enable_fixed_events(struct acpi_softc *sc)
726 {
727 static int beenhere;
728 ACPI_STATUS rv;
729
730 KASSERT(beenhere == 0);
731 beenhere = 1;
732
733 /*
734 * Check for fixed-hardware buttons.
735 */
736
737 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->PwrButton == 0) {
738 aprint_normal("%s: fixed-feature power button present\n",
739 sc->sc_dev.dv_xname);
740 sc->sc_smpsw_power.smpsw_name = sc->sc_dev.dv_xname;
741 sc->sc_smpsw_power.smpsw_type = PSWITCH_TYPE_POWER;
742 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
743 aprint_error("%s: unable to register fixed power "
744 "button with sysmon\n", sc->sc_dev.dv_xname);
745 } else {
746 rv = AcpiInstallFixedEventHandler(
747 ACPI_EVENT_POWER_BUTTON,
748 acpi_fixed_button_handler, &sc->sc_smpsw_power);
749 if (ACPI_FAILURE(rv)) {
750 aprint_error("%s: unable to install handler "
751 "for fixed power button: %s\n",
752 sc->sc_dev.dv_xname,
753 AcpiFormatException(rv));
754 }
755 }
756 }
757
758 if (AcpiGbl_FADT != NULL && AcpiGbl_FADT->SleepButton == 0) {
759 aprint_normal("%s: fixed-feature sleep button present\n",
760 sc->sc_dev.dv_xname);
761 sc->sc_smpsw_sleep.smpsw_name = sc->sc_dev.dv_xname;
762 sc->sc_smpsw_sleep.smpsw_type = PSWITCH_TYPE_SLEEP;
763 if (sysmon_pswitch_register(&sc->sc_smpsw_power) != 0) {
764 aprint_error("%s: unable to register fixed sleep "
765 "button with sysmon\n", sc->sc_dev.dv_xname);
766 } else {
767 rv = AcpiInstallFixedEventHandler(
768 ACPI_EVENT_SLEEP_BUTTON,
769 acpi_fixed_button_handler, &sc->sc_smpsw_sleep);
770 if (ACPI_FAILURE(rv)) {
771 aprint_error("%s: unable to install handler "
772 "for fixed sleep button: %s\n",
773 sc->sc_dev.dv_xname,
774 AcpiFormatException(rv));
775 }
776 }
777 }
778 }
779
780 /*
781 * acpi_fixed_button_handler:
782 *
783 * Event handler for the fixed buttons.
784 */
785 static UINT32
786 acpi_fixed_button_handler(void *context)
787 {
788 struct sysmon_pswitch *smpsw = context;
789 int rv;
790
791 #ifdef ACPI_BUT_DEBUG
792 printf("%s: fixed button handler\n", smpsw->smpsw_name);
793 #endif
794
795 rv = AcpiOsQueueForExecution(OSD_PRIORITY_LO,
796 acpi_fixed_button_pressed, smpsw);
797 if (ACPI_FAILURE(rv))
798 printf("%s: WARNING: unable to queue fixed button pressed "
799 "callback: %s\n", smpsw->smpsw_name,
800 AcpiFormatException(rv));
801
802 return ACPI_INTERRUPT_HANDLED;
803 }
804
805 /*
806 * acpi_fixed_button_pressed:
807 *
808 * Deal with a fixed button being pressed.
809 */
810 static void
811 acpi_fixed_button_pressed(void *context)
812 {
813 struct sysmon_pswitch *smpsw = context;
814
815 #ifdef ACPI_BUT_DEBUG
816 printf("%s: fixed button pressed, calling sysmon\n",
817 smpsw->smpsw_name);
818 #endif
819
820 sysmon_pswitch_event(smpsw, PSWITCH_EVENT_PRESSED);
821 }
822
823 /*****************************************************************************
824 * ACPI utility routines.
825 *****************************************************************************/
826
827 /*
828 * acpi_eval_integer:
829 *
830 * Evaluate an integer object.
831 */
832 ACPI_STATUS
833 acpi_eval_integer(ACPI_HANDLE handle, const char *path, ACPI_INTEGER *valp)
834 {
835 ACPI_STATUS rv;
836 ACPI_BUFFER buf;
837 ACPI_OBJECT param;
838
839 if (handle == NULL)
840 handle = ACPI_ROOT_OBJECT;
841
842 buf.Pointer = ¶m;
843 buf.Length = sizeof(param);
844
845 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_INTEGER);
846 if (ACPI_SUCCESS(rv))
847 *valp = param.Integer.Value;
848
849 return rv;
850 }
851
852 /*
853 * acpi_eval_string:
854 *
855 * Evaluate a (Unicode) string object.
856 */
857 ACPI_STATUS
858 acpi_eval_string(ACPI_HANDLE handle, const char *path, char **stringp)
859 {
860 ACPI_STATUS rv;
861 ACPI_BUFFER buf;
862
863 if (handle == NULL)
864 handle = ACPI_ROOT_OBJECT;
865
866 buf.Pointer = NULL;
867 buf.Length = ACPI_ALLOCATE_BUFFER;
868
869 rv = AcpiEvaluateObjectTyped(handle, path, NULL, &buf, ACPI_TYPE_STRING);
870 if (ACPI_SUCCESS(rv)) {
871 ACPI_OBJECT *param = buf.Pointer;
872 const char *ptr = param->String.Pointer;
873 size_t len = param->String.Length;
874 if ((*stringp = AcpiOsAllocate(len)) == NULL)
875 rv = AE_NO_MEMORY;
876 else
877 (void)memcpy(*stringp, ptr, len);
878 AcpiOsFree(param);
879 }
880
881 return rv;
882 }
883
884
885 /*
886 * acpi_eval_struct:
887 *
888 * Evaluate a more complex structure.
889 * Caller must free buf.Pointer by AcpiOsFree().
890 */
891 ACPI_STATUS
892 acpi_eval_struct(ACPI_HANDLE handle, const char *path, ACPI_BUFFER *bufp)
893 {
894 ACPI_STATUS rv;
895
896 if (handle == NULL)
897 handle = ACPI_ROOT_OBJECT;
898
899 bufp->Pointer = NULL;
900 bufp->Length = ACPI_ALLOCATE_BUFFER;
901
902 rv = AcpiEvaluateObject(handle, path, NULL, bufp);
903
904 return rv;
905 }
906
907 /*
908 * acpi_foreach_package_object:
909 *
910 * Iterate over all objects in a in a packages and pass then all
911 * to a function. If the called function returns non AE_OK, the
912 * iteration is stopped and that value is returned.
913 */
914
915 ACPI_STATUS
916 acpi_foreach_package_object(ACPI_OBJECT *pkg,
917 ACPI_STATUS (*func)(ACPI_OBJECT *, void *),
918 void *arg)
919 {
920 ACPI_STATUS rv = AE_OK;
921 int i;
922
923 if (pkg == NULL || pkg->Type != ACPI_TYPE_PACKAGE)
924 return AE_BAD_PARAMETER;
925
926 for (i = 0; i < pkg->Package.Count; i++) {
927 rv = (*func)(&pkg->Package.Elements[i], arg);
928 if (ACPI_FAILURE(rv))
929 break;
930 }
931
932 return rv;
933 }
934
935 const char *
936 acpi_name(ACPI_HANDLE handle)
937 {
938 static char buffer[80];
939 ACPI_BUFFER buf;
940 ACPI_STATUS rv;
941
942 buf.Length = sizeof(buffer);
943 buf.Pointer = buffer;
944
945 rv = AcpiGetName(handle, ACPI_FULL_PATHNAME, &buf);
946 if (ACPI_FAILURE(rv))
947 return "(unknown acpi path)";
948 return buffer;
949 }
950
951 /*
952 * acpi_get:
953 *
954 * Fetch data info the specified (empty) ACPI buffer.
955 * Caller must free buf.Pointer by AcpiOsFree().
956 */
957 ACPI_STATUS
958 acpi_get(ACPI_HANDLE handle, ACPI_BUFFER *buf,
959 ACPI_STATUS (*getit)(ACPI_HANDLE, ACPI_BUFFER *))
960 {
961 buf->Pointer = NULL;
962 buf->Length = ACPI_ALLOCATE_BUFFER;
963
964 return (*getit)(handle, buf);
965 }
966
967
968 /*
969 * acpi_match_hid
970 *
971 * Match given ids against _HID and _CIDs
972 */
973 int
974 acpi_match_hid(ACPI_DEVICE_INFO *ad, const char * const *ids)
975 {
976 int i;
977
978 while (*ids) {
979 if (ad->Valid & ACPI_VALID_HID) {
980 if (pmatch(ad->HardwareId.Value, *ids, NULL) == 2)
981 return 1;
982 }
983
984 if (ad->Valid & ACPI_VALID_CID) {
985 for (i = 0; i < ad->CompatibilityId.Count; i++) {
986 if (pmatch(ad->CompatibilityId.Id[i].Value, *ids, NULL) == 2)
987 return 1;
988 }
989 }
990 ids++;
991 }
992
993 return 0;
994 }
995
996 /*
997 * acpi_set_wake_gpe
998 *
999 * Set GPE as both Runtime and Wake
1000 */
1001 void
1002 acpi_set_wake_gpe(ACPI_HANDLE handle)
1003 {
1004 ACPI_BUFFER buf;
1005 ACPI_STATUS rv;
1006 ACPI_OBJECT *p, *elt;
1007
1008 rv = acpi_eval_struct(handle, METHOD_NAME__PRW, &buf);
1009 if (ACPI_FAILURE(rv))
1010 return; /* just ignore */
1011
1012 p = buf.Pointer;
1013 if (p->Type != ACPI_TYPE_PACKAGE || p->Package.Count < 2)
1014 goto out; /* just ignore */
1015
1016 elt = p->Package.Elements;
1017
1018 /* TBD: package support */
1019 AcpiSetGpeType(NULL, elt[0].Integer.Value, ACPI_GPE_TYPE_WAKE_RUN);
1020 AcpiEnableGpe(NULL, elt[0].Integer.Value, ACPI_NOT_ISR);
1021
1022 out:
1023 AcpiOsFree(buf.Pointer);
1024 }
1025
1026
1027 /*****************************************************************************
1028 * ACPI sleep support.
1029 *****************************************************************************/
1030
1031 static int
1032 is_available_state(struct acpi_softc *sc, int state)
1033 {
1034 UINT8 type_a, type_b;
1035
1036 return ACPI_SUCCESS(AcpiGetSleepTypeData((UINT8)state,
1037 &type_a, &type_b));
1038 }
1039
1040 /*
1041 * acpi_enter_sleep_state:
1042 *
1043 * enter to the specified sleep state.
1044 */
1045
1046 ACPI_STATUS
1047 acpi_enter_sleep_state(struct acpi_softc *sc, int state)
1048 {
1049 int s;
1050 ACPI_STATUS ret = AE_OK;
1051
1052 switch (state) {
1053 case ACPI_STATE_S0:
1054 break;
1055 case ACPI_STATE_S1:
1056 case ACPI_STATE_S2:
1057 case ACPI_STATE_S3:
1058 case ACPI_STATE_S4:
1059 if (!is_available_state(sc, state)) {
1060 printf("acpi: cannot enter the sleep state (%d).\n",
1061 state);
1062 break;
1063 }
1064 ret = AcpiEnterSleepStatePrep(state);
1065 if (ACPI_FAILURE(ret)) {
1066 printf("acpi: failed preparing to sleep (%s)\n",
1067 AcpiFormatException(ret));
1068 break;
1069 }
1070 if (state==ACPI_STATE_S1) {
1071 /* just enter the state */
1072 acpi_md_OsDisableInterrupt();
1073 AcpiEnterSleepState((UINT8)state);
1074 AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
1075 } else {
1076 /* XXX: powerhooks(9) framework is too poor to
1077 * support ACPI sleep state...
1078 */
1079 dopowerhooks(PWR_SOFTSUSPEND);
1080 s = splhigh();
1081 dopowerhooks(PWR_SUSPEND);
1082 acpi_md_sleep(state);
1083 dopowerhooks(PWR_RESUME);
1084 splx(s);
1085 dopowerhooks(PWR_SOFTRESUME);
1086 if (state==ACPI_STATE_S4)
1087 AcpiEnable();
1088 }
1089 AcpiLeaveSleepState((UINT8)state);
1090 break;
1091 case ACPI_STATE_S5:
1092 ret = AcpiEnterSleepStatePrep(ACPI_STATE_S5);
1093 if (ACPI_FAILURE(ret)) {
1094 printf("acpi: failed preparing to sleep (%s)\n",
1095 AcpiFormatException(ret));
1096 break;
1097 }
1098 acpi_md_OsDisableInterrupt();
1099 AcpiEnterSleepState(ACPI_STATE_S5);
1100 printf("WARNING: powerdown failed!\n");
1101 break;
1102 }
1103
1104 return ret;
1105 }
1106
1107 #ifdef PCI_INTR_FIXUP
1108 ACPI_STATUS acpi_pci_fixup_bus(ACPI_HANDLE, UINT32, void *, void **);
1109 /*
1110 * acpi_pci_fixup:
1111 *
1112 * Set up PCI devices that BIOS didn't handle right.
1113 * Iterate through all devices and try to get the _PTR
1114 * (PCI Routing Table). If it exists then make sure all
1115 * interrupt links that it uses are working.
1116 */
1117 void
1118 acpi_pci_fixup(struct acpi_softc *sc)
1119 {
1120 ACPI_HANDLE parent;
1121 ACPI_STATUS rv;
1122
1123 #ifdef ACPI_DEBUG
1124 printf("acpi_pci_fixup starts:\n");
1125 #endif
1126 rv = AcpiGetHandle(ACPI_ROOT_OBJECT, "\\_SB_", &parent);
1127 if (ACPI_FAILURE(rv))
1128 return;
1129 sc->sc_pci_bus = 0;
1130 AcpiWalkNamespace(ACPI_TYPE_DEVICE, parent, 100,
1131 acpi_pci_fixup_bus, sc, NULL);
1132 }
1133
1134 static uint
1135 acpi_get_intr(ACPI_HANDLE handle)
1136 {
1137 ACPI_BUFFER ret;
1138 ACPI_STATUS rv;
1139 ACPI_RESOURCE *res;
1140 ACPI_RESOURCE_IRQ *irq;
1141 uint intr;
1142
1143 intr = -1;
1144 rv = acpi_get(handle, &ret, AcpiGetCurrentResources);
1145 if (ACPI_FAILURE(rv))
1146 return intr;
1147 for (res = ret.Pointer; res->Type != ACPI_RESOURCE_TYPE_END_TAG;
1148 res = ACPI_NEXT_RESOURCE(res)) {
1149 if (res->Type == ACPI_RESOURCE_TYPE_IRQ) {
1150 irq = (ACPI_RESOURCE_IRQ *)&res->Data;
1151 if (irq->InterruptCount == 1)
1152 intr = irq->Interrupts[0];
1153 break;
1154 }
1155 }
1156 AcpiOsFree(ret.Pointer);
1157 return intr;
1158 }
1159
1160 static void
1161 acpi_pci_set_line(int bus, int dev, int pin, int line)
1162 {
1163 ACPI_STATUS err;
1164 ACPI_PCI_ID pid;
1165 UINT32 intr, id, bhlc;
1166 int func, nfunc;
1167
1168 pid.Bus = bus;
1169 pid.Device = dev;
1170 pid.Function = 0;
1171
1172 err = AcpiOsReadPciConfiguration(&pid, PCI_BHLC_REG, &bhlc, 32);
1173 if (err)
1174 return;
1175 if (PCI_HDRTYPE_MULTIFN(bhlc))
1176 nfunc = 8;
1177 else
1178 nfunc = 1;
1179
1180 for (func = 0; func < nfunc; func++) {
1181 pid.Function = func;
1182
1183 err = AcpiOsReadPciConfiguration(&pid, PCI_ID_REG, &id, 32);
1184 if (err || PCI_VENDOR(id) == PCI_VENDOR_INVALID ||
1185 PCI_VENDOR(id) == 0)
1186 continue;
1187
1188 err = AcpiOsReadPciConfiguration(&pid, PCI_INTERRUPT_REG,
1189 &intr, 32);
1190 if (err) {
1191 printf("AcpiOsReadPciConfiguration failed %d\n", err);
1192 return;
1193 }
1194 if (pin == PCI_INTERRUPT_PIN(intr) &&
1195 line != PCI_INTERRUPT_LINE(intr)) {
1196 #ifdef ACPI_DEBUG
1197 printf("acpi fixup pci intr: %d:%d:%d %c: %d -> %d\n",
1198 bus, dev, func,
1199 pin + '@', PCI_INTERRUPT_LINE(intr),
1200 line);
1201 #endif
1202 intr &= ~(PCI_INTERRUPT_LINE_MASK <<
1203 PCI_INTERRUPT_LINE_SHIFT);
1204 intr |= line << PCI_INTERRUPT_LINE_SHIFT;
1205 err = AcpiOsWritePciConfiguration(&pid,
1206 PCI_INTERRUPT_REG, intr, 32);
1207 if (err) {
1208 printf("AcpiOsWritePciConfiguration failed"
1209 " %d\n", err);
1210 return;
1211 }
1212 }
1213 }
1214 }
1215
1216 ACPI_STATUS
1217 acpi_pci_fixup_bus(ACPI_HANDLE handle, UINT32 level, void *context,
1218 void **status)
1219 {
1220 struct acpi_softc *sc = context;
1221 ACPI_STATUS rv;
1222 ACPI_BUFFER buf;
1223 UINT8 *Buffer;
1224 ACPI_PCI_ROUTING_TABLE *PrtElement;
1225 ACPI_HANDLE link;
1226 uint line;
1227 ACPI_INTEGER val;
1228
1229 rv = acpi_get(handle, &buf, AcpiGetIrqRoutingTable);
1230 if (ACPI_FAILURE(rv))
1231 return AE_OK;
1232
1233 /*
1234 * If at level 1, this is a PCI root bus. Try the _BBN method
1235 * to get the right PCI bus numbering for the following
1236 * busses (this is a depth-first walk). It may fail,
1237 * for example if there's only one root bus, but that
1238 * case should be ok, so we'll ignore that.
1239 */
1240 if (level == 1) {
1241 rv = acpi_eval_integer(handle, METHOD_NAME__BBN, &val);
1242 if (!ACPI_FAILURE(rv)) {
1243 #ifdef ACPI_DEBUG
1244 printf("%s: fixup: _BBN success, bus # was %d now %d\n",
1245 sc->sc_dev.dv_xname, sc->sc_pci_bus,
1246 ACPI_LOWORD(val));
1247 #endif
1248 sc->sc_pci_bus = ACPI_LOWORD(val);
1249 }
1250 }
1251
1252
1253 #ifdef ACPI_DEBUG
1254 printf("%s: fixing up PCI bus %d at level %u\n", sc->sc_dev.dv_xname,
1255 sc->sc_pci_bus, level);
1256 #endif
1257
1258 for (Buffer = buf.Pointer; ; Buffer += PrtElement->Length) {
1259 PrtElement = (ACPI_PCI_ROUTING_TABLE *)Buffer;
1260 if (PrtElement->Length == 0)
1261 break;
1262 if (PrtElement->Source[0] == 0)
1263 continue;
1264
1265 rv = AcpiGetHandle(NULL, PrtElement->Source, &link);
1266 if (ACPI_FAILURE(rv))
1267 continue;
1268 line = acpi_get_intr(link);
1269 if (line == (uint)-1 || line == 0) {
1270 printf("%s: fixing up intr link %s\n",
1271 sc->sc_dev.dv_xname, PrtElement->Source);
1272 rv = acpi_allocate_resources(link);
1273 if (ACPI_FAILURE(rv)) {
1274 printf("%s: interrupt allocation failed %s\n",
1275 sc->sc_dev.dv_xname, PrtElement->Source);
1276 continue;
1277 }
1278 line = acpi_get_intr(link);
1279 if (line == (uint)-1) {
1280 printf("%s: get intr failed %s\n",
1281 sc->sc_dev.dv_xname, PrtElement->Source);
1282 continue;
1283 }
1284 }
1285
1286 acpi_pci_set_line(sc->sc_pci_bus, PrtElement->Address >> 16,
1287 PrtElement->Pin + 1, line);
1288 }
1289
1290 sc->sc_pci_bus++;
1291
1292 AcpiOsFree(buf.Pointer);
1293 return AE_OK;
1294 }
1295 #endif /* PCI_INTR_FIXUP */
1296
1297 #if defined(PCI_INTR_FIXUP) || defined(ACPI_ACTIVATE_DEV)
1298 /* XXX This very incomplete */
1299 static ACPI_STATUS
1300 acpi_allocate_resources(ACPI_HANDLE handle)
1301 {
1302 ACPI_BUFFER bufp, bufc, bufn;
1303 ACPI_RESOURCE *resp, *resc, *resn;
1304 ACPI_RESOURCE_IRQ *irq;
1305 ACPI_STATUS rv;
1306 uint delta;
1307
1308 rv = acpi_get(handle, &bufp, AcpiGetPossibleResources);
1309 if (ACPI_FAILURE(rv))
1310 goto out;
1311 rv = acpi_get(handle, &bufc, AcpiGetCurrentResources);
1312 if (ACPI_FAILURE(rv)) {
1313 goto out1;
1314 }
1315
1316 bufn.Length = 1000;
1317 bufn.Pointer = resn = malloc(bufn.Length, M_ACPI, M_WAITOK);
1318 resp = bufp.Pointer;
1319 resc = bufc.Pointer;
1320 while (resc->Type != ACPI_RESOURCE_TYPE_END_TAG &&
1321 resp->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1322 while (resc->Type != resp->Type && resp->Type != ACPI_RESOURCE_TYPE_END_TAG)
1323 resp = ACPI_NEXT_RESOURCE(resp);
1324 if (resp->Type == ACPI_RESOURCE_TYPE_END_TAG)
1325 break;
1326 /* Found identical Id */
1327 resn->Type = resc->Type;
1328 switch (resc->Type) {
1329 case ACPI_RESOURCE_TYPE_IRQ:
1330 memcpy(&resn->Data, &resp->Data,
1331 sizeof(ACPI_RESOURCE_IRQ));
1332 irq = (ACPI_RESOURCE_IRQ *)&resn->Data;
1333 irq->Interrupts[0] =
1334 ((ACPI_RESOURCE_IRQ *)&resp->Data)->
1335 Interrupts[irq->InterruptCount-1];
1336 irq->InterruptCount = 1;
1337 resn->Length = ACPI_RS_SIZE(ACPI_RESOURCE_IRQ);
1338 break;
1339 case ACPI_RESOURCE_TYPE_IO:
1340 memcpy(&resn->Data, &resp->Data,
1341 sizeof(ACPI_RESOURCE_IO));
1342 resn->Length = resp->Length;
1343 break;
1344 default:
1345 printf("acpi_allocate_resources: res=%d\n", resc->Type);
1346 rv = AE_BAD_DATA;
1347 goto out2;
1348 }
1349 resc = ACPI_NEXT_RESOURCE(resc);
1350 resn = ACPI_NEXT_RESOURCE(resn);
1351 resp = ACPI_NEXT_RESOURCE(resp);
1352 delta = (UINT8 *)resn - (UINT8 *)bufn.Pointer;
1353 if (delta >=
1354 bufn.Length-ACPI_RS_SIZE(ACPI_RESOURCE_DATA)) {
1355 bufn.Length *= 2;
1356 bufn.Pointer = realloc(bufn.Pointer, bufn.Length,
1357 M_ACPI, M_WAITOK);
1358 resn = (ACPI_RESOURCE *)((UINT8 *)bufn.Pointer + delta);
1359 }
1360 }
1361 if (resc->Type != ACPI_RESOURCE_TYPE_END_TAG) {
1362 printf("acpi_allocate_resources: resc not exhausted\n");
1363 rv = AE_BAD_DATA;
1364 goto out3;
1365 }
1366
1367 resn->Type = ACPI_RESOURCE_TYPE_END_TAG;
1368 rv = AcpiSetCurrentResources(handle, &bufn);
1369 if (ACPI_FAILURE(rv)) {
1370 printf("acpi_allocate_resources: AcpiSetCurrentResources %s\n",
1371 AcpiFormatException(rv));
1372 }
1373
1374 out3:
1375 free(bufn.Pointer, M_ACPI);
1376 out2:
1377 AcpiOsFree(bufc.Pointer);
1378 out1:
1379 AcpiOsFree(bufp.Pointer);
1380 out:
1381 return rv;
1382 }
1383 #endif /* PCI_INTR_FIXUP || ACPI_ACTIVATE_DEV */
1384
1385 SYSCTL_SETUP(sysctl_acpi_setup, "sysctl hw.acpi subtree setup")
1386 {
1387 const struct sysctlnode *node;
1388 const struct sysctlnode *ssnode;
1389
1390 if (sysctl_createv(clog, 0, NULL, NULL,
1391 CTLFLAG_PERMANENT,
1392 CTLTYPE_NODE, "hw", NULL,
1393 NULL, 0, NULL, 0,
1394 CTL_HW, CTL_EOL) != 0)
1395 return;
1396
1397 if (sysctl_createv(clog, 0, NULL, &node,
1398 CTLFLAG_PERMANENT,
1399 CTLTYPE_NODE, "acpi", NULL,
1400 NULL, 0, NULL, 0,
1401 CTL_HW, CTL_CREATE, CTL_EOL) != 0)
1402 return;
1403
1404 acpi_node = node->sysctl_num;
1405
1406 /* ACPI sleepstate sysctl */
1407 if (sysctl_createv(NULL, 0, NULL, &node,
1408 CTLFLAG_PERMANENT,
1409 CTLTYPE_NODE, "machdep", NULL,
1410 NULL, 0, NULL, 0, CTL_MACHDEP, CTL_EOL) != 0)
1411 return;
1412 if (sysctl_createv(NULL, 0, &node, &ssnode,
1413 CTLFLAG_READWRITE, CTLTYPE_INT, "sleep_state",
1414 NULL, sysctl_hw_acpi_sleepstate, 0, NULL, 0, CTL_CREATE,
1415 CTL_EOL) != 0)
1416 return;
1417 }
1418
1419 static int
1420 sysctl_hw_acpi_sleepstate(SYSCTLFN_ARGS)
1421 {
1422 int error, t;
1423 struct sysctlnode node;
1424
1425 node = *rnode;
1426 t = acpi_sleepstate;
1427 node.sysctl_data = &t;
1428 error = sysctl_lookup(SYSCTLFN_CALL(&node));
1429 if (error || newp == NULL)
1430 return error;
1431
1432 if (t < ACPI_STATE_S0 || t > ACPI_STATE_S5)
1433 return EINVAL;
1434
1435 if (acpi_softc != NULL && acpi_sleepstate != t) {
1436 acpi_sleepstate = t;
1437 aprint_normal("acpi0: entering state %d\n", t);
1438 acpi_enter_sleep_state(acpi_softc, t);
1439 aprint_normal("acpi0: resuming\n");
1440 t = acpi_sleepstate = ACPI_STATE_S0;
1441 }
1442
1443 return 0;
1444 }
1445