o Use `long' instead of `long long' for PCI addresses on Alpha.
o Synchronized header declarations with PCI specs rev. 2.2.
o lspci: Dump all capabilities defined in PCI 2.2.
o lspci: Even htype1 has a capability list.
o lspci: Mask out bottommost 2 bits of capability pointers as required
by the specs.
o Added overall support for reporting of region sizes (needs support
in the kernel, but I've already sent a patch to Linus).
o pci_fill_info() returns a bitmask of what it suceeded to read (reading
of sizes can fail if the kernel doesn't support it).
o Some new IDs.
+Wed Jul 7 00:55:48 1999 Martin Mares <mj@albireo.ucw.cz>
+
+ * lib/proc.c (proc_scan): HAVE_LONG_ADDRESS instead of HAVE_64BIT_ADDRESS.
+
+ * lspci.c: ADDR_FORMAT now depends on both HAVE_64BIT_ADDRESS and
+ HAVE_LONG_ADDRESS.
+
+ * lib/configure: HAVE_64BIT_ADDRESS now doesn't imply that the addresses
+ are represented as long long. Introduced a new flag HAVE_LONG_ADDRESS
+ to indicate this. Both Sparc architectures now use both 64BIT_ADDRESS
+ and LONG_ADDRESS since they have 32-bit userland, but don't set LONG_ADDRESS
+ on Alpha.
+
+ * lspci.c (show_msi): Added dumping of the MSI capability.
+ (show_slotid): The same for SlotID capability.
+ (show_caps): Seperated capability dumping, because it should
+ be used for both htype0 and htype1. Even PCI 2.2 doesn't mention
+ layout of htype2, so I'm a bit unsure about it wrt capabilities
+ -- they at least have to live somewhere else since address 0x34
+ is already defined differently in htype2.
+
+ * lib/header.h (PCI_STATUS_UDF): Marked as obsolete (PCI 2.2).
+ (PCI_BASE_ADDRESS_MEM_TYPE_1M): Ditto.
+ (PCI_CAP_ID_*): Added some new capabilities defined in PCI 2.2.
+
+ * lspci.c (show_htype0): Mask out lowest 2 bits from all capability pointers
+ (required by the PCI 2.2 specs).
+
+Mon Jul 5 12:45:19 1999 Martin Mares <mj@albireo.ucw.cz>
+
+ * lspci.c (show_size): Added new function for dumping of region sizes.
+ (show_rom): Added. Now correctly dumps unassigned ROM addresses, disabled
+ ROMs et cetera.
+
+ * lib/pci.h (struct pci_dev): known_fields moved to the public part
+ of the structure.
+
+ * Added support for region sizes. Needs support in the kernel, because
+ sizes have to be scanned before drivers initialize yourself. pci_fill_info()
+ now returns a bitmask of what fields were really read.
+
Mon Jun 28 18:37:51 1999 Dave Jones <dave@powertweak.com>
* Makefile:
-# $Id: Makefile,v 1.17 1999/07/01 21:33:29 mj Exp $
+# $Id: Makefile,v 1.18 1999/07/07 11:23:03 mj Exp $
# Makefile for Linux PCI Utilities
# (c) 1998--1999 Martin Mares <mj@atrey.karlin.mff.cuni.cz>
ROOT=/
PREFIX=/usr
-VERSION=2.0
+VERSION=2.1-pre4
SUFFIX=
#SUFFIX=-alpha
DATE=99-05-19
/*
- * $Id: access.c,v 1.3 1999/01/27 14:53:02 mj Exp $
+ * $Id: access.c,v 1.4 1999/07/07 11:23:08 mj Exp $
*
* The PCI Library -- User Access
*
return d->methods->write(d, pos, buf, len);
}
-void
+int
pci_fill_info(struct pci_dev *d, int flags)
{
if (flags & PCI_FILL_RESCAN)
d->known_fields = 0;
}
if (flags & ~d->known_fields)
- d->methods->fill_info(d, flags & ~d->known_fields);
- d->known_fields |= flags;
+ d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields);
+ return d->known_fields;
}
void
echo >>$c '#define HAVE_PM_INTEL_CONF'
ok=1
;;
- alpha|sparc|sparc64)
- echo >>$c '#define HAVE_64BIT_ADDRESS'
+ alpha) echo >>$c '#define HAVE_64BIT_ADDRESS'
+# echo -n " syscalls"
+# echo >>$c '#define HAVE_PM_SYSCALLS'
+# ok=1
+ ;;
+ sparc|sparc64) echo >>$c '#define HAVE_64BIT_ADDRESS'
+ echo >>$c '#define HAVE_LONG_ADDRESS'
# echo -n " syscalls"
# echo >>$c '#define HAVE_PM_SYSCALLS'
# ok=1
/*
- * $Id: generic.c,v 1.4 1999/02/28 20:23:10 mj Exp $
+ * $Id: generic.c,v 1.5 1999/07/07 11:23:09 mj Exp $
*
* The PCI Library -- Generic Direct Access Functions
*
pci_generic_scan_bus(a, busmap, 0);
}
-void
+int
pci_generic_fill_info(struct pci_dev *d, int flags)
{
struct pci_access *a = d->access;
d->rom_base_addr = a;
}
}
+ return flags & ~PCI_FILL_SIZES;
}
static int
/*
- * $Id: header.h,v 1.3 1999/04/26 19:46:02 mj Exp $
+ * $Id: header.h,v 1.4 1999/07/07 11:23:10 mj Exp $
*
* The PCI Library -- PCI Header Structure (extracted from <linux/pci.h>)
*
#define PCI_STATUS 0x06 /* 16 bits */
#define PCI_STATUS_CAP_LIST 0x10 /* Support Capability List */
#define PCI_STATUS_66MHZ 0x20 /* Support 66 Mhz PCI 2.1 bus */
-#define PCI_STATUS_UDF 0x40 /* Support User Definable Features */
+#define PCI_STATUS_UDF 0x40 /* Support User Definable Features [obsolete] */
#define PCI_STATUS_FAST_BACK 0x80 /* Accept fast-back to back */
#define PCI_STATUS_PARITY 0x100 /* Detected parity error */
#define PCI_STATUS_DEVSEL_MASK 0x600 /* DEVSEL timing */
#define PCI_BASE_ADDRESS_SPACE_MEMORY 0x00
#define PCI_BASE_ADDRESS_MEM_TYPE_MASK 0x06
#define PCI_BASE_ADDRESS_MEM_TYPE_32 0x00 /* 32 bit address */
-#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M */
+#define PCI_BASE_ADDRESS_MEM_TYPE_1M 0x02 /* Below 1M [obsolete] */
#define PCI_BASE_ADDRESS_MEM_TYPE_64 0x04 /* 64 bit address */
#define PCI_BASE_ADDRESS_MEM_PREFETCH 0x08 /* prefetchable? */
-#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fL)
-#define PCI_BASE_ADDRESS_IO_MASK (~0x03L)
+#define PCI_BASE_ADDRESS_MEM_MASK (~0x0fUL)
+#define PCI_BASE_ADDRESS_IO_MASK (~0x03UL)
/* bit 1 is reserved if address_space = 1 */
/* Header type 0 (normal devices) */
#define PCI_PREF_LIMIT_UPPER32 0x2c
#define PCI_IO_BASE_UPPER16 0x30 /* Upper half of I/O addresses */
#define PCI_IO_LIMIT_UPPER16 0x32
-/* 0x34-0x3b is reserved */
+/* 0x34 same as for htype 0 */
+/* 0x35-0x3b is reserved */
#define PCI_ROM_ADDRESS1 0x38 /* Same as PCI_ROM_ADDRESS, but for htype 1 */
/* 0x3c-0x3d are same as for htype 0 */
#define PCI_BRIDGE_CONTROL 0x3e
/* 0x48-0x7f reserved */
/* Capability lists */
+
#define PCI_CAP_LIST_ID 0 /* Capability ID */
#define PCI_CAP_ID_PM 0x01 /* Power Management */
#define PCI_CAP_ID_AGP 0x02 /* Accelerated Graphics Port */
+#define PCI_CAP_ID_VPD 0x03 /* Vital Product Data */
+#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
+#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
+#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
#define PCI_CAP_SIZEOF 4
#define PCI_AGP_COMMAND_RATE1 0x0001 /* Use 4x rate */
#define PCI_AGP_SIZEOF 12
+/* Slot Identification */
+
+#define PCI_SID_ESR 2 /* Expansion Slot Register */
+#define PCI_SID_ESR_NSLOTS 0x1f /* Number of expansion slots available */
+#define PCI_SID_ESR_FIC 0x20 /* First In Chassis Flag */
+#define PCI_SID_CHASSIS_NR 3 /* Chassis Number */
+
+/* Message Signalled Interrupts registers */
+
+#define PCI_MSI_FLAGS 2 /* Various flags */
+#define PCI_MSI_FLAGS_64BIT 0x80 /* 64-bit addresses allowed */
+#define PCI_MSI_FLAGS_QSIZE 0x70 /* Message queue size configured */
+#define PCI_MSI_FLAGS_QMASK 0x0e /* Maximum queue size available */
+#define PCI_MSI_FLAGS_ENABLE 0x01 /* MSI feature enabled */
+#define PCI_MSI_RFU 3 /* Rest of capability flags */
+#define PCI_MSI_ADDRESS_LO 4 /* Lower 32 bits */
+#define PCI_MSI_ADDRESS_HI 8 /* Upper 32 bits (if PCI_MSI_FLAGS_64BIT set) */
+#define PCI_MSI_DATA_32 8 /* 16 bits of data for 32-bit devices */
+#define PCI_MSI_DATA_64 12 /* 16 bits of data for 64-bit devices */
+
/*
* The PCI interface treats multi-function devices as independent
* devices. The slot/function address of each device is encoded
/*
- * $Id: internal.h,v 1.1 1999/01/22 21:05:29 mj Exp $
+ * $Id: internal.h,v 1.2 1999/07/07 11:23:10 mj Exp $
*
* The PCI Library -- Internal Include File
*
void (*init)(struct pci_access *);
void (*cleanup)(struct pci_access *);
void (*scan)(struct pci_access *);
- void (*fill_info)(struct pci_dev *, int flags);
+ int (*fill_info)(struct pci_dev *, int flags);
int (*read)(struct pci_dev *, int pos, byte *buf, int len);
int (*write)(struct pci_dev *, int pos, byte *buf, int len);
void (*init_dev)(struct pci_dev *);
};
void pci_generic_scan(struct pci_access *);
-void pci_generic_fill_info(struct pci_dev *, int flags);
+int pci_generic_fill_info(struct pci_dev *, int flags);
int pci_generic_block_read(struct pci_dev *, int pos, byte *buf, int len);
int pci_generic_block_write(struct pci_dev *, int pos, byte *buf, int len);
/*
- * $Id: pci.h,v 1.3 1999/02/28 20:23:11 mj Exp $
+ * $Id: pci.h,v 1.4 1999/07/07 11:23:11 mj Exp $
*
* The PCI Library
*
typedef __u16 u16;
typedef __u32 u32;
-#ifdef HAVE_64BIT_ADDRESS
+#ifdef HAVE_LONG_ADDRESS
typedef unsigned long long pciaddr_t;
#else
typedef unsigned long pciaddr_t;
byte dev, func; /* Device and function */
/* These fields are set by pci_fill_info() */
+ int known_fields; /* Set of info fields already known */
word vendor_id, device_id; /* Identity of the device */
int irq; /* IRQ number */
pciaddr_t base_addr[6]; /* Base addresses */
+ pciaddr_t size[6]; /* Region sizes */
pciaddr_t rom_base_addr; /* Expansion ROM base address */
+ pciaddr_t rom_size; /* Expansion ROM size */
/* Fields used internally: */
struct pci_access *access;
struct pci_methods *methods;
byte *cache; /* Cached information */
int cache_len;
- int known_fields; /* Set of info fields that is already known */
int hdrtype; /* Direct methods: header type */
void *aux; /* Auxillary data */
};
int pci_write_long(struct pci_dev *, int pos, u32 data);
int pci_write_block(struct pci_dev *, int pos, byte *buf, int len);
-void pci_fill_info(struct pci_dev *, int flags); /* Fill in device information */
+int pci_fill_info(struct pci_dev *, int flags); /* Fill in device information */
#define PCI_FILL_IDENT 1
#define PCI_FILL_IRQ 2
#define PCI_FILL_BASES 4
#define PCI_FILL_ROM_BASE 8
+#define PCI_FILL_SIZES 16
#define PCI_FILL_RESCAN 0x10000
void pci_setup_cache(struct pci_dev *, byte *cache, int len);
/*
- * $Id: proc.c,v 1.3 1999/06/17 17:51:11 mj Exp $
+ * $Id: proc.c,v 1.4 1999/07/07 11:23:12 mj Exp $
*
* The PCI Library -- Configuration Access via /proc/bus/pci
*
while (fgets(buf, sizeof(buf)-1, f))
{
struct pci_dev *d = pci_alloc_dev(a);
- unsigned int dfn, vend;
+ unsigned int dfn, vend, cnt, known;
- sscanf(buf,
-#ifdef HAVE_64BIT_ADDRESS
- "%x %x %x %llx %llx %llx %llx %llx %llx %llx",
+ cnt = sscanf(buf,
+#ifdef HAVE_LONG_ADDRESS
+ "%x %x %x %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx %llx",
#else
- "%x %x %x %lx %lx %lx %lx %lx %lx %lx",
+ "%x %x %x %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx %lx",
#endif
&dfn,
&vend,
&d->base_addr[3],
&d->base_addr[4],
&d->base_addr[5],
- &d->rom_base_addr);
+ &d->rom_base_addr,
+ &d->size[0],
+ &d->size[1],
+ &d->size[2],
+ &d->size[3],
+ &d->size[4],
+ &d->size[5],
+ &d->rom_size);
+ if (cnt != 9 && cnt != 10 && cnt != 17)
+ a->error("proc: parse error (read only %d items)", cnt);
d->bus = dfn >> 8U;
d->dev = PCI_SLOT(dfn & 0xff);
d->func = PCI_FUNC(dfn & 0xff);
d->vendor_id = vend >> 16U;
d->device_id = vend & 0xffff;
- d->known_fields = a->buscentric ? PCI_FILL_IDENT
- : (PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE);
+ known = PCI_FILL_IDENT;
+ if (!a->buscentric)
+ {
+ known |= PCI_FILL_IRQ | PCI_FILL_BASES;
+ if (cnt >= 10)
+ known |= PCI_FILL_ROM_BASE;
+ if (cnt >= 17)
+ known |= PCI_FILL_SIZES;
+ }
+ d->known_fields = known;
pci_link_dev(a, d);
}
fclose(f);
/*
- * $Id: lspci.c,v 1.26 1999/06/17 17:51:45 mj Exp $
+ * $Id: lspci.c,v 1.27 1999/07/07 11:23:04 mj Exp $
*
* Linux PCI Utilities -- List All PCI Devices
*
#endif
#ifdef HAVE_64BIT_ADDRESS
+#ifdef HAVE_LONG_ADDRESS
#define ADDR_FORMAT "%016Lx"
#else
+#define ADDR_FORMAT "%016lx"
+#endif
+#else
#define ADDR_FORMAT "%08lx"
#endif
}
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_info(p, PCI_FILL_IDENT | PCI_FILL_IRQ | PCI_FILL_BASES | PCI_FILL_ROM_BASE | PCI_FILL_SIZES);
return d;
}
putchar('\n');
}
+static void
+show_size(pciaddr_t x)
+{
+ printf(" [size=");
+ if (x < 1024)
+ printf("%d", (int) x);
+ else if (x < 1048576)
+ printf("%dK", (int)(x / 1024));
+ else if (x < 0x80000000)
+ printf("%dM", (int)(x / 1048576));
+ else
+ printf(ADDR_FORMAT, x);
+ putchar(']');
+}
+
static void
show_bases(struct device *d, int cnt)
{
for(i=0; i<cnt; i++)
{
pciaddr_t pos = p->base_addr[i];
+ pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->size[i] : 0;
u32 flg = get_conf_long(d, PCI_BASE_ADDRESS_0 + 4*i);
if (flg == 0xffffffff)
flg = 0;
- if (!pos && !flg)
+ if (!pos && !flg && !len)
continue;
if (verbose > 1)
printf("\tRegion %d: ", i);
{
if (i >= cnt - 1)
{
- printf("<invalid-64bit-slot>\n");
+ printf("<invalid-64bit-slot>");
done = 1;
}
else
if (!(cmd & PCI_COMMAND_MEMORY))
printf(" [disabled]");
}
+ if (len)
+ show_size(len);
putchar('\n');
}
}
}
static void
-show_htype0(struct device *d)
+show_rom(struct device *d)
{
- unsigned long rom = d->dev->rom_base_addr;
+ struct pci_dev *p = d->dev;
+ pciaddr_t rom = p->rom_base_addr;
+ pciaddr_t len = (p->known_fields & PCI_FILL_SIZES) ? p->rom_size : 0;
- show_bases(d, 6);
- if (rom & 1)
- printf("\tExpansion ROM at %08lx%s\n", rom & PCI_ROM_ADDRESS_MASK,
- (rom & PCI_ROM_ADDRESS_ENABLE) ? "" : " [disabled]");
+ if (!rom && !len)
+ return;
+ printf("\tExpansion ROM at ");
+ if (rom & PCI_ROM_ADDRESS_MASK)
+ printf(ADDR_FORMAT, rom & PCI_ROM_ADDRESS_MASK);
+ else
+ printf("<unassigned>");
+ if (!(rom & PCI_ROM_ADDRESS_ENABLE))
+ printf(" [disabled]");
+ show_size(len);
+ putchar('\n');
+}
+
+static void
+show_msi(struct device *d, int where, int cap)
+{
+ int is64;
+ u32 t;
+ u16 w;
+
+ printf("Message Signalled Interrupts: 64bit%c Queue=%d/%d Enable%c\n",
+ FLAG(cap, PCI_MSI_FLAGS_64BIT),
+ (cap & PCI_MSI_FLAGS_QSIZE) >> 4,
+ (cap & PCI_MSI_FLAGS_QMASK) >> 1,
+ FLAG(cap, PCI_MSI_FLAGS_ENABLE));
+ if (verbose < 2)
+ return;
+ is64 = cap & PCI_MSI_FLAGS_64BIT;
+ config_fetch(d, where + PCI_MSI_ADDRESS_LO, (is64 ? PCI_MSI_DATA_64 : PCI_MSI_DATA_32) + 2 - PCI_MSI_ADDRESS_LO);
+ printf("\t\tAddress: ");
+ if (is64)
+ {
+ t = get_conf_long(d, where + PCI_MSI_ADDRESS_HI);
+ w = get_conf_word(d, where + PCI_MSI_DATA_64);
+ printf("%08x", t);
+ }
+ else
+ w = get_conf_word(d, where + PCI_MSI_DATA_32);
+ t = get_conf_long(d, where + PCI_MSI_ADDRESS_LO);
+ printf("%08x Data: %04x\n", t, w);
+}
+
+static void
+show_slotid(int cap)
+{
+ int esr = cap & 0xff;
+ int chs = cap >> 8;
+
+ printf("Slot ID: %d slots, First%c, chassis %02x\n",
+ esr & PCI_SID_ESR_NSLOTS,
+ FLAG(esr, PCI_SID_ESR_FIC),
+ chs);
+}
+
+static void
+show_caps(struct device *d)
+{
if (get_conf_word(d, PCI_STATUS) & PCI_STATUS_CAP_LIST)
{
- int where = get_conf_byte(d, PCI_CAPABILITY_LIST);
+ int where = get_conf_byte(d, PCI_CAPABILITY_LIST) & ~3;
while (where)
{
int id, next, cap;
break;
}
id = get_conf_byte(d, where + PCI_CAP_LIST_ID);
- next = get_conf_byte(d, where + PCI_CAP_LIST_NEXT);
+ next = get_conf_byte(d, where + PCI_CAP_LIST_NEXT) & ~3;
cap = get_conf_word(d, where + PCI_CAP_FLAGS);
printf("[%02x] ", where);
if (id == 0xff)
case PCI_CAP_ID_AGP:
show_agp(d, where, cap);
break;
+ case PCI_CAP_ID_VPD:
+ printf("Vital Product Data\n");
+ break;
+ case PCI_CAP_ID_SLOTID:
+ show_slotid(cap);
+ break;
+ case PCI_CAP_ID_MSI:
+ show_msi(d, where, cap);
+ break;
default:
- printf("#%02x [%04x]", id, cap);
+ printf("#%02x [%04x]\n", id, cap);
}
where = next;
}
}
}
+static void
+show_htype0(struct device *d)
+{
+ show_bases(d, 6);
+ show_rom(d);
+ show_caps(d);
+}
+
static void
show_htype1(struct device *d)
{
- struct pci_dev *p = d->dev;
u32 io_base = get_conf_byte(d, PCI_IO_BASE);
u32 io_limit = get_conf_byte(d, PCI_IO_LIMIT);
u32 io_type = io_base & PCI_IO_RANGE_TYPE_MASK;
u32 pref_base = get_conf_word(d, PCI_PREF_MEMORY_BASE);
u32 pref_limit = get_conf_word(d, PCI_PREF_MEMORY_LIMIT);
u32 pref_type = pref_base & PCI_PREF_RANGE_TYPE_MASK;
- unsigned long rom = p->rom_base_addr;
word brc = get_conf_word(d, PCI_BRIDGE_CONTROL);
show_bases(d, 2);
if (get_conf_word(d, PCI_SEC_STATUS) & PCI_STATUS_SIG_SYSTEM_ERROR)
printf("\tSecondary status: SERR\n");
- if (rom & 1)
- printf("\tExpansion ROM at %08lx%s\n", rom & PCI_ROM_ADDRESS_MASK,
- (rom & PCI_ROM_ADDRESS_ENABLE) ? "" : " [disabled]");
+ show_rom(d);
if (verbose > 1)
printf("\tBridgeCtl: Parity%c SERR%c NoISA%c VGA%c MAbort%c >Reset%c FastB2B%c\n",
FLAG(brc, PCI_BRIDGE_CTL_MASTER_ABORT),
FLAG(brc, PCI_BRIDGE_CTL_BUS_RESET),
FLAG(brc, PCI_BRIDGE_CTL_FAST_BACK));
+
+ show_caps(d);
}
static void
# Maintained by Martin Mares <pci-ids@ucw.cz>
# If you have any new entries, send them to the maintainer.
#
-# $Id: pci.ids,v 1.28 1999/07/01 21:33:30 mj Exp $
+# $Id: pci.ids,v 1.29 1999/07/07 11:23:05 mj Exp $
#
# Vendors and devices. Please keep sorted.
C 0E Intelligent controller
0000 I2O
+S 1092 Diamond Multimedia
+ 8760 Fireport 40 Dual SCSI Host Adapter
+ 4820 Viper V550 Graphics Accelerator
S 10b4 STB Systems Inc
273e Velocity 4400
-
S 1102 Creative Labs
1015 Graphics Blaster CT6710
-
S 125c Aurora Technologies, Inc.
0640 Aries 16000P