* Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
* PCI-PCI bridges cleanup
*/
-
+#include <linux/config.h>
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/init.h>
}
void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus * bus,
- struct pbus_set_ranges_data * ranges)
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
{
- struct pci_controller *hose = (struct pci_controller *)bus->sysdata;
+ struct pci_controller *hose = (struct pci_controller *)dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = hose->io_space->start;
+ else if (res->flags & IORESOURCE_MEM)
+ offset = hose->mem_space->start;
- ranges->io_start -= hose->io_space->start;
- ranges->io_end -= hose->io_space->start;
- ranges->mem_start -= hose->mem_space->start;
- ranges->mem_end -= hose->mem_space->start;
-/* FIXME: On older alphas we could use dense memory space
- to access prefetchable resources. */
- ranges->prefetch_start -= hose->mem_space->start;
- ranges->prefetch_end -= hose->mem_space->start;
+ region->start = res->start - offset;
+ region->end = res->end - offset;
}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
int
pcibios_enable_device(struct pci_dev *dev, int mask)
{
* Convert from Linux-centric to bus-centric addresses for bridge devices.
*/
void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
{
- struct pci_sys_data *root = bus->sysdata;
+ struct pci_sys_data *root = dev->sysdata;
+ unsigned long offset = 0;
+
+ if (res->flags & IORESOURCE_IO)
+ offset = root->io_offset;
+ if (res->flags & IORESOURCE_MEM)
+ offset = root->mem_offset;
- ranges->io_start -= root->io_offset;
- ranges->io_end -= root->io_offset;
- ranges->mem_start -= root->mem_offset;
- ranges->mem_end -= root->mem_offset;
- ranges->prefetch_start -= root->mem_offset;
- ranges->prefetch_end -= root->mem_offset;
+ region->start = res->start - offset;
+ region->end = res->end - offset;
}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_fixup_bus);
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
/*
* This is the standard PCI-PCI bridge swizzling algorithm:
*
}
}
-void __devinit
-pcibios_fixup_pbus_ranges (struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-}
-
/*
* Called after each bus is probed, but before its children
* are examined.
/* ??? FIXME -- record old value for shutdown. */
}
-void __devinit
-pcibios_fixup_pbus_ranges (struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
-{
-}
-
static inline int
pcibios_enable_resources (struct pci_dev *dev, int mask)
{
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus,
- struct pbus_set_ranges_data *ranges)
-{
-}
-
int pcibios_enable_resources(struct pci_dev *dev)
{
u16 cmd, old_cmd;
pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
}
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus,
- struct pbus_set_ranges_data *ranges)
+#if 0 /* original DDB5074 code */
+void __devinit
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
{
/*
* our caller figure out range by going through the dev structures.
* different view of the addressing space.
*/
-#if 0 /* original DDB5074 code */
if (bus->number == 0) {
ranges->io_start -= bus->resource[0]->start;
ranges->io_end -= bus->resource[0]->start;
ranges->mem_start -= bus->resource[1]->start;
ranges->mem_end -= bus->resource[1]->start;
}
-#endif
}
+#endif
int pcibios_enable_resources(struct pci_dev *dev)
{
pci_fixup_irqs(pci_swizzle, pci_map_irq);
}
-void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus * bus,
- struct pbus_set_ranges_data * ranges)
-{
-}
-
int __init
pcibios_enable_device(struct pci_dev *dev)
{
pci_fixup_irqs (macepci_swizzle, macepci_map_irq);
}
-/* XXX anybody know what this is supposed to do? */
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus * bus,
- struct pbus_set_ranges_data * ranges)
-{
-}
-
/*
* Handle errors from the bridge. This includes master and target aborts,
* various command and address errors, and the interrupt test. This gets
/*
** called by drivers/pci/setup-res.c:pci_setup_bridge().
*/
-void __devinit pcibios_fixup_pbus_ranges(
- struct pci_bus *bus,
- struct pbus_set_ranges_data *ranges
+void __devinit pcibios_resource_to_bus(
+ struct pci_dev *dev,
+ struct pci_bus_region *region,
+ struct resource *res
)
{
+ struct pci_bus *bus = dev->bus;
struct pci_hba_data *hba = HBA_DATA(bus->dev->platform_data);
- /*
- ** I/O space may see busnumbers here. Something
- ** in the form of 0xbbxxxx where bb is the bus num
- ** and xxxx is the I/O port space address.
- ** Remaining address translation are done in the
- ** PCI Host adapter specific code - ie dino_out8.
- */
- ranges->io_start = PCI_PORT_ADDR(ranges->io_start);
- ranges->io_end = PCI_PORT_ADDR(ranges->io_end);
-
- /* Convert MMIO addr to PCI addr (undo global virtualization) */
- ranges->mem_start = PCI_BUS_ADDR(hba, ranges->mem_start);
- ranges->mem_end = PCI_BUS_ADDR(hba, ranges->mem_end);
+ if (res->flags & IORESOURCE_IO) {
+ /*
+ ** I/O space may see busnumbers here. Something
+ ** in the form of 0xbbxxxx where bb is the bus num
+ ** and xxxx is the I/O port space address.
+ ** Remaining address translation are done in the
+ ** PCI Host adapter specific code - ie dino_out8.
+ */
+ region->start = PCI_PORT_ADDR(res->start);
+ region->end = PCI_PORT_ADDR(res->end);
+ } else if (res->flags & IORESOURCE_MEM) {
+ /* Convert MMIO addr to PCI addr (undo global virtualization) */
+ region->start = PCI_BUS_ADDR(hba, res->start);
+ region->end = PCI_BUS_ADDR(hba, res->end);
+ }
- DBG_RES("pcibios_fixup_pbus_ranges(%02x, [%lx,%lx %lx,%lx])\n", bus->number,
- ranges->io_start, ranges->io_end,
- ranges->mem_start, ranges->mem_end);
+ DBG_RES("pcibios_resource_to_bus(%02x %s [%lx,%lx])\n",
+ bus->number, res->flags & IORESOURCE_IO ? "IO" : "MEM",
+ region->start, region->end);
/* KLUGE ALERT
** if this resource isn't linked to a "parent", then it seems
pcibios_link_hba_resources(&hba->lmmio_space, bus->resource[1]);
}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_resource_to_bus);
+#endif
+
#define MAX(val1, val2) ((val1) > (val2) ? (val1) : (val2))
return PCI_SLOT(dev->devfn);
}
-void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus * bus, struct pbus_set_ranges_data * ranges)
-{
-}
-
unsigned long resource_fixup(struct pci_dev * dev, struct resource * res,
unsigned long start, unsigned long size)
{
return NULL;
}
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *pbus,
- struct pbus_set_ranges_data *pranges)
-{
-}
-
void
pcibios_update_resource(struct pci_dev *dev, struct resource *res,
int resource)
}
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *bus, struct pbus_set_ranges_data *ranges)
-{
-}
-
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
struct list_head *ln;
{ 0 }
};
-void __devinit pcibios_fixup_pbus_ranges(struct pci_bus *b,
- struct pbus_set_ranges_data *range)
-{
- /* No fixups needed */
-}
-
/*
* Called after each bus is probed, but before its children
* are examined.
}
-void __devinit
-pcibios_fixup_pbus_ranges(struct pci_bus *bus,
- struct pbus_set_ranges_data *ranges)
-{
-}
-
void __init pcibios_init(void)
{
extern unsigned long memory_start, memory_end;
* pcibios_fixup_bus()
* pcibios_init()
* pcibios_setup()
- * pcibios_fixup_pbus_ranges()
*/
#include <linux/kernel.h>
requires that if there is no I/O ports or memory behind the
bridge, corresponding range must be turned off by writing base
value greater than limit to the bridge's base/limit registers. */
-static void __devinit
-pci_setup_bridge(struct pci_bus *bus)
+static void __devinit pci_setup_bridge(struct pci_bus *bus)
{
- struct pbus_set_ranges_data ranges;
struct pci_dev *bridge = bus->self;
+ struct pci_bus_region region;
u32 l;
- if (!bridge || (bridge->class >> 8) != PCI_CLASS_BRIDGE_PCI)
- return;
-
- ranges.io_start = bus->resource[0]->start;
- ranges.io_end = bus->resource[0]->end;
- ranges.mem_start = bus->resource[1]->start;
- ranges.mem_end = bus->resource[1]->end;
- ranges.prefetch_start = bus->resource[2]->start;
- ranges.prefetch_end = bus->resource[2]->end;
- pcibios_fixup_pbus_ranges(bus, &ranges);
-
DBGC((KERN_INFO "PCI: Bus %d, bridge: %s\n",
bus->number, bridge->dev.name));
/* Set up the top and bottom of the PCI I/O segment for this bus. */
+ pcibios_resource_to_bus(bridge, ®ion, bus->resource[0]);
if (bus->resource[0]->flags & IORESOURCE_IO) {
pci_read_config_dword(bridge, PCI_IO_BASE, &l);
l &= 0xffff0000;
- l |= (ranges.io_start >> 8) & 0x00f0;
- l |= ranges.io_end & 0xf000;
+ l |= (region.start >> 8) & 0x00f0;
+ l |= region.end & 0xf000;
/* Set up upper 16 bits of I/O base/limit. */
pci_write_config_word(bridge, PCI_IO_BASE_UPPER16,
- ranges.io_start >> 16);
+ region.start >> 16);
pci_write_config_word(bridge, PCI_IO_LIMIT_UPPER16,
- ranges.io_end >> 16);
+ region.end >> 16);
DBGC((KERN_INFO " IO window: %04lx-%04lx\n",
- ranges.io_start, ranges.io_end));
+ region.start, region.end));
}
else {
/* Clear upper 16 bits of I/O base/limit. */
/* Set up the top and bottom of the PCI Memory segment
for this bus. */
+ pcibios_resource_to_bus(bridge, ®ion, bus->resource[1]);
if (bus->resource[1]->flags & IORESOURCE_MEM) {
- l = (ranges.mem_start >> 16) & 0xfff0;
- l |= ranges.mem_end & 0xfff00000;
+ l = (region.start >> 16) & 0xfff0;
+ l |= region.end & 0xfff00000;
DBGC((KERN_INFO " MEM window: %08lx-%08lx\n",
- ranges.mem_start, ranges.mem_end));
+ region.start, region.end));
}
else {
l = 0x0000fff0;
pci_write_config_dword(bridge, PCI_PREF_LIMIT_UPPER32, 0);
/* Set up PREF base/limit. */
+ pcibios_resource_to_bus(bridge, ®ion, bus->resource[2]);
if (bus->resource[2]->flags & IORESOURCE_PREFETCH) {
- l = (ranges.prefetch_start >> 16) & 0xfff0;
- l |= ranges.prefetch_end & 0xfff00000;
+ l = (region.start >> 16) & 0xfff0;
+ l |= region.end & 0xfff00000;
DBGC((KERN_INFO " PREFETCH window: %08lx-%08lx\n",
- ranges.prefetch_start, ranges.prefetch_end));
+ region.start, region.end));
}
else {
l = 0x0000fff0;
/* Return the index of the PCI controller for device PDEV. */
extern int pci_controller_num(struct pci_dev *pdev);
+
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res);
+
#endif /* __KERNEL__ */
/* Values for the `which' argument to sys_pciconfig_iobase. */
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res);
+
#endif /* __KERNEL__ */
#endif
--- /dev/null
+/*
+ * linux/include/asm-generic/pci.h
+ *
+ * Copyright (C) 2003 Russell King
+ */
+#ifndef _ASM_GENERIC_PCI_H
+#define _ASM_GENERIC_PCI_H
+
+/**
+ * pcibios_resource_to_bus - convert resource to PCI bus address
+ * @dev: device which owns this resource
+ * @region: converted bus-centric region (start,end)
+ * @res: resource to convert
+ *
+ * Convert a resource to a PCI device bus address or bus window.
+ */
+static inline void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res)
+{
+ region->start = res->start;
+ region->end = res->end;
+}
+
+#endif
/* implement the pci_ DMA API in terms of the generic device dma_ one */
#include <asm-generic/pci-dma-compat.h>
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
#endif /* __i386_PCI_H */
extern int pci_mmap_page_range (struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
#endif /* _ASM_IA64_PCI_H */
#endif /* __KERNEL__ */
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
#endif /* _ASM_PCI_H */
#endif /* __KERNEL__ */
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
#endif /* _ASM_PCI_H */
+
/* export the pci_ DMA API in terms of the dma_ one */
#include <asm-generic/pci-dma-compat.h>
+extern void
+pcibios_resource_to_bus(struct pci_dev *dev, struct pci_bus_region *region,
+ struct resource *res);
+
#endif /* __ASM_PARISC_PCI_H */
#endif /* __KERNEL__ */
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
#endif /* __PPC_PCI_H */
#endif /* __KERNEL__ */
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
#endif /* __PPC64_PCI_H */
#endif /* __KERNEL__ */
+/* generic pci stuff */
+#include <asm-generic/pci.h>
#endif /* __ASM_SH_PCI_H */
#endif /* __KERNEL__ */
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
#endif /* __SPARC64_PCI_H */
#endif /* __KERNEL__ */
+/* generic pci stuff */
+#include <asm-generic/pci.h>
+
#endif /* __x8664_PCI_H */
int (*write)(struct pci_bus *bus, unsigned int devfn, int where, int size, u32 val);
};
-struct pbus_set_ranges_data
-{
- unsigned long io_start, io_end;
- unsigned long mem_start, mem_end;
- unsigned long prefetch_start, prefetch_end;
+struct pci_bus_region {
+ unsigned long start;
+ unsigned long end;
};
struct pci_driver {
unsigned long, unsigned long);
void pcibios_update_resource(struct pci_dev *, struct resource *, int);
void pcibios_update_irq(struct pci_dev *, int irq);
-void pcibios_fixup_pbus_ranges(struct pci_bus *, struct pbus_set_ranges_data *);
/* Generic PCI functions used internally */