patch-2.4.0-test12 linux/arch/alpha/kernel/pci.c
Next file: linux/arch/alpha/kernel/pci_iommu.c
Previous file: linux/arch/alpha/kernel/core_cia.c
Back to the patch index
Back to the overall index
- Lines: 310
- Date:
Mon Dec 11 13:46:26 2000
- Orig file:
v2.4.0-test11/linux/arch/alpha/kernel/pci.c
- Orig date:
Mon Aug 7 14:31:40 2000
diff -u --recursive --new-file v2.4.0-test11/linux/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c
@@ -8,6 +8,11 @@
/* 2.3.x PCI/resources, 1999 Andrea Arcangeli <andrea@suse.de> */
+/*
+ * Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+ * PCI-PCI bridges cleanup
+ */
+
#include <linux/string.h>
#include <linux/pci.h>
#include <linux/init.h>
@@ -51,13 +56,13 @@
static void __init
quirk_eisa_bridge(struct pci_dev *dev)
{
- dev->class = PCI_CLASS_BRIDGE_EISA;
+ dev->class = PCI_CLASS_BRIDGE_EISA << 8;
}
static void __init
quirk_isa_bridge(struct pci_dev *dev)
{
- dev->class = PCI_CLASS_BRIDGE_ISA;
+ dev->class = PCI_CLASS_BRIDGE_ISA << 8;
}
static void __init
@@ -71,6 +76,24 @@
dev->resource[3].end = dev->resource[3].start + 7;
}
+/*
+ * Notorious Cy82C693 chip. One of its numerous bugs: although
+ * Cypress IDE controller doesn't support native mode, it has
+ * programmable addresses of IDE command/control registers.
+ * This violates PCI specifications, confuses IDE subsystem
+ * and causes resource conflict between primary HD_CMD register
+ * and floppy controller. Ugh.
+ * Fix that.
+ */
+static void __init
+quirk_cypress_ide_ports(struct pci_dev *dev)
+{
+ if (dev->class >> 8 != PCI_CLASS_STORAGE_IDE)
+ return;
+ dev->resource[0].flags = 0;
+ dev->resource[1].flags = 0;
+}
+
static void __init
quirk_vga_enable_rom(struct pci_dev *dev)
{
@@ -78,7 +101,6 @@
But if its a Cirrus 543x/544x DISABLE it, since
enabling ROM disables the memory... */
if ((dev->class >> 8) == PCI_CLASS_DISPLAY_VGA &&
- /* But if its a Cirrus 543x/544x DISABLE it */
(dev->vendor != PCI_VENDOR_ID_CIRRUS ||
(dev->device < 0x00a0) || (dev->device > 0x00ac)))
{
@@ -98,6 +120,8 @@
quirk_isa_bridge },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5229,
quirk_ali_ide_ports },
+ { PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
+ quirk_cypress_ide_ports },
{ PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID, quirk_vga_enable_rom },
{ 0 }
};
@@ -122,18 +146,12 @@
start = PCIBIOS_MIN_IO + hose->io_space->start;
/*
- * Aligning to 0x800 rather than the minimum base of
- * 0x400 is an attempt to avoid having devices in
- * any 0x?C?? range, which is where the de4x5 driver
- * probes for EISA cards.
- *
- * Adaptecs, especially, resent such intrusions.
- *
- * The de4x5 driver has the eisa probe conditionalized
- * out for Alpha, so lower the minimum base back to 0x400.
+ * Put everything into 0x00-0xff region modulo 0x400
*/
- alignto = MAX(0x400, size);
- start = ALIGN(start, alignto);
+ if (start & 0x300) {
+ start = (start + 0x3ff) & ~0x3ff;
+ res->start = start;
+ }
}
else if (res->flags & IORESOURCE_MEM) {
/* Make sure we start at our min on all hoses */
@@ -181,44 +199,6 @@
#undef MB
#undef GB
-/*
- * Pre-layout host-independant device initialization.
- */
-
-static void __init
-pcibios_assign_special(struct pci_dev * dev)
-{
- int i;
-
- /* The first three resources of an IDE controler are often magic,
- so leave them unchanged. This is true, for instance, of the
- Contaq 82C693 as seen on SX164 and DP264. */
-
- if (dev->class >> 8 == PCI_CLASS_STORAGE_IDE) {
- /* Resource 1 of IDE controller is the address of HD_CMD
- register which actually occupies a single byte (0x3f6
- for ide0) in reported 0x3f4-3f7 range. We have to fix
- that to avoid resource conflict with AT-style floppy
- controller. */
- dev->resource[1].start += 2;
- dev->resource[1].end = dev->resource[1].start;
- for (i = 0; i < PCI_NUM_RESOURCES; i++)
- if (dev->resource[i].flags && dev->resource[i].start)
- pci_claim_resource(dev, i);
- }
- /*
- * We don't have code that will init the CYPRESS bridge correctly
- * so we do the next best thing, and depend on the previous
- * console code to do the right thing, and ignore it here... :-\
- */
- else if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
- dev->device == PCI_DEVICE_ID_CONTAQ_82C693)
- for (i = 0; i < PCI_NUM_RESOURCES; i++)
- if (dev->resource[i].flags && dev->resource[i].start)
- pci_claim_resource(dev, i);
-}
-
-
void __init
pcibios_init(void)
{
@@ -257,7 +237,6 @@
pcibios_fixup_resource(&dev->resource[i],
hose->mem_space);
}
- pcibios_assign_special(dev);
}
void __init
@@ -265,17 +244,33 @@
{
/* Propogate hose info into the subordinate devices. */
- struct pci_controler *hose = (struct pci_controler *) bus->sysdata;
+ struct pci_controler *hose = bus->sysdata;
struct list_head *ln;
+ struct pci_dev *dev = bus->self;
- /* ???? */
- bus->resource[0] = hose->io_space;
- bus->resource[1] = hose->mem_space;
-
- /* If this is a bridge, get the current bases */
- if (bus->self) {
- pci_read_bridge_bases(bus);
- pcibios_fixup_device_resources(bus->self, bus->parent);
+ if (!dev) {
+ /* Root bus */
+ bus->resource[0] = hose->io_space;
+ bus->resource[1] = hose->mem_space;
+ } else {
+ /* This is a bridge. Do not care how it's initialized,
+ just link its resources to the bus ones */
+ int i;
+
+ for(i=0; i<3; i++) {
+ bus->resource[i] =
+ &dev->resource[PCI_BRIDGE_RESOURCES+i];
+ bus->resource[i]->name = bus->name;
+ }
+ bus->resource[0]->flags |= pci_bridge_check_io(dev);
+ bus->resource[1]->flags |= IORESOURCE_MEM;
+ /* For now, propogate hose limits to the bus;
+ we'll adjust them later. */
+ bus->resource[0]->end = hose->io_space->end;
+ bus->resource[1]->end = hose->mem_space->end;
+ /* Turn off downstream PF memory address range by default */
+ bus->resource[2]->start = 1024*1024;
+ bus->resource[2]->end = bus->resource[2]->start - 1;
}
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
@@ -285,7 +280,7 @@
}
}
-void __init
+void
pcibios_update_resource(struct pci_dev *dev, struct resource *root,
struct resource *res, int resource)
{
@@ -385,99 +380,6 @@
pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
}
-#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
-
-static void __init
-pcibios_size_bridge(struct pci_bus *bus, struct pbus_set_ranges_data *outer)
-{
- struct pbus_set_ranges_data inner;
- struct pci_dev *dev;
- struct pci_dev *bridge = bus->self;
- struct pci_controler *hose = bus->sysdata;
- struct list_head *ln;
-
- if (!bridge)
- return; /* host bridge, nothing to do */
-
- /* set reasonable default locations for pcibios_align_resource */
- inner.io_start = hose->io_space->start + PCIBIOS_MIN_IO;
- inner.mem_start = hose->mem_space->start + PCIBIOS_MIN_MEM;
- inner.io_end = inner.io_start;
- inner.mem_end = inner.mem_start;
-
- /* Collect information about how our direct children are layed out. */
- for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
- int i;
- dev = pci_dev_b(ln);
-
- /* Skip bridges for now */
- if (dev->class >> 8 == PCI_CLASS_BRIDGE_PCI)
- continue;
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource res;
- unsigned long size;
-
- memcpy(&res, &dev->resource[i], sizeof(res));
- size = res.end - res.start + 1;
-
- if (res.flags & IORESOURCE_IO) {
- res.start = inner.io_end;
- pcibios_align_resource(dev, &res, size);
- inner.io_end = res.start + size;
- } else if (res.flags & IORESOURCE_MEM) {
- res.start = inner.mem_end;
- pcibios_align_resource(dev, &res, size);
- inner.mem_end = res.start + size;
- }
- }
- }
-
- /* And for all of the subordinate busses. */
- for (ln=bus->children.next; ln != &bus->children; ln=ln->next)
- pcibios_size_bridge(pci_bus_b(ln), &inner);
-
- /* turn the ending locations into sizes (subtract start) */
- inner.io_end -= inner.io_start;
- inner.mem_end -= inner.mem_start;
-
- /* Align the sizes up by bridge rules */
- inner.io_end = ROUND_UP(inner.io_end, 4*1024) - 1;
- inner.mem_end = ROUND_UP(inner.mem_end, 1*1024*1024) - 1;
-
- /* Adjust the bridge's allocation requirements */
- bridge->resource[0].end = bridge->resource[0].start + inner.io_end;
- bridge->resource[1].end = bridge->resource[1].start + inner.mem_end;
-
- bridge->resource[PCI_BRIDGE_RESOURCES].end =
- bridge->resource[PCI_BRIDGE_RESOURCES].start + inner.io_end;
- bridge->resource[PCI_BRIDGE_RESOURCES+1].end =
- bridge->resource[PCI_BRIDGE_RESOURCES+1].start + inner.mem_end;
-
- /* adjust parent's resource requirements */
- if (outer) {
- outer->io_end = ROUND_UP(outer->io_end, 4*1024);
- outer->io_end += inner.io_end;
-
- outer->mem_end = ROUND_UP(outer->mem_end, 1*1024*1024);
- outer->mem_end += inner.mem_end;
- }
-}
-
-#undef ROUND_UP
-
-static void __init
-pcibios_size_bridges(void)
-{
- struct list_head *ln1, *ln2;
-
- for(ln1=pci_root_buses.next; ln1 != &pci_root_buses; ln1=ln1->next)
- for(ln2 = pci_bus_b(ln1)->children.next;
- ln2 != &pci_bus_b(ln1)->children;
- ln2 = ln2->next)
- pcibios_size_bridge(pci_bus_b(ln2), NULL);
-}
-
void __init
common_init_pci(void)
{
@@ -495,10 +397,8 @@
next_busno += 1;
}
- pcibios_size_bridges();
pci_assign_unassigned_resources();
pci_fixup_irqs(alpha_mv.pci_swizzle, alpha_mv.pci_map_irq);
- pci_set_bus_ranges();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)