patch-2.3.13 linux/drivers/pci/proc.c
Next file: linux/drivers/pci/quirks.c
Previous file: linux/drivers/pci/pci.c
Back to the patch index
Back to the overall index
- Lines: 317
- Date:
Sat Aug 7 12:59:40 1999
- Orig file:
v2.3.12/linux/drivers/pci/proc.c
- Orig date:
Wed Jun 30 13:38:20 1999
diff -u --recursive --new-file v2.3.12/linux/drivers/pci/proc.c linux/drivers/pci/proc.c
@@ -6,12 +6,12 @@
* Copyright (c) 1997, 1998 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
*/
-#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
+
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -247,14 +247,15 @@
dev->vendor,
dev->device,
dev->irq);
- for(i=0; i<6; i++)
+ for(i=0; i<6; i++) {
len += sprintf(buf+len,
#if BITS_PER_LONG == 32
"\t%08lx",
#else
"\t%016lx",
#endif
- dev->base_address[i]);
+ dev->resource[i].start | (dev->resource[i].flags & 0xf));
+ }
len += sprintf(buf+len,
#if BITS_PER_LONG == 32
"\t%08lx",
@@ -321,7 +322,7 @@
return 0;
}
-__initfunc(void proc_bus_pci_add(struct pci_bus *bus))
+void __init proc_bus_pci_add(struct pci_bus *bus)
{
while (bus) {
struct pci_dev *dev;
@@ -334,15 +335,266 @@
}
}
-__initfunc(void pci_proc_init(void))
+static const char *pci_strclass (unsigned int class)
{
- if (!pci_present())
- return;
- proc_bus_pci_dir = create_proc_entry("pci", S_IFDIR, proc_bus);
- proc_register(proc_bus_pci_dir, &proc_pci_devices);
- proc_bus_pci_add(&pci_root);
+ switch (class >> 8) {
+ case PCI_CLASS_NOT_DEFINED: return "Non-VGA device";
+ case PCI_CLASS_NOT_DEFINED_VGA: return "VGA compatible device";
+
+ case PCI_CLASS_STORAGE_SCSI: return "SCSI storage controller";
+ case PCI_CLASS_STORAGE_IDE: return "IDE interface";
+ case PCI_CLASS_STORAGE_FLOPPY: return "Floppy disk controller";
+ case PCI_CLASS_STORAGE_IPI: return "IPI bus controller";
+ case PCI_CLASS_STORAGE_RAID: return "RAID bus controller";
+ case PCI_CLASS_STORAGE_OTHER: return "Unknown mass storage controller";
+
+ case PCI_CLASS_NETWORK_ETHERNET: return "Ethernet controller";
+ case PCI_CLASS_NETWORK_TOKEN_RING: return "Token ring network controller";
+ case PCI_CLASS_NETWORK_FDDI: return "FDDI network controller";
+ case PCI_CLASS_NETWORK_ATM: return "ATM network controller";
+ case PCI_CLASS_NETWORK_OTHER: return "Network controller";
+
+ case PCI_CLASS_DISPLAY_VGA: return "VGA compatible controller";
+ case PCI_CLASS_DISPLAY_XGA: return "XGA compatible controller";
+ case PCI_CLASS_DISPLAY_OTHER: return "Display controller";
+
+ case PCI_CLASS_MULTIMEDIA_VIDEO: return "Multimedia video controller";
+ case PCI_CLASS_MULTIMEDIA_AUDIO: return "Multimedia audio controller";
+ case PCI_CLASS_MULTIMEDIA_OTHER: return "Multimedia controller";
+
+ case PCI_CLASS_MEMORY_RAM: return "RAM memory";
+ case PCI_CLASS_MEMORY_FLASH: return "FLASH memory";
+ case PCI_CLASS_MEMORY_OTHER: return "Memory";
+
+ case PCI_CLASS_BRIDGE_HOST: return "Host bridge";
+ case PCI_CLASS_BRIDGE_ISA: return "ISA bridge";
+ case PCI_CLASS_BRIDGE_EISA: return "EISA bridge";
+ case PCI_CLASS_BRIDGE_MC: return "MicroChannel bridge";
+ case PCI_CLASS_BRIDGE_PCI: return "PCI bridge";
+ case PCI_CLASS_BRIDGE_PCMCIA: return "PCMCIA bridge";
+ case PCI_CLASS_BRIDGE_NUBUS: return "NuBus bridge";
+ case PCI_CLASS_BRIDGE_CARDBUS: return "CardBus bridge";
+ case PCI_CLASS_BRIDGE_OTHER: return "Bridge";
+
+ case PCI_CLASS_COMMUNICATION_SERIAL: return "Serial controller";
+ case PCI_CLASS_COMMUNICATION_PARALLEL: return "Parallel controller";
+ case PCI_CLASS_COMMUNICATION_OTHER: return "Communication controller";
+
+ case PCI_CLASS_SYSTEM_PIC: return "PIC";
+ case PCI_CLASS_SYSTEM_DMA: return "DMA controller";
+ case PCI_CLASS_SYSTEM_TIMER: return "Timer";
+ case PCI_CLASS_SYSTEM_RTC: return "RTC";
+ case PCI_CLASS_SYSTEM_OTHER: return "System peripheral";
+
+ case PCI_CLASS_INPUT_KEYBOARD: return "Keyboard controller";
+ case PCI_CLASS_INPUT_PEN: return "Digitizer Pen";
+ case PCI_CLASS_INPUT_MOUSE: return "Mouse controller";
+ case PCI_CLASS_INPUT_OTHER: return "Input device controller";
+
+ case PCI_CLASS_DOCKING_GENERIC: return "Generic Docking Station";
+ case PCI_CLASS_DOCKING_OTHER: return "Docking Station";
+
+ case PCI_CLASS_PROCESSOR_386: return "386";
+ case PCI_CLASS_PROCESSOR_486: return "486";
+ case PCI_CLASS_PROCESSOR_PENTIUM: return "Pentium";
+ case PCI_CLASS_PROCESSOR_ALPHA: return "Alpha";
+ case PCI_CLASS_PROCESSOR_POWERPC: return "Power PC";
+ case PCI_CLASS_PROCESSOR_CO: return "Co-processor";
+
+ case PCI_CLASS_SERIAL_FIREWIRE: return "FireWire (IEEE 1394)";
+ case PCI_CLASS_SERIAL_ACCESS: return "ACCESS Bus";
+ case PCI_CLASS_SERIAL_SSA: return "SSA";
+ case PCI_CLASS_SERIAL_USB: return "USB Controller";
+ case PCI_CLASS_SERIAL_FIBER: return "Fiber Channel";
-#ifdef CONFIG_PCI_OLD_PROC
- proc_old_pci_init();
-#endif
+ case PCI_CLASS_HOT_SWAP_CONTROLLER: return "Hot Swap Controller";
+
+ default: return "Unknown class";
+ }
+}
+
+/*
+ * Convert some of the configuration space registers of the device at
+ * address (bus,devfn) into a string (possibly several lines each).
+ * The configuration string is stored starting at buf[len]. If the
+ * string would exceed the size of the buffer (SIZE), 0 is returned.
+ */
+static int sprint_dev_config(struct pci_dev *dev, char *buf, int size)
+{
+ unsigned int class_rev, bus, devfn;
+ unsigned short vendor, device, status;
+ unsigned char bist, latency, min_gnt, max_lat;
+ int reg, len = 0;
+ const char *str;
+
+ bus = dev->bus->number;
+ devfn = dev->devfn;
+
+ pcibios_read_config_dword(bus, devfn, PCI_CLASS_REVISION, &class_rev);
+ pcibios_read_config_word (bus, devfn, PCI_VENDOR_ID, &vendor);
+ pcibios_read_config_word (bus, devfn, PCI_DEVICE_ID, &device);
+ pcibios_read_config_word (bus, devfn, PCI_STATUS, &status);
+ pcibios_read_config_byte (bus, devfn, PCI_BIST, &bist);
+ pcibios_read_config_byte (bus, devfn, PCI_LATENCY_TIMER, &latency);
+ pcibios_read_config_byte (bus, devfn, PCI_MIN_GNT, &min_gnt);
+ pcibios_read_config_byte (bus, devfn, PCI_MAX_LAT, &max_lat);
+ if (len + 80 > size) {
+ return -1;
+ }
+ len += sprintf(buf + len, " Bus %2d, device %3d, function %2d:\n",
+ bus, PCI_SLOT(devfn), PCI_FUNC(devfn));
+
+ if (len + 80 > size) {
+ return -1;
+ }
+ len += sprintf(buf + len, " %s: %s (rev %d).\n ",
+ pci_strclass(class_rev >> 8),
+ dev->name,
+ class_rev & 0xff);
+
+ switch (status & PCI_STATUS_DEVSEL_MASK) {
+ case PCI_STATUS_DEVSEL_FAST: str = "Fast devsel. "; break;
+ case PCI_STATUS_DEVSEL_MEDIUM: str = "Medium devsel. "; break;
+ case PCI_STATUS_DEVSEL_SLOW: str = "Slow devsel. "; break;
+ default: str = "Unknown devsel. ";
+ }
+ if (len + strlen(str) > size) {
+ return -1;
+ }
+ len += sprintf(buf + len, str);
+
+ if (status & PCI_STATUS_FAST_BACK) {
+# define fast_b2b_capable "Fast back-to-back capable. "
+ if (len + strlen(fast_b2b_capable) > size) {
+ return -1;
+ }
+ len += sprintf(buf + len, fast_b2b_capable);
+# undef fast_b2b_capable
+ }
+
+ if (bist & PCI_BIST_CAPABLE) {
+# define BIST_capable "BIST capable. "
+ if (len + strlen(BIST_capable) > size) {
+ return -1;
+ }
+ len += sprintf(buf + len, BIST_capable);
+# undef BIST_capable
+ }
+
+ if (dev->irq) {
+ if (len + 40 > size) {
+ return -1;
+ }
+ len += sprintf(buf + len, "IRQ %d. ", dev->irq);
+ }
+
+ if (dev->master) {
+ if (len + 80 > size) {
+ return -1;
+ }
+ len += sprintf(buf + len, "Master Capable. ");
+ if (latency)
+ len += sprintf(buf + len, "Latency=%d. ", latency);
+ else
+ len += sprintf(buf + len, "No bursts. ");
+ if (min_gnt)
+ len += sprintf(buf + len, "Min Gnt=%d.", min_gnt);
+ if (max_lat)
+ len += sprintf(buf + len, "Max Lat=%d.", max_lat);
+ }
+
+ for (reg = 0; reg < 6; reg++) {
+ struct resource *res = dev->resource + reg;
+ unsigned long base, end, flags;
+
+ if (len + 40 > size) {
+ return -1;
+ }
+ base = res->start;
+ end = res->end;
+ flags = res->flags;
+ if (!end)
+ continue;
+
+ if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
+ len += sprintf(buf + len,
+ "\n I/O at 0x%lx [0x%lx].",
+ base, end);
+ } else {
+ const char *pref, *type = "unknown";
+
+ if (flags & PCI_BASE_ADDRESS_MEM_PREFETCH) {
+ pref = "P";
+ } else {
+ pref = "Non-p";
+ }
+ switch (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) {
+ case PCI_BASE_ADDRESS_MEM_TYPE_32:
+ type = "32 bit"; break;
+ case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+ type = "20 bit"; break;
+ case PCI_BASE_ADDRESS_MEM_TYPE_64:
+ type = "64 bit"; break;
+ }
+ len += sprintf(buf + len,
+ "\n %srefetchable %s memory at "
+ "0x%lx [0x%lx].", pref, type,
+ base,
+ end);
+ }
+ }
+
+ len += sprintf(buf + len, "\n");
+ return len;
+}
+
+
+/*
+ * Return list of PCI devices as a character string for /proc/pci.
+ * BUF is a buffer that is PAGE_SIZE bytes long.
+ */
+int get_pci_list(char *buf)
+{
+ int nprinted, len, size;
+ struct pci_dev *dev;
+ static int complained = 0;
+# define MSG "\nwarning: page-size limit reached!\n"
+
+ if (!complained) {
+ complained++;
+ printk(KERN_INFO "%s uses obsolete /proc/pci interface\n",
+ current->comm);
+ }
+
+ /* reserve same for truncation warning message: */
+ size = PAGE_SIZE - (strlen(MSG) + 1);
+ len = sprintf(buf, "PCI devices found:\n");
+
+ for (dev = pci_devices; dev; dev = dev->next) {
+ nprinted = sprint_dev_config(dev, buf + len, size - len);
+ if (nprinted < 0) {
+ return len + sprintf(buf + len, MSG);
+ }
+ len += nprinted;
+ }
+ return len;
}
+
+static struct proc_dir_entry proc_old_pci = {
+ PROC_PCI, 3, "pci",
+ S_IFREG | S_IRUGO, 1, 0, 0,
+ 0, &proc_array_inode_operations
+};
+
+static int __init pci_proc_init(void)
+{
+ if (pci_present()) {
+ proc_bus_pci_dir = create_proc_entry("pci", S_IFDIR, proc_bus);
+ proc_register(proc_bus_pci_dir, &proc_pci_devices);
+ proc_bus_pci_add(&pci_root);
+ proc_register(&proc_root, &proc_old_pci);
+ }
+ return 0;
+}
+
+__initcall(pci_proc_init);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)