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