|
From: Andy P. <at...@us...> - 2002-04-09 17:08:09
|
Update of /cvsroot/linux-vax/kernel-2.4/drivers/pci
In directory usw-pr-cvs1:/tmp/cvs-serv6177/pci
Modified Files:
Makefile compat.c gen-devlist.c names.c pci.c pci.ids proc.c
quirks.c setup-bus.c setup-irq.c setup-res.c
Log Message:
synch 2.4.15 commit 27
Index: Makefile
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- Makefile 14 Jan 2001 18:35:34 -0000 1.1.1.1
+++ Makefile 9 Apr 2002 16:45:52 -0000 1.2
@@ -13,14 +13,23 @@
export-objs := pci.o
-obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o setup-res.o
+obj-$(CONFIG_PCI) += pci.o quirks.o compat.o names.o
obj-$(CONFIG_PROC_FS) += proc.o
+ifndef CONFIG_SPARC64
+obj-$(CONFIG_PCI) += setup-res.o
+endif
+
#
# Some architectures use the generic PCI setup functions
#
obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
+obj-$(CONFIG_PARISC) += setup-bus.o
+obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
+obj-$(CONFIG_ALL_PPC) += setup-bus.o
+obj-$(CONFIG_DDB5476) += setup-bus.o
+obj-$(CONFIG_SGI_IP27) += setup-irq.o
ifndef CONFIG_X86
obj-y += syscall.o
Index: compat.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/compat.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- compat.c 14 Jan 2001 18:35:38 -0000 1.1.1.1
+++ compat.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -3,7 +3,7 @@
*
* PCI Bus Services -- Function For Backward Compatibility
*
- * Copyright 1998--2000 Martin Mares <mj...@su...>
+ * Copyright 1998--2000 Martin Mares <mj...@uc...>
*/
#include <linux/types.h>
Index: gen-devlist.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/gen-devlist.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- gen-devlist.c 14 Jan 2001 18:36:02 -0000 1.1.1.1
+++ gen-devlist.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -1,7 +1,7 @@
/*
* Generate devlist.h and classlist.h from the PCI ID file.
*
- * (c) 1999--2000 Martin Mares <mj...@su...>
+ * (c) 1999--2000 Martin Mares <mj...@uc...>
*/
#include <stdio.h>
@@ -68,6 +68,7 @@
bra[-1] = 0;
if (vendor_len + strlen(c) + 1 > MAX_NAME_SIZE) {
fprintf(stderr, "Line %d: Device name too long\n", lino);
+ fprintf(stderr, "%s\n", c);
return 1;
}
}
Index: names.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/names.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- names.c 14 Jan 2001 18:35:42 -0000 1.1.1.1
+++ names.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -32,9 +32,9 @@
* real memory.. Parse the same file multiple times
* to get all the info.
*/
-#define VENDOR( vendor, name ) static const char __vendorstr_##vendor[] __initdata = name;
+#define VENDOR( vendor, name ) static char __vendorstr_##vendor[] __initdata = name;
#define ENDVENDOR()
-#define DEVICE( vendor, device, name ) static const char __devicestr_##vendor##device[] __initdata = name;
+#define DEVICE( vendor, device, name ) static char __devicestr_##vendor##device[] __initdata = name;
#include "devlist.h"
@@ -43,7 +43,7 @@
#define DEVICE( vendor, device, name ) { 0x##device, 0, __devicestr_##vendor##device },
#include "devlist.h"
-static const struct pci_vendor_info __initdata pci_vendor_list[] = {
+static struct pci_vendor_info __initdata pci_vendor_list[] = {
#define VENDOR( vendor, name ) { 0x##vendor, sizeof(__devices_##vendor) / sizeof(struct pci_device_info), __vendorstr_##vendor, __devices_##vendor },
#define ENDVENDOR()
#define DEVICE( vendor, device, name )
@@ -52,7 +52,7 @@
#define VENDORS (sizeof(pci_vendor_list)/sizeof(struct pci_vendor_info))
-void __init pci_name_device(struct pci_dev *dev)
+void __devinit pci_name_device(struct pci_dev *dev)
{
const struct pci_vendor_info *vendor_p = pci_vendor_list;
int i = VENDORS;
Index: pci.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/pci.c,v
retrieving revision 1.1.1.2
retrieving revision 1.2
diff -u -r1.1.1.2 -r1.2
--- pci.c 25 Feb 2001 23:15:09 -0000 1.1.1.2
+++ pci.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -6,7 +6,7 @@
* Copyright 1993 -- 1997 Drew Eckhardt, Frederic Potter,
* David Mosberger-Tang
*
- * Copyright 1997 -- 2000 Martin Mares <mj...@su...>
+ * Copyright 1997 -- 2000 Martin Mares <mj...@uc...>
*/
#include <linux/config.h>
@@ -21,6 +21,8 @@
#include <linux/spinlock.h>
#include <linux/pm.h>
[...1360 lines suppressed...]
+EXPORT_SYMBOL(pci_set_power_state);
+EXPORT_SYMBOL(pci_save_state);
+EXPORT_SYMBOL(pci_restore_state);
+EXPORT_SYMBOL(pci_enable_wake);
+
/* Obsolete functions */
EXPORT_SYMBOL(pcibios_present);
@@ -1236,4 +2023,11 @@
EXPORT_SYMBOL(isa_dma_bridge_buggy);
EXPORT_SYMBOL(pci_pci_problems);
+
+/* Pool allocator */
+
+EXPORT_SYMBOL (pci_pool_create);
+EXPORT_SYMBOL (pci_pool_destroy);
+EXPORT_SYMBOL (pci_pool_alloc);
+EXPORT_SYMBOL (pci_pool_free);
Index: pci.ids
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/pci.ids,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- pci.ids 14 Jan 2001 18:36:00 -0000 1.1.1.1
+++ pci.ids 9 Apr 2002 16:45:52 -0000 1.2
@@ -1,8 +1,11 @@
#
# List of PCI ID's
#
-# Maintained by Martin Mares <pc...@uc...>
-# If you have any new entries, send them to the maintainer.
+# Maintained by Martin Mares <mj...@uc...> and other volunteers from the
+# Linux PCI ID's Project at http://pciids.sf.net/. New data are always
+# welcome (if they are accurate), we're eagerly expecting new entries,
+# so if you have anything to contribute, please visit the home page or
+# send a diff -u against the most recent pci.ids to pc...@uc....
#
[...1675 lines suppressed...]
7810 AIC-7810
@@ -4783,6 +5235,7 @@
00c0 7899A
00c1 7899B
00c3 7899D
+ 00c5 RAID subsystem HBA
00cf 7899P
907f Atronics
2015 IDE-2015PL
@@ -4965,8 +5418,8 @@
00 UHCI
10 OHCI
80 Unspecified
- Fe USB Device
- 04 Fiber Channel
+ fe USB Device
+ 04 Fibre Channel
05 SMBus
06 InfiniBand
C 0d Wireless controller
Index: proc.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/proc.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- proc.c 14 Jan 2001 18:35:40 -0000 1.1.1.1
+++ proc.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -3,7 +3,7 @@
*
* Procfs interface for the PCI bus.
*
- * Copyright (c) 1997--1999 Martin Mares <mj...@su...>
+ * Copyright (c) 1997--1999 Martin Mares <mj...@uc...>
*/
#include <linux/types.h>
@@ -11,6 +11,7 @@
#include <linux/pci.h>
#include <linux/proc_fs.h>
#include <linux/init.h>
+#include <linux/seq_file.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -191,10 +192,109 @@
return nbytes;
}
+struct pci_filp_private {
+ enum pci_mmap_state mmap_state;
+ int write_combine;
+};
+
+static int proc_bus_pci_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+ const struct proc_dir_entry *dp = inode->u.generic_ip;
+ struct pci_dev *dev = dp->data;
+#ifdef HAVE_PCI_MMAP
+ struct pci_filp_private *fpriv = file->private_data;
+#endif /* HAVE_PCI_MMAP */
+ int ret = 0;
+
+ switch (cmd) {
+ case PCIIOC_CONTROLLER:
+ ret = pci_controller_num(dev);
+ break;
+
+#ifdef HAVE_PCI_MMAP
+ case PCIIOC_MMAP_IS_IO:
+ fpriv->mmap_state = pci_mmap_io;
+ break;
+
+ case PCIIOC_MMAP_IS_MEM:
+ fpriv->mmap_state = pci_mmap_mem;
+ break;
+
+ case PCIIOC_WRITE_COMBINE:
+ if (arg)
+ fpriv->write_combine = 1;
+ else
+ fpriv->write_combine = 0;
+ break;
+
+#endif /* HAVE_PCI_MMAP */
+
+ default:
+ ret = -EINVAL;
+ break;
+ };
+
+ return ret;
+}
+
+#ifdef HAVE_PCI_MMAP
+static int proc_bus_pci_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct inode *inode = file->f_dentry->d_inode;
+ const struct proc_dir_entry *dp = inode->u.generic_ip;
+ struct pci_dev *dev = dp->data;
+ struct pci_filp_private *fpriv = file->private_data;
+ int ret;
+
+ if (!capable(CAP_SYS_RAWIO))
+ return -EPERM;
+
+ ret = pci_mmap_page_range(dev, vma,
+ fpriv->mmap_state,
+ fpriv->write_combine);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int proc_bus_pci_open(struct inode *inode, struct file *file)
+{
+ struct pci_filp_private *fpriv = kmalloc(sizeof(*fpriv), GFP_KERNEL);
+
+ if (!fpriv)
+ return -ENOMEM;
+
+ fpriv->mmap_state = pci_mmap_io;
+ fpriv->write_combine = 0;
+
+ file->private_data = fpriv;
+
+ return 0;
+}
+
+static int proc_bus_pci_release(struct inode *inode, struct file *file)
+{
+ kfree(file->private_data);
+ file->private_data = NULL;
+
+ return 0;
+}
+#endif /* HAVE_PCI_MMAP */
+
static struct file_operations proc_bus_pci_operations = {
- llseek: proc_bus_pci_lseek,
- read: proc_bus_pci_read,
- write: proc_bus_pci_write,
+ llseek: proc_bus_pci_lseek,
+ read: proc_bus_pci_read,
+ write: proc_bus_pci_write,
+ ioctl: proc_bus_pci_ioctl,
+#ifdef HAVE_PCI_MMAP
+ open: proc_bus_pci_open,
+ release: proc_bus_pci_release,
+ mmap: proc_bus_pci_mmap,
+#ifdef HAVE_ARCH_PCI_GET_UNMAPPED_AREA
+ get_unmapped_area: get_pci_unmapped_area,
+#endif /* HAVE_ARCH_PCI_GET_UNMAPPED_AREA */
+#endif /* HAVE_PCI_MMAP */
};
#if BITS_PER_LONG == 32
@@ -203,53 +303,72 @@
#define LONG_FORMAT "\t%16lx"
#endif
-static int
-get_pci_dev_info(char *buf, char **start, off_t pos, int count)
+/* iterator */
+static void *pci_seq_start(struct seq_file *m, loff_t *pos)
+{
+ struct list_head *p = &pci_devices;
+ loff_t n = *pos;
+
+ /* XXX: surely we need some locking for traversing the list? */
+ while (n--) {
+ p = p->next;
+ if (p == &pci_devices)
+ return NULL;
+ }
+ return p;
+}
+static void *pci_seq_next(struct seq_file *m, void *v, loff_t *pos)
+{
+ struct list_head *p = v;
+ (*pos)++;
+ return p->next != &pci_devices ? p->next : NULL;
+}
+static void pci_seq_stop(struct seq_file *m, void *v)
{
+ /* release whatever locks we need */
+}
+
+static int show_device(struct seq_file *m, void *v)
+{
+ struct list_head *p = v;
const struct pci_dev *dev;
- off_t at = 0;
- int len, i, cnt;
+ const struct pci_driver *drv;
+ int i;
- cnt = 0;
- pci_for_each_dev(dev) {
- const struct pci_driver *drv = pci_dev_driver(dev);
- len = sprintf(buf, "%02x%02x\t%04x%04x\t%x",
+ if (p == &pci_devices)
+ return 0;
+
+ dev = pci_dev_g(p);
+ drv = pci_dev_driver(dev);
+ seq_printf(m, "%02x%02x\t%04x%04x\t%x",
dev->bus->number,
dev->devfn,
dev->vendor,
dev->device,
dev->irq);
- /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
- for(i=0; i<7; i++)
- len += sprintf(buf+len, LONG_FORMAT,
- dev->resource[i].start | (dev->resource[i].flags & PCI_REGION_FLAG_MASK));
- for(i=0; i<7; i++)
- len += sprintf(buf+len, LONG_FORMAT, dev->resource[i].start < dev->resource[i].end ?
- dev->resource[i].end - dev->resource[i].start + 1 : 0);
- buf[len++] = '\t';
- if (drv)
- len += sprintf(buf+len, "%s", drv->name);
- buf[len++] = '\n';
- at += len;
- if (at >= pos) {
- if (!*start) {
- *start = buf + (pos - (at - len));
- cnt = at - pos;
- } else
- cnt += len;
- buf += len;
- if (cnt >= count)
- /*
- * proc_file_read() gives us 1KB of slack so it's OK if the
- * above printfs write a little beyond the buffer end (we
- * never write more than 1KB beyond the buffer end).
- */
- break;
- }
- }
- return (count > cnt) ? cnt : count;
+ /* Here should be 7 and not PCI_NUM_RESOURCES as we need to preserve compatibility */
+ for(i=0; i<7; i++)
+ seq_printf(m, LONG_FORMAT,
+ dev->resource[i].start |
+ (dev->resource[i].flags & PCI_REGION_FLAG_MASK));
+ for(i=0; i<7; i++)
+ seq_printf(m, LONG_FORMAT,
+ dev->resource[i].start < dev->resource[i].end ?
+ dev->resource[i].end - dev->resource[i].start + 1 : 0);
+ seq_putc(m, '\t');
+ if (drv)
+ seq_printf(m, "%s", drv->name);
+ seq_putc(m, '\n');
+ return 0;
}
+static struct seq_operations proc_bus_pci_devices_op = {
+ start: pci_seq_start,
+ next: pci_seq_next,
+ stop: pci_seq_stop,
+ show: show_device
+};
+
static struct proc_dir_entry *proc_bus_pci_dir;
int pci_proc_attach_device(struct pci_dev *dev)
@@ -287,6 +406,28 @@
return 0;
}
+int pci_proc_attach_bus(struct pci_bus* bus)
+{
+ struct proc_dir_entry *de = bus->procdir;
+
+ if (!de) {
+ char name[16];
+ sprintf(name, "%02x", bus->number);
+ de = bus->procdir = proc_mkdir(name, proc_bus_pci_dir);
+ if (!de)
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+int pci_proc_detach_bus(struct pci_bus* bus)
+{
+ struct proc_dir_entry *de = bus->procdir;
+ if (de)
+ remove_proc_entry(de->name, proc_bus_pci_dir);
+ return 0;
+}
+
/*
* Backward compatible /proc/pci interface.
@@ -298,54 +439,56 @@
* 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)
+static int show_dev_config(struct seq_file *m, void *v)
{
+ struct list_head *p = v;
+ struct pci_dev *dev;
+ struct pci_driver *drv;
u32 class_rev;
unsigned char latency, min_gnt, max_lat, *class;
- int reg, len = 0;
+ int reg;
+
+ if (p == &pci_devices) {
+ seq_puts(m, "PCI devices found:\n");
+ return 0;
+ }
+
+ dev = pci_dev_g(p);
+ drv = pci_dev_driver(dev);
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_rev);
pci_read_config_byte (dev, PCI_LATENCY_TIMER, &latency);
pci_read_config_byte (dev, PCI_MIN_GNT, &min_gnt);
pci_read_config_byte (dev, PCI_MAX_LAT, &max_lat);
- if (len + 160 > size)
- return -1;
- len += sprintf(buf + len, " Bus %2d, device %3d, function %2d:\n",
- dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
+ seq_printf(m, " Bus %2d, device %3d, function %2d:\n",
+ dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
class = pci_class_name(class_rev >> 16);
if (class)
- len += sprintf(buf+len, " %s", class);
+ seq_printf(m, " %s", class);
else
- len += sprintf(buf+len, " Class %04x", class_rev >> 16);
- len += sprintf(buf+len, ": %s (rev %d).\n", dev->name, class_rev & 0xff);
+ seq_printf(m, " Class %04x", class_rev >> 16);
+ seq_printf(m, ": %s (rev %d).\n", dev->name, class_rev & 0xff);
- if (dev->irq) {
- if (len + 40 > size)
- return -1;
- len += sprintf(buf + len, " IRQ %d.\n", dev->irq);
- }
+ if (dev->irq)
+ seq_printf(m, " IRQ %d.\n", dev->irq);
if (latency || min_gnt || max_lat) {
- if (len + 80 > size)
- return -1;
- len += sprintf(buf + len, " Master Capable. ");
+ seq_printf(m, " Master Capable. ");
if (latency)
- len += sprintf(buf + len, "Latency=%d. ", latency);
+ seq_printf(m, "Latency=%d. ", latency);
else
- len += sprintf(buf + len, "No bursts. ");
+ seq_puts(m, "No bursts. ");
if (min_gnt)
- len += sprintf(buf + len, "Min Gnt=%d.", min_gnt);
+ seq_printf(m, "Min Gnt=%d.", min_gnt);
if (max_lat)
- len += sprintf(buf + len, "Max Lat=%d.", max_lat);
- len += sprintf(buf + len, "\n");
+ seq_printf(m, "Max Lat=%d.", max_lat);
+ seq_putc(m, '\n');
}
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;
@@ -353,9 +496,8 @@
continue;
if (flags & PCI_BASE_ADDRESS_SPACE_IO) {
- len += sprintf(buf + len,
- " I/O at 0x%lx [0x%lx].\n",
- base, end);
+ seq_printf(m, " I/O at 0x%lx [0x%lx].\n",
+ base, end);
} else {
const char *pref, *type = "unknown";
@@ -371,65 +513,58 @@
case PCI_BASE_ADDRESS_MEM_TYPE_64:
type = "64 bit"; break;
}
- len += sprintf(buf + len,
- " %srefetchable %s memory at "
+ seq_printf(m, " %srefetchable %s memory at "
"0x%lx [0x%lx].\n", pref, type,
base,
end);
}
}
-
- return len;
+ return 0;
}
-/*
- * Return list of PCI devices as a character string for /proc/pci.
- * BUF is a buffer that is PAGE_SIZE bytes long.
- */
-static int pci_read_proc(char *buf, char **start, off_t off,
- int count, int *eof, void *data)
-{
- int nprinted, len, begin = 0;
- struct pci_dev *dev;
-
- len = sprintf(buf, "PCI devices found:\n");
+static struct seq_operations proc_pci_op = {
+ start: pci_seq_start,
+ next: pci_seq_next,
+ stop: pci_seq_stop,
+ show: show_dev_config
+};
- *eof = 1;
- pci_for_each_dev(dev) {
- nprinted = sprint_dev_config(dev, buf + len, PAGE_SIZE - len);
- if (nprinted < 0) {
- *eof = 0;
- break;
- }
- len += nprinted;
- if (len+begin < off) {
- begin += len;
- len = 0;
- }
- if (len+begin >= off+count)
- break;
- }
- off -= begin;
- *start = buf + off;
- len -= off;
- if (len>count)
- len = count;
- if (len<0)
- len = 0;
- return len;
+static int proc_bus_pci_dev_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &proc_bus_pci_devices_op);
}
+static struct file_operations proc_bus_pci_dev_operations = {
+ open: proc_bus_pci_dev_open,
+ read: seq_read,
+ llseek: seq_lseek,
+ release: seq_release,
+};
+static int proc_pci_open(struct inode *inode, struct file *file)
+{
+ return seq_open(file, &proc_pci_op);
+}
+static struct file_operations proc_pci_operations = {
+ open: proc_pci_open,
+ read: seq_read,
+ llseek: seq_lseek,
+ release: seq_release,
+};
static int __init pci_proc_init(void)
{
if (pci_present()) {
+ struct proc_dir_entry *entry;
struct pci_dev *dev;
proc_bus_pci_dir = proc_mkdir("pci", proc_bus);
- create_proc_info_entry("devices", 0, proc_bus_pci_dir,
- get_pci_dev_info);
+ entry = create_proc_entry("devices", 0, proc_bus_pci_dir);
+ if (entry)
+ entry->proc_fops = &proc_bus_pci_dev_operations;
pci_for_each_dev(dev) {
pci_proc_attach_device(dev);
}
- create_proc_read_entry("pci", 0, NULL, pci_read_proc, NULL);
+ entry = create_proc_entry("pci", 0, NULL);
+ if (entry)
+ entry->proc_fops = &proc_pci_operations;
}
return 0;
}
Index: quirks.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/quirks.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- quirks.c 14 Jan 2001 18:35:41 -0000 1.1.1.1
+++ quirks.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -5,17 +5,19 @@
* bugs. Devices present only on certain architectures (host
* bridges et cetera) should be handled in arch-specific code.
*
- * Copyright (c) 1999 Martin Mares <mj...@su...>
+ * Copyright (c) 1999 Martin Mares <mj...@uc...>
*
* The bridge optimization stuff has been removed. If you really
* have a silly BIOS which is unable to set your host bridge right,
* use the PowerTweak utility (see http://powertweak.sourceforge.net).
*/
+#include <linux/config.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/pci.h>
#include <linux/init.h>
+#include <linux/delay.h>
#undef DEBUG
@@ -31,7 +33,7 @@
while ((d = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_0, d))) {
pci_read_config_byte(d, 0x82, &dlc);
if (!(dlc & 1<<1)) {
- printk("PCI: PIIX3: Enabling Passive Release on %s\n", d->slot_name);
+ printk(KERN_ERR "PCI: PIIX3: Enabling Passive Release on %s\n", d->slot_name);
dlc |= 1<<1;
pci_write_config_byte(d, 0x82, dlc);
}
@@ -85,6 +87,66 @@
}
/*
+ * VIA Apollo KT133 needs PCI latency patch
+ * Made according to a windows driver based patch by George E. Breese
+ * see PCI Latency Adjust on http://www.viahardware.com/download/viatweak.shtm
+ * Also see http://home.tiscalinet.de/au-ja/review-kt133a-1-en.html for
+ * the info on which Mr Breese based his work.
+ *
+ * Updated based on further information from the site and also on
+ * information provided by VIA
+ */
+static void __init quirk_vialatency(struct pci_dev *dev)
+{
+ struct pci_dev *p;
+ u8 rev;
+ u8 busarb;
+ /* Ok we have a potential problem chipset here. Now see if we have
+ a buggy southbridge */
+
+ p=pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, NULL);
+ if(p!=NULL)
+ {
+ pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
+ /* 0x40 - 0x4f == 686B, 0x10 - 0x2f == 686A; thanks Dan Hollis */
+ /* Check for buggy part revisions */
+ if (rev < 0x40 || rev > 0x42)
+ return;
+ }
+ else
+ {
+ p = pci_find_device(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231, NULL);
+ if(p==NULL) /* No problem parts */
+ return;
+ pci_read_config_byte(p, PCI_CLASS_REVISION, &rev);
+ /* Check for buggy part revisions */
+ if (rev < 0x10 || rev > 0x12)
+ return;
+ }
+
+ /*
+ * Ok we have the problem. Now set the PCI master grant to
+ * occur every master grant. The apparent bug is that under high
+ * PCI load (quite common in Linux of course) you can get data
+ * loss when the CPU is held off the bus for 3 bus master requests
+ * This happens to include the IDE controllers....
+ *
+ * VIA only apply this fix when an SB Live! is present but under
+ * both Linux and Windows this isnt enough, and we have seen
+ * corruption without SB Live! but with things like 3 UDMA IDE
+ * controllers. So we ignore that bit of the VIA recommendation..
+ */
+
+ pci_read_config_byte(dev, 0x76, &busarb);
+ /* Set bit 4 and bi 5 of byte 76 to 0x01
+ "Master priority rotation on every PCI master grant */
+ busarb &= ~(1<<5);
+ busarb |= (1<<4);
+ pci_write_config_byte(dev, 0x76, busarb);
+ printk(KERN_INFO "Applying VIA southbridge workaround.\n");
+}
+
+/*
* VIA Apollo VP3 needs ETBF on BT848/878
*/
@@ -96,6 +158,15 @@
pci_pci_problems|=PCIPCI_VIAETBF;
}
}
+static void __init quirk_vsfx(struct pci_dev *dev)
+{
+ if((pci_pci_problems&PCIPCI_VSFX)==0)
+ {
+ printk(KERN_INFO "Limiting direct PCI/PCI transfers.\n");
+ pci_pci_problems|=PCIPCI_VSFX;
+ }
+}
+
/*
* Natoma has some interesting boundary conditions with Zoran stuff
@@ -215,6 +286,86 @@
quirk_io_region(dev, smb, 16, PCI_BRIDGE_RESOURCES + 2);
}
+
+#ifdef CONFIG_X86_IO_APIC
+extern int nr_ioapics;
+
+/*
+ * VIA 686A/B: If an IO-APIC is active, we need to route all on-chip
+ * devices to the external APIC.
+ *
+ * TODO: When we have device-specific interrupt routers,
+ * this code will go away from quirks.
+ */
+static void __init quirk_via_ioapic(struct pci_dev *dev)
+{
+ u8 tmp;
+
+ if (nr_ioapics < 1)
+ tmp = 0; /* nothing routed to external APIC */
+ else
+ tmp = 0x1f; /* all known bits (4-0) routed to external APIC */
+
+ printk(KERN_INFO "PCI: %sbling Via external APIC routing\n",
+ tmp == 0 ? "Disa" : "Ena");
+
+ /* Offset 0x58: External APIC IRQ output control */
+ pci_write_config_byte (dev, 0x58, tmp);
+}
+
+#endif /* CONFIG_X86_IO_APIC */
+
+
+/*
+ * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
+ * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
+ * when written, it makes an internal connection to the PIC.
+ * For these devices, this register is defined to be 4 bits wide.
+ * Normally this is fine. However for IO-APIC motherboards, or
+ * non-x86 architectures (yes Via exists on PPC among other places),
+ * we must mask the PCI_INTERRUPT_LINE value versus 0xf to get
+ * interrupts delivered properly.
+ *
+ * TODO: When we have device-specific interrupt routers,
+ * quirk_via_irqpic will go away from quirks.
+ */
+
+/*
+ * FIXME: it is questionable that quirk_via_acpi
+ * is needed. It shows up as an ISA bridge, and does not
+ * support the PCI_INTERRUPT_LINE register at all. Therefore
+ * it seems like setting the pci_dev's 'irq' to the
+ * value of the ACPI SCI interrupt is only done for convenience.
+ * -jgarzik
+ */
+static void __init quirk_via_acpi(struct pci_dev *d)
+{
+ /*
+ * VIA ACPI device: SCI IRQ line in PCI config byte 0x42
+ */
+ u8 irq;
+ pci_read_config_byte(d, 0x42, &irq);
+ irq &= 0xf;
+ if (irq && (irq != 2))
+ d->irq = irq;
+}
+
+static void __init quirk_via_irqpic(struct pci_dev *dev)
+{
+ u8 irq, new_irq = dev->irq & 0xf;
+
+ pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &irq);
+
+ if (new_irq != irq) {
+ printk(KERN_INFO "PCI: Via IRQ fixup for %s, from %d to %d\n",
+ dev->slot_name, irq, new_irq);
+
+ udelay(15);
+ pci_write_config_byte(dev, PCI_INTERRUPT_LINE, new_irq);
+ }
+}
+
+
/*
* PIIX3 USB: We have to disable USB interrupts that are
* hardwired to PIRQD# and may be shared with an
@@ -248,6 +399,62 @@
}
/*
+ * CardBus controllers have a legacy base address that enables them
+ * to respond as i82365 pcmcia controllers. We don't want them to
+ * do this even if the Linux CardBus driver is not loaded, because
+ * the Linux i82365 driver does not (and should not) handle CardBus.
+ */
+static void __init quirk_cardbus_legacy(struct pci_dev *dev)
+{
+ if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)
+ return;
+ pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);
+}
+
+/*
+ * The AMD io apic can hang the box when an apic irq is masked.
+ * We check all revs >= B0 (yet not in the pre production!) as the bug
+ * is currently marked NoFix
+ *
+ * We have multiple reports of hangs with this chipset that went away with
+ * noapic specified. For the moment we assume its the errata. We may be wrong
+ * of course. However the advice is demonstrably good even if so..
+ */
+
+static void __init quirk_amd_ioapic(struct pci_dev *dev)
+{
+ u8 rev;
+
+ pci_read_config_byte(dev, PCI_REVISION_ID, &rev);
+ if(rev >= 0x02)
+ {
+ printk(KERN_WARNING "I/O APIC: AMD Errata #22 may be present. In the event of instability try\n");
+ printk(KERN_WARNING " : booting with the \"noapic\" option.\n");
+ }
+}
+
+/*
+ * Following the PCI ordering rules is optional on the AMD762. I'm not
+ * sure what the designers were smoking but let's not inhale...
+ *
+ * To be fair to AMD, it follows the spec by default, its BIOS people
+ * who turn it off!
+ */
+
+static void __init quirk_amd_ordering(struct pci_dev *dev)
+{
+ u32 pcic;
+
+ pci_read_config_dword(dev, 0x42, &pcic);
+ if((pcic&2)==0)
+ {
+ pcic |= 2;
+ printk(KERN_WARNING "BIOS disabled PCI ordering compliance, so we enabled it again.\n");
+ pci_write_config_dword(dev, 0x42, pcic);
+ }
+}
+
+/*
* The main table of quirks.
*/
@@ -275,6 +482,10 @@
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443BX_2, quirk_natoma },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_5597, quirk_nopcipci },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_496, quirk_nopcipci },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8363_0, quirk_vialatency },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8371_1, quirk_vialatency },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, 0x3112 /* Not out yet ? */, quirk_vialatency },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C576, quirk_vsfx },
{ PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_viaetbf },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C597_0, quirk_vt82c598_id },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_vt82c586_acpi },
@@ -283,6 +494,20 @@
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M7101, quirk_ali7101_acpi },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371SB_2, quirk_piix3_usb },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_2, quirk_piix3_usb },
+ { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy },
+
+#ifdef CONFIG_X86_IO_APIC
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686, quirk_via_ioapic },
+#endif
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_3, quirk_via_acpi },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_4, quirk_via_acpi },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C586_2, quirk_via_irqpic },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_5, quirk_via_irqpic },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_82C686_6, quirk_via_irqpic },
+
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, quirk_amd_ioapic },
+ { PCI_FIXUP_FINAL, PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, quirk_amd_ordering },
+
{ 0 }
};
@@ -294,7 +519,7 @@
(f->vendor == dev->vendor || f->vendor == (u16) PCI_ANY_ID) &&
(f->device == dev->device || f->device == (u16) PCI_ANY_ID)) {
#ifdef DEBUG
- printk("PCI: Calling quirk %p for %s\n", f->hook, dev->slot_name);
+ printk(KERN_INFO "PCI: Calling quirk %p for %s\n", f->hook, dev->slot_name);
#endif
f->hook(dev);
}
Index: setup-bus.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/setup-bus.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- setup-bus.c 14 Jan 2001 18:36:03 -0000 1.1.1.1
+++ setup-bus.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -23,7 +23,7 @@
#include <linux/slab.h>
-#define DEBUG_CONFIG 1
+#define DEBUG_CONFIG 0
#if DEBUG_CONFIG
# define DBGC(args) printk args
#else
@@ -136,9 +136,9 @@
ranges.mem_end = bus->resource[1]->end;
pcibios_fixup_pbus_ranges(bus, &ranges);
- DBGC(("PCI: Bus %d, bridge: %s\n", bus->number, bridge->name));
- DBGC((" IO window: %04lx-%04lx\n", ranges.io_start, ranges.io_end));
- DBGC((" MEM window: %08lx-%08lx\n", ranges.mem_start, ranges.mem_end));
+ DBGC((KERN_ERR "PCI: Bus %d, bridge: %s\n", bus->number, bridge->name));
+ DBGC((KERN_ERR " IO window: %04lx-%04lx\n", ranges.io_start, ranges.io_end));
+ DBGC((KERN_ERR " MEM window: %08lx-%08lx\n", ranges.mem_start, ranges.mem_end));
/* Set up the top and bottom of the PCI I/O segment for this bus. */
pci_read_config_dword(bridge, PCI_IO_BASE, &l);
Index: setup-irq.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/setup-irq.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- setup-irq.c 14 Jan 2001 18:36:03 -0000 1.1.1.1
+++ setup-irq.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -53,7 +53,7 @@
irq = 0;
dev->irq = irq;
- DBGC(("PCI fixup irq: (%s) got %d\n", dev->name, dev->irq));
+ DBGC((KERN_ERR "PCI fixup irq: (%s) got %d\n", dev->name, dev->irq));
/* Always tell the device, so the driver knows what is
the real IRQ to use; the device does not use it. */
Index: setup-res.c
===================================================================
RCS file: /cvsroot/linux-vax/kernel-2.4/drivers/pci/setup-res.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- setup-res.c 14 Jan 2001 18:36:01 -0000 1.1.1.1
+++ setup-res.c 9 Apr 2002 16:45:52 -0000 1.2
@@ -25,7 +25,7 @@
#include <linux/slab.h>
-#define DEBUG_CONFIG 1
+#define DEBUG_CONFIG 0
#if DEBUG_CONFIG
# define DBGC(args) printk args
#else
@@ -115,12 +115,13 @@
* window (it will just not perform as well).
*/
if (!(res->flags & IORESOURCE_PREFETCH) || pci_assign_bus_resource(bus, dev, res, size, min, 0, i) < 0) {
- printk(KERN_ERR "PCI: Failed to allocate resource %d for %s\n", i, dev->name);
+ printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
+ i, res->start, res->end, dev->slot_name);
return -EBUSY;
}
}
- DBGC((" got res[%lx:%lx] for resource %d of %s\n", res->start,
+ DBGC((KERN_ERR " got res[%lx:%lx] for resource %d of %s\n", res->start,
res->end, i, dev->name));
return 0;
@@ -163,6 +164,10 @@
size = ln->res->end - ln->res->start;
if (r_size > size) {
tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
+ if (!tmp) {
+ printk(KERN_ERR "pdev_sort_resources(): kmalloc() failed!\n");
+ continue;
+ }
tmp->next = ln;
tmp->res = r;
tmp->dev = dev;
@@ -180,7 +185,7 @@
u16 cmd;
int i;
- DBGC(("PCI enable device: (%s)\n", dev->name));
+ DBGC((KERN_ERR "PCI enable device: (%s)\n", dev->name));
pci_read_config_word(dev, PCI_COMMAND, &cmd);
@@ -225,5 +230,5 @@
/* Enable the appropriate bits in the PCI command register. */
pci_write_config_word(dev, PCI_COMMAND, cmd);
- DBGC((" cmd reg 0x%x\n", cmd));
+ DBGC((KERN_ERR " cmd reg 0x%x\n", cmd));
}
|