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