patch-2.4.6 linux/arch/sparc64/kernel/pci_common.c
Next file: linux/arch/sparc64/kernel/pci_impl.h
Previous file: linux/arch/sparc64/kernel/pci.c
Back to the patch index
Back to the overall index
- Lines: 275
- Date:
Fri Jun 29 19:38:26 2001
- Orig file:
v2.4.5/linux/arch/sparc64/kernel/pci_common.c
- Orig date:
Sat May 19 18:13:15 2001
diff -u --recursive --new-file v2.4.5/linux/arch/sparc64/kernel/pci_common.c linux/arch/sparc64/kernel/pci_common.c
@@ -1,4 +1,4 @@
-/* $Id: pci_common.c,v 1.18 2001/05/18 23:06:35 davem Exp $
+/* $Id: pci_common.c,v 1.26 2001/06/28 01:32:18 davem Exp $
* pci_common.c: PCI controller common support.
*
* Copyright (C) 1999 David S. Miller (davem@redhat.com)
@@ -93,12 +93,38 @@
}
/* Older versions of OBP on PCI systems encode 64-bit MEM
- * space assignments incorrectly, this fixes them up.
+ * space assignments incorrectly, this fixes them up. We also
+ * take the opportunity here to hide other kinds of bogus
+ * assignments.
*/
-static void __init fixup_obp_assignments(struct pcidev_cookie *pcp)
+static void __init fixup_obp_assignments(struct pci_dev *pdev,
+ struct pcidev_cookie *pcp)
{
int i;
+ if (pdev->vendor == PCI_VENDOR_ID_AL &&
+ (pdev->device == PCI_DEVICE_ID_AL_M7101 ||
+ pdev->device == PCI_DEVICE_ID_AL_M1533)) {
+ int i;
+
+ /* Zap all of the normal resources, they are
+ * meaningless and generate bogus resource collision
+ * messages. This is OpenBoot's ill-fated attempt to
+ * represent the implicit resources that these devices
+ * have.
+ */
+ pcp->num_prom_assignments = 0;
+ for (i = 0; i < 6; i++) {
+ pdev->resource[i].start =
+ pdev->resource[i].end =
+ pdev->resource[i].flags = 0;
+ }
+ pdev->resource[PCI_ROM_RESOURCE].start =
+ pdev->resource[PCI_ROM_RESOURCE].end =
+ pdev->resource[PCI_ROM_RESOURCE].flags = 0;
+ return;
+ }
+
for (i = 0; i < pcp->num_prom_assignments; i++) {
struct linux_prom_pci_registers *ap;
int space;
@@ -194,7 +220,7 @@
(err / sizeof(pcp->prom_assignments[0]));
}
- fixup_obp_assignments(pcp);
+ fixup_obp_assignments(pdev, pcp);
pdev->sysdata = pcp;
}
@@ -231,11 +257,13 @@
}
}
-static void __init bad_assignment(struct linux_prom_pci_registers *ap,
+static void __init bad_assignment(struct pci_dev *pdev,
+ struct linux_prom_pci_registers *ap,
struct resource *res,
int do_prom_halt)
{
- prom_printf("PCI: Bogus PROM assignment.\n");
+ prom_printf("PCI: Bogus PROM assignment. BUS[%02x] DEVFN[%x]\n",
+ pdev->bus->number, pdev->devfn);
if (ap)
prom_printf("PCI: phys[%08x:%08x:%08x] size[%08x:%08x]\n",
ap->phys_hi, ap->phys_mid, ap->phys_lo,
@@ -293,7 +321,7 @@
case PCI_ROM_ADDRESS:
/* It had better be MEM space. */
if (space != 2)
- bad_assignment(ap, NULL, 0);
+ bad_assignment(pdev, ap, NULL, 0);
res = &pdev->resource[PCI_ROM_RESOURCE];
break;
@@ -308,7 +336,7 @@
break;
default:
- bad_assignment(ap, NULL, 0);
+ bad_assignment(pdev, ap, NULL, 0);
res = NULL;
break;
};
@@ -316,6 +344,19 @@
return res;
}
+static int __init pdev_resource_collisions_expected(struct pci_dev *pdev)
+{
+ if (pdev->vendor != PCI_VENDOR_ID_SUN)
+ return 0;
+
+ if (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS ||
+ pdev->device == PCI_DEVICE_ID_SUN_RIO_1394 ||
+ pdev->device == PCI_DEVICE_ID_SUN_RIO_USB)
+ return 1;
+
+ return 0;
+}
+
static void __init pdev_record_assignments(struct pci_pbm_info *pbm,
struct pci_dev *pdev)
{
@@ -332,14 +373,15 @@
ap = &pcp->prom_assignments[i];
root = get_root_resource(ap, pbm);
res = get_device_resource(ap, pdev);
- if (root == NULL || res == NULL)
+ if (root == NULL || res == NULL ||
+ res->flags == 0)
continue;
/* Ok we know which resource this PROM assignment is
* for, sanity check it.
*/
if ((res->start & 0xffffffffUL) != ap->phys_lo)
- bad_assignment(ap, res, 1);
+ bad_assignment(pdev, ap, res, 1);
/* If it is a 64-bit MEM space assignment, verify that
* the resource is too and that the upper 32-bits match.
@@ -348,9 +390,9 @@
if (((res->flags & IORESOURCE_MEM) == 0) ||
((res->flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK)
!= PCI_BASE_ADDRESS_MEM_TYPE_64))
- bad_assignment(ap, res, 1);
+ bad_assignment(pdev, ap, res, 1);
if ((res->start >> 32) != ap->phys_mid)
- bad_assignment(ap, res, 1);
+ bad_assignment(pdev, ap, res, 1);
/* PBM cannot generate cpu initiated PIOs
* to the full 64-bit space. Therefore the
@@ -374,12 +416,17 @@
if (request_resource(root, res) < 0) {
/* OK, there is some conflict. But this is fine
* since we'll reassign it in the fixup pass.
- * Nevertheless notify the user that OBP made
- * an error.
+ *
+ * We notify the user that OBP made an error if it
+ * is a case we don't expect.
*/
- printk(KERN_ERR "PCI: Address space collision on region %ld "
- "of device %s\n",
- (res - &pdev->resource[0]), pdev->name);
+ if (!pdev_resource_collisions_expected(pdev)) {
+ printk(KERN_ERR "PCI: Address space collision on region %ld "
+ "[%016lx:%016lx] of device %s\n",
+ (res - &pdev->resource[0]),
+ res->start, res->end,
+ pdev->name);
+ }
}
}
}
@@ -397,6 +444,23 @@
pci_record_assignments(pbm, pci_bus_b(walk));
}
+/* Return non-zero if PDEV has implicit I/O resources even
+ * though it may not have an I/O base address register
+ * active.
+ */
+static int __init has_implicit_io(struct pci_dev *pdev)
+{
+ int class = pdev->class >> 8;
+
+ if (class == PCI_CLASS_NOT_DEFINED ||
+ class == PCI_CLASS_NOT_DEFINED_VGA ||
+ class == PCI_CLASS_STORAGE_IDE ||
+ (pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+ return 1;
+
+ return 0;
+}
+
static void __init pdev_assign_unassigned(struct pci_pbm_info *pbm,
struct pci_dev *pdev)
{
@@ -460,7 +524,7 @@
*/
if (io_seen || mem_seen) {
pci_read_config_word(pdev, PCI_COMMAND, &cmd);
- if (io_seen)
+ if (io_seen || has_implicit_io(pdev))
cmd |= PCI_COMMAND_IO;
if (mem_seen)
cmd |= PCI_COMMAND_MEMORY;
@@ -649,17 +713,22 @@
line = ((pci_irq_line - 1) & 3);
}
- /* Now figure out the slot. */
+ /* Now figure out the slot.
+ *
+ * Basically, device number zero on the top-level bus is
+ * always the PCI host controller. Slot 0 is then device 1.
+ * PBM A supports two external slots (0 and 1), and PBM B
+ * supports 4 external slots (0, 1, 2, and 3). On-board PCI
+ * devices are wired to device numbers outside of these
+ * ranges. -DaveM
+ */
if (pdev->bus->number == pbm->pci_first_busno) {
- if (pbm == &pbm->parent->pbm_A)
- slot = (pdev->devfn >> 3) - 1;
- else
- slot = (pdev->devfn >> 3) - 2;
+ slot = (pdev->devfn >> 3) - 1;
} else {
- if (pbm == &pbm->parent->pbm_A)
- slot = (pdev->bus->self->devfn >> 3) - 1;
- else
- slot = (pdev->bus->self->devfn >> 3) - 2;
+ /* Underneath a bridge, use slot number of parent
+ * bridge.
+ */
+ slot = (pdev->bus->self->devfn >> 3) - 1;
}
slot = slot << 2;
@@ -819,6 +888,46 @@
walk = &pbus->children;
for (walk = walk->next; walk != &pbus->children; walk = walk->next)
pci_setup_busmastering(pbm, pci_bus_b(walk));
+}
+
+void pci_register_legacy_regions(struct resource *io_res,
+ struct resource *mem_res)
+{
+ struct resource *p;
+
+ /* VGA Video RAM. */
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return;
+
+ memset(p, 0, sizeof(*p));
+ p->name = "Video RAM area";
+ p->start = mem_res->start + 0xa0000UL;
+ p->end = p->start + 0x1ffffUL;
+ p->flags = IORESOURCE_BUSY;
+ request_resource(mem_res, p);
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return;
+
+ memset(p, 0, sizeof(*p));
+ p->name = "System ROM";
+ p->start = mem_res->start + 0xf0000UL;
+ p->end = p->start + 0xffffUL;
+ p->flags = IORESOURCE_BUSY;
+ request_resource(mem_res, p);
+
+ p = kmalloc(sizeof(*p), GFP_KERNEL);
+ if (!p)
+ return;
+
+ memset(p, 0, sizeof(*p));
+ p->name = "Video ROM";
+ p->start = mem_res->start + 0xc0000UL;
+ p->end = p->start + 0x7fffUL;
+ p->flags = IORESOURCE_BUSY;
+ request_resource(mem_res, p);
}
/* Generic helper routines for PCI error reporting. */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)