]> mj.ucw.cz Git - pciutils.git/commitdiff
Added support for 4096-byte extended configuration space.
authorMartin Mares <mj@ucw.cz>
Sun, 27 Jun 2004 11:20:31 +0000 (11:20 +0000)
committerMartin Mares <mj@ucw.cz>
Fri, 5 May 2006 12:18:21 +0000 (14:18 +0200)
git-archimport-id: mj@ucw.cz--public/pciutils--main--2.2--patch-50

ChangeLog
lib/aix-device.c
lib/dump.c
lib/fbsd-device.c
lib/i386-ports.c
lib/nbsd-libpci.c
lib/proc.c
lib/sysfs.c
lspci.c
setpci.c

index ea598718de88b9e8b12ba79cff2e0a8dbc7367f6..7812665106315912b1e531f867781d6fca366dcb 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2004-06-27  Martin Mares  <mj@ucw.cz>
+
+       * lspci.c (check_root): Gone. No explicit checks for root are needed,
+       report correct errors reported by the libpci instead.
+
+       * lspci.c: Added dumping of the extended config space on "-xxxx".
+       Better caching of config registers.
+
+       * setpci.c (main): Allow access to whole 4096 bytes of the config space.
+
+       * lib/sysfs.c, lib/proc.c: Don't print error messages on short reads,
+       just return the appropriate error code.
+
+       * lib: Added support for extended (4096-byte) configuration space,
+       currently implemented only in Linux proc and sysfs access methods
+       and of course in the dump reader.
+
 2004-05-29  Martin Mares  <mj@ucw.cz>
 
        * Released as 2.1.99-test5.
index 55b2f306dd80ae0a0d492d0bed2fb37449b856c1..93a8e4e72f6607d4f9504eae127d05a54cbbaecf 100644 (file)
@@ -222,8 +222,12 @@ static int
 aix_read(struct pci_dev *d, int pos, byte *buf, int len)
 {
   struct mdio mdio;
-  int fd = aix_bus_open(d->access, d->bus);
+  int fd;
 
+  if (pos + len > 256)
+    return 0;
+
+  fd = aix_bus_open(d->access, d->bus);
   mdio.md_addr = (ulong) pos;
   mdio.md_size = len;
   mdio.md_incr = MV_BYTE;
@@ -240,8 +244,12 @@ static int
 aix_write(struct pci_dev *d, int pos, byte *buf, int len)
 {
   struct mdio mdio;
-  int fd = aix_bus_open(d->access, d->bus);
+  int fd;
+
+  if (pos + len > 256)
+    return 0;
 
+  fd = aix_bus_open(d->access, d->bus);
   mdio.md_addr = (ulong) pos;
   mdio.md_size = len;
   mdio.md_incr = MV_BYTE;
index 4baeae407ecce05b53018b2261dfc39e933d0939..02b2ce4fe9309cfd1f001ee0fd32af2faf776cc9 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *     The PCI Library -- Reading of Bus Dumps
  *
- *     Copyright (c) 1997--2003 Martin Mares <mj@ucw.cz>
+ *     Copyright (c) 1997--2004 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
 
 #include "internal.h"
 
+struct dump_data {
+  int len;
+  byte data[1];
+};
+
 static int
 dump_detect(struct pci_access *a)
 {
   return !!a->method_params[PCI_ACCESS_DUMP];
 }
 
+static void
+dump_alloc_data(struct pci_dev *dev, int len)
+{
+  struct dump_data *dd = pci_malloc(dev->access, sizeof(struct dump_data) + len - 1);
+  dd->len = len;
+  memset(dd->data, 0xff, len);
+  dev->aux = dd;
+}
+
 static void
 dump_init(struct pci_access *a)
 {
@@ -48,22 +62,32 @@ dump_init(struct pci_access *a)
           sscanf(buf, "%x:%x:%x.%d", &mn, &bn, &dn, &fn) == 4))
        {
          dev = pci_get_dev(a, mn, bn, dn, fn);
-         dev->aux = pci_malloc(a, 256);
-         memset(dev->aux, 0xff, 256);
+         dump_alloc_data(dev, 256);
          pci_link_dev(a, dev);
        }
       else if (!len)
        dev = NULL;
-      else if (dev && len >= 51 && buf[2] == ':' && buf[3] == ' ' &&
+      else if (dev &&
+              (len >= 51 && buf[2] == ':' && buf[3] == ' ' || len >= 52 && buf[3] == ':' && buf[4] == ' ') &&
               sscanf(buf, "%x: ", &i) == 1)
        {
-         z = buf+3;
+         struct dump_data *dd = dev->aux;
+         z = strchr(buf, ' ') + 1;
          while (isspace(z[0]) && isxdigit(z[1]) && isxdigit(z[2]))
            {
              z++;
              if (sscanf(z, "%x", &j) != 1 || i >= 256)
                a->error("dump: Malformed line");
-             ((byte *) dev->aux)[i++] = j;
+             if (i >= 4096)
+               break;
+             if (i > dd->len)          /* Need to re-allocate the buffer */
+               {
+                 dump_alloc_data(dev, 4096);
+                 memcpy(((struct dump_data *) dev->aux)->data, dd->data, 256);
+                 pci_mfree(dd);
+                 dd = dev->aux;
+               }
+             dd->data[i++] = j;
              z += 2;
            }
        }
@@ -83,17 +107,19 @@ dump_scan(struct pci_access *a UNUSED)
 static int
 dump_read(struct pci_dev *d, int pos, byte *buf, int len)
 {
-  if (!d->aux)
+  struct dump_data *dd;
+  if (!(dd = d->aux))
     {
       struct pci_dev *e = d->access->devices;
       while (e && (e->bus != d->bus || e->dev != d->dev || e->func != d->func))
        e = e->next;
-      if (e)
-       d = e;
-      else
+      if (!e)
        return 0;
+      dd = e->aux;
     }
-  memcpy(buf, (byte *) d->aux + pos, len);
+  if (pos + len > dd->len)
+    return 0;
+  memcpy(buf, dd->data + pos, len);
   return 1;
 }
 
index 09041e370b740564b59b8d2da37f396407bbe9f4..c0af6a11a14fad4f1283b9701d336ba2be16caba 100644 (file)
@@ -74,6 +74,9 @@ fbsd_read(struct pci_dev *d, int pos, byte *buf, int len)
       return pci_generic_block_read(d, pos, buf, len);
     }
 
+  if (pos >= 256)
+    return 0;
+
   pi.pi_sel.pc_bus = d->bus;
   pi.pi_sel.pc_dev = d->dev;
   pi.pi_sel.pc_func = d->func;
@@ -109,6 +112,9 @@ fbsd_write(struct pci_dev *d, int pos, byte *buf, int len)
       return pci_generic_block_write(d, pos, buf, len);
     }
 
+  if (pos >= 256)
+    return 0;
+
   pi.pi_sel.pc_bus = d->bus;
   pi.pi_sel.pc_dev = d->dev;
   pi.pi_sel.pc_func = d->func;
index d1088c3ffa3d502478549f83bf99f3bda611d8b5..f225d248179958ae10c1580c5872f4a6ca743128 100644 (file)
@@ -102,6 +102,10 @@ static int
 conf1_read(struct pci_dev *d, int pos, byte *buf, int len)
 {
   int addr = 0xcfc + (pos&3);
+
+  if (pos >= 256)
+    return 0;
+
   outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
 
   switch (len)
@@ -125,6 +129,10 @@ static int
 conf1_write(struct pci_dev *d, int pos, byte *buf, int len)
 {
   int addr = 0xcfc + (pos&3);
+
+  if (pos >= 256)
+    return 0;
+
   outl(0x80000000 | ((d->bus & 0xff) << 16) | (PCI_DEVFN(d->dev, d->func) << 8) | (pos&~3), 0xcf8);
 
   switch (len)
@@ -173,6 +181,9 @@ conf2_read(struct pci_dev *d, int pos, byte *buf, int len)
 {
   int addr = 0xc000 | (d->dev << 8) | pos;
 
+  if (pos >= 256)
+    return 0;
+
   if (d->dev >= 16)
     /* conf2 supports only 16 devices per bus */
     return 0;
@@ -202,6 +213,9 @@ conf2_write(struct pci_dev *d, int pos, byte *buf, int len)
 {
   int addr = 0xc000 | (d->dev << 8) | pos;
 
+  if (pos >= 256)
+    return 0;
+
   if (d->dev >= 16)
     d->access->error("conf2_write: only first 16 devices exist.");
   outb((d->func << 1) | 0xf0, 0xcf8);
index 0b247c0e10a0ee5b98bdfd14d5d3fd75b7c307be..650728796bce27c1063857af5725b42aa28a46e0 100644 (file)
@@ -67,6 +67,9 @@ nbsd_read(struct pci_dev *d, int pos, byte *buf, int len)
   if (!(len == 1 || len == 2 || len == 4))
     return pci_generic_block_read(d, pos, buf, len);
 
+  if (pos >= 256)
+    return 0;
+
   shift = 8*(pos % 4);
   pos &= ~3;
        
@@ -97,6 +100,9 @@ nbsd_write(struct pci_dev *d, int pos, byte *buf, int len)
   if (!(len == 1 || len == 2 || len == 4))
     return pci_generic_block_write(d, pos, buf, len);
 
+  if (pos >= 256)
+    return 0;
+
   /*
    *  BEWARE: NetBSD seems to support only 32-bit access, so we have
    *  to emulate byte and word writes by read-modify-write, possibly
index 0262143a7b62a4e95561574c919b1429013788cf..9d02b4107d5dc9781c2b4bb10556c63d0ecce655 100644 (file)
@@ -153,10 +153,7 @@ proc_read(struct pci_dev *d, int pos, byte *buf, int len)
       return 0;
     }
   else if (res != len)
-    {
-      d->access->warning("proc_read: tried to read %d bytes at %d, but got only %d", len, pos, res);
-      return 0;
-    }
+    d->access->warning("proc_read: tried to read %d bytes at %d, but got only %d", len, pos, res);
   return 1;
 }
 
@@ -176,7 +173,7 @@ proc_write(struct pci_dev *d, int pos, byte *buf, int len)
     }
   else if (res != len)
     {
-      d->access->warning("proc_write: tried to write %d bytes at %d, but got only %d", len, pos, res);
+      d->access->warning("proc_write: tried to write %d bytes at %d, but only %d succeeded", len, pos, res);
       return 0;
     }
   return 1;
index c0cf5a3bfef5202db1f69a689fbee9811e03b0ef..0cdfe9ab9b75d50b53d2b3043420dd4633bb6a59 100644 (file)
@@ -222,10 +222,7 @@ static int sysfs_read(struct pci_dev *d, int pos, byte *buf, int len)
       return 0;
     }
   else if (res != len)
-    {
-      d->access->warning("sysfs_read: tried to read %d bytes at %d, but got only %d", len, pos, res);
-      return 0;
-    }
+    return 0;
   return 1;
 }
 
@@ -244,7 +241,7 @@ static int sysfs_write(struct pci_dev *d, int pos, byte *buf, int len)
     }
   else if (res != len)
     {
-      d->access->warning("sysfs_write: tried to write %d bytes at %d, but got only %d", len, pos, res);
+      d->access->warning("sysfs_write: tried to write %d bytes at %d, but only %d succeeded", len, pos, res);
       return 0;
     }
   return 1;
diff --git a/lspci.c b/lspci.c
index b65202d9c01539c8f4acfc16c72aabe35d5c4dc2..07e91844bcd64b3410ed4dcb8bc77d9ca4c49ee2 100644 (file)
--- a/lspci.c
+++ b/lspci.c
@@ -34,6 +34,7 @@ Usage: lspci [<switches>]\n\
 -b\t\tBus-centric view (PCI addresses and IRQ's instead of those seen by the CPU)\n\
 -x\t\tShow hex-dump of the standard portion of config space\n\
 -xxx\t\tShow hex-dump of the whole config space (dangerous; root only)\n\
+-xxxx\t\tShow hex-dump of the 4096-byte extended config space (root only)\n\
 -s [[[[<domain>]:]<bus>]:][<slot>][.[<func>]]\tShow only devices in selected slots\n\
 -d [<vendor>]:[<device>]\tShow only selected devices\n\
 -t\t\tShow bus tree\n\
@@ -71,7 +72,6 @@ static struct device *first_dev;
 static struct device *
 scan_device(struct pci_dev *p)
 {
-  int how_much = (show_hex > 2) ? 256 : 64;
   struct device *d;
 
   if (!pci_filter_match(&filter, p))
@@ -79,16 +79,16 @@ scan_device(struct pci_dev *p)
   d = xmalloc(sizeof(struct device));
   bzero(d, sizeof(*d));
   d->dev = p;
-  if (!pci_read_block(p, 0, d->config, how_much))
-    die("Unable to read %d bytes of configuration space.", how_much);
-  if (how_much < 128 && (d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
+  d->config_cnt = 64;
+  if (!pci_read_block(p, 0, d->config, 64))
+    die("Unable to read the configuration space header.");
+  if ((d->config[PCI_HEADER_TYPE] & 0x7f) == PCI_HEADER_TYPE_CARDBUS)
     {
       /* For cardbus bridges, we need to fetch 64 bytes more to get the full standard header... */
       if (!pci_read_block(p, 64, d->config+64, 64))
        die("Unable to read cardbus bridge extension data.");
-      how_much = 128;
+      d->config_cnt = 128;
     }
-  d->config_cnt = how_much;
   pci_setup_cache(p, d->config, d->config_cnt);
   pci_fill_info(p, PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
   return d;
@@ -109,27 +109,11 @@ scan_devices(void)
       }
 }
 
-static int
-check_root(void)
-{
-#ifdef OS_WINDOWS
-  return 1;
-#else
-  static int is_root = -1;
-
-  if (is_root < 0)
-    is_root = !geteuid();
-  return is_root;
-#endif
-}
-
 static int
 config_fetch(struct device *d, unsigned int pos, unsigned int len)
 {
   if (pos + len < d->config_cnt)
     return 1;
-  if (pacc->method != PCI_ACCESS_DUMP && !check_root())
-    return 0;
   return pci_read_block(d->dev, pos, d->config + pos, len);
 }
 
@@ -1308,9 +1292,17 @@ show_verbose(struct device *d)
 static void
 show_hex_dump(struct device *d)
 {
-  unsigned int i;
+  unsigned int i, cnt;
 
-  for(i=0; i<d->config_cnt; i++)
+  cnt = d->config_cnt;
+  if (show_hex >= 3 && config_fetch(d, cnt, 256-cnt))
+    {
+      cnt = 256;
+      if (show_hex >= 4 && config_fetch(d, 256, 4096-256))
+       cnt = 4096;
+    }
+
+  for(i=0; i<cnt; i++)
     {
       if (! (i & 15))
        printf("%02x:", i);
@@ -1815,8 +1807,6 @@ map_the_bus(void)
   if (pacc->method == PCI_ACCESS_PROC_BUS_PCI ||
       pacc->method == PCI_ACCESS_DUMP)
     printf("WARNING: Bus mapping can be reliable only with direct hardware access enabled.\n\n");
-  else if (!check_root())
-    die("Only root can map the bus.");
   bus_info = xmalloc(sizeof(struct bus_info) * 256);
   bzero(bus_info, sizeof(struct bus_info) * 256);
   if (filter.bus >= 0)
index 9c781760063141f6890e1973e46593721d065c8b..4f9953d5bcd3548e7f90ce6dc3b1dc527d572c39 100644 (file)
--- a/setpci.c
+++ b/setpci.c
@@ -1,7 +1,7 @@
 /*
  *     The PCI Utilities -- Manipulate PCI Configuration Registers
  *
- *     Copyright (c) 1998--2003 Martin Mares <mj@ucw.cz>
+ *     Copyright (c) 1998--2004 Martin Mares <mj@ucw.cz>
  *
  *     Can be freely distributed and used under the terms of the GNU GPL.
  */
@@ -454,7 +454,7 @@ next:
              ll = r->offset;
              op->width = r->width;
            }
-         if (ll > 0x100 || ll + op->width*((n < 0) ? 1 : n) > 0x100)
+         if (ll > 0x1000 || ll + op->width*((n < 0) ? 1 : n) > 0x1000)
            die("Register number out of range!");
          if (ll & (op->width - 1))
            die("Unaligned register address!");