patch-2.4.6 linux/arch/ppc/kernel/pci.c
Next file: linux/arch/ppc/kernel/pmac_pci.c
Previous file: linux/arch/ppc/kernel/mk_defs.c
Back to the patch index
Back to the overall index
- Lines: 457
- Date:
Mon Jul 2 14:34:57 2001
- Orig file:
v2.4.5/linux/arch/ppc/kernel/pci.c
- Orig date:
Mon May 21 17:04:47 2001
diff -u --recursive --new-file v2.4.5/linux/arch/ppc/kernel/pci.c linux/arch/ppc/kernel/pci.c
@@ -1,5 +1,5 @@
/*
- * BK Id: SCCS/s.pci.c 1.21 05/21/01 01:31:30 cort
+ * BK Id: SCCS/s.pci.c 1.26 06/28/01 08:02:41 trini
*/
/*
* Common pmac/prep/chrp pci routines. -- Cort
@@ -40,11 +40,10 @@
unsigned long isa_mem_base = 0;
unsigned long pci_dram_offset = 0;
-static u8* pci_to_OF_bus_map;
-
static void pcibios_fixup_resources(struct pci_dev* dev);
#ifdef CONFIG_ALL_PPC
static void pcibios_fixup_cardbus(struct pci_dev* dev);
+static u8* pci_to_OF_bus_map;
#endif
/* By default, we don't re-assign bus numbers. We do this only on
@@ -73,8 +72,13 @@
u32 new, check;
int reg;
struct pci_controller* hose = dev->sysdata;
+ unsigned long io_offset;
new = res->start;
+ if (hose && res->flags & IORESOURCE_IO) {
+ io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ new -= io_offset;
+ }
if (hose && res->flags & IORESOURCE_MEM)
new -= hose->pci_mem_offset;
new |= (res->flags & PCI_REGION_FLAG_MASK);
@@ -98,40 +102,43 @@
}
static void
-pcibios_fixup_resources(struct pci_dev* dev)
+pcibios_fixup_resources(struct pci_dev *dev)
{
- struct pci_controller* hose =
- (struct pci_controller *)dev->sysdata;
+ struct pci_controller* hose = (struct pci_controller *)dev->sysdata;
int i;
+ unsigned long offset;
+
if (!hose) {
- printk("No hose for PCI dev %x.%x !\n", dev->bus->number, dev->devfn >> 3);
+ printk(KERN_ERR "No hose for PCI dev %s!\n", dev->slot_name);
return;
}
for (i = 0; i < DEVICE_COUNT_RESOURCE; i++) {
struct resource *res = dev->resource + i;
- if (!res->start)
+ if (!res->start || !res->flags)
continue;
- if ((res->flags & IORESOURCE_MEM) && hose->pci_mem_offset) {
- res->start += hose->pci_mem_offset;
- res->end += hose->pci_mem_offset;
+ if (res->end == 0xffffffff) {
+ DBG("PCI:%s Resource %d [%08lx-%08lx] is unassigned\n",
+ dev->slot_name, i, res->start, res->end);
+ res->end -= res->start;
+ res->start = 0;
+ continue;
+ }
+ offset = 0;
+ if (res->flags & IORESOURCE_MEM) {
+ offset = hose->pci_mem_offset;
+ } else if (res->flags & IORESOURCE_IO) {
+ offset = (unsigned long) hose->io_base_virt
+ - isa_io_base;
+ }
+ if (offset != 0) {
+ res->start += offset;
+ res->end += offset;
#ifdef DEBUG
- printk("Fixup mem res, dev: %x.%x, res_start: %lx->%lx\n",
- dev->bus->number, dev->devfn>>3, res->start-hose->pci_mem_offset,
- res->start);
+ printk("Fixup res %d (%lx) of dev %s: %lx -> %lx\n",
+ i, res->flags, dev->slot_name,
+ res->start - offset, res->start);
#endif
}
-
- if ((res->flags & IORESOURCE_IO)
- && (unsigned long) hose->io_base_virt != isa_io_base) {
- unsigned long offs;
-
- offs = (unsigned long)hose->io_base_virt - isa_io_base;
- res->start += offs;
- res->end += offs;
- printk("Fixup IO res, dev: %x.%x, res_start: %lx->%lx\n",
- dev->bus->number, dev->devfn>>3,
- res->start - offs, res->start);
- }
}
}
@@ -228,22 +235,27 @@
{
struct list_head *ln;
struct pci_bus *bus;
- struct pci_dev *dev;
- int idx;
- struct resource *r, *pr;
+ int i;
+ struct resource *res, *pr;
/* Depth-First Search on bus tree */
- for (ln=bus_list->next; ln != bus_list; ln=ln->next) {
+ for (ln = bus_list->next; ln != bus_list; ln=ln->next) {
bus = pci_bus_b(ln);
- if ((dev = bus->self)) {
- for (idx = PCI_BRIDGE_RESOURCES; idx < PCI_NUM_RESOURCES; idx++) {
- r = &dev->resource[idx];
- if (!r->start)
- continue;
- pr = pci_find_parent_resource(dev, r);
- if (!pr || request_resource(pr, r) < 0)
- printk(KERN_ERR "PCI: Cannot allocate resource region %d of bridge %s\n", idx, dev->slot_name);
- }
+ for (i = 0; i < 4; ++i) {
+ if ((res = bus->resource[i]) == NULL || !res->flags)
+ continue;
+ if (bus->parent == NULL)
+ pr = (res->flags & IORESOURCE_IO)?
+ &ioport_resource: &iomem_resource;
+ else
+ pr = pci_find_parent_resource(bus->self, res);
+
+ if (pr && request_resource(pr, res) == 0)
+ continue;
+ printk(KERN_ERR "PCI: Cannot allocate resource region "
+ "%d of PCI bridge %d\n", i, bus->number);
+ DBG("PCI: resource is %lx..%lx (%lx), parent %p\n",
+ res->start, res->end, res->flags, pr);
}
pcibios_allocate_bus_resources(&bus->children);
}
@@ -253,13 +265,15 @@
{
struct resource *pr, *r = &dev->resource[idx];
- DBG("PCI:%x:%x:%x: Resource %08lx-%08lx (f=%lx)\n",
- dev->bus->number, dev->devfn >> 3, dev->devfn & 7,
- r->start, r->end, r->flags);
+ DBG("PCI:%s: Resource %d: %08lx-%08lx (f=%lx)\n",
+ dev->slot_name, idx, r->start, r->end, r->flags);
pr = pci_find_parent_resource(dev, r);
if (!pr || request_resource(pr, r) < 0) {
printk(KERN_ERR "PCI: Cannot allocate resource region %d"
" of device %s\n", idx, dev->slot_name);
+ if (pr)
+ DBG("PCI: parent is %p: %08lx-%08lx (f=%lx)\n",
+ pr, pr->start, pr->end, pr->flags);
/* We'll assign a new address later */
r->end -= r->start;
r->start = 0;
@@ -276,20 +290,12 @@
pci_for_each_dev(dev) {
pci_read_config_word(dev, PCI_COMMAND, &command);
- for(idx = 0; idx < 6; idx++) {
+ for (idx = 0; idx < 6; idx++) {
r = &dev->resource[idx];
if (r->parent) /* Already allocated */
continue;
if (!r->start) /* Not assigned at all */
continue;
- if (r->end == 0xffffffff) {
- /* LongTrail OF quirk: unassigned */
- DBG("PCI: Resource %08lx-%08lx was unassigned\n", r->start, r->end);
- r->end -= r->start;
- r->start = 0;
- continue;
- }
-
if (r->flags & IORESOURCE_IO)
disabled = !(command & PCI_COMMAND_IO);
else
@@ -306,7 +312,8 @@
DBG("PCI: Switching off ROM of %s\n", dev->slot_name);
r->flags &= ~PCI_ROM_ADDRESS_ENABLE;
pci_read_config_dword(dev, dev->rom_base_reg, ®);
- pci_write_config_dword(dev, dev->rom_base_reg, reg & ~PCI_ROM_ADDRESS_ENABLE);
+ pci_write_config_dword(dev, dev->rom_base_reg,
+ reg & ~PCI_ROM_ADDRESS_ENABLE);
}
}
}
@@ -325,21 +332,14 @@
if (!class || class == PCI_CLASS_BRIDGE_HOST)
continue;
- for(idx=0; idx<6; idx++) {
+ for (idx = 0; idx < 6; idx++) {
r = &dev->resource[idx];
-#if 0 /* we don't need this PC-ism */
- /*
- * Don't touch IDE controllers and I/O ports of video cards!
- */
- if ((class == PCI_CLASS_STORAGE_IDE && idx < 4) ||
- (class == PCI_CLASS_DISPLAY_VGA && (r->flags & IORESOURCE_IO)))
- continue;
-#endif
/*
- * We shall assign a new address to this resource, either because
- * the BIOS (sic) forgot to do so or because we have decided the old
- * address was unusable for some reason.
+ * We shall assign a new address to this resource,
+ * either because the BIOS (sic) forgot to do so
+ * or because we have decided the old address was
+ * unusable for some reason.
*/
if (!r->start && r->end &&
(!ppc_md.pcibios_enable_device_hook ||
@@ -347,13 +347,13 @@
pci_assign_resource(dev, idx);
}
- if (0) { /* don't assign ROMs */
- r = &dev->resource[PCI_ROM_RESOURCE];
- r->end -= r->start;
- r->start = 0;
- if (r->end)
- pci_assign_resource(dev, PCI_ROM_RESOURCE);
- }
+#if 0 /* don't assign ROMs */
+ r = &dev->resource[PCI_ROM_RESOURCE];
+ r->end -= r->start;
+ r->start = 0;
+ if (r->end)
+ pci_assign_resource(dev, PCI_ROM_RESOURCE);
+#endif
}
}
@@ -496,10 +496,15 @@
&& ((reg[0] >> 16) & 0xff) == bus)
return node;
- /* For PCI<->PCI bridges or CardBus bridges, we go down */
+ /* For PCI<->PCI bridges or CardBus bridges, we go down
+ * Note: some OFs create a parent node "multifunc-device" as
+ * a fake root for all functions of a multi-function device,
+ * we go down them as well.
+ */
class_code = (unsigned int *) get_property(node, "class-code", 0);
- if (!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
- (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS))
+ if ((!class_code || ((*class_code >> 8) != PCI_CLASS_BRIDGE_PCI &&
+ (*class_code >> 8) != PCI_CLASS_BRIDGE_CARDBUS)) &&
+ strcmp(node->name, "multifunc-device"))
continue;
sub_node = scan_OF_childs_for_device(node->child, bus, dev_fn);
if (sub_node)
@@ -682,9 +687,9 @@
{
struct pci_controller *hose;
struct pci_bus *bus;
- int next_busno, i;
+ int next_busno;
- printk("PCI: Probing PCI hardware\n");
+ printk(KERN_INFO "PCI: Probing PCI hardware\n");
/* Scan all of the recorded PCI controllers. */
for (next_busno = 0, hose = hose_head; hose; hose = hose->next) {
@@ -692,18 +697,6 @@
hose->first_busno = next_busno;
hose->last_busno = 0xff;
bus = pci_scan_bus(hose->first_busno, hose->ops, hose);
- if (hose->io_resource.flags) {
- unsigned long offs;
-
- offs = (unsigned long)hose->io_base_virt - isa_io_base;
- hose->io_resource.start += offs;
- hose->io_resource.end += offs;
- bus->resource[0] = &hose->io_resource;
- }
- for (i = 0; i < 3; ++i)
- if (hose->mem_resources[i].flags)
- bus->resource[i+1] = &hose->mem_resources[i];
- hose->bus = bus;
hose->last_busno = bus->subordinate;
if (pci_assign_all_busses || next_busno <= hose->last_busno)
next_busno = hose->last_busno+1;
@@ -716,7 +709,7 @@
*/
if (pci_assign_all_busses && have_of)
pcibios_make_OF_bus_map();
-
+
/* Call machine dependant fixup */
if (ppc_md.pcibios_fixup)
ppc_md.pcibios_fixup();
@@ -727,27 +720,7 @@
pcibios_allocate_resources(1);
pcibios_assign_resources();
-#ifdef CONFIG_BLK_DEV_IDE
- /* OF fails to initialize IDE controllers on macs
- * (and maybe other machines)
- *
- * Ideally, this should be moved to the IDE layer, but we need
- * to check specifically with Andre Hedrick how to do it cleanly
- * since the common IDE code seem to care about the fact that the
- * BIOS may have disabled a controller.
- *
- * -- BenH
- */
- if (_machine == _MACH_Pmac) {
- struct pci_dev *dev;
- pci_for_each_dev(dev)
- {
- if ((dev->class >> 16) == PCI_BASE_CLASS_STORAGE)
- pci_enable_device(dev);
- }
- }
-#endif /* CONFIG_BLK_DEV_IDE */
-
+ /* Call machine dependent post-init code */
if (ppc_md.pcibios_after_init)
ppc_md.pcibios_after_init();
}
@@ -775,21 +748,62 @@
void __init pcibios_fixup_bus(struct pci_bus *bus)
{
- struct pci_controller *hose;
+ struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
+ unsigned long io_offset;
+ struct resource *res;
+ int i;
+
+ io_offset = (unsigned long)hose->io_base_virt - isa_io_base;
+ if (bus->parent == NULL) {
+ /* This is a host bridge - fill in its resources */
+ hose->bus = bus;
- pci_read_bridge_bases(bus);
+ bus->resource[0] = res = &hose->io_resource;
+ if (!res->flags) {
+ if (io_offset)
+ printk(KERN_ERR "I/O resource not set for host"
+ " bridge %d\n", hose->index);
+ res->start = 0;
+ res->end = IO_SPACE_LIMIT;
+ res->flags = IORESOURCE_IO;
+ }
+ res->start += io_offset;
+ res->end += io_offset;
- hose = pci_bus_to_hose(bus->number);
+ for (i = 0; i < 3; ++i) {
+ res = &hose->mem_resources[i];
+ if (!res->flags) {
+ if (i > 0)
+ continue;
+ printk(KERN_ERR "Memory resource not set for "
+ "host bridge %d\n", hose->index);
+ res->start = hose->pci_mem_offset;
+ res->end = ~0U;
+ res->flags = IORESOURCE_MEM;
+ }
+ bus->resource[i+1] = res;
+ }
+ } else {
+ /* This is a subordinate bridge */
+ pci_read_bridge_bases(bus);
- /* Apply pci_mem_offset to bridge mem resource */
- if (hose->first_busno != bus->number)
- if (bus->resource[1]->start && (bus->resource[1]->end != -1))
- {
- bus->resource[1]->start += hose->pci_mem_offset;
- bus->resource[1]->end += hose->pci_mem_offset;
+ for (i = 0; i < 4; ++i) {
+ if ((res = bus->resource[i]) == NULL)
+ continue;
+ if (!res->flags)
+ continue;
+ if (io_offset && (res->flags & IORESOURCE_IO)) {
+ res->start += io_offset;
+ res->end += io_offset;
+ } else if (hose->pci_mem_offset
+ && (res->flags & IORESOURCE_MEM)) {
+ res->start += hose->pci_mem_offset;
+ res->end += hose->pci_mem_offset;
+ }
}
+ }
- if ( ppc_md.pcibios_fixup_bus )
+ if (ppc_md.pcibios_fixup_bus)
ppc_md.pcibios_fixup_bus(bus);
}
@@ -881,26 +895,17 @@
return hose->pci_mem_offset;
}
-#ifdef CONFIG_POWER4
-extern unsigned long pci_address_offset(int, unsigned int);
-#endif /* CONFIG_POWER4 */
-
unsigned long
pci_resource_to_bus(struct pci_dev *pdev, struct resource *res)
{
/* Hack alert again ! See comments in chrp_pci.c
*/
-#ifdef CONFIG_POWER4
- unsigned long offset = pci_address_offset(pdev->bus->number, res->flags);
- return res->start - offset;
-#else /* CONFIG_POWER4 */
struct pci_controller* hose =
(struct pci_controller *)pdev->sysdata;
if (hose && res->flags & IORESOURCE_MEM)
return res->start - hose->pci_mem_offset;
/* We may want to do something with IOs here... */
return res->start;
-#endif
}
/*
@@ -1072,27 +1077,19 @@
unsigned long
pci_phys_to_bus(unsigned long pa, int busnr)
{
-#ifdef CONFIG_POWER4
- return pa - pci_address_offset(busnr, IORESOURCE_MEM);
-#else /* CONFIG_POWER4 */
struct pci_controller* hose = pci_bus_to_hose(busnr);
if (!hose)
return pa;
return pa - hose->pci_mem_offset;
-#endif
}
unsigned long
pci_bus_to_phys(unsigned int ba, int busnr)
{
-#ifdef CONFIG_POWER4
- return ba + pci_address_offset(dev->bus->number, IORESOURCE_MEM);
-#else /* CONFIG_POWER4 */
struct pci_controller* hose = pci_bus_to_hose(busnr);
if (!hose)
return ba;
return ba + hose->pci_mem_offset;
-#endif
}
/* Provide information on locations of various I/O regions in physical
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)