[patch] 2.5: PCI setup reorg (alpha, arm, parisc)

Ivan Kokshaysky (ink@jurassic.park.msu.ru)
Sat, 22 Dec 2001 19:05:48 +0300


[Ouch. Forgot to cc this to l-k, hence another post...]

Only generic and alpha changes here - parisc folks should be almost in
sync, and required ARM changes look more or less straightforward.

Generic changes:
- Code disabling pci devices before reallocation is now arch specific
and supposed to be in pcibios_fixup_bus(). Same with re-enabling
devices after allocation - much hated pdev_enable_device() removed thus.
This gives architectures more freedom to handle specific console
devices and other odd stuff.
- Handling of PCI-PCI bridge resources gets completely generic, so
the only thing architectures must care of is proper initialization
of the root bus resources.
- Fast-Back-to-Back/PERR/SERR support.
Added new field in the struct pci_bus - bridge_ctl. It has the same
format as PCI-PCI bridge control register (and allows to get rid
of IORESOURCE_BUS_HAS_VGA hack).
New function - pcibios_init_bus(). Common for all platforms, but
safely could be defined as noop, as it's done for i386.
Primary purpose - set appropriate bits in the bus->bridge_ctl
depending on bus capabilities. The FBB bit will be cleared by
pci_setup_device() if any of devices on the bus doesn't support FBB;
PERR/SERR could be cleared in arch specific code as well if certain
broken devices are present.
Some specific bridge setup (setting secondary latency etc.)
also can be done in pcibios_init_bus().
- Two recent patches from Russell King included.

Prefetchable memory support not included for now.

Alpha specific:
- Do not enable _all_ devices on startup - pcibios_enable_device()
isn't noop anymore.
- Allow configs with multiple graphic cards, as Jay and Richard
suggested; make sure that at least one display is enabled.
- Framework for setting up PCI control on various core logic chipsets -
alpha_mv.pci_control(). I have code for cia/pyxis (reasonably tested)
and tsunami (completely untested), but it's not included for now...

Ivan.

diff -urpN 2.5.1/arch/alpha/kernel/pci.c linux/arch/alpha/kernel/pci.c
--- 2.5.1/arch/alpha/kernel/pci.c Fri Dec 21 21:29:03 2001
+++ linux/arch/alpha/kernel/pci.c Fri Dec 21 21:52:27 2001
@@ -24,6 +24,12 @@
#include "proto.h"
#include "pci_impl.h"

+#define DEBUG_CONFIG 1
+#if DEBUG_CONFIG
+# define DBGC(args) printk args
+#else
+# define DBGC(args)
+#endif

/*
* Some string constants used by the various core logics.
@@ -109,6 +115,33 @@ quirk_cypress(struct pci_dev *dev)
}
}

+static int __initdata vga_enabled;
+
+/* Called for each device after PCI setup is done. */
+static void __init
+pcibios_fixup_final(struct pci_dev *dev)
+{
+ /* If no display devices are enabled, enable
+ the first one we've found. */
+ if (((dev->class >> 8) == PCI_CLASS_NOT_DEFINED_VGA ||
+ (dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) && !vga_enabled) {
+ pci_enable_device(dev);
+ vga_enabled = 1;
+ }
+ /* These (may) have I/O scattered all around and may not
+ use I/O base address registers at all. So we just have to
+ always enable IO to these devices. */
+ else if ((dev->class >> 8) == PCI_CLASS_NOT_DEFINED ||
+ (dev->class >> 8) == PCI_CLASS_STORAGE_IDE) {
+ u16 cmd;
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_IO;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ pci_enable_device(dev);
+ pci_set_master(dev);
+ }
+}
+
struct pci_fixup pcibios_fixups[] __initdata = {
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82375,
quirk_eisa_bridge },
@@ -118,6 +151,8 @@ struct pci_fixup pcibios_fixups[] __init
quirk_ali_ide_ports },
{ PCI_FIXUP_HEADER, PCI_VENDOR_ID_CONTAQ, PCI_DEVICE_ID_CONTAQ_82C693,
quirk_cypress },
+ { PCI_FIXUP_FINAL, PCI_ANY_ID, PCI_ANY_ID,
+ pcibios_fixup_final },
{ 0 }
};

@@ -235,40 +270,69 @@ pcibios_fixup_device_resources(struct pc
void __init
pcibios_fixup_bus(struct pci_bus *bus)
{
- /* Propogate hose info into the subordinate devices. */
+ /* Propagate hose info into the subordinate devices.
+ Setup FBB/PERR/SERR depending on the bus capabilities. */

- struct pci_controller *hose = bus->sysdata;
struct list_head *ln;
- struct pci_dev *dev = bus->self;
+ u16 cmdbits = 0;
+
+ if (!bus->self) {
+ /* Initialize the root bus resources. */
+ struct pci_controller *hose = bus->sysdata;

- 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;
+
+ /* Setup our pci controller. */
+ if (alpha_mv.pci_control)
+ bus->bridge_ctl = alpha_mv.pci_control(bus);
+ else
+ bus->bridge_ctl &= ~PCI_COMMAND_FAST_BACK;
}

+ if (bus->bridge_ctl & PCI_BRIDGE_CTL_PARITY)
+ cmdbits |= PCI_COMMAND_PARITY;
+ if (bus->bridge_ctl & PCI_BRIDGE_CTL_SERR)
+ cmdbits |= PCI_COMMAND_SERR;
+ if (bus->bridge_ctl & PCI_BRIDGE_CTL_FAST_BACK)
+ cmdbits |= PCI_COMMAND_FAST_BACK;
+
for (ln = bus->devices.next; ln != &bus->devices; ln = ln->next) {
struct pci_dev *dev = pci_dev_b(ln);
- if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ u16 class = dev->class >> 8;
+ u16 cmd;
+ u32 reg;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+
+ /* First, disable the device to avoid side
+ effects of possibly overlapping I/O and
+ memory ranges.
+ Don't touch VGAs and all sorts of bridges. */
+ if (class == PCI_CLASS_NOT_DEFINED_VGA ||
+ class >> 8 == PCI_BASE_CLASS_DISPLAY) {
+ /* Check that at least one display device
+ is enabled. */
+ if (cmd & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY))
+ vga_enabled = 1;
+ } else if (class >> 8 != PCI_BASE_CLASS_BRIDGE)
+ cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY
+ | PCI_COMMAND_MASTER);
+
+ cmd |= cmdbits;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+ /* Disable the ROM. Several devices act funny (ie. do not
+ respond to memory space writes) when it is left enabled.
+ A good example are QlogicISP adapters. */
+ if (dev->rom_base_reg) {
+ pci_read_config_dword(dev, dev->rom_base_reg, &reg);
+ reg &= ~PCI_ROM_ADDRESS_ENABLE;
+ pci_write_config_dword(dev, dev->rom_base_reg, reg);
+ dev->resource[PCI_ROM_RESOURCE].flags &=
+ ~PCI_ROM_ADDRESS_ENABLE;
+ }
+ if (class != PCI_CLASS_BRIDGE_PCI)
pcibios_fixup_device_resources(dev, bus);
}
}
@@ -353,24 +417,79 @@ pcibios_fixup_pbus_ranges(struct pci_bus
int
pcibios_enable_device(struct pci_dev *dev)
{
- /* Nothing to do, since we enable all devices at startup. */
+ u16 cmd, oldcmd;
+ int i;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ oldcmd = cmd;
+
+ for (i = 0; i < PCI_NUM_RESOURCES; i++) {
+ struct resource *res = &dev->resource[i];
+
+ if (res->flags & IORESOURCE_IO)
+ cmd |= PCI_COMMAND_IO;
+ else if (res->flags & IORESOURCE_MEM)
+ cmd |= PCI_COMMAND_MEMORY;
+ }
+
+ if (cmd != oldcmd) {
+ DBGC((KERN_INFO "PCI: Enabling device: (%s), cmd %x\n",
+ dev->name, cmd));
+ /* Enable the appropriate bits in the PCI command register. */
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
return 0;
}

-/*
- * If we set up a device for bus mastering, we need to check the latency
- * timer as certain firmware forgets to set it properly, as seen
- * on SX164 and LX164 with SRM.
- */
void
pcibios_set_master(struct pci_dev *dev)
{
- u8 lat;
- pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
- if (lat >= 16) return;
- printk("PCI: Setting latency timer of device %s to 64\n",
- dev->slot_name);
- pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
+ /* Set the cacheline size and default latency (32). */
+ pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
+ (32 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
+
+#if 0 /* ??? Turning on MWI might be dangerous... */
+ {
+ u8 cacheline;
+
+ pci_read_config_byte(dev, PCI_CACHE_LINE_SIZE, &cacheline);
+ /* If this cacheline size is supported,
+ turn on write/invalidate. */
+ if (cacheline) {
+ u16 cmd;
+
+ pci_read_config_word(dev, PCI_COMMAND, &cmd);
+ cmd |= PCI_COMMAND_INVALIDATE;
+ pci_write_config_word(dev, PCI_COMMAND, cmd);
+ }
+ }
+#endif
+}
+
+void __init
+pcibios_init_bus(struct pci_bus *bus)
+{
+ struct pci_dev *dev = bus->self;
+ u16 status;
+ /* Set FBB bit for now. Disable ISA IO forwarding. Enable PERR/SERR. */
+ u16 ctl = PCI_BRIDGE_CTL_FAST_BACK | PCI_BRIDGE_CTL_NO_ISA |
+ PCI_BRIDGE_CTL_PARITY | PCI_BRIDGE_CTL_SERR;
+
+ /* We deal only with pci controllers and pci-pci bridges. */
+ if (dev) {
+ if ((dev->class >> 8) != PCI_CLASS_BRIDGE_PCI)
+ return;
+ /* PCI-PCI bridge - set default latency (32)
+ for secondary bus. */
+ pci_write_config_byte(dev, PCI_SEC_LATENCY_TIMER, 32);
+ /* Read bridge control. */
+ pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &bus->bridge_ctl);
+ /* Does the bridge support FBB on its secondary bus? */
+ pci_read_config_word(dev, PCI_SEC_STATUS, &status);
+ if (!(status & PCI_BRIDGE_CTL_FAST_BACK))
+ ctl &= ~PCI_BRIDGE_CTL_FAST_BACK;
+ }
+ bus->bridge_ctl |= ctl;
}

void __init
diff -urpN 2.5.1/drivers/pci/pci.c linux/drivers/pci/pci.c
--- 2.5.1/drivers/pci/pci.c Fri Dec 21 21:29:03 2001
+++ linux/drivers/pci/pci.c Fri Dec 21 21:29:43 2001
@@ -914,13 +914,15 @@ static void pci_read_bases(struct pci_de
l = 0;
if ((l & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_MEMORY) {
res->start = l & PCI_BASE_ADDRESS_MEM_MASK;
+ res->flags |= l & ~PCI_BASE_ADDRESS_MEM_MASK;
sz = pci_size(sz, PCI_BASE_ADDRESS_MEM_MASK);
} else {
res->start = l & PCI_BASE_ADDRESS_IO_MASK;
+ res->flags |= l & ~PCI_BASE_ADDRESS_IO_MASK;
sz = pci_size(sz, PCI_BASE_ADDRESS_IO_MASK & 0xffff);
}
res->end = res->start + (unsigned long) sz;
- res->flags |= (l & 0xf) | pci_calc_resource_flags(l);
+ res->flags |= pci_calc_resource_flags(l);
if ((l & (PCI_BASE_ADDRESS_SPACE | PCI_BASE_ADDRESS_MEM_TYPE_MASK))
== (PCI_BASE_ADDRESS_SPACE_MEMORY | PCI_BASE_ADDRESS_MEM_TYPE_64)) {
pci_read_config_dword(dev, reg+4, &l);
@@ -1210,6 +1212,7 @@ static void pci_read_irq(struct pci_dev
int pci_setup_device(struct pci_dev * dev)
{
u32 class;
+ unsigned short status;

sprintf(dev->slot_name, "%02x:%02x.%d", dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
sprintf(dev->name, "PCI device %04x:%04x", dev->vendor, dev->device);
@@ -1260,6 +1263,11 @@ int pci_setup_device(struct pci_dev * de
dev->class = PCI_CLASS_NOT_DEFINED;
}

+ /* FBB capability - if not, clear bit in parent bridge_ctl. */
+ pci_read_config_word(dev, PCI_STATUS, &status);
+ if (!(status & PCI_STATUS_FAST_BACK))
+ dev->bus->bridge_ctl &= ~PCI_BRIDGE_CTL_FAST_BACK;
+
/* We found a fine healthy device, go go go... */
return 0;
}
@@ -1341,6 +1349,8 @@ unsigned int __devinit pci_do_scan_bus(s
unsigned int devfn, max, pass;
struct list_head *ln;
struct pci_dev *dev, dev0;
+
+ pcibios_init_bus(bus);

DBG("Scanning bus %02x\n", bus->number);
max = bus->secondary;
diff -urpN 2.5.1/drivers/pci/setup-bus.c linux/drivers/pci/setup-bus.c
--- 2.5.1/drivers/pci/setup-bus.c Fri Dec 21 21:29:03 2001
+++ linux/drivers/pci/setup-bus.c Fri Dec 21 21:33:58 2001
@@ -12,6 +12,16 @@
/*
* Nov 2000, Ivan Kokshaysky <ink@jurassic.park.msu.ru>
* PCI-PCI bridges cleanup, sorted resource allocation
+ * Jul 2001, Grant Grundler <grundler@parisc-linux.org>,
+ * Ivan Kokshaysky <ink@jurassic.park.msu.ru>
+ * Further cleanup, generic Fast-Back-to-Back/PERR/SERR support
+ */
+
+/* NOTE: during reallocation we may have temporarily overlapping
+ * IO or MEM ranges, so the arch code (pcibios_fixup_bus()) is
+ * responsible for disabling all devices, probably except console
+ * (VGA, serial etc.) and bridges the console device might be
+ * behind -- typically AGP or PCI-(E)ISA bridges.
*/

#include <linux/init.h>
@@ -46,23 +56,9 @@ pbus_assign_resources_sorted(struct pci_
for (ln=bus->devices.next; ln != &bus->devices; ln=ln->next) {
struct pci_dev *dev = pci_dev_b(ln);
u16 class = dev->class >> 8;
- u16 cmd;

- /* First, disable the device to avoid side
- effects of possibly overlapping I/O and
- memory ranges.
- Leave VGA enabled - for obvious reason. :-)
- Same with all sorts of bridges - they may
- have VGA behind them. */
- if (class == PCI_CLASS_DISPLAY_VGA
- || class == PCI_CLASS_NOT_DEFINED_VGA)
- found_vga = 1;
- else if (class >> 8 != PCI_BASE_CLASS_BRIDGE) {
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
- cmd &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY
- | PCI_COMMAND_MASTER);
- pci_write_config_word(dev, PCI_COMMAND, cmd);
- }
+ found_vga |= (class == PCI_CLASS_DISPLAY_VGA ||
+ class == PCI_CLASS_NOT_DEFINED_VGA);

/* Reserve some resources for CardBus.
Are these values reasonable? */
@@ -100,20 +96,6 @@ pbus_assign_resources_sorted(struct pci_
ranges->io_end += io_reserved;
ranges->mem_end += mem_reserved;

- /* PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
- 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. */
-#if 1
- /* But assuming that some hardware designed before 1998 might
- not support this (very unlikely - at least all DEC bridges
- are ok and I believe that was standard de-facto. -ink), we
- must allow for at least one unit. */
- if (ranges->io_end == ranges->io_start)
- ranges->io_end += 1;
- if (ranges->mem_end == ranges->mem_start)
- ranges->mem_end += 1;
-#endif
ranges->io_end = ROUND_UP(ranges->io_end, 4*1024);
ranges->mem_end = ROUND_UP(ranges->mem_end, 1024*1024);

@@ -130,6 +112,7 @@ pci_setup_bridge(struct pci_bus *bus)

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;
@@ -147,8 +130,11 @@ pci_setup_bridge(struct pci_bus *bus)
l |= ranges.io_end & 0xf000;
pci_write_config_dword(bridge, PCI_IO_BASE, l);

- /* Clear upper 16 bits of I/O base/limit. */
- pci_write_config_dword(bridge, PCI_IO_BASE_UPPER16, 0);
+ /* Set up upper 16 bits of I/O base/limit. */
+ pci_write_config_word(bridge, PCI_IO_BASE_UPPER16,
+ ranges.io_start >> 16);
+ pci_write_config_word(bridge, PCI_IO_LIMIT_UPPER16,
+ ranges.io_end >> 16);

/* Clear out the upper 32 bits of PREF base/limit. */
pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
@@ -160,15 +146,34 @@ pci_setup_bridge(struct pci_bus *bus)
l |= ranges.mem_end & 0xfff00000;
pci_write_config_dword(bridge, PCI_MEMORY_BASE, l);

- /* Set up PREF base/limit. */
- l = (bus->resource[2]->start >> 16) & 0xfff0;
- l |= bus->resource[2]->end & 0xfff00000;
- pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, l);
-
- /* Check if we have VGA behind the bridge.
- Enable ISA in either case. */
- l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
- pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
+ /* Disable PREF memory range. */
+ pci_write_config_dword(bridge, PCI_PREF_MEMORY_BASE, 0x0000fff0);
+
+ pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
+
+ pci_enable_device(bridge);
+ pci_set_master(bridge);
+}
+
+/* Check whether the bridge supports I/O forwarding.
+ If not, its I/O base/limit register must be
+ read-only and read as 0. */
+static unsigned long __init
+pci_bridge_check_io(struct pci_dev *bridge)
+{
+ u16 io;
+
+ pci_read_config_word(bridge, PCI_IO_BASE, &io);
+ if (!io) {
+ pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0);
+ pci_read_config_word(bridge, PCI_IO_BASE, &io);
+ pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
+ }
+ if (io)
+ return IORESOURCE_IO;
+ printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n",
+ bridge->name);
+ return 0;
}

static void __init
@@ -181,26 +186,52 @@ pbus_assign_resources(struct pci_bus *bu
struct pci_bus *b;

ranges->found_vga = 1;
- /* Propogate presence of the VGA to upstream bridges */
- for (b = bus; b->parent; b = b->parent) {
-#if 0
- /* ? Do we actually need to enable PF memory? */
- b->resource[2]->start = 0;
-#endif
- b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA;
- }
+ /* Propagate presence of the VGA to upstream bridges */
+ for (b = bus; b->parent; b = b->parent)
+ b->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
}
for (ln=bus->children.next; ln != &bus->children; ln=ln->next) {
struct pci_bus *b = pci_bus_b(ln);
+ struct pci_dev *bridge = b->self;
+ int i;

+ /* Link bus resources to the bridge ones. */
+ for (i = 0; i < 3; i++) {
+ b->resource[i] =
+ &bridge->resource[PCI_BRIDGE_RESOURCES + i];
+ b->resource[i]->name = bus->name;
+ }
+ b->resource[0]->flags |= pci_bridge_check_io(bridge);
+ b->resource[1]->flags |= IORESOURCE_MEM;
b->resource[0]->start = ranges->io_start = ranges->io_end;
b->resource[1]->start = ranges->mem_start = ranges->mem_end;

+ /* For now, set IO and MEM limits of this bus
+ same as limits of its parent bus. */
+ b->resource[0]->end = bus->resource[0]->end;
+ b->resource[1]->end = bus->resource[1]->end;
+
pbus_assign_resources(b, ranges);

+ /* PCI-to-PCI Bridge Architecture Specification rev. 1.1 (1998)
+ 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.
+ This is done automatically for empty (start==end) ranges. */
b->resource[0]->end = ranges->io_end - 1;
b->resource[1]->end = ranges->mem_end - 1;

+ /* Add bridge resources to the resource tree. */
+ if (b->resource[0]->end > b->resource[0]->start &&
+ request_resource(bus->resource[0], b->resource[0]) < 0)
+ printk(KERN_ERR "PCI: failed to request IO "
+ "for bus %d\n", b->number);
+ if (b->resource[1]->end > b->resource[1]->start &&
+ request_resource(bus->resource[1], b->resource[1]) < 0)
+ printk(KERN_ERR "PCI: failed to request MEM "
+ "for bus %d\n", b->number);
+
pci_setup_bridge(b);
}
}
@@ -210,7 +241,6 @@ pci_assign_unassigned_resources(void)
{
struct pbus_set_ranges_data ranges;
struct list_head *ln;
- struct pci_dev *dev;

for(ln=pci_root_buses.next; ln != &pci_root_buses; ln=ln->next) {
struct pci_bus *b = pci_bus_b(ln);
@@ -222,28 +252,4 @@ pci_assign_unassigned_resources(void)
ranges.found_vga = 0;
pbus_assign_resources(b, &ranges);
}
- pci_for_each_dev(dev) {
- pdev_enable_device(dev);
- }
-}
-
-/* Check whether the bridge supports I/O forwarding.
- If not, its I/O base/limit register must be
- read-only and read as 0. */
-unsigned long __init
-pci_bridge_check_io(struct pci_dev *bridge)
-{
- u16 io;
-
- pci_read_config_word(bridge, PCI_IO_BASE, &io);
- if (!io) {
- pci_write_config_word(bridge, PCI_IO_BASE, 0xf0f0);
- pci_read_config_word(bridge, PCI_IO_BASE, &io);
- pci_write_config_word(bridge, PCI_IO_BASE, 0x0);
- }
- if (io)
- return IORESOURCE_IO;
- printk(KERN_WARNING "PCI: bridge %s does not support I/O forwarding!\n",
- bridge->name);
- return 0;
}
diff -urpN 2.5.1/drivers/pci/setup-res.c linux/drivers/pci/setup-res.c
--- 2.5.1/drivers/pci/setup-res.c Fri Dec 21 21:29:03 2001
+++ linux/drivers/pci/setup-res.c Fri Dec 21 21:29:43 2001
@@ -177,57 +177,3 @@ pdev_sort_resources(struct pci_dev *dev,
}
}
}
-
-void __init
-pdev_enable_device(struct pci_dev *dev)
-{
- u32 reg;
- u16 cmd;
- int i;
-
- DBGC((KERN_ERR "PCI enable device: (%s)\n", dev->name));
-
- pci_read_config_word(dev, PCI_COMMAND, &cmd);
-
- for (i = 0; i < PCI_NUM_RESOURCES; i++) {
- struct resource *res = &dev->resource[i];
-
- if (res->flags & IORESOURCE_IO)
- cmd |= PCI_COMMAND_IO;
- else if (res->flags & IORESOURCE_MEM)
- cmd |= PCI_COMMAND_MEMORY;
- }
-
- /* Special case, disable the ROM. Several devices act funny
- (ie. do not respond to memory space writes) when it is left
- enabled. A good example are QlogicISP adapters. */
-
- if (dev->rom_base_reg) {
- pci_read_config_dword(dev, dev->rom_base_reg, &reg);
- reg &= ~PCI_ROM_ADDRESS_ENABLE;
- pci_write_config_dword(dev, dev->rom_base_reg, reg);
- dev->resource[PCI_ROM_RESOURCE].flags &= ~PCI_ROM_ADDRESS_ENABLE;
- }
-
- /* All of these (may) have I/O scattered all around and may not
- use I/O base address registers at all. So we just have to
- always enable IO to these devices. */
- if ((dev->class >> 8) == PCI_CLASS_NOT_DEFINED
- || (dev->class >> 8) == PCI_CLASS_NOT_DEFINED_VGA
- || (dev->class >> 8) == PCI_CLASS_STORAGE_IDE
- || (dev->class >> 16) == PCI_BASE_CLASS_DISPLAY) {
- cmd |= PCI_COMMAND_IO;
- }
-
- /* Do not enable bus mastering. A device could corrupt
- * system memory by DMAing before a driver is ready for it. */
-
- /* Set the cache line and default latency (32). */
- pci_write_config_word(dev, PCI_CACHE_LINE_SIZE,
- (32 << 8) | (L1_CACHE_BYTES / sizeof(u32)));
-
- /* Enable the appropriate bits in the PCI command register. */
- pci_write_config_word(dev, PCI_COMMAND, cmd);
-
- DBGC((KERN_ERR " cmd reg 0x%x\n", cmd));
-}
diff -urpN 2.5.1/include/asm-alpha/machvec.h linux/include/asm-alpha/machvec.h
--- 2.5.1/include/asm-alpha/machvec.h Fri Dec 21 21:29:03 2001
+++ linux/include/asm-alpha/machvec.h Fri Dec 21 21:29:43 2001
@@ -18,7 +18,7 @@ struct task_struct;
struct mm_struct;
struct pt_regs;
struct vm_area_struct;
-struct linux_hose_info;
+struct pci_bus;
struct pci_dev;
struct pci_ops;
struct pci_controller;
@@ -79,6 +79,7 @@ struct alpha_machine_vector
void (*ack_irq)(unsigned long);
void (*device_interrupt)(unsigned long vector, struct pt_regs *regs);
void (*machine_check)(u64 vector, u64 la, struct pt_regs *regs);
+ u16 (*pci_control)(struct pci_bus *);

void (*init_arch)(void);
void (*init_irq)(void);
diff -urpN 2.5.1/include/asm-i386/pci.h linux/include/asm-i386/pci.h
--- 2.5.1/include/asm-i386/pci.h Fri Dec 21 21:29:03 2001
+++ linux/include/asm-i386/pci.h Fri Dec 21 21:29:43 2001
@@ -263,6 +263,11 @@ static inline int pci_controller_num(str
return 0;
}

+/* Set up bus control bits (FBB/PERR/SERR etc.) supported by PCI controller. */
+static inline void pcibios_init_bus(struct pci_bus *bus)
+{
+}
+
#define HAVE_PCI_MMAP
extern int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
enum pci_mmap_state mmap_state, int write_combine);
diff -urpN 2.5.1/include/linux/ioport.h linux/include/linux/ioport.h
--- 2.5.1/include/linux/ioport.h Fri Dec 21 21:29:03 2001
+++ linux/include/linux/ioport.h Fri Dec 21 21:29:43 2001
@@ -40,7 +40,6 @@ struct resource_list {
#define IORESOURCE_CACHEABLE 0x00004000
#define IORESOURCE_RANGELENGTH 0x00008000
#define IORESOURCE_SHADOWABLE 0x00010000
-#define IORESOURCE_BUS_HAS_VGA 0x00080000

#define IORESOURCE_UNSET 0x20000000
#define IORESOURCE_AUTO 0x40000000
diff -urpN 2.5.1/include/linux/pci.h linux/include/linux/pci.h
--- 2.5.1/include/linux/pci.h Fri Dec 21 21:29:03 2001
+++ linux/include/linux/pci.h Fri Dec 21 21:29:43 2001
@@ -429,6 +429,8 @@ struct pci_bus {
unsigned char productver; /* product version */
unsigned char checksum; /* if zero - checksum passed */
unsigned char pad1;
+ unsigned short bridge_ctl; /* manage NO_ISA/FBB/et al behaviors */
+ unsigned short pad2;
};

#define pci_bus_b(n) list_entry(n, struct pci_bus, node)
@@ -491,8 +493,10 @@ struct pci_driver {
#define pci_for_each_dev(dev) \
for(dev = pci_dev_g(pci_devices.next); dev != pci_dev_g(&pci_devices); dev = pci_dev_g(dev->global_list.next))

-void pcibios_init(void);
-void pcibios_fixup_bus(struct pci_bus *);
+/* pcibios_*() == arch specific implementation */
+void pcibios_init(void); /* global init */
+void pcibios_init_bus(struct pci_bus *); /* before each bus scan */
+void pcibios_fixup_bus(struct pci_bus *); /* after each bus scan */
int pcibios_enable_device(struct pci_dev *);
char *pcibios_setup (char *str);

@@ -575,9 +579,7 @@ int pci_enable_wake(struct pci_dev *dev,

int pci_claim_resource(struct pci_dev *, int);
void pci_assign_unassigned_resources(void);
-void pdev_enable_device(struct pci_dev *);
void pdev_sort_resources(struct pci_dev *, struct resource_list *, u32);
-unsigned long pci_bridge_check_io(struct pci_dev *);
void pci_fixup_irqs(u8 (*)(struct pci_dev *, u8 *),
int (*)(struct pci_dev *, u8, u8));
#define HAVE_PCI_REQ_REGIONS
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/