acpi_verbose.c revision 1.10.4.3 1 /* $NetBSD: acpi_verbose.c,v 1.10.4.3 2010/10/22 07:21:53 uebayasi Exp $ */
2
3 /*-
4 * Copyright (c) 2003, 2007, 2010 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, and Jukka Ruohonen.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 /*
33 * Copyright 2001, 2003 Wasabi Systems, Inc.
34 * All rights reserved.
35 *
36 * Written by Jason R. Thorpe for Wasabi Systems, Inc.
37 *
38 * Redistribution and use in source and binary forms, with or without
39 * modification, are permitted provided that the following conditions
40 * are met:
41 * 1. Redistributions of source code must retain the above copyright
42 * notice, this list of conditions and the following disclaimer.
43 * 2. Redistributions in binary form must reproduce the above copyright
44 * notice, this list of conditions and the following disclaimer in the
45 * documentation and/or other materials provided with the distribution.
46 * 3. All advertising materials mentioning features or use of this software
47 * must display the following acknowledgement:
48 * This product includes software developed for the NetBSD Project by
49 * Wasabi Systems, Inc.
50 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
51 * or promote products derived from this software without specific prior
52 * written permission.
53 *
54 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
55 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
56 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
57 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
58 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
59 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
60 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
61 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
62 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
63 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
64 * POSSIBILITY OF SUCH DAMAGE.
65 */
66
67 #include <sys/cdefs.h>
68 __KERNEL_RCSID(0, "$NetBSD: acpi_verbose.c,v 1.10.4.3 2010/10/22 07:21:53 uebayasi Exp $");
69
70 #include <sys/param.h>
71 #include <sys/device.h>
72 #include <sys/kernel.h>
73 #include <sys/systm.h>
74 #include <sys/module.h>
75
76 #include <dev/acpi/acpireg.h>
77 #include <dev/acpi/acpivar.h>
78 #include <dev/acpi/acpidevs_data.h>
79
80 #include <dev/pci/pcivar.h>
81
82 #include <prop/proplib.h>
83
84 #include "locators.h"
85
86 static bool acpiverbose_modcmd_prop(prop_dictionary_t);
87
88 void acpi_print_verbose_real(struct acpi_softc *);
89 void acpi_print_dev_real(const char *);
90 static void acpi_print_madt(struct acpi_softc *);
91 static ACPI_STATUS acpi_print_madt_callback(ACPI_SUBTABLE_HEADER *, void *);
92 static void acpi_print_fadt(struct acpi_softc *);
93 static void acpi_print_devnodes(struct acpi_softc *);
94 static void acpi_print_tree(struct acpi_devnode *, uint32_t);
95 static device_t device_find_by_acpi_pci_info(const struct acpi_pci_info *);
96
97 extern ACPI_TABLE_HEADER *madt_header;
98
99 MODULE(MODULE_CLASS_MISC, acpiverbose, NULL);
100
101 static int
102 acpiverbose_modcmd(modcmd_t cmd, void *arg)
103 {
104 static void (*saved_print_verbose)(struct acpi_softc *);
105 static void (*saved_print_dev)(const char *);
106 bool dump;
107
108 dump = false;
109
110 switch (cmd) {
111
112 case MODULE_CMD_INIT:
113 saved_print_verbose = acpi_print_verbose;
114 saved_print_dev = acpi_print_dev;
115 acpi_print_verbose = acpi_print_verbose_real;
116 acpi_print_dev = acpi_print_dev_real;
117 acpi_verbose_loaded = 1;
118
119 if (arg != NULL)
120 dump = acpiverbose_modcmd_prop(arg);
121
122 if (dump != false)
123 acpi_print_verbose_real(acpi_softc);
124
125 return 0;
126
127 case MODULE_CMD_FINI:
128 acpi_print_verbose = saved_print_verbose;
129 acpi_print_dev = saved_print_dev;
130 acpi_verbose_loaded = 0;
131 return 0;
132
133 default:
134 return ENOTTY;
135 }
136 }
137
138 static bool
139 acpiverbose_modcmd_prop(prop_dictionary_t dict)
140 {
141 prop_object_t obj;
142
143 obj = prop_dictionary_get(dict, "dump");
144
145 if (obj == NULL || prop_object_type(obj) != PROP_TYPE_BOOL)
146 return false;
147
148 return prop_bool_true(obj);
149 }
150
151 void
152 acpi_print_verbose_real(struct acpi_softc *sc)
153 {
154
155 acpi_print_madt(sc);
156 acpi_print_fadt(sc);
157 acpi_print_devnodes(sc);
158 acpi_print_tree(sc->sc_root, 0);
159 }
160
161 void
162 acpi_print_dev_real(const char *pnpstr)
163 {
164 int i;
165
166 for (i = 0; i < __arraycount(acpi_knowndevs); i++) {
167
168 if (strcmp(acpi_knowndevs[i].pnp, pnpstr) == 0)
169 aprint_normal("[%s] ", acpi_knowndevs[i].str);
170 }
171 }
172
173 static void
174 acpi_print_madt(struct acpi_softc *sc)
175 {
176 ACPI_TABLE_MADT *madt;
177 ACPI_STATUS rv;
178
179 rv = acpi_madt_map();
180
181 if (ACPI_FAILURE(rv) && rv != AE_ALREADY_EXISTS)
182 return;
183
184 if (madt_header == NULL)
185 return;
186
187 madt = (ACPI_TABLE_MADT *)madt_header;
188 acpi_madt_walk(acpi_print_madt_callback, sc);
189 }
190
191 static ACPI_STATUS
192 acpi_print_madt_callback(ACPI_SUBTABLE_HEADER *hdr, void *aux)
193 {
194 struct acpi_softc *sc = aux;
195 device_t self = sc->sc_dev;
196
197 /*
198 * See ACPI 4.0, section 5.2.12.
199 */
200 switch (hdr->Type) {
201
202 case ACPI_MADT_TYPE_LOCAL_APIC:
203
204 aprint_normal_dev(self, "[MADT] %-15s: "
205 "CPU ID %u, LAPIC ID %u, FLAGS 0x%02X", "LAPIC",
206 ((ACPI_MADT_LOCAL_APIC *)hdr)->ProcessorId,
207 ((ACPI_MADT_LOCAL_APIC *)hdr)->Id,
208 ((ACPI_MADT_LOCAL_APIC *)hdr)->LapicFlags);
209
210 break;
211
212 case ACPI_MADT_TYPE_IO_APIC:
213
214 aprint_normal_dev(self, "[MADT] %-15s: "
215 "ID %u, GSI %u, ADDR 0x%04X", "I/O APIC",
216 ((ACPI_MADT_IO_APIC *)hdr)->Id,
217 ((ACPI_MADT_IO_APIC *)hdr)->GlobalIrqBase,
218 ((ACPI_MADT_IO_APIC *)hdr)->Address);
219
220 break;
221
222 case ACPI_MADT_TYPE_INTERRUPT_OVERRIDE:
223
224 aprint_normal_dev(self, "[MADT] %-15s: "
225 "BUS %u, IRQ %u, GSI %u, FLAGS 0x%02X", "INTR OVERRIDE",
226 ((ACPI_MADT_INTERRUPT_OVERRIDE *)hdr)->Bus,
227 ((ACPI_MADT_INTERRUPT_OVERRIDE *)hdr)->SourceIrq,
228 ((ACPI_MADT_INTERRUPT_OVERRIDE *)hdr)->GlobalIrq,
229 ((ACPI_MADT_INTERRUPT_OVERRIDE *)hdr)->IntiFlags);
230
231 break;
232
233 case ACPI_MADT_TYPE_NMI_SOURCE:
234
235 aprint_normal_dev(self, "[MADT] %-15s: "
236 "GSI %u, FLAGS 0x%02X", "NMI SOURCE",
237 ((ACPI_MADT_NMI_SOURCE *)hdr)->GlobalIrq,
238 ((ACPI_MADT_NMI_SOURCE *)hdr)->IntiFlags);
239
240 break;
241
242 case ACPI_MADT_TYPE_LOCAL_APIC_NMI:
243
244 aprint_normal_dev(self, "[MADT] %-15s: "
245 "CPU ID %u, LINT %u, FLAGS 0x%02X", "LAPIC NMI",
246 ((ACPI_MADT_LOCAL_APIC_NMI *)hdr)->ProcessorId,
247 ((ACPI_MADT_LOCAL_APIC_NMI *)hdr)->Lint,
248 ((ACPI_MADT_LOCAL_APIC_NMI *)hdr)->IntiFlags);
249
250 break;
251
252 case ACPI_MADT_TYPE_LOCAL_APIC_OVERRIDE:
253
254 aprint_normal_dev(self, "[MADT] %-15s: "
255 "ADDR 0x%016" PRIX64"", "APIC OVERRIDE",
256 ((ACPI_MADT_LOCAL_APIC_OVERRIDE *)hdr)->Address);
257
258 break;
259
260 case ACPI_MADT_TYPE_IO_SAPIC:
261
262 aprint_normal_dev(self, "[MADT] %-15s: "
263 "ID %u, GSI %u, ADDR 0x%016" PRIX64"", "I/O SAPIC",
264 ((ACPI_MADT_IO_SAPIC *)hdr)->Id,
265 ((ACPI_MADT_IO_SAPIC *)hdr)->GlobalIrqBase,
266 ((ACPI_MADT_IO_SAPIC *)hdr)->Address);
267
268 break;
269
270 case ACPI_MADT_TYPE_LOCAL_SAPIC:
271
272 aprint_normal_dev(self, "[MADT] %-15s: "
273 "CPU ID %u, ID %u, EID %u, UID %u, FLAGS 0x%02X", "LSAPIC",
274 ((ACPI_MADT_LOCAL_SAPIC*)hdr)->ProcessorId,
275 ((ACPI_MADT_LOCAL_SAPIC*)hdr)->Id,
276 ((ACPI_MADT_LOCAL_SAPIC*)hdr)->Eid,
277 ((ACPI_MADT_LOCAL_SAPIC*)hdr)->Uid,
278 ((ACPI_MADT_LOCAL_SAPIC*)hdr)->LapicFlags);
279
280 break;
281
282 case ACPI_MADT_TYPE_INTERRUPT_SOURCE:
283
284 aprint_normal_dev(self, "[MADT] %-15s: ID %u, EID %u, "
285 "TYPE %u, PMI %u, GSI %u, FLAGS 0x%02X", "INTR SOURCE",
286 ((ACPI_MADT_INTERRUPT_SOURCE *)hdr)->Id,
287 ((ACPI_MADT_INTERRUPT_SOURCE *)hdr)->Eid,
288 ((ACPI_MADT_INTERRUPT_SOURCE *)hdr)->Type,
289 ((ACPI_MADT_INTERRUPT_SOURCE *)hdr)->IoSapicVector,
290 ((ACPI_MADT_INTERRUPT_SOURCE *)hdr)->GlobalIrq,
291 ((ACPI_MADT_INTERRUPT_SOURCE *)hdr)->Flags);
292
293 break;
294
295 case ACPI_MADT_TYPE_LOCAL_X2APIC:
296
297 aprint_normal_dev(self, "[MADT] %-15s: "
298 "ID %u, UID %u, FLAGS 0x%02X", "X2APIC",
299 ((ACPI_MADT_LOCAL_X2APIC *)hdr)->LocalApicId,
300 ((ACPI_MADT_LOCAL_X2APIC *)hdr)->Uid,
301 ((ACPI_MADT_LOCAL_X2APIC *)hdr)->LapicFlags);
302
303 break;
304
305 case ACPI_MADT_TYPE_LOCAL_X2APIC_NMI:
306
307 aprint_normal_dev(self, "[MADT] %-15s: "
308 "UID %u, LINT %u, FLAGS 0x%02X", "X2APIC NMI",
309 ((ACPI_MADT_LOCAL_X2APIC_NMI *)hdr)->Uid,
310 ((ACPI_MADT_LOCAL_X2APIC_NMI *)hdr)->Lint,
311 ((ACPI_MADT_LOCAL_X2APIC_NMI *)hdr)->IntiFlags);
312
313 break;
314
315 default:
316 aprint_normal_dev(self, "[MADT] %-15s", "UNKNOWN");
317 break;
318 }
319
320 aprint_normal("\n");
321
322 return AE_OK;
323 }
324
325 static void
326 acpi_print_fadt(struct acpi_softc *sc)
327 {
328 uint32_t i;
329
330 /*
331 * See ACPI 4.0, section 5.2.9.
332 */
333 struct acpi_fadt {
334 uint32_t fadt_offset;
335 const char *fadt_name;
336 uint64_t fadt_value;
337 };
338
339 const struct acpi_fadt acpi_fadt_table[] = {
340
341 { 36, "FACS", AcpiGbl_FADT.Facs },
342 { 40, "DSDT", AcpiGbl_FADT.Dsdt },
343 { 44, "INT_MODEL", AcpiGbl_FADT.Model },
344 { 45, "PM_PROFILE", AcpiGbl_FADT.PreferredProfile },
345 { 46, "SCI_INT", AcpiGbl_FADT.SciInterrupt },
346 { 48, "SMI_CMD", AcpiGbl_FADT.SmiCommand },
347 { 52, "ACPI_ENABLE", AcpiGbl_FADT.AcpiEnable },
348 { 53, "ACPI_DISABLE", AcpiGbl_FADT.AcpiDisable },
349 { 54, "S4BIOS_REQ", AcpiGbl_FADT.S4BiosRequest },
350 { 55, "PSTATE_CNT", AcpiGbl_FADT.PstateControl },
351 { 56, "PM1a_EVT_BLK", AcpiGbl_FADT.Pm1aEventBlock },
352 { 60, "PM1b_EVT_BLK", AcpiGbl_FADT.Pm1bEventBlock },
353 { 64, "PM1a_CNT_BLK", AcpiGbl_FADT.Pm1aControlBlock },
354 { 68, "PM1b_CNT_BLK", AcpiGbl_FADT.Pm1bControlBlock },
355 { 72, "PM2_CNT_BLK", AcpiGbl_FADT.Pm2ControlBlock },
356 { 76, "PM_TMR_BLK", AcpiGbl_FADT.PmTimerBlock },
357 { 80, "GPE0_BLK", AcpiGbl_FADT.Gpe0Block },
358 { 84, "GPE1_BLK", AcpiGbl_FADT.Gpe1Block },
359 { 88, "PM1_EVT_LEN", AcpiGbl_FADT.Pm1EventLength },
360 { 89, "PM1_CNT_LEN", AcpiGbl_FADT.Pm1ControlLength },
361 { 90, "PM2_CNT_LEN", AcpiGbl_FADT.Pm2ControlLength },
362 { 91, "PM_TMR_LEN", AcpiGbl_FADT.PmTimerLength },
363 { 92, "GPE0_BLK_LEN", AcpiGbl_FADT.Gpe0BlockLength },
364 { 93, "GPE1_BLK_LEN", AcpiGbl_FADT.Gpe1BlockLength },
365 { 94, "GPE1_BASE", AcpiGbl_FADT.Gpe1Base },
366 { 95, "CST_CNT", AcpiGbl_FADT.CstControl },
367 { 96, "P_LVL2_LAT", AcpiGbl_FADT.C2Latency },
368 { 98, "P_LVL3_LAT", AcpiGbl_FADT.C3Latency },
369 { 100, "FLUSH_SIZE", AcpiGbl_FADT.FlushSize },
370 { 102, "FLUSH_STRIDE", AcpiGbl_FADT.FlushStride },
371 { 104, "DUTY_OFFSET", AcpiGbl_FADT.DutyOffset },
372 { 105, "DUTY_WIDTH", AcpiGbl_FADT.DutyWidth },
373 { 106, "DAY_ALRM", AcpiGbl_FADT.DayAlarm },
374 { 107, "MON_ALRM", AcpiGbl_FADT.MonthAlarm },
375 { 108, "CENTURY", AcpiGbl_FADT.Century },
376 { 109, "IAPC_BOOT_ARCH",AcpiGbl_FADT.BootFlags },
377 { 128, "RESET_VALUE", AcpiGbl_FADT.ResetValue },
378 };
379
380 const struct acpi_fadt acpi_fadt_flags[] = {
381
382 { 0, "WBINVD", ACPI_FADT_WBINVD },
383 { 1, "WBINVD_FLUSH", ACPI_FADT_WBINVD_FLUSH },
384 { 2, "PROC_C1", ACPI_FADT_C1_SUPPORTED },
385 { 3, "P_LVL2_UP", ACPI_FADT_C2_MP_SUPPORTED },
386 { 4, "PWR_BUTTON", ACPI_FADT_POWER_BUTTON },
387 { 5, "SLP_BUTTON", ACPI_FADT_SLEEP_BUTTON },
388 { 6, "FIX_RTC", ACPI_FADT_FIXED_RTC },
389 { 7, "RTC_S4", ACPI_FADT_S4_RTC_WAKE },
390 { 8, "TMR_VAL_EXT", ACPI_FADT_32BIT_TIMER },
391 { 9, "DCK_CAP", ACPI_FADT_DOCKING_SUPPORTED },
392 { 10, "RESET_REG_SUP",ACPI_FADT_RESET_REGISTER },
393 { 11, "SEALED_CASE", ACPI_FADT_SEALED_CASE },
394 { 12, "HEADLESS", ACPI_FADT_HEADLESS },
395 { 13, "CPU_SW_SLP", ACPI_FADT_SLEEP_TYPE },
396 { 14, "PCI_EXP_WAK", ACPI_FADT_PCI_EXPRESS_WAKE },
397 { 15, "PLATFORM_CLK", ACPI_FADT_PLATFORM_CLOCK },
398 { 16, "S4_RTC_STS", ACPI_FADT_S4_RTC_VALID },
399 { 17, "REMOTE_POWER", ACPI_FADT_REMOTE_POWER_ON },
400 { 18, "APIC_CLUSTER", ACPI_FADT_APIC_CLUSTER },
401 { 19, "APIC_PHYSICAL",ACPI_FADT_APIC_PHYSICAL },
402 };
403
404 for (i = 0; i < __arraycount(acpi_fadt_table); i++) {
405
406 aprint_normal_dev(sc->sc_dev,
407 "[FADT] %-15s: 0x%016" PRIX64"\n",
408 acpi_fadt_table[i].fadt_name,
409 acpi_fadt_table[i].fadt_value);
410 }
411
412 for (i = 0; i < __arraycount(acpi_fadt_flags); i++) {
413
414 aprint_normal_dev(sc->sc_dev,
415 "[FADT] %-15s: 0x%016" PRIX64"\n",
416 acpi_fadt_flags[i].fadt_name, AcpiGbl_FADT.Flags &
417 acpi_fadt_flags[i].fadt_value);
418
419 KASSERT(i == acpi_fadt_flags[i].fadt_offset);
420 KASSERT(__BIT(acpi_fadt_flags[i].fadt_offset) ==
421 acpi_fadt_flags[i].fadt_value);
422 }
423 }
424
425 static void
426 acpi_print_devnodes(struct acpi_softc *sc)
427 {
428 struct acpi_devnode *ad;
429 ACPI_DEVICE_INFO *di;
430
431 SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
432
433 di = ad->ad_devinfo;
434 aprint_normal_dev(sc->sc_dev, "[%-4s] ", ad->ad_name);
435
436 aprint_normal("HID %-10s ",
437 ((di->Valid & ACPI_VALID_HID) != 0) ?
438 di->HardwareId.String: "-");
439
440 aprint_normal("UID %-4s ",
441 ((di->Valid & ACPI_VALID_UID) != 0) ?
442 di->UniqueId.String : "-");
443
444 if ((di->Valid & ACPI_VALID_STA) != 0)
445 aprint_normal("STA 0x%08X ", di->CurrentStatus);
446 else
447 aprint_normal("STA %10s ", "-");
448
449 if ((di->Valid & ACPI_VALID_ADR) != 0)
450 aprint_normal("ADR 0x%016" PRIX64"", di->Address);
451 else
452 aprint_normal("ADR -");
453
454 aprint_normal("\n");
455 }
456 aprint_normal("\n");
457 }
458
459 static void
460 acpi_print_tree(struct acpi_devnode *ad, uint32_t level)
461 {
462 struct acpi_devnode *child;
463 device_t pcidev;
464 uint32_t i;
465
466 for (i = 0; i < level; i++)
467 aprint_normal(" ");
468
469 aprint_normal("%-5s [%02u] [%c%c] ", ad->ad_name, ad->ad_type,
470 ((ad->ad_flags & ACPI_DEVICE_POWER) != 0) ? 'P' : ' ',
471 ((ad->ad_flags & ACPI_DEVICE_WAKEUP) != 0) ? 'W' : ' ');
472
473 if (ad->ad_device != NULL)
474 aprint_normal("<%s> ", device_xname(ad->ad_device));
475
476 if (ad->ad_pciinfo != NULL) {
477
478 aprint_normal("(PCI) @ 0x%02X:0x%02X:0x%02X:0x%02X ",
479 ad->ad_pciinfo->ap_segment, ad->ad_pciinfo->ap_bus,
480 ad->ad_pciinfo->ap_device, ad->ad_pciinfo->ap_function);
481
482 if ((ad->ad_devinfo->Flags & ACPI_PCI_ROOT_BRIDGE) != 0)
483 aprint_normal("[R] ");
484
485 if (ad->ad_pciinfo->ap_bridge != false)
486 aprint_normal("[B] -> 0x%02X ",
487 ad->ad_pciinfo->ap_downbus);
488
489 pcidev = device_find_by_acpi_pci_info(ad->ad_pciinfo);
490 if (pcidev != NULL)
491 aprint_normal("<%s>", device_xname(pcidev));
492 }
493
494 aprint_normal("\n");
495
496 SIMPLEQ_FOREACH(child, &ad->ad_child_head, ad_child_list)
497 acpi_print_tree(child, level + 1);
498 }
499
500 /*
501 * device_find_by_acpi_pci_info:
502 *
503 * Returns the device corresponding to the given PCI info, or NULL
504 * if it doesn't exist.
505 */
506 static device_t
507 device_find_by_acpi_pci_info(const struct acpi_pci_info *ap)
508 {
509 device_t dv, pr;
510 struct pci_softc *pci;
511 deviter_t di;
512
513 if (ap->ap_function == 0xFFFF)
514 return NULL;
515
516 for (dv = deviter_first(&di, DEVITER_F_ROOT_FIRST); dv != NULL;
517 dv = deviter_next(&di)) {
518 pr = device_parent(dv);
519 if ((pr == NULL) || !device_is_a(pr, "pci"))
520 continue;
521 if (dv->dv_locators == NULL) /* This should not happen. */
522 continue;
523 pci = device_private(pr);
524 if (pci->sc_bus == ap->ap_bus &&
525 device_locator(dv, PCICF_DEV) == ap->ap_device &&
526 device_locator(dv, PCICF_FUNCTION) == ap->ap_function)
527 break;
528 }
529 deviter_release(&di);
530
531 return dv;
532 }
533