pci_subr.c revision 1.64 1 /* $NetBSD: pci_subr.c,v 1.64 2006/05/31 10:01:18 drochner Exp $ */
2
3 /*
4 * Copyright (c) 1997 Zubin D. Dittia. All rights reserved.
5 * Copyright (c) 1995, 1996, 1998, 2000
6 * Christopher G. Demetriou. All rights reserved.
7 * Copyright (c) 1994 Charles M. Hannum. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. All advertising materials mentioning features or use of this software
18 * must display the following acknowledgement:
19 * This product includes software developed by Charles M. Hannum.
20 * 4. The name of the author may not be used to endorse or promote products
21 * derived from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 /*
36 * PCI autoconfiguration support functions.
37 *
38 * Note: This file is also built into a userland library (libpci).
39 * Pay attention to this when you make modifications.
40 */
41
42 #include <sys/cdefs.h>
43 __KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.64 2006/05/31 10:01:18 drochner Exp $");
44
45 #ifdef _KERNEL_OPT
46 #include "opt_pci.h"
47 #endif
48
49 #include <sys/param.h>
50
51 #ifdef _KERNEL
52 #include <sys/systm.h>
53 #include <machine/intr.h>
54 #else
55 #include <pci.h>
56 #include <stdio.h>
57 #endif
58
59 #include <dev/pci/pcireg.h>
60 #ifdef _KERNEL
61 #include <dev/pci/pcivar.h>
62 #endif
63 #ifdef PCIVERBOSE
64 #include <dev/pci/pcidevs.h>
65 #endif
66
67 /*
68 * Descriptions of known PCI classes and subclasses.
69 *
70 * Subclasses are described in the same way as classes, but have a
71 * NULL subclass pointer.
72 */
73 struct pci_class {
74 const char *name;
75 int val; /* as wide as pci_{,sub}class_t */
76 const struct pci_class *subclasses;
77 };
78
79 static const struct pci_class pci_subclass_prehistoric[] = {
80 { "miscellaneous", PCI_SUBCLASS_PREHISTORIC_MISC, },
81 { "VGA", PCI_SUBCLASS_PREHISTORIC_VGA, },
82 { 0 }
83 };
84
85 static const struct pci_class pci_subclass_mass_storage[] = {
86 { "SCSI", PCI_SUBCLASS_MASS_STORAGE_SCSI, },
87 { "IDE", PCI_SUBCLASS_MASS_STORAGE_IDE, },
88 { "floppy", PCI_SUBCLASS_MASS_STORAGE_FLOPPY, },
89 { "IPI", PCI_SUBCLASS_MASS_STORAGE_IPI, },
90 { "RAID", PCI_SUBCLASS_MASS_STORAGE_RAID, },
91 { "ATA", PCI_SUBCLASS_MASS_STORAGE_ATA, },
92 { "SATA", PCI_SUBCLASS_MASS_STORAGE_SATA, },
93 { "SAS", PCI_SUBCLASS_MASS_STORAGE_SAS, },
94 { "miscellaneous", PCI_SUBCLASS_MASS_STORAGE_MISC, },
95 { 0 },
96 };
97
98 static const struct pci_class pci_subclass_network[] = {
99 { "ethernet", PCI_SUBCLASS_NETWORK_ETHERNET, },
100 { "token ring", PCI_SUBCLASS_NETWORK_TOKENRING, },
101 { "FDDI", PCI_SUBCLASS_NETWORK_FDDI, },
102 { "ATM", PCI_SUBCLASS_NETWORK_ATM, },
103 { "ISDN", PCI_SUBCLASS_NETWORK_ISDN, },
104 { "WorldFip", PCI_SUBCLASS_NETWORK_WORLDFIP, },
105 { "PCMIG Multi Computing", PCI_SUBCLASS_NETWORK_PCIMGMULTICOMP, },
106 { "miscellaneous", PCI_SUBCLASS_NETWORK_MISC, },
107 { 0 },
108 };
109
110 static const struct pci_class pci_subclass_display[] = {
111 { "VGA", PCI_SUBCLASS_DISPLAY_VGA, },
112 { "XGA", PCI_SUBCLASS_DISPLAY_XGA, },
113 { "3D", PCI_SUBCLASS_DISPLAY_3D, },
114 { "miscellaneous", PCI_SUBCLASS_DISPLAY_MISC, },
115 { 0 },
116 };
117
118 static const struct pci_class pci_subclass_multimedia[] = {
119 { "video", PCI_SUBCLASS_MULTIMEDIA_VIDEO, },
120 { "audio", PCI_SUBCLASS_MULTIMEDIA_AUDIO, },
121 { "telephony", PCI_SUBCLASS_MULTIMEDIA_TELEPHONY, },
122 { "miscellaneous", PCI_SUBCLASS_MULTIMEDIA_MISC, },
123 { 0 },
124 };
125
126 static const struct pci_class pci_subclass_memory[] = {
127 { "RAM", PCI_SUBCLASS_MEMORY_RAM, },
128 { "flash", PCI_SUBCLASS_MEMORY_FLASH, },
129 { "miscellaneous", PCI_SUBCLASS_MEMORY_MISC, },
130 { 0 },
131 };
132
133 static const struct pci_class pci_subclass_bridge[] = {
134 { "host", PCI_SUBCLASS_BRIDGE_HOST, },
135 { "ISA", PCI_SUBCLASS_BRIDGE_ISA, },
136 { "EISA", PCI_SUBCLASS_BRIDGE_EISA, },
137 { "MicroChannel", PCI_SUBCLASS_BRIDGE_MC, },
138 { "PCI", PCI_SUBCLASS_BRIDGE_PCI, },
139 { "PCMCIA", PCI_SUBCLASS_BRIDGE_PCMCIA, },
140 { "NuBus", PCI_SUBCLASS_BRIDGE_NUBUS, },
141 { "CardBus", PCI_SUBCLASS_BRIDGE_CARDBUS, },
142 { "RACEway", PCI_SUBCLASS_BRIDGE_RACEWAY, },
143 { "Semi-transparent PCI", PCI_SUBCLASS_BRIDGE_STPCI, },
144 { "InfiniBand", PCI_SUBCLASS_BRIDGE_INFINIBAND, },
145 { "miscellaneous", PCI_SUBCLASS_BRIDGE_MISC, },
146 { 0 },
147 };
148
149 static const struct pci_class pci_subclass_communications[] = {
150 { "serial", PCI_SUBCLASS_COMMUNICATIONS_SERIAL, },
151 { "parallel", PCI_SUBCLASS_COMMUNICATIONS_PARALLEL, },
152 { "multi-port serial", PCI_SUBCLASS_COMMUNICATIONS_MPSERIAL, },
153 { "modem", PCI_SUBCLASS_COMMUNICATIONS_MODEM, },
154 { "GPIB", PCI_SUBCLASS_COMMUNICATIONS_GPIB, },
155 { "smartcard", PCI_SUBCLASS_COMMUNICATIONS_SMARTCARD, },
156 { "miscellaneous", PCI_SUBCLASS_COMMUNICATIONS_MISC, },
157 { 0 },
158 };
159
160 static const struct pci_class pci_subclass_system[] = {
161 { "interrupt", PCI_SUBCLASS_SYSTEM_PIC, },
162 { "8237 DMA", PCI_SUBCLASS_SYSTEM_DMA, },
163 { "8254 timer", PCI_SUBCLASS_SYSTEM_TIMER, },
164 { "RTC", PCI_SUBCLASS_SYSTEM_RTC, },
165 { "PCI Hot-Plug", PCI_SUBCLASS_SYSTEM_PCIHOTPLUG, },
166 { "SD Host Controller", PCI_SUBCLASS_SYSTEM_SDHC, },
167 { "miscellaneous", PCI_SUBCLASS_SYSTEM_MISC, },
168 { 0 },
169 };
170
171 static const struct pci_class pci_subclass_input[] = {
172 { "keyboard", PCI_SUBCLASS_INPUT_KEYBOARD, },
173 { "digitizer", PCI_SUBCLASS_INPUT_DIGITIZER, },
174 { "mouse", PCI_SUBCLASS_INPUT_MOUSE, },
175 { "scanner", PCI_SUBCLASS_INPUT_SCANNER, },
176 { "game port", PCI_SUBCLASS_INPUT_GAMEPORT, },
177 { "miscellaneous", PCI_SUBCLASS_INPUT_MISC, },
178 { 0 },
179 };
180
181 static const struct pci_class pci_subclass_dock[] = {
182 { "generic", PCI_SUBCLASS_DOCK_GENERIC, },
183 { "miscellaneous", PCI_SUBCLASS_DOCK_MISC, },
184 { 0 },
185 };
186
187 static const struct pci_class pci_subclass_processor[] = {
188 { "386", PCI_SUBCLASS_PROCESSOR_386, },
189 { "486", PCI_SUBCLASS_PROCESSOR_486, },
190 { "Pentium", PCI_SUBCLASS_PROCESSOR_PENTIUM, },
191 { "Alpha", PCI_SUBCLASS_PROCESSOR_ALPHA, },
192 { "PowerPC", PCI_SUBCLASS_PROCESSOR_POWERPC, },
193 { "MIPS", PCI_SUBCLASS_PROCESSOR_MIPS, },
194 { "Co-processor", PCI_SUBCLASS_PROCESSOR_COPROC, },
195 { 0 },
196 };
197
198 static const struct pci_class pci_subclass_serialbus[] = {
199 { "Firewire", PCI_SUBCLASS_SERIALBUS_FIREWIRE, },
200 { "ACCESS.bus", PCI_SUBCLASS_SERIALBUS_ACCESS, },
201 { "SSA", PCI_SUBCLASS_SERIALBUS_SSA, },
202 { "USB", PCI_SUBCLASS_SERIALBUS_USB, },
203 /* XXX Fiber Channel/_FIBRECHANNEL */
204 { "Fiber Channel", PCI_SUBCLASS_SERIALBUS_FIBER, },
205 { "SMBus", PCI_SUBCLASS_SERIALBUS_SMBUS, },
206 { "InfiniBand", PCI_SUBCLASS_SERIALBUS_INFINIBAND, },
207 { "IPMI", PCI_SUBCLASS_SERIALBUS_IPMI, },
208 { "SERCOS", PCI_SUBCLASS_SERIALBUS_SERCOS, },
209 { "CANbus", PCI_SUBCLASS_SERIALBUS_CANBUS, },
210 { 0 },
211 };
212
213 static const struct pci_class pci_subclass_wireless[] = {
214 { "IrDA", PCI_SUBCLASS_WIRELESS_IRDA, },
215 { "Consumer IR", PCI_SUBCLASS_WIRELESS_CONSUMERIR, },
216 { "RF", PCI_SUBCLASS_WIRELESS_RF, },
217 { "bluetooth", PCI_SUBCLASS_WIRELESS_BLUETOOTH, },
218 { "broadband", PCI_SUBCLASS_WIRELESS_BROADBAND, },
219 { "802.11a (5 GHz)", PCI_SUBCLASS_WIRELESS_802_11A, },
220 { "802.11b (2.4 GHz)", PCI_SUBCLASS_WIRELESS_802_11B, },
221 { "miscellaneous", PCI_SUBCLASS_WIRELESS_MISC, },
222 { 0 },
223 };
224
225 static const struct pci_class pci_subclass_i2o[] = {
226 { "standard", PCI_SUBCLASS_I2O_STANDARD, },
227 { 0 },
228 };
229
230 static const struct pci_class pci_subclass_satcom[] = {
231 { "TV", PCI_SUBCLASS_SATCOM_TV, },
232 { "audio", PCI_SUBCLASS_SATCOM_AUDIO, },
233 { "voice", PCI_SUBCLASS_SATCOM_VOICE, },
234 { "data", PCI_SUBCLASS_SATCOM_DATA, },
235 { 0 },
236 };
237
238 static const struct pci_class pci_subclass_crypto[] = {
239 { "network/computing", PCI_SUBCLASS_CRYPTO_NETCOMP, },
240 { "entertainment", PCI_SUBCLASS_CRYPTO_ENTERTAINMENT, },
241 { "miscellaneous", PCI_SUBCLASS_CRYPTO_MISC, },
242 { 0 },
243 };
244
245 static const struct pci_class pci_subclass_dasp[] = {
246 { "DPIO", PCI_SUBCLASS_DASP_DPIO, },
247 { "Time and Frequency", PCI_SUBCLASS_DASP_TIMEFREQ, },
248 { "synchronization", PCI_SUBCLASS_DASP_SYNC, },
249 { "management", PCI_SUBCLASS_DASP_MGMT, },
250 { "miscellaneous", PCI_SUBCLASS_DASP_MISC, },
251 { 0 },
252 };
253
254 static const struct pci_class pci_class[] = {
255 { "prehistoric", PCI_CLASS_PREHISTORIC,
256 pci_subclass_prehistoric, },
257 { "mass storage", PCI_CLASS_MASS_STORAGE,
258 pci_subclass_mass_storage, },
259 { "network", PCI_CLASS_NETWORK,
260 pci_subclass_network, },
261 { "display", PCI_CLASS_DISPLAY,
262 pci_subclass_display, },
263 { "multimedia", PCI_CLASS_MULTIMEDIA,
264 pci_subclass_multimedia, },
265 { "memory", PCI_CLASS_MEMORY,
266 pci_subclass_memory, },
267 { "bridge", PCI_CLASS_BRIDGE,
268 pci_subclass_bridge, },
269 { "communications", PCI_CLASS_COMMUNICATIONS,
270 pci_subclass_communications, },
271 { "system", PCI_CLASS_SYSTEM,
272 pci_subclass_system, },
273 { "input", PCI_CLASS_INPUT,
274 pci_subclass_input, },
275 { "dock", PCI_CLASS_DOCK,
276 pci_subclass_dock, },
277 { "processor", PCI_CLASS_PROCESSOR,
278 pci_subclass_processor, },
279 { "serial bus", PCI_CLASS_SERIALBUS,
280 pci_subclass_serialbus, },
281 { "wireless", PCI_CLASS_WIRELESS,
282 pci_subclass_wireless, },
283 { "I2O", PCI_CLASS_I2O,
284 pci_subclass_i2o, },
285 { "satellite comm", PCI_CLASS_SATCOM,
286 pci_subclass_satcom, },
287 { "crypto", PCI_CLASS_CRYPTO,
288 pci_subclass_crypto, },
289 { "DASP", PCI_CLASS_DASP,
290 pci_subclass_dasp, },
291 { "undefined", PCI_CLASS_UNDEFINED,
292 0, },
293 { 0 },
294 };
295
296 #ifdef PCIVERBOSE
297 /*
298 * Descriptions of of known vendors and devices ("products").
299 */
300 struct pci_vendor {
301 pci_vendor_id_t vendor;
302 const char *vendorname;
303 };
304 struct pci_product {
305 pci_vendor_id_t vendor;
306 pci_product_id_t product;
307 const char *productname;
308 };
309
310 #include <dev/pci/pcidevs_data.h>
311 #endif /* PCIVERBOSE */
312
313 const char *
314 pci_findvendor(pcireg_t id_reg)
315 {
316 #ifdef PCIVERBOSE
317 pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
318 int n;
319
320 for (n = 0; n < pci_nvendors; n++)
321 if (pci_vendors[n].vendor == vendor)
322 return (pci_vendors[n].vendorname);
323 #endif
324 return (NULL);
325 }
326
327 const char *
328 pci_findproduct(pcireg_t id_reg)
329 {
330 #ifdef PCIVERBOSE
331 pci_vendor_id_t vendor = PCI_VENDOR(id_reg);
332 pci_product_id_t product = PCI_PRODUCT(id_reg);
333 int n;
334
335 for (n = 0; n < pci_nproducts; n++)
336 if (pci_products[n].vendor == vendor &&
337 pci_products[n].product == product)
338 return (pci_products[n].productname);
339 #endif
340 return (NULL);
341 }
342
343 void
344 pci_devinfo(pcireg_t id_reg, pcireg_t class_reg, int showclass, char *cp,
345 size_t l)
346 {
347 pci_vendor_id_t vendor;
348 pci_product_id_t product;
349 pci_class_t class;
350 pci_subclass_t subclass;
351 pci_interface_t interface;
352 pci_revision_t revision;
353 const char *vendor_namep, *product_namep;
354 const struct pci_class *classp, *subclassp;
355 #ifdef PCIVERBOSE
356 const char *unmatched = "unknown ";
357 #else
358 const char *unmatched = "";
359 #endif
360 char *ep;
361
362 ep = cp + l;
363
364 vendor = PCI_VENDOR(id_reg);
365 product = PCI_PRODUCT(id_reg);
366
367 class = PCI_CLASS(class_reg);
368 subclass = PCI_SUBCLASS(class_reg);
369 interface = PCI_INTERFACE(class_reg);
370 revision = PCI_REVISION(class_reg);
371
372 vendor_namep = pci_findvendor(id_reg);
373 product_namep = pci_findproduct(id_reg);
374
375 classp = pci_class;
376 while (classp->name != NULL) {
377 if (class == classp->val)
378 break;
379 classp++;
380 }
381
382 subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
383 while (subclassp && subclassp->name != NULL) {
384 if (subclass == subclassp->val)
385 break;
386 subclassp++;
387 }
388
389 if (vendor_namep == NULL)
390 cp += snprintf(cp, ep - cp, "%svendor 0x%04x product 0x%04x",
391 unmatched, vendor, product);
392 else if (product_namep != NULL)
393 cp += snprintf(cp, ep - cp, "%s %s", vendor_namep,
394 product_namep);
395 else
396 cp += snprintf(cp, ep - cp, "%s product 0x%04x",
397 vendor_namep, product);
398 if (showclass) {
399 cp += snprintf(cp, ep - cp, " (");
400 if (classp->name == NULL)
401 cp += snprintf(cp, ep - cp,
402 "class 0x%02x, subclass 0x%02x", class, subclass);
403 else {
404 if (subclassp == NULL || subclassp->name == NULL)
405 cp += snprintf(cp, ep - cp,
406 "%s subclass 0x%02x",
407 classp->name, subclass);
408 else
409 cp += snprintf(cp, ep - cp, "%s %s",
410 subclassp->name, classp->name);
411 }
412 if (interface != 0)
413 cp += snprintf(cp, ep - cp, ", interface 0x%02x",
414 interface);
415 if (revision != 0)
416 cp += snprintf(cp, ep - cp, ", revision 0x%02x",
417 revision);
418 cp += snprintf(cp, ep - cp, ")");
419 }
420 }
421
422 /*
423 * Print out most of the PCI configuration registers. Typically used
424 * in a device attach routine like this:
425 *
426 * #ifdef MYDEV_DEBUG
427 * printf("%s: ", sc->sc_dev.dv_xname);
428 * pci_conf_print(pa->pa_pc, pa->pa_tag, NULL);
429 * #endif
430 */
431
432 #define i2o(i) ((i) * 4)
433 #define o2i(o) ((o) / 4)
434 #define onoff(str, bit) \
435 printf(" %s: %s\n", (str), (rval & (bit)) ? "on" : "off");
436
437 static void
438 pci_conf_print_common(
439 #ifdef _KERNEL
440 pci_chipset_tag_t pc, pcitag_t tag,
441 #endif
442 const pcireg_t *regs)
443 {
444 const char *name;
445 const struct pci_class *classp, *subclassp;
446 pcireg_t rval;
447
448 rval = regs[o2i(PCI_ID_REG)];
449 name = pci_findvendor(rval);
450 if (name)
451 printf(" Vendor Name: %s (0x%04x)\n", name,
452 PCI_VENDOR(rval));
453 else
454 printf(" Vendor ID: 0x%04x\n", PCI_VENDOR(rval));
455 name = pci_findproduct(rval);
456 if (name)
457 printf(" Device Name: %s (0x%04x)\n", name,
458 PCI_PRODUCT(rval));
459 else
460 printf(" Device ID: 0x%04x\n", PCI_PRODUCT(rval));
461
462 rval = regs[o2i(PCI_COMMAND_STATUS_REG)];
463
464 printf(" Command register: 0x%04x\n", rval & 0xffff);
465 onoff("I/O space accesses", PCI_COMMAND_IO_ENABLE);
466 onoff("Memory space accesses", PCI_COMMAND_MEM_ENABLE);
467 onoff("Bus mastering", PCI_COMMAND_MASTER_ENABLE);
468 onoff("Special cycles", PCI_COMMAND_SPECIAL_ENABLE);
469 onoff("MWI transactions", PCI_COMMAND_INVALIDATE_ENABLE);
470 onoff("Palette snooping", PCI_COMMAND_PALETTE_ENABLE);
471 onoff("Parity error checking", PCI_COMMAND_PARITY_ENABLE);
472 onoff("Address/data stepping", PCI_COMMAND_STEPPING_ENABLE);
473 onoff("System error (SERR)", PCI_COMMAND_SERR_ENABLE);
474 onoff("Fast back-to-back transactions", PCI_COMMAND_BACKTOBACK_ENABLE);
475
476 printf(" Status register: 0x%04x\n", (rval >> 16) & 0xffff);
477 onoff("Capability List support", PCI_STATUS_CAPLIST_SUPPORT);
478 onoff("66 MHz capable", PCI_STATUS_66MHZ_SUPPORT);
479 onoff("User Definable Features (UDF) support", PCI_STATUS_UDF_SUPPORT);
480 onoff("Fast back-to-back capable", PCI_STATUS_BACKTOBACK_SUPPORT);
481 onoff("Data parity error detected", PCI_STATUS_PARITY_ERROR);
482
483 printf(" DEVSEL timing: ");
484 switch (rval & PCI_STATUS_DEVSEL_MASK) {
485 case PCI_STATUS_DEVSEL_FAST:
486 printf("fast");
487 break;
488 case PCI_STATUS_DEVSEL_MEDIUM:
489 printf("medium");
490 break;
491 case PCI_STATUS_DEVSEL_SLOW:
492 printf("slow");
493 break;
494 default:
495 printf("unknown/reserved"); /* XXX */
496 break;
497 }
498 printf(" (0x%x)\n", (rval & PCI_STATUS_DEVSEL_MASK) >> 25);
499
500 onoff("Slave signaled Target Abort", PCI_STATUS_TARGET_TARGET_ABORT);
501 onoff("Master received Target Abort", PCI_STATUS_MASTER_TARGET_ABORT);
502 onoff("Master received Master Abort", PCI_STATUS_MASTER_ABORT);
503 onoff("Asserted System Error (SERR)", PCI_STATUS_SPECIAL_ERROR);
504 onoff("Parity error detected", PCI_STATUS_PARITY_DETECT);
505
506 rval = regs[o2i(PCI_CLASS_REG)];
507 for (classp = pci_class; classp->name != NULL; classp++) {
508 if (PCI_CLASS(rval) == classp->val)
509 break;
510 }
511 subclassp = (classp->name != NULL) ? classp->subclasses : NULL;
512 while (subclassp && subclassp->name != NULL) {
513 if (PCI_SUBCLASS(rval) == subclassp->val)
514 break;
515 subclassp++;
516 }
517 if (classp->name != NULL) {
518 printf(" Class Name: %s (0x%02x)\n", classp->name,
519 PCI_CLASS(rval));
520 if (subclassp != NULL && subclassp->name != NULL)
521 printf(" Subclass Name: %s (0x%02x)\n",
522 subclassp->name, PCI_SUBCLASS(rval));
523 else
524 printf(" Subclass ID: 0x%02x\n", PCI_SUBCLASS(rval));
525 } else {
526 printf(" Class ID: 0x%02x\n", PCI_CLASS(rval));
527 printf(" Subclass ID: 0x%02x\n", PCI_SUBCLASS(rval));
528 }
529 printf(" Interface: 0x%02x\n", PCI_INTERFACE(rval));
530 printf(" Revision ID: 0x%02x\n", PCI_REVISION(rval));
531
532 rval = regs[o2i(PCI_BHLC_REG)];
533 printf(" BIST: 0x%02x\n", PCI_BIST(rval));
534 printf(" Header Type: 0x%02x%s (0x%02x)\n", PCI_HDRTYPE_TYPE(rval),
535 PCI_HDRTYPE_MULTIFN(rval) ? "+multifunction" : "",
536 PCI_HDRTYPE(rval));
537 printf(" Latency Timer: 0x%02x\n", PCI_LATTIMER(rval));
538 printf(" Cache Line Size: 0x%02x\n", PCI_CACHELINE(rval));
539 }
540
541 static int
542 pci_conf_print_bar(
543 #ifdef _KERNEL
544 pci_chipset_tag_t pc, pcitag_t tag,
545 #endif
546 const pcireg_t *regs, int reg, const char *name
547 #ifdef _KERNEL
548 , int sizebar
549 #endif
550 )
551 {
552 int width;
553 pcireg_t rval, rval64h;
554 #ifdef _KERNEL
555 int s;
556 pcireg_t mask, mask64h;
557 #endif
558
559 width = 4;
560
561 /*
562 * Section 6.2.5.1, `Address Maps', tells us that:
563 *
564 * 1) The builtin software should have already mapped the
565 * device in a reasonable way.
566 *
567 * 2) A device which wants 2^n bytes of memory will hardwire
568 * the bottom n bits of the address to 0. As recommended,
569 * we write all 1s and see what we get back.
570 */
571
572 rval = regs[o2i(reg)];
573 if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM &&
574 PCI_MAPREG_MEM_TYPE(rval) == PCI_MAPREG_MEM_TYPE_64BIT) {
575 rval64h = regs[o2i(reg + 4)];
576 width = 8;
577 } else
578 rval64h = 0;
579
580 #ifdef _KERNEL
581 /* XXX don't size unknown memory type? */
582 if (rval != 0 && sizebar) {
583 /*
584 * The following sequence seems to make some devices
585 * (e.g. host bus bridges, which don't normally
586 * have their space mapped) very unhappy, to
587 * the point of crashing the system.
588 *
589 * Therefore, if the mapping register is zero to
590 * start out with, don't bother trying.
591 */
592 s = splhigh();
593 pci_conf_write(pc, tag, reg, 0xffffffff);
594 mask = pci_conf_read(pc, tag, reg);
595 pci_conf_write(pc, tag, reg, rval);
596 if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM &&
597 PCI_MAPREG_MEM_TYPE(rval) == PCI_MAPREG_MEM_TYPE_64BIT) {
598 pci_conf_write(pc, tag, reg + 4, 0xffffffff);
599 mask64h = pci_conf_read(pc, tag, reg + 4);
600 pci_conf_write(pc, tag, reg + 4, rval64h);
601 } else
602 mask64h = 0;
603 splx(s);
604 } else
605 mask = mask64h = 0;
606 #endif /* _KERNEL */
607
608 printf(" Base address register at 0x%02x", reg);
609 if (name)
610 printf(" (%s)", name);
611 printf("\n ");
612 if (rval == 0) {
613 printf("not implemented(?)\n");
614 return width;
615 }
616 printf("type: ");
617 if (PCI_MAPREG_TYPE(rval) == PCI_MAPREG_TYPE_MEM) {
618 const char *type, *prefetch;
619
620 switch (PCI_MAPREG_MEM_TYPE(rval)) {
621 case PCI_MAPREG_MEM_TYPE_32BIT:
622 type = "32-bit";
623 break;
624 case PCI_MAPREG_MEM_TYPE_32BIT_1M:
625 type = "32-bit-1M";
626 break;
627 case PCI_MAPREG_MEM_TYPE_64BIT:
628 type = "64-bit";
629 break;
630 default:
631 type = "unknown (XXX)";
632 break;
633 }
634 if (PCI_MAPREG_MEM_PREFETCHABLE(rval))
635 prefetch = "";
636 else
637 prefetch = "non";
638 printf("%s %sprefetchable memory\n", type, prefetch);
639 switch (PCI_MAPREG_MEM_TYPE(rval)) {
640 case PCI_MAPREG_MEM_TYPE_64BIT:
641 printf(" base: 0x%016llx, ",
642 PCI_MAPREG_MEM64_ADDR(
643 ((((long long) rval64h) << 32) | rval)));
644 #ifdef _KERNEL
645 if (sizebar)
646 printf("size: 0x%016llx",
647 PCI_MAPREG_MEM64_SIZE(
648 ((((long long) mask64h) << 32) | mask)));
649 else
650 #endif /* _KERNEL */
651 printf("not sized");
652 printf("\n");
653 break;
654 case PCI_MAPREG_MEM_TYPE_32BIT:
655 case PCI_MAPREG_MEM_TYPE_32BIT_1M:
656 default:
657 printf(" base: 0x%08x, ",
658 PCI_MAPREG_MEM_ADDR(rval));
659 #ifdef _KERNEL
660 if (sizebar)
661 printf("size: 0x%08x",
662 PCI_MAPREG_MEM_SIZE(mask));
663 else
664 #endif /* _KERNEL */
665 printf("not sized");
666 printf("\n");
667 break;
668 }
669 } else {
670 #ifdef _KERNEL
671 if (sizebar)
672 printf("%d-bit ", mask & ~0x0000ffff ? 32 : 16);
673 #endif /* _KERNEL */
674 printf("i/o\n");
675 printf(" base: 0x%08x, ", PCI_MAPREG_IO_ADDR(rval));
676 #ifdef _KERNEL
677 if (sizebar)
678 printf("size: 0x%08x", PCI_MAPREG_IO_SIZE(mask));
679 else
680 #endif /* _KERNEL */
681 printf("not sized");
682 printf("\n");
683 }
684
685 return width;
686 }
687
688 static void
689 pci_conf_print_regs(const pcireg_t *regs, int first, int pastlast)
690 {
691 int off, needaddr, neednl;
692
693 needaddr = 1;
694 neednl = 0;
695 for (off = first; off < pastlast; off += 4) {
696 if ((off % 16) == 0 || needaddr) {
697 printf(" 0x%02x:", off);
698 needaddr = 0;
699 }
700 printf(" 0x%08x", regs[o2i(off)]);
701 neednl = 1;
702 if ((off % 16) == 12) {
703 printf("\n");
704 neednl = 0;
705 }
706 }
707 if (neednl)
708 printf("\n");
709 }
710
711 static void
712 pci_conf_print_type0(
713 #ifdef _KERNEL
714 pci_chipset_tag_t pc, pcitag_t tag,
715 #endif
716 const pcireg_t *regs
717 #ifdef _KERNEL
718 , int sizebars
719 #endif
720 )
721 {
722 int off, width;
723 pcireg_t rval;
724
725 for (off = PCI_MAPREG_START; off < PCI_MAPREG_END; off += width) {
726 #ifdef _KERNEL
727 width = pci_conf_print_bar(pc, tag, regs, off, NULL, sizebars);
728 #else
729 width = pci_conf_print_bar(regs, off, NULL);
730 #endif
731 }
732
733 printf(" Cardbus CIS Pointer: 0x%08x\n", regs[o2i(0x28)]);
734
735 rval = regs[o2i(PCI_SUBSYS_ID_REG)];
736 printf(" Subsystem vendor ID: 0x%04x\n", PCI_VENDOR(rval));
737 printf(" Subsystem ID: 0x%04x\n", PCI_PRODUCT(rval));
738
739 /* XXX */
740 printf(" Expansion ROM Base Address: 0x%08x\n", regs[o2i(0x30)]);
741
742 if (regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)
743 printf(" Capability list pointer: 0x%02x\n",
744 PCI_CAPLIST_PTR(regs[o2i(PCI_CAPLISTPTR_REG)]));
745 else
746 printf(" Reserved @ 0x34: 0x%08x\n", regs[o2i(0x34)]);
747
748 printf(" Reserved @ 0x38: 0x%08x\n", regs[o2i(0x38)]);
749
750 rval = regs[o2i(PCI_INTERRUPT_REG)];
751 printf(" Maximum Latency: 0x%02x\n", (rval >> 24) & 0xff);
752 printf(" Minimum Grant: 0x%02x\n", (rval >> 16) & 0xff);
753 printf(" Interrupt pin: 0x%02x ", PCI_INTERRUPT_PIN(rval));
754 switch (PCI_INTERRUPT_PIN(rval)) {
755 case PCI_INTERRUPT_PIN_NONE:
756 printf("(none)");
757 break;
758 case PCI_INTERRUPT_PIN_A:
759 printf("(pin A)");
760 break;
761 case PCI_INTERRUPT_PIN_B:
762 printf("(pin B)");
763 break;
764 case PCI_INTERRUPT_PIN_C:
765 printf("(pin C)");
766 break;
767 case PCI_INTERRUPT_PIN_D:
768 printf("(pin D)");
769 break;
770 default:
771 printf("(? ? ?)");
772 break;
773 }
774 printf("\n");
775 printf(" Interrupt line: 0x%02x\n", PCI_INTERRUPT_LINE(rval));
776 }
777
778 static void
779 pci_conf_print_caplist(
780 #ifdef _KERNEL
781 pci_chipset_tag_t pc, pcitag_t tag,
782 #endif
783 const pcireg_t *regs, int capoff)
784 {
785 static const char unk[] = "unknown";
786 static const char *pmrev[8] = {
787 unk, "1.0", "1.1", "1.2", unk, unk, unk, unk
788 };
789 int off;
790 pcireg_t rval;
791
792 for (off = PCI_CAPLIST_PTR(regs[o2i(capoff)]);
793 off != 0;
794 off = PCI_CAPLIST_NEXT(regs[o2i(off)])) {
795 rval = regs[o2i(off)];
796 printf(" Capability register at 0x%02x\n", off);
797
798 printf(" type: 0x%02x (", PCI_CAPLIST_CAP(rval));
799 switch (PCI_CAPLIST_CAP(rval)) {
800 case PCI_CAP_RESERVED0:
801 printf("reserved");
802 break;
803 case PCI_CAP_PWRMGMT:
804 printf("Power Management, rev. %s",
805 pmrev[(rval >> 0) & 0x07]);
806 break;
807 case PCI_CAP_AGP:
808 printf("AGP, rev. %d.%d",
809 PCI_CAP_AGP_MAJOR(rval),
810 PCI_CAP_AGP_MINOR(rval));
811 break;
812 case PCI_CAP_VPD:
813 printf("VPD");
814 break;
815 case PCI_CAP_SLOTID:
816 printf("SlotID");
817 break;
818 case PCI_CAP_MSI:
819 printf("MSI");
820 break;
821 case PCI_CAP_CPCI_HOTSWAP:
822 printf("CompactPCI Hot-swapping");
823 break;
824 case PCI_CAP_PCIX:
825 printf("PCI-X");
826 break;
827 case PCI_CAP_LDT:
828 printf("LDT");
829 break;
830 case PCI_CAP_VENDSPEC:
831 printf("Vendor-specific");
832 break;
833 case PCI_CAP_DEBUGPORT:
834 printf("Debug Port");
835 break;
836 case PCI_CAP_CPCI_RSRCCTL:
837 printf("CompactPCI Resource Control");
838 break;
839 case PCI_CAP_HOTPLUG:
840 printf("Hot-Plug");
841 break;
842 case PCI_CAP_AGP8:
843 printf("AGP 8x");
844 break;
845 case PCI_CAP_SECURE:
846 printf("Secure Device");
847 break;
848 case PCI_CAP_PCIEXPRESS:
849 printf("PCI Express");
850 break;
851 case PCI_CAP_MSIX:
852 printf("MSI-X");
853 break;
854 default:
855 printf("unknown");
856 }
857 printf(")\n");
858 }
859 }
860
861 static void
862 pci_conf_print_type1(
863 #ifdef _KERNEL
864 pci_chipset_tag_t pc, pcitag_t tag,
865 #endif
866 const pcireg_t *regs
867 #ifdef _KERNEL
868 , int sizebars
869 #endif
870 )
871 {
872 int off, width;
873 pcireg_t rval;
874
875 /*
876 * XXX these need to be printed in more detail, need to be
877 * XXX checked against specs/docs, etc.
878 *
879 * This layout was cribbed from the TI PCI2030 PCI-to-PCI
880 * Bridge chip documentation, and may not be correct with
881 * respect to various standards. (XXX)
882 */
883
884 for (off = 0x10; off < 0x18; off += width) {
885 #ifdef _KERNEL
886 width = pci_conf_print_bar(pc, tag, regs, off, NULL, sizebars);
887 #else
888 width = pci_conf_print_bar(regs, off, NULL);
889 #endif
890 }
891
892 printf(" Primary bus number: 0x%02x\n",
893 (regs[o2i(0x18)] >> 0) & 0xff);
894 printf(" Secondary bus number: 0x%02x\n",
895 (regs[o2i(0x18)] >> 8) & 0xff);
896 printf(" Subordinate bus number: 0x%02x\n",
897 (regs[o2i(0x18)] >> 16) & 0xff);
898 printf(" Secondary bus latency timer: 0x%02x\n",
899 (regs[o2i(0x18)] >> 24) & 0xff);
900
901 rval = (regs[o2i(0x1c)] >> 16) & 0xffff;
902 printf(" Secondary status register: 0x%04x\n", rval); /* XXX bits */
903 onoff("66 MHz capable", 0x0020);
904 onoff("User Definable Features (UDF) support", 0x0040);
905 onoff("Fast back-to-back capable", 0x0080);
906 onoff("Data parity error detected", 0x0100);
907
908 printf(" DEVSEL timing: ");
909 switch (rval & 0x0600) {
910 case 0x0000:
911 printf("fast");
912 break;
913 case 0x0200:
914 printf("medium");
915 break;
916 case 0x0400:
917 printf("slow");
918 break;
919 default:
920 printf("unknown/reserved"); /* XXX */
921 break;
922 }
923 printf(" (0x%x)\n", (rval & 0x0600) >> 9);
924
925 onoff("Signaled Target Abort", 0x0800);
926 onoff("Received Target Abort", 0x1000);
927 onoff("Received Master Abort", 0x2000);
928 onoff("System Error", 0x4000);
929 onoff("Parity Error", 0x8000);
930
931 /* XXX Print more prettily */
932 printf(" I/O region:\n");
933 printf(" base register: 0x%02x\n", (regs[o2i(0x1c)] >> 0) & 0xff);
934 printf(" limit register: 0x%02x\n", (regs[o2i(0x1c)] >> 8) & 0xff);
935 printf(" base upper 16 bits register: 0x%04x\n",
936 (regs[o2i(0x30)] >> 0) & 0xffff);
937 printf(" limit upper 16 bits register: 0x%04x\n",
938 (regs[o2i(0x30)] >> 16) & 0xffff);
939
940 /* XXX Print more prettily */
941 printf(" Memory region:\n");
942 printf(" base register: 0x%04x\n",
943 (regs[o2i(0x20)] >> 0) & 0xffff);
944 printf(" limit register: 0x%04x\n",
945 (regs[o2i(0x20)] >> 16) & 0xffff);
946
947 /* XXX Print more prettily */
948 printf(" Prefetchable memory region:\n");
949 printf(" base register: 0x%04x\n",
950 (regs[o2i(0x24)] >> 0) & 0xffff);
951 printf(" limit register: 0x%04x\n",
952 (regs[o2i(0x24)] >> 16) & 0xffff);
953 printf(" base upper 32 bits register: 0x%08x\n", regs[o2i(0x28)]);
954 printf(" limit upper 32 bits register: 0x%08x\n", regs[o2i(0x2c)]);
955
956 if (regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)
957 printf(" Capability list pointer: 0x%02x\n",
958 PCI_CAPLIST_PTR(regs[o2i(PCI_CAPLISTPTR_REG)]));
959 else
960 printf(" Reserved @ 0x34: 0x%08x\n", regs[o2i(0x34)]);
961
962 /* XXX */
963 printf(" Expansion ROM Base Address: 0x%08x\n", regs[o2i(0x38)]);
964
965 printf(" Interrupt line: 0x%02x\n",
966 (regs[o2i(0x3c)] >> 0) & 0xff);
967 printf(" Interrupt pin: 0x%02x ",
968 (regs[o2i(0x3c)] >> 8) & 0xff);
969 switch ((regs[o2i(0x3c)] >> 8) & 0xff) {
970 case PCI_INTERRUPT_PIN_NONE:
971 printf("(none)");
972 break;
973 case PCI_INTERRUPT_PIN_A:
974 printf("(pin A)");
975 break;
976 case PCI_INTERRUPT_PIN_B:
977 printf("(pin B)");
978 break;
979 case PCI_INTERRUPT_PIN_C:
980 printf("(pin C)");
981 break;
982 case PCI_INTERRUPT_PIN_D:
983 printf("(pin D)");
984 break;
985 default:
986 printf("(? ? ?)");
987 break;
988 }
989 printf("\n");
990 rval = (regs[o2i(0x3c)] >> 16) & 0xffff;
991 printf(" Bridge control register: 0x%04x\n", rval); /* XXX bits */
992 onoff("Parity error response", 0x0001);
993 onoff("Secondary SERR forwarding", 0x0002);
994 onoff("ISA enable", 0x0004);
995 onoff("VGA enable", 0x0008);
996 onoff("Master abort reporting", 0x0020);
997 onoff("Secondary bus reset", 0x0040);
998 onoff("Fast back-to-back capable", 0x0080);
999 }
1000
1001 static void
1002 pci_conf_print_type2(
1003 #ifdef _KERNEL
1004 pci_chipset_tag_t pc, pcitag_t tag,
1005 #endif
1006 const pcireg_t *regs
1007 #ifdef _KERNEL
1008 , int sizebars
1009 #endif
1010 )
1011 {
1012 pcireg_t rval;
1013
1014 /*
1015 * XXX these need to be printed in more detail, need to be
1016 * XXX checked against specs/docs, etc.
1017 *
1018 * This layout was cribbed from the TI PCI1130 PCI-to-CardBus
1019 * controller chip documentation, and may not be correct with
1020 * respect to various standards. (XXX)
1021 */
1022
1023 #ifdef _KERNEL
1024 pci_conf_print_bar(pc, tag, regs, 0x10,
1025 "CardBus socket/ExCA registers", sizebars);
1026 #else
1027 pci_conf_print_bar(regs, 0x10, "CardBus socket/ExCA registers");
1028 #endif
1029
1030 if (regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)
1031 printf(" Capability list pointer: 0x%02x\n",
1032 PCI_CAPLIST_PTR(regs[o2i(PCI_CARDBUS_CAPLISTPTR_REG)]));
1033 else
1034 printf(" Reserved @ 0x14: 0x%04x\n",
1035 (regs[o2i(0x14)] >> 0) & 0xffff);
1036 rval = (regs[o2i(0x14)] >> 16) & 0xffff;
1037 printf(" Secondary status register: 0x%04x\n", rval);
1038 onoff("66 MHz capable", 0x0020);
1039 onoff("User Definable Features (UDF) support", 0x0040);
1040 onoff("Fast back-to-back capable", 0x0080);
1041 onoff("Data parity error detection", 0x0100);
1042
1043 printf(" DEVSEL timing: ");
1044 switch (rval & 0x0600) {
1045 case 0x0000:
1046 printf("fast");
1047 break;
1048 case 0x0200:
1049 printf("medium");
1050 break;
1051 case 0x0400:
1052 printf("slow");
1053 break;
1054 default:
1055 printf("unknown/reserved"); /* XXX */
1056 break;
1057 }
1058 printf(" (0x%x)\n", (rval & 0x0600) >> 9);
1059 onoff("PCI target aborts terminate CardBus bus master transactions",
1060 0x0800);
1061 onoff("CardBus target aborts terminate PCI bus master transactions",
1062 0x1000);
1063 onoff("Bus initiator aborts terminate initiator transactions",
1064 0x2000);
1065 onoff("System error", 0x4000);
1066 onoff("Parity error", 0x8000);
1067
1068 printf(" PCI bus number: 0x%02x\n",
1069 (regs[o2i(0x18)] >> 0) & 0xff);
1070 printf(" CardBus bus number: 0x%02x\n",
1071 (regs[o2i(0x18)] >> 8) & 0xff);
1072 printf(" Subordinate bus number: 0x%02x\n",
1073 (regs[o2i(0x18)] >> 16) & 0xff);
1074 printf(" CardBus latency timer: 0x%02x\n",
1075 (regs[o2i(0x18)] >> 24) & 0xff);
1076
1077 /* XXX Print more prettily */
1078 printf(" CardBus memory region 0:\n");
1079 printf(" base register: 0x%08x\n", regs[o2i(0x1c)]);
1080 printf(" limit register: 0x%08x\n", regs[o2i(0x20)]);
1081 printf(" CardBus memory region 1:\n");
1082 printf(" base register: 0x%08x\n", regs[o2i(0x24)]);
1083 printf(" limit register: 0x%08x\n", regs[o2i(0x28)]);
1084 printf(" CardBus I/O region 0:\n");
1085 printf(" base register: 0x%08x\n", regs[o2i(0x2c)]);
1086 printf(" limit register: 0x%08x\n", regs[o2i(0x30)]);
1087 printf(" CardBus I/O region 1:\n");
1088 printf(" base register: 0x%08x\n", regs[o2i(0x34)]);
1089 printf(" limit register: 0x%08x\n", regs[o2i(0x38)]);
1090
1091 printf(" Interrupt line: 0x%02x\n",
1092 (regs[o2i(0x3c)] >> 0) & 0xff);
1093 printf(" Interrupt pin: 0x%02x ",
1094 (regs[o2i(0x3c)] >> 8) & 0xff);
1095 switch ((regs[o2i(0x3c)] >> 8) & 0xff) {
1096 case PCI_INTERRUPT_PIN_NONE:
1097 printf("(none)");
1098 break;
1099 case PCI_INTERRUPT_PIN_A:
1100 printf("(pin A)");
1101 break;
1102 case PCI_INTERRUPT_PIN_B:
1103 printf("(pin B)");
1104 break;
1105 case PCI_INTERRUPT_PIN_C:
1106 printf("(pin C)");
1107 break;
1108 case PCI_INTERRUPT_PIN_D:
1109 printf("(pin D)");
1110 break;
1111 default:
1112 printf("(? ? ?)");
1113 break;
1114 }
1115 printf("\n");
1116 rval = (regs[o2i(0x3c)] >> 16) & 0xffff;
1117 printf(" Bridge control register: 0x%04x\n", rval);
1118 onoff("Parity error response", 0x0001);
1119 onoff("CardBus SERR forwarding", 0x0002);
1120 onoff("ISA enable", 0x0004);
1121 onoff("VGA enable", 0x0008);
1122 onoff("CardBus master abort reporting", 0x0020);
1123 onoff("CardBus reset", 0x0040);
1124 onoff("Functional interrupts routed by ExCA registers", 0x0080);
1125 onoff("Memory window 0 prefetchable", 0x0100);
1126 onoff("Memory window 1 prefetchable", 0x0200);
1127 onoff("Write posting enable", 0x0400);
1128
1129 rval = regs[o2i(0x40)];
1130 printf(" Subsystem vendor ID: 0x%04x\n", PCI_VENDOR(rval));
1131 printf(" Subsystem ID: 0x%04x\n", PCI_PRODUCT(rval));
1132
1133 #ifdef _KERNEL
1134 pci_conf_print_bar(pc, tag, regs, 0x44, "legacy-mode registers",
1135 sizebars);
1136 #else
1137 pci_conf_print_bar(regs, 0x44, "legacy-mode registers");
1138 #endif
1139 }
1140
1141 void
1142 pci_conf_print(
1143 #ifdef _KERNEL
1144 pci_chipset_tag_t pc, pcitag_t tag,
1145 void (*printfn)(pci_chipset_tag_t, pcitag_t, const pcireg_t *)
1146 #else
1147 int pcifd, u_int bus, u_int dev, u_int func
1148 #endif
1149 )
1150 {
1151 pcireg_t regs[o2i(256)];
1152 int off, capoff, endoff, hdrtype;
1153 const char *typename;
1154 #ifdef _KERNEL
1155 void (*typeprintfn)(pci_chipset_tag_t, pcitag_t, const pcireg_t *, int);
1156 int sizebars;
1157 #else
1158 void (*typeprintfn)(const pcireg_t *);
1159 #endif
1160
1161 printf("PCI configuration registers:\n");
1162
1163 for (off = 0; off < 256; off += 4) {
1164 #ifdef _KERNEL
1165 regs[o2i(off)] = pci_conf_read(pc, tag, off);
1166 #else
1167 if (pcibus_conf_read(pcifd, bus, dev, func, off,
1168 ®s[o2i(off)]) == -1)
1169 regs[o2i(off)] = 0;
1170 #endif
1171 }
1172
1173 #ifdef _KERNEL
1174 sizebars = 1;
1175 if (PCI_CLASS(regs[o2i(PCI_CLASS_REG)]) == PCI_CLASS_BRIDGE &&
1176 PCI_SUBCLASS(regs[o2i(PCI_CLASS_REG)]) == PCI_SUBCLASS_BRIDGE_HOST)
1177 sizebars = 0;
1178 #endif
1179
1180 /* common header */
1181 printf(" Common header:\n");
1182 pci_conf_print_regs(regs, 0, 16);
1183
1184 printf("\n");
1185 #ifdef _KERNEL
1186 pci_conf_print_common(pc, tag, regs);
1187 #else
1188 pci_conf_print_common(regs);
1189 #endif
1190 printf("\n");
1191
1192 /* type-dependent header */
1193 hdrtype = PCI_HDRTYPE_TYPE(regs[o2i(PCI_BHLC_REG)]);
1194 switch (hdrtype) { /* XXX make a table, eventually */
1195 case 0:
1196 /* Standard device header */
1197 typename = "\"normal\" device";
1198 typeprintfn = &pci_conf_print_type0;
1199 capoff = PCI_CAPLISTPTR_REG;
1200 endoff = 64;
1201 break;
1202 case 1:
1203 /* PCI-PCI bridge header */
1204 typename = "PCI-PCI bridge";
1205 typeprintfn = &pci_conf_print_type1;
1206 capoff = PCI_CAPLISTPTR_REG;
1207 endoff = 64;
1208 break;
1209 case 2:
1210 /* PCI-CardBus bridge header */
1211 typename = "PCI-CardBus bridge";
1212 typeprintfn = &pci_conf_print_type2;
1213 capoff = PCI_CARDBUS_CAPLISTPTR_REG;
1214 endoff = 72;
1215 break;
1216 default:
1217 typename = NULL;
1218 typeprintfn = 0;
1219 capoff = -1;
1220 endoff = 64;
1221 break;
1222 }
1223 printf(" Type %d ", hdrtype);
1224 if (typename != NULL)
1225 printf("(%s) ", typename);
1226 printf("header:\n");
1227 pci_conf_print_regs(regs, 16, endoff);
1228 printf("\n");
1229 if (typeprintfn) {
1230 #ifdef _KERNEL
1231 (*typeprintfn)(pc, tag, regs, sizebars);
1232 #else
1233 (*typeprintfn)(regs);
1234 #endif
1235 } else
1236 printf(" Don't know how to pretty-print type %d header.\n",
1237 hdrtype);
1238 printf("\n");
1239
1240 /* capability list, if present */
1241 if ((regs[o2i(PCI_COMMAND_STATUS_REG)] & PCI_STATUS_CAPLIST_SUPPORT)
1242 && (capoff > 0)) {
1243 #ifdef _KERNEL
1244 pci_conf_print_caplist(pc, tag, regs, capoff);
1245 #else
1246 pci_conf_print_caplist(regs, capoff);
1247 #endif
1248 printf("\n");
1249 }
1250
1251 /* device-dependent header */
1252 printf(" Device-dependent header:\n");
1253 pci_conf_print_regs(regs, endoff, 256);
1254 printf("\n");
1255 #ifdef _KERNEL
1256 if (printfn)
1257 (*printfn)(pc, tag, regs);
1258 else
1259 printf(" Don't know how to pretty-print device-dependent header.\n");
1260 printf("\n");
1261 #endif /* _KERNEL */
1262 }
1263