X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fmips%2Fpci%2Fpci-ip27.c;h=068e0e508e15a0c72851afaa2feccf5b95b8961e;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=b996766a286af9bfb0184af513b85195ccee24b2;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/arch/mips/pci/pci-ip27.c b/arch/mips/pci/pci-ip27.c index b996766a2..068e0e508 100644 --- a/arch/mips/pci/pci-ip27.c +++ b/arch/mips/pci/pci-ip27.c @@ -4,7 +4,7 @@ * for more details. * * Copyright (C) 2003 Christoph Hellwig (hch@lst.de) - * Copyright (C) 1999, 2000 Ralf Baechle (ralf@gnu.org) + * Copyright (C) 1999, 2000, 04 Ralf Baechle (ralf@linux-mips.org) * Copyright (C) 1999, 2000 Silicon Graphics, Inc. */ #include @@ -12,11 +12,12 @@ #include #include #include -#include #include #include #include +extern unsigned int allocate_irqno(void); + /* * Max #PCI busses we can handle; ie, max #PCI bridges. */ @@ -81,7 +82,7 @@ static int pci_conf0_read_config(struct pci_bus *bus, unsigned int devfn, else res = get_dbe(*value, (u32 *) addr); - return PCIBIOS_SUCCESSFUL; + return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; oh_my_gawd: @@ -110,6 +111,79 @@ oh_my_gawd: return PCIBIOS_SUCCESSFUL; } +static int pci_conf1_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int busno = bus->number; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + volatile void *addr; + u32 cf, shift, mask; + int res; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; + + if (size == 1) + res = get_dbe(*value, (u8 *) addr); + else if (size == 2) + res = get_dbe(*value, (u16 *) addr); + else + res = get_dbe(*value, (u32 *) addr); + + return res ? PCIBIOS_DEVICE_NOT_FOUND : PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) { + *value = 0; + return PCIBIOS_SUCCESSFUL; + } + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | where]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + *value = (cf >> shift) & mask; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_read_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 * value) +{ + if (bus->number > 0) + return pci_conf1_read_config(bus, devfn, where, size, value); + + return pci_conf0_read_config(bus, devfn, where, size, value); +} + static int pci_conf0_write_config(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 value) { @@ -176,16 +250,95 @@ oh_my_gawd: return PCIBIOS_SUCCESSFUL; } +static int pci_conf1_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct bridge_controller *bc = BRIDGE_CONTROLLER(bus); + bridge_t *bridge = bc->base; + int slot = PCI_SLOT(devfn); + int fn = PCI_FUNC(devfn); + int busno = bus->number; + volatile void *addr; + u32 cf, shift, mask, smask; + int res; + + bridge->b_pci_cfg = (busno << 16) | (slot << 11); + addr = &bridge->b_type1_cfg.c[(fn << 8) | PCI_VENDOR_ID]; + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to look at it for real ... + */ + if (cf == (PCI_VENDOR_ID_SGI | (PCI_DEVICE_ID_SGI_IOC3 << 16))) + goto oh_my_gawd; + + addr = &bridge->b_type1_cfg.c[(fn << 8) | (where ^ (4 - size))]; + + if (size == 1) { + res = put_dbe(value, (u8 *) addr); + } else if (size == 2) { + res = put_dbe(value, (u16 *) addr); + } else { + res = put_dbe(value, (u32 *) addr); + } + + if (res) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; + +oh_my_gawd: + + /* + * IOC3 is fucked fucked beyond believe ... Don't even give the + * generic PCI code a chance to touch the wrong register. + */ + if ((where >= 0x14 && where < 0x40) || (where >= 0x48)) + return PCIBIOS_SUCCESSFUL; + + /* + * IOC3 is fucked fucked beyond believe ... Don't try to access + * anything but 32-bit words ... + */ + addr = &bridge->b_type0_cfg_dev[slot].f[fn].l[where >> 2]; + + if (get_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + shift = ((where & 3) << 3); + mask = (0xffffffffU >> ((4 - size) << 3)); + smask = mask << shift; + + cf = (cf & ~smask) | ((value & mask) << shift); + if (put_dbe(cf, (u32 *) addr)) + return PCIBIOS_DEVICE_NOT_FOUND; + + return PCIBIOS_SUCCESSFUL; +} + +static int pci_write_config(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + if (bus->number > 0) + return pci_conf1_write_config(bus, devfn, where, size, value); + + return pci_conf0_write_config(bus, devfn, where, size, value); +} + static struct pci_ops bridge_pci_ops = { - .read = pci_conf0_read_config, - .write = pci_conf0_write_config, + .read = pci_read_config, + .write = pci_write_config, }; int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) { + unsigned long offset = NODE_OFFSET(nasid); struct bridge_controller *bc; - bridge_t *bridge; static int num_bridges = 0; + bridge_t *bridge; + int slot; printk("a bridge\n"); @@ -193,21 +346,23 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) if (!num_bridges) ioport_resource.end = ~0UL; - bc = &bridges[num_bridges++]; + bc = &bridges[num_bridges]; bc->pc.pci_ops = &bridge_pci_ops; bc->pc.mem_resource = &bc->mem; bc->pc.io_resource = &bc->io; + bc->pc.index = num_bridges; + bc->mem.name = "Bridge PCI MEM"; - bc->pc.mem_offset = 0; + bc->pc.mem_offset = offset; bc->mem.start = 0; bc->mem.end = ~0UL; bc->mem.flags = IORESOURCE_MEM; bc->io.name = "Bridge IO MEM"; + bc->pc.io_offset = offset; bc->io.start = 0UL; - bc->pc.io_offset = 0UL; bc->io.end = ~0UL; bc->io.flags = IORESOURCE_IO; @@ -231,7 +386,7 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) /* * Until otherwise set up, assume all interrupts are from slot 0 */ - bridge->b_int_device = (u32) 0x0; + bridge->b_int_device = 0x0; /* * swap pio's to pci mem and io space (big windows) @@ -248,11 +403,18 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) bridge->b_dir_map = (masterwid << 20); /* DMA */ bridge->b_int_enable = 0; + for (slot = 0; slot < 8; slot ++) { + bridge->b_device[slot].reg |= BRIDGE_DEV_SWAP_DIR; + bc->pci_int[slot] = -1; + } bridge->b_wid_tflush; /* wait until Bridge PIO complete */ bc->base = bridge; register_pci_controller(&bc->pc); + + num_bridges++; + return 0; } @@ -268,17 +430,13 @@ int __init bridge_probe(nasid_t nasid, int widget_id, int masterwid) int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); - int irq; + int irq = bc->pci_int[slot]; - irq = allocate_irqno(); - - /* - * Argh... This API doesn't handle with errors at all ... - */ if (irq == -1) { - printk(KERN_ERR "Can't allocate interrupt for PCI device %s\n", - pci_name(dev)); - return -1; + irq = bc->pci_int[slot] = request_bridge_irq(bc); + if (irq < 0) + panic("Can't allocate interrupt for PCI device %s\n", + pci_name(dev)); } irq_to_bridge[irq] = bc; @@ -287,6 +445,12 @@ int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) return irq; } +/* Do platform specific device initialization at pci_enable_device() time */ +int pcibios_plat_dev_init(struct pci_dev *dev) +{ + return 0; +} + /* * Device might live on a subordinate PCI bus. XXX Walk up the chain of buses * to find the slot number in sense of the bridge device register. @@ -294,7 +458,7 @@ int __devinit pcibios_map_irq(struct pci_dev *dev, u8 slot, u8 pin) * settings. */ -static void __init pci_disable_swapping(struct pci_dev *dev) +static inline void pci_disable_swapping(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); bridge_t *bridge = bc->base; @@ -305,7 +469,7 @@ static void __init pci_disable_swapping(struct pci_dev *dev) bridge->b_widget.w_tflush; /* Flush */ } -static void __init pci_enable_swapping(struct pci_dev *dev) +static inline void pci_enable_swapping(struct pci_dev *dev) { struct bridge_controller *bc = BRIDGE_CONTROLLER(dev->bus); bridge_t *bridge = bc->base; @@ -318,122 +482,8 @@ static void __init pci_enable_swapping(struct pci_dev *dev) static void __init pci_fixup_ioc3(struct pci_dev *d) { - struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); - unsigned long offset = NODE_OFFSET(bc->nasid); - - printk("PCI: Fixing base addresses for IOC3 device %s\n", pci_name(d)); - - d->resource[0].start |= offset; - d->resource[0].end |= offset; - pci_disable_swapping(d); } DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SGI, PCI_DEVICE_ID_SGI_IOC3, - pci_fixup_ioc3); - -static void __init pci_fixup_isp1020(struct pci_dev *d) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); - unsigned short command; - - d->resource[0].start |= (unsigned long) bc->nasid << 32; - printk("PCI: Fixing isp1020 in [bus:slot.fn] %s\n", pci_name(d)); - - /* - * Configure device to allow bus mastering, i/o and memory mapping. - * Older qlogicisp driver expects to have the IO space enable - * bit set. Things stop working if we program the controllers as not - * having PCI_COMMAND_MEMORY, so we have to fudge the mem_flags. - */ - pci_set_master(d); - pci_read_config_word(d, PCI_COMMAND, &command); - command |= PCI_COMMAND_MEMORY; - command |= PCI_COMMAND_IO; - pci_write_config_word(d, PCI_COMMAND, command); - d->resource[1].flags |= 1; - - pci_enable_swapping(d); -} - -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP1020, - pci_fixup_isp1020); - -static void __init pci_fixup_isp2x00(struct pci_dev *d) -{ - struct bridge_controller *bc = BRIDGE_CONTROLLER(d->bus); - bridge_t *bridge = bc->base; - bridgereg_t devreg; - int i; - int slot = PCI_SLOT(d->devfn); - unsigned int start; - unsigned short command; - - printk("PCI: Fixing isp2x00 in [bus:slot.fn] %s\n", pci_name(d)); - - /* set the resource struct for this device */ - start = (u32) (u64) bridge; /* yes, we want to lose the upper 32 bits here */ - start |= BRIDGE_DEVIO(slot); - - d->resource[0].start = start; - d->resource[0].end = d->resource[0].start + 0xff; - d->resource[0].flags = IORESOURCE_IO; - - d->resource[1].start = start; - d->resource[1].end = d->resource[0].start + 0xfff; - d->resource[1].flags = IORESOURCE_MEM; - - /* - * set the bridge device(x) reg for this device - */ - devreg = bridge->b_device[slot].reg; - /* point device(x) to it appropriate small window */ - devreg &= ~BRIDGE_DEV_OFF_MASK; - devreg |= (start >> 20) & BRIDGE_DEV_OFF_MASK; - bridge->b_device[slot].reg = devreg; - - pci_enable_swapping(d); - - /* set card's base addr reg */ - //pci_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x500001); - //pci_write_config_dword(d, PCI_BASE_ADDRESS_1, 0x8b00000); - //pci_write_config_dword(d, PCI_ROM_ADDRESS, 0x8b20000); - - /* I got these from booting irix on system... */ - pci_write_config_dword(d, PCI_BASE_ADDRESS_0, 0x200001); - //pci_write_config_dword(d, PCI_BASE_ADDRESS_1, 0xf800000); - pci_write_config_dword(d, PCI_ROM_ADDRESS, 0x10200000); - - pci_write_config_dword(d, PCI_BASE_ADDRESS_1, start); - //pci_write_config_dword(d, PCI_ROM_ADDRESS, (start | 0x20000)); - - /* set cache line size */ - pci_write_config_dword(d, PCI_CACHE_LINE_SIZE, 0xf080); - - /* set pci bus timeout */ - bridge->b_bus_timeout |= BRIDGE_BUS_PCI_RETRY_HLD(0x3); - bridge->b_wid_tflush; - printk("PCI: bridge bus timeout= 0x%x \n", bridge->b_bus_timeout); - - /* set host error field */ - bridge->b_int_host_err = 0x44; - bridge->b_wid_tflush; - - bridge->b_wid_tflush; /* wait until Bridge PIO complete */ - for (i = 0; i < 8; i++) - printk("PCI: device(%d)= 0x%x\n", i, - bridge->b_device[i].reg); - - /* configure device to allow bus mastering, i/o and memory mapping */ - pci_set_master(d); - pci_read_config_word(d, PCI_COMMAND, &command); - command |= PCI_COMMAND_MEMORY; - command |= PCI_COMMAND_IO; - pci_write_config_word(d, PCI_COMMAND, command); - /*d->resource[1].flags |= 1; */ -} - -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2100, - pci_fixup_isp2x00); -DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_QLOGIC, PCI_DEVICE_ID_QLOGIC_ISP2200, - pci_fixup_isp2x00); + pci_fixup_ioc3);