[parisc-linux] proposed changes to dino.c
James Bottomley
James.Bottomley at steeleye.com
Tue Dec 9 21:37:16 MST 2003
This updates dino to configure unassigned resources (primarily so I can
get it to recognise my yenta cardbus bridge).
The side effect is that it will reorder all the resources in the dino
window.
James
===== drivers/parisc/dino.c 1.9 vs edited =====
--- 1.9/drivers/parisc/dino.c Fri Oct 10 05:11:03 2003
+++ edited/drivers/parisc/dino.c Tue Dec 9 22:33:18 2003
@@ -165,6 +165,13 @@
#define DINO_CFG_TOK(bus,dfn,pos) ((u32) ((bus)<<16 | (dfn)<<8 | (pos)))
+/*
+ * keep the current highest bus count to assist in allocating busses. This
+ * tries to keep a global bus count total so that when we discover an
+ * entirely new bus, it can be given a unique bus number.
+ */
+static int dino_current_bus = 0;
+
static int dino_cfg_read(struct pci_bus *bus, unsigned int devfn, int where,
int size, u32 *val)
{
@@ -559,8 +566,14 @@
__FUNCTION__, bus, bus->secondary, bus->dev->platform_data);
/* Firmware doesn't set up card-mode dino, so we have to */
- if (is_card_dino(&dino_dev->hba.dev->id))
+ if (is_card_dino(&dino_dev->hba.dev->id)) {
dino_card_setup(bus, dino_dev->hba.base_addr);
+ } else {
+ bus->resource[0] = &(dino_dev->hba.io_space);
+ bus->resource[1] = &(dino_dev->hba.lmmio_space);
+ pci_bus_assign_resources(bus);
+ pci_enable_bridges(bus);
+ }
/* If this is a PCI-PCI Bridge, read the window registers etc */
if (bus->self)
@@ -595,9 +608,29 @@
}
#endif
}
+ if(dev->irq == 255) {
+#if 0
+ /* This code tries to assign an unassigned interrupt
+ * leave it disabled unless you know what you're doing
+ * since the pin<->interrupt line mapping varies
+ * by bus and machine */
+
+ u32 irq_pin;
+
+ dino_cfg_read(dev->bus, dev->devfn, PCI_INTERRUPT_PIN, 1, &irq_pin);
+ dev->irq = (irq_pin + PCI_SLOT(dev->devfn)) % 4 ;
+ dino_cfg_write(dev->bus, dev->devfn, PCI_INTERRUPT_LINE, 1, dev->irq);
+ dev->irq += dino_dev->dino_region->data.irqbase
+ printk(KERN_WARNING "Device %s has undefined IRQ, setting to %d\n", dev->slot_name, irq_pin);
+#else
+ dev->irq = 65535;
+ printk(KERN_WARNING "Device %s has unassigned IRQ\n", dev->slot_name);
+#endif
+ } else {
- /* Adjust INT_LINE for that busses region */
- dev->irq = dino_dev->dino_region->data.irqbase + dev->irq;
+ /* Adjust INT_LINE for that busses region */
+ dev->irq += dino_dev->dino_region->data.irqbase;
+ }
}
}
@@ -826,6 +859,7 @@
const int name_len = 32;
char *name;
int is_cujo = 0;
+ struct pci_bus *bus;
name = kmalloc(name_len, GFP_KERNEL);
if(name)
@@ -911,9 +945,19 @@
** It's not used to avoid chicken/egg problems
** with configuration accessor functions.
*/
- dino_dev->hba.hba_bus =
- pci_scan_bus_parented(&dev->dev, dino_dev->hba.hba_num,
- &dino_cfg_ops, NULL);
+ bus = pci_scan_bus_parented(&dev->dev, dino_current_bus,
+ &dino_cfg_ops, NULL);
+ if(bus) {
+ /* This code *depends* on scanning being single threaded
+ * if it isn't, this global bus number count will fail
+ */
+ dino_current_bus = bus->subordinate + 1;
+ } else {
+ printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (probably duplicate bus number %d)\n", dev->dev.bus_id, dino_current_bus);
+ /* increment the bus number in case of duplicates */
+ dino_current_bus++;
+ }
+ dino_dev->hba.hba_bus = bus;
return 0;
}
More information about the parisc-linux
mailing list