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