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