[PATCH] bogo-resource-management for 2.2.15 bios32.c (Miata+SRM+IDE fix)

From: David Huggins-Daines (dhd@linuxcare.com)
Date: Wed May 10 2000 - 16:23:08 EST


Hi,

Certain Miatas (most notably the 600au) have a problem where the SRM
console will configure the Cypress PCI-IDE interface's I/O space at
0x90a0.

Because the 2.2 kernel ignores the Cypress chip completely when doing
PCI bus layout, it has a bad habit of putting the Qlogic-ISP's I/O
space controller at 0x9000. If one enables the PCI IDE driver, it
claims this space to the exclusion of the SCSI host adaptor, with
predictable results...

This patch tries to avoid placing devices on top of the Cypress chip's
I/O space.

This patch is admittedly bogus, but so is bios32.c (or, arguably, so
is the SRM console on Miata, or the Cypress chip, or any number of
other things :-) 2.3 does things right, thankfully.

I'd appreciate if people could test it on other machines with the
Cypress (i.e. the 164SX/LX, DP264, and DS20) and with other PCI
devices to see if it breaks anything that wasn't already broken.

Cheers

(I hope Gnus will not try to encode this as quoted-unreadable :P)

diff -urN linux/arch/alpha/kernel/bios32.c linux-cypress-hack/arch/alpha/kernel/bios32.c
--- linux/arch/alpha/kernel/bios32.c Thu May 4 00:23:58 2000
+++ linux-cypress-hack/arch/alpha/kernel/bios32.c Thu May 4 12:41:48 2000
@@ -439,17 +439,6 @@
                 return;
         }
 
- /*
- * 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... :-\
- */
- if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
- dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
- DBG_DEVS(("disable_dev: ignoring CYPRESS bridge...\n"));
- return;
- }
-
 #if DEBUG_DEVS && 0
         /* Worse HACK: Don't disable the video card, so I can see where
            it is *really* falling over. */
@@ -489,6 +478,8 @@
         unsigned int orig_base;
         unsigned int alignto;
         unsigned long handle;
+ int cypress_hack = 0;
+ static unsigned int cypress_base = 0, cypress_size = 0;
 
         /*
          * HACK: the PCI-to-EISA bridge does not seem to identify
@@ -509,14 +500,27 @@
         }
 
         /*
- * 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... :-\
+ * We don't have code that will init the CYPRESS bridge correctly.
+ *
+ * Unfortunately, we can't just ignore it on 600au Miatas (at
+ * least) because it means we don't reserve the I/O space it
+ * takes up, and SRM has a bad habit of configuring the
+ * IDE-DMA control registers at 0x90a0, which is above
+ * DEFAULT_IO_BASE. Usually this results in a resource
+ * conflict with the Qlogic SCSI controller, which is
+ * obviously a Bad Thing.
+ *
+ * So, in the absence of real resource management such as we
+ * have in 2.3 (which does not have this problem), we will add
+ * a special case for it where we try half-heartedly (and
+ * hopefully not to the detriment of other devices) to avoid
+ * this particular I/O space given to it by the console which
+ * causes our problems.
          */
         if (dev->vendor == PCI_VENDOR_ID_CONTAQ &&
             dev->device == PCI_DEVICE_ID_CONTAQ_82C693) {
- DBG_DEVS(("layout_dev: ignoring CYPRESS bridge...\n"));
- return;
+ DBG_DEVS(("layout_dev: CYPRESS HACK!\n"));
+ cypress_hack = 1;
         }
 
         bus = dev->bus;
@@ -565,12 +569,63 @@
                          * Adaptecs, especially, resent such intrusions.
                          */
                         alignto = MAX(0x800, size);
- base = ALIGN(io_base, alignto);
- io_base = base + size;
 
+ /* We don't have real resource management, so
+ just try to make sure it doesn't overlay
+ anything else we allocate here */
+ if (cypress_hack) {
+ base = orig_base & ~1;
+ if (base < DEFAULT_IO_BASE) /* don't care */
+ goto rewrite_ioconfig;
+
+ if (base >= io_base) {
+ if (cypress_base)
+ printk(KERN_WARNING
+ "bios32.c: already reserved CYPRESS "
+ "space (%d bytes at %#x), possible "
+ "resource confilct!\n", cypress_size,
+ cypress_base);
+ cypress_base = base;
+ cypress_size = size;
+ DBG_DEVS(("CYPRESS HACK: reserving %d bytes at %#x\n",
+ cypress_size, cypress_base));
+ } else {
+ /* argh! we already clobbered it */
+ printk(KERN_WARNING
+ "bios32.c: CYPRESS at %#x (<=%#x), possible"
+ "resource conflict!\n", base, io_base);
+ }
+ } else {
+ if (cypress_base) {
+ unsigned int cypress_end
+ = cypress_base + cypress_size;
+ DBG_DEVS(("cypress %#x-%#x, dev %#x-%#x\n",
+ cypress_base, cypress_end,
+ io_base, io_base + size));
+ if ((cypress_base >= io_base
+ && cypress_base < io_base + size)
+ || (cypress_end > io_base
+ && cypress_end <= io_base + size)
+ || (cypress_base <= io_base
+ && cypress_end >= io_base + size))
+ {
+ io_base = cypress_base + cypress_size;
+ DBG_DEVS(("CYPRESS HACK: moving io_base to %#x\n",
+ io_base));
+ }
+ }
+
+ base = ALIGN(io_base, alignto);
+ io_base = base + size;
+ DBG_DEVS(("layout_dev: base %#x io_base %#x\n",
+ base, io_base));
+ }
+
+ rewrite_ioconfig:
                         pcibios_write_config_dword(bus->number, dev->devfn,
                                                    off, base | 0x1);
- new_io_reset(dev, off, orig_base);
+ if (!cypress_hack)
+ new_io_reset(dev, off, orig_base);
 
                         handle = PCI_HANDLE(bus->number) | base | 1;
                         dev->base_address[idx] = handle;
@@ -626,7 +681,14 @@
                          */
                         /* align to multiple of size of minimum base */
                         alignto = MAX(0x1000, size);
- base = ALIGN(mem_base, alignto);
+
+ if (cypress_hack) {
+ /* Don't bother, we shouldn't have conflicts */
+ base = orig_base;
+ goto rewrite_memconfig;
+ } else {
+ base = ALIGN(mem_base, alignto);
+ }
                         if (size > 7 * 16*MB) {
                                 printk("bios32 WARNING: slot %d, function %d"
                                        " requests 0x%x bytes of contiguous"
@@ -648,9 +710,11 @@
                         }
                         mem_base = base + size;
 
+ rewrite_memconfig:
                         pcibios_write_config_dword(bus->number, dev->devfn,
                                                    off, base);
- new_io_reset(dev, off, orig_base);
+ if (!cypress_hack)
+ new_io_reset(dev, off, orig_base);
 
                         handle = PCI_HANDLE(bus->number) | base;
                         dev->base_address[idx] = handle;

-- 
David Huggins-Daines, Senior GNU/Linux Consultant, Linuxcare, Inc.
613.562.1239 desk, 613.223.0225 mobile
dhd@linuxcare.com, http://www.linuxcare.com/
Linuxcare. Support for the revolution.



This archive was generated by hypermail 2b29 : Mon May 15 2000 - 21:00:29 EST