Date: Wed, 24 Sep 1997 23:01:33 +0200 (MET DST)
From: Wout Klaren <W.Klaren@inter.NL.net>
To: linux-m68k@lists.linux-m68k.org
Subject: L68K: More patches for the Hades
Sender: owner-linux-m68k@phil.uni-sb.de
Reply-To: Wout Klaren <W.Klaren@inter.NL.net>

Hello,

Here are some more patches for the Hades. These patches add the following
features to the kernel:

- PCI bus support.
- Software emulation of TT SCSI DMA. This increases transfer rates at
  least ten times compared to PIO transfers.
- inw, outw, inl and outl functions in asm/io.h. These functions swap the
  byteorder to make it easier to port existing PCI drivers for Linux/i386 
  to Linux/m68k. Note that insw, outsw, insl and outsl will also be needed
  here, but these are already defined in asm/ide.h. These should probably
  be moved to asm/io.h.

The DMA emulation needs autovector interrupt 2. Because this interrupt is
disabled on the Atari, I made a new configuration option CONFIG_HADES. If
this option is defined, the default interrupt level will be 0 instead of
2. This option also enables PCI support.


Greetings,


Wout Klaren



diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/Documentation/Configure.help linux-2.1.55/Documentation/Configure.help
--- linux-2.1.55.orig/Documentation/Configure.help	Mon Sep 22 21:59:51 1997
+++ linux-2.1.55/Documentation/Configure.help	Wed Sep 24 20:47:37 1997
@@ -5600,6 +5600,16 @@
   this kernel on an Atari, say Y here and browse the material
   available in Documentation/m68k; otherwise say N.
 
+Hades support
+CONFIG_HADES
+  This option enables support for the Hades Atari clone. If you say
+  Y here, PCI bus support will be compiled in and the TT SCSI DMA
+  emulation option for SCSI will be enabled. Note that a kernel
+  without this option set (but with Atari support) will also work
+  on the Hades, but without PCI bus support and SCSI transfers will
+  be very slow. If you plan to use this kernel on a Hades, say Y
+  here; otherwise say N.
+
 Macintosh support
 CONFIG_MAC
   This option would enable support for the Apple Macintosh if there was
@@ -5835,7 +5845,7 @@
   read Documentation/modules.txt.  This driver supports both styles of
   NCR integration into the system: the TT style (separate DMA), and
   the Falcon style (via ST-DMA, replacing ACSI). It does NOT support
-  other schemes, like in the Hades (without DMA).
+  other schemes.
 
 Long delays for Toshiba CD-ROMs
 CONFIG_ATARI_SCSI_TOSHIBA_DELAY
@@ -5843,6 +5853,14 @@
   accommodate some flaky Toshiba CD-ROM drives. Say Y if you intend to
   use a Toshiba CD-ROM drive; otherwise, the option is not needed and
   would impact performance a bit, so say N.
+
+Hades SCSI DMA emulator (EXPERIMENTAL)
+CONFIG_TT_DMA_EMUL
+  This option enables code which emulates the TT SCSI DMA chip on the
+  Hades. This increases the SCSI transfer rates at least ten times
+  compared to PIO transfers. Note that this code is experimental and
+  has only been tested on a Hades with a 68060 processor. Before you
+  use this, make backups of your entire hard disk.
 
 Ariadne support
 CONFIG_ARIADNE
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/arch/m68k/atari/ataints.c linux-2.1.55/arch/m68k/atari/ataints.c
--- linux-2.1.55.orig/arch/m68k/atari/ataints.c	Mon Sep 22 21:59:57 1997
+++ linux-2.1.55/arch/m68k/atari/ataints.c	Mon Sep 15 22:17:02 1997
@@ -374,10 +374,13 @@
 		tt_scu.vme_mask = 0x60;		/* enable MFP and SCC ints */
 	}
 	else {
-		/* If no SCU, the HSYNC interrupt needs to be disabled this
-		 * way. (Else _inthandler in kernel/sys_call.S gets overruns)
+		/* If no SCU and no Hades, the HSYNC interrupt needs to be
+		 * disabled this way. (Else _inthandler in kernel/sys_call.S
+		 * gets overruns)
 		 */
-		vectors[VEC_INT2] = falcon_hblhandler;
+
+		if (!is_hades)
+			vectors[VEC_INT2] = falcon_hblhandler;
 	}
 
 	if (ATARIHW_PRESENT(PCM_8BIT) && ATARIHW_PRESENT(MICROWIRE)) {
@@ -414,7 +417,14 @@
                       unsigned long flags, const char *devname, void *dev_id)
 {
 	int vector;
-	
+
+	/*
+	 * The following is a hack to make some PCI card drivers work,
+	 * which set the SA_SHIRQ flag.
+	 */
+
+	flags &= ~SA_SHIRQ;
+
 	if (flags < IRQ_TYPE_SLOW || flags > IRQ_TYPE_PRIO) {
 		printk ("%s: Bad irq type %ld requested from %s\n",
 		        __FUNCTION__, flags, devname);
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/arch/m68k/atari/config.c linux-2.1.55/arch/m68k/atari/config.c
--- linux-2.1.55.orig/arch/m68k/atari/config.c	Mon Sep 22 22:11:25 1997
+++ linux-2.1.55/arch/m68k/atari/config.c	Mon Sep 22 20:55:44 1997
@@ -501,6 +501,24 @@
               : "d0" );
 
     }
+
+    /*
+     * On the Hades map the PCI memory, I/O and configuration areas
+     * (0x80000000 - 0xbfffffff).
+     *
+     * Settings: supervisor only, non-cacheable, serialized, read and write.
+     */
+
+    if (is_hades) {
+        __asm__ __volatile__ ("movel %0,%/d0\n\t"
+                              ".chip 68040\n\t"
+                              "movec %%d0,%%itt0\n\t"
+                              "movec %%d0,%%dtt0\n\t"
+                              ".chip 68k\n\t"
+                              : /* no outputs */
+                              : "g" (0x803fa040)
+                              : "d0");
+    }
 }
 
 __initfunc(static void
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/arch/m68k/config.in linux-2.1.55/arch/m68k/config.in
--- linux-2.1.55.orig/arch/m68k/config.in	Mon Sep 22 21:59:57 1997
+++ linux-2.1.55/arch/m68k/config.in	Mon Sep 22 21:18:17 1997
@@ -23,6 +23,12 @@
 
 bool 'Amiga support' CONFIG_AMIGA
 bool 'Atari support' CONFIG_ATARI
+if [ "$CONFIG_ATARI" = "y" ]; then
+  bool '  Hades support' CONFIG_HADES
+  if [ "$CONFIG_HADES" = "y" ]; then
+    define_bool CONFIG_PCI y
+  fi  
+fi
 bool 'Macintosh support' CONFIG_MAC
 
 comment 'Processor type'
@@ -171,6 +177,9 @@
 if [ "$CONFIG_ATARI" = "y" ]; then
   dep_tristate 'Atari native SCSI support' CONFIG_ATARI_SCSI $CONFIG_SCSI
   bool 'Long delays for Toshiba CD-ROMs' CONFIG_ATARI_SCSI_TOSHIBA_DELAY
+  if [ "$CONFIG_EXPERIMENTAL" = "y" -a "$CONFIG_HADES" = "y" ]; then
+    bool 'Hades SCSI DMA emulator (EXPERIMENTAL)' CONFIG_TT_DMA_EMUL
+  fi
 fi
 #dep_tristate 'SCSI debugging host adapter' CONFIG_SCSI_DEBUG $CONFIG_SCSI
 endmenu
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/arch/m68k/kernel/Makefile linux-2.1.55/arch/m68k/kernel/Makefile
--- linux-2.1.55.orig/arch/m68k/kernel/Makefile	Mon Sep 22 22:00:01 1997
+++ linux-2.1.55/arch/m68k/kernel/Makefile	Mon Sep 15 22:19:05 1997
@@ -23,6 +23,10 @@
 O_OBJS += kgdb.o
 endif
 
+ifdef CONFIG_PCI
+O_OBJS += bios32.o
+endif
+
 head.o: head.S
 
 include $(TOPDIR)/Rules.make
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/arch/m68k/kernel/bios32.c linux-2.1.55/arch/m68k/kernel/bios32.c
--- linux-2.1.55.orig/arch/m68k/kernel/bios32.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.55/arch/m68k/kernel/bios32.c	Mon Sep 22 21:53:10 1997
@@ -0,0 +1,580 @@
+/*
+ * bios32.c - PCI BIOS functions for Alpha systems not using BIOS
+ *	      emulation code.
+ *
+ * Written by Wout Klaren.
+ *
+ * Based on the DEC Alpha bios32.c by Dave Rusling and David Mosberger.
+ */
+
+#include <linux/config.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+#if 0
+# define DBG_DEVS(args)		printk args
+#else
+# define DBG_DEVS(args)
+#endif
+
+#ifdef CONFIG_PCI
+
+/*
+ * PCI support for Linux/m68k. Currently only the Hades is supported.
+ *
+ * Notes:
+ *
+ * 1. The PCI memory area starts at address 0x80000000 and the
+ *    I/O area starts at 0xB0000000. Therefore these offsets
+ *    are added to the base addresses when they are read and
+ *    substracted when they are written.
+ *
+ * 2. The support for PCI bridges in the DEC Alpha version has
+ *    been removed in this version.
+ */
+
+#include <linux/bios32.h>
+#include <linux/pci.h>
+#include <linux/malloc.h>
+#include <linux/mm.h>
+
+#include <asm/atarihw.h>
+#include <asm/atariints.h>
+#include <asm/byteorder.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+
+#define KB		1024
+#define MB		(1024*KB)
+#define GB		(1024*MB)
+
+#define MAJOR_REV	0
+#define MINOR_REV	0
+
+/*
+ * Base addresses of the PCI memory and I/O areas on the Hades.
+ */
+
+static unsigned long pci_mem_base = 0;
+static unsigned long pci_io_base = 0;
+
+/*
+ * Align VAL to ALIGN, which must be a power of two.
+ */
+
+#define ALIGN(val,align)	(((val) + ((align) - 1)) & ~((align) - 1))
+
+/*
+ * Calculate the address of the PCI configuration area of the given
+ * device.
+ *
+ * BUG: boards with multiple functions are probably not correctly
+ * supported.
+ */
+
+static int mk_conf_addr(unsigned char bus, unsigned char device_fn,
+			unsigned char where, unsigned long *pci_addr)
+{
+	static const unsigned long pci_conf_base[] = { 0xA0080000, 0xA0040000,
+						       0xA0020000, 0xA0010000 };
+	int device = device_fn >> 3;
+
+	DBG_DEVS(("mk_conf_addr(bus=%d ,device_fn=0x%x, where=0x%x, pci_addr=0x%p)\n",
+		  bus, device_fn, where, pci_addr));
+
+	if (device > 3) {
+		DBG_DEVS(("mk_conf_addr: device (%d) > 3, returning -1\n", device));
+		return -1;
+	}
+
+	*pci_addr = pci_conf_base[device] | (where);
+	DBG_DEVS(("mk_conf_addr: returning pci_addr 0x%lx\n", *pci_addr));
+	return 0;
+}
+
+int pcibios_read_config_byte(unsigned char bus, unsigned char device_fn,
+			     unsigned char where, unsigned char *value)
+{
+	unsigned long pci_addr;
+
+	*value = 0xff;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = *((unsigned char *)pci_addr);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_read_config_word(unsigned char bus, unsigned char device_fn,
+			     unsigned char where, unsigned short *value)
+{
+	unsigned long pci_addr;
+
+	*value = 0xffff;
+
+	if (where & 0x1)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = le16_to_cpu(*((unsigned short *)pci_addr));
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_read_config_dword(unsigned char bus, unsigned char device_fn,
+			      unsigned char where, unsigned int *value)
+{
+	unsigned long pci_addr;
+
+	*value = 0xffffffff;
+
+	if (where & 0x3)
+		return PCIBIOS_BAD_REGISTER_NUMBER;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr))
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*value = le32_to_cpu(*((unsigned int *)pci_addr));
+
+	if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5))
+	{
+		if ((*value & PCI_BASE_ADDRESS_SPACE) ==
+		    PCI_BASE_ADDRESS_SPACE_IO)
+			*value += pci_io_base;
+		else
+		{
+			if (*value == 0)
+			{
+				/*
+				 * Base address is 0. Test if this base
+				 * address register is used.
+				 */
+
+				*((unsigned long *)pci_addr) = 0xffffffff;
+				if (*((unsigned long *)pci_addr) != 0)
+					*value += pci_mem_base;
+			}
+			else
+				*value += pci_mem_base;
+		}
+	}
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_byte(unsigned char bus, unsigned char device_fn,
+			      unsigned char where, unsigned char value)
+{
+	unsigned long pci_addr;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*((unsigned char *)pci_addr) = value;
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_word(unsigned char bus, unsigned char device_fn,
+			      unsigned char where, unsigned short value)
+{
+	unsigned long pci_addr;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	*((unsigned short *)pci_addr) = cpu_to_le16(value);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+int pcibios_write_config_dword(unsigned char bus, unsigned char device_fn,
+			       unsigned char where, unsigned int value)
+{
+	unsigned long pci_addr;
+
+	if (mk_conf_addr(bus, device_fn, where, &pci_addr) < 0)
+		return PCIBIOS_DEVICE_NOT_FOUND;
+
+	if ((where >= PCI_BASE_ADDRESS_0) && (where <= PCI_BASE_ADDRESS_5))
+	{
+		if ((value & PCI_BASE_ADDRESS_SPACE) ==
+		    PCI_BASE_ADDRESS_SPACE_IO)
+			value -= pci_io_base;
+		else
+			value -= pci_mem_base;
+	}
+
+	*((unsigned int *)pci_addr) = cpu_to_le32(value);
+
+	return PCIBIOS_SUCCESSFUL;
+}
+
+/*
+ * Macro to enable programming of the PCI devices. On the Hades this
+ * define should be true, because the Hades has no PCI BIOS.
+ */
+
+#define PCI_MODIFY		1
+
+#if PCI_MODIFY
+
+/*
+ * Leave some room for a VGA card. We assume that the VGA card is
+ * always in the first 32M of PCI memory. For the time being we do
+ * not program the VGA card, because to make this work we also
+ * need to change the frame buffer device.
+ */
+
+#define FIRST_IO_ADDR	0x10000
+#define FIRST_MEM_ADDR	0x02000000
+
+static unsigned int io_base = FIRST_IO_ADDR;	/* Skip first 64K. */
+static unsigned int mem_base = FIRST_MEM_ADDR;	/* Skip first 32M. */
+
+/*
+ * Disable PCI device DEV so that it does not respond to I/O or memory
+ * accesses.
+ */
+
+__initfunc(static void disable_dev(struct pci_dev *dev))
+{
+	struct pci_bus *bus;
+	unsigned short cmd;
+
+	if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
+	    dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
+	    dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
+		return;
+
+	bus = dev->bus;
+	pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
+
+	cmd &= (~PCI_COMMAND_IO & ~PCI_COMMAND_MEMORY & ~PCI_COMMAND_MASTER);
+	pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND, cmd);
+}
+
+/*
+ * Layout memory and I/O for a device:
+ */
+
+#define MAX(val1, val2) ( ((val1) > (val2)) ? val1 : val2)
+
+__initfunc(static void layout_dev(struct pci_dev *dev))
+{
+	struct pci_bus *bus;
+	unsigned short cmd;
+	unsigned int base, mask, size, reg;
+	unsigned int alignto;
+
+	/*
+	 * Skip video cards for the time being.
+	 */
+
+	if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
+	    dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
+	    dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
+		return;
+
+	bus = dev->bus;
+	pcibios_read_config_word(bus->number, dev->devfn, PCI_COMMAND, &cmd);
+
+	for (reg = PCI_BASE_ADDRESS_0; reg <= PCI_BASE_ADDRESS_5; reg += 4)
+	{
+		/*
+		 * Figure out how much space and of what type this
+		 * device wants.
+		 */
+
+		pcibios_write_config_dword(bus->number, dev->devfn, reg,
+					   0xffffffff);
+		pcibios_read_config_dword(bus->number, dev->devfn, reg, &base);
+
+		if (!base)
+		{
+			/* this base-address register is unused */
+			continue;
+		}
+
+		/*
+		 * We've read the base address register back after
+		 * writing all ones and so now we must decode it.
+		 */
+
+		if (base & PCI_BASE_ADDRESS_SPACE_IO)
+		{
+			/*
+			 * I/O space base address register.
+			 */
+
+			cmd |= PCI_COMMAND_IO;
+
+			base &= PCI_BASE_ADDRESS_IO_MASK;
+			mask = (~base << 1) | 0x1;
+			size = (mask & base) & 0xffffffff;
+			/* align to multiple of size of minimum base */
+			alignto = MAX(0x400, size) ;
+			base = ALIGN(io_base, alignto);
+			io_base = base + size;
+			pcibios_write_config_dword(bus->number, dev->devfn,
+						   reg, base | 0x1);
+			DBG_DEVS(("layout_dev: IO address: %lX\n", base));
+		}
+		else
+		{
+			unsigned int type;
+
+			/*
+			 * Memory space base address register.
+			 */
+
+			cmd |= PCI_COMMAND_MEMORY;
+			type = base & PCI_BASE_ADDRESS_MEM_TYPE_MASK;
+			base &= PCI_BASE_ADDRESS_MEM_MASK;
+			mask = (~base << 1) | 0x1;
+			size = (mask & base) & 0xffffffff;
+			switch (type)
+			{
+			case PCI_BASE_ADDRESS_MEM_TYPE_32:
+				break;
+
+			case PCI_BASE_ADDRESS_MEM_TYPE_64:
+				printk("bios32 WARNING: "
+				       "ignoring 64-bit device in "
+				       "slot %d, function %d: \n",
+				       PCI_SLOT(dev->devfn),
+				       PCI_FUNC(dev->devfn));
+				reg += 4;	/* skip extra 4 bytes */
+				continue;
+
+			case PCI_BASE_ADDRESS_MEM_TYPE_1M:
+				printk("bios32 WARNING: slot %d, function %d "
+				       "requests memory below 1MB---don't "
+				       "know how to do that.\n",
+				       PCI_SLOT(dev->devfn),
+				       PCI_FUNC(dev->devfn));
+				continue;
+			}
+
+			/*
+			 * Align to multiple of size of minimum base
+			 */
+
+			alignto = MAX(0x1000, size) ;
+			base = ALIGN(mem_base, alignto);
+			mem_base = base + size;
+			pcibios_write_config_dword(bus->number, dev->devfn,
+						   reg, base);
+		}
+	}
+
+	/*
+	 * Enable device:
+	 */
+
+	if (dev->class >> 8 == PCI_CLASS_NOT_DEFINED ||
+	    dev->class >> 8 == PCI_CLASS_NOT_DEFINED_VGA ||
+	    dev->class >> 8 == PCI_CLASS_DISPLAY_VGA ||
+	    dev->class >> 8 == PCI_CLASS_DISPLAY_XGA)
+	{
+		/*
+		 * 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 I/O to these
+		 * devices.
+		 */
+		cmd |= PCI_COMMAND_IO;
+	}
+
+	pcibios_write_config_word(bus->number, dev->devfn, PCI_COMMAND,
+				  cmd | PCI_COMMAND_MASTER);
+	DBG_DEVS(("layout_dev: bus %d  slot 0x%x  VID 0x%x  DID 0x%x  class 0x%x\n",
+		  bus->number, PCI_SLOT(dev->devfn), dev->vendor, dev->device, dev->class));
+}
+
+__initfunc(static void layout_bus(struct pci_bus *bus))
+{
+	struct pci_dev *dev;
+
+	DBG_DEVS(("layout_bus: starting bus %d\n", bus->number));
+
+	if (!bus->devices && !bus->children)
+		return;
+
+	/*
+	 * Align the current bases on appropriate boundaries (4K for
+	 * IO and 1MB for memory).
+	 */
+
+	io_base = ALIGN(io_base, 4*KB);
+	mem_base = ALIGN(mem_base, 1*MB);
+
+	/*
+	 * PCI devices might have been setup by a PCI BIOS emulation
+	 * running under TOS. In these cases there is a
+	 * window during which two devices may have an overlapping
+	 * address range.  To avoid this causing trouble, we first
+	 * turn off the I/O and memory address decoders for all PCI
+	 * devices.  They'll be re-enabled only once all address
+	 * decoders are programmed consistently.
+	 */
+
+	for (dev = bus->devices; dev; dev = dev->sibling)
+	{
+		if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
+			disable_dev(dev);
+	}
+
+	/*
+	 * Allocate space to each device:
+	 */
+
+	DBG_DEVS(("layout_bus: starting bus %d devices\n", bus->number));
+
+	for (dev = bus->devices; dev; dev = dev->sibling)
+	{
+		if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
+			layout_dev(dev);
+	}
+}
+
+#endif /* !PCI_MODIFY */
+
+/*
+ * Given the vendor and device ids, find the n'th instance of that device
+ * in the system.
+ */
+
+int pcibios_find_device(unsigned short vendor, unsigned short device_id,
+			unsigned short index, unsigned char *bus,
+			unsigned char *devfn)
+{
+	unsigned int curr = 0;
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next)
+	{
+		if (dev->vendor == vendor && dev->device == device_id)
+		{
+			if (curr == index)
+			{
+				*devfn = dev->devfn;
+				*bus = dev->bus->number;
+				return PCIBIOS_SUCCESSFUL;
+			}
+			++curr;
+		}
+	}
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+/*
+ * Given the class, find the n'th instance of that device
+ * in the system.
+ */
+
+int pcibios_find_class(unsigned int class_code, unsigned short index,
+		       unsigned char *bus, unsigned char *devfn)
+{
+	unsigned int curr = 0;
+	struct pci_dev *dev;
+
+	for (dev = pci_devices; dev; dev = dev->next)
+	{
+		if (dev->class == class_code)
+		{
+			if (curr == index)
+			{
+				*devfn = dev->devfn;
+				*bus = dev->bus->number;
+				return PCIBIOS_SUCCESSFUL;
+			}
+			++curr;
+		}
+	}
+	return PCIBIOS_DEVICE_NOT_FOUND;
+}
+
+int pcibios_present(void)
+{
+	if (is_hades)
+		return 1;
+	else
+		return 0;
+}
+
+__initfunc(unsigned long pcibios_init(unsigned long mem_start,
+				      unsigned long mem_end))
+{
+	printk("Linux/m68k PCI BIOS32 revision %x.%02x\n", MAJOR_REV, MINOR_REV);
+
+#if !PCI_MODIFY
+	printk("...NOT modifying existing PCI configuration\n");
+#endif
+
+	return mem_start;
+}
+
+/*
+ * static inline void hades_fixup(void)
+ *
+ * Assign IRQ numbers as used by Linux to the interrupt pins
+ * of the PCI cards.
+ */
+
+__initfunc(static inline void hades_fixup(void))
+{
+	char irq_tab[4] = {
+			    IRQ_TT_MFP_IO0,	/* Slot 0. */
+			    IRQ_TT_MFP_IO1,	/* Slot 1. */
+			    IRQ_TT_MFP_SCC,	/* Slot 2. */
+			    IRQ_TT_MFP_SCSIDMA	/* Slot 3. */
+			  };
+	struct pci_dev *dev;
+	unsigned char slot;
+
+	/*
+	 * Go through all devices, fixing up irqs as we see fit:
+	 */
+
+	for (dev = pci_devices; dev; dev = dev->next)
+	{
+		if (dev->class >> 16 != PCI_BASE_CLASS_BRIDGE)
+		{
+			slot = PCI_SLOT(dev->devfn);	/* Determine slot number. */
+			dev->irq = irq_tab[slot];
+#if PCI_MODIFY
+			pcibios_write_config_byte(dev->bus->number, dev->devfn,
+						  PCI_INTERRUPT_LINE, dev->irq);
+#endif
+		}
+	}
+}
+
+__initfunc(unsigned long pcibios_fixup(unsigned long mem_start,
+				       unsigned long mem_end))
+{
+#if PCI_MODIFY
+	/*
+	 * Scan the tree, allocating PCI memory and I/O space.
+	 */
+
+	layout_bus(&pci_root);
+#endif
+
+	pci_mem_base = 0x80000000;
+	pci_io_base = 0xB0000000;
+
+	/*
+	 * Now is the time to do all those dirty little deeds...
+	 */
+
+	hades_fixup();
+
+	return mem_start;
+}
+#endif /* CONFIG_PCI */
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/drivers/scsi/atari_dma_emul.c linux-2.1.55/drivers/scsi/atari_dma_emul.c
--- linux-2.1.55.orig/drivers/scsi/atari_dma_emul.c	Thu Jan  1 01:00:00 1970
+++ linux-2.1.55/drivers/scsi/atari_dma_emul.c	Wed Sep 24 21:04:19 1997
@@ -0,0 +1,462 @@
+/*
+ * atari_dma_emul.c -- TT SCSI DMA emulator for the Hades.
+ *
+ * Copyright 1997 Wout Klaren <W.Klaren@inter.nl.net>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file COPYING in the main directory of this archive
+ * for more details.
+ *
+ * This code was written using the Hades TOS source code as a
+ * reference. This source code can be found on the home page
+ * of Medusa Computer Systems.
+ *
+ * Version 0.1, 1997-09-24.
+ * 
+ * This code should be considered experimental. It has only been
+ * tested on a Hades with a 68060. It might not work on a Hades
+ * with a 68040. Make backups of your hard drives before using
+ * this code.
+ */
+
+#include <asm/uaccess.h>
+
+#define hades_dma_ctrl		(*(unsigned char *) 0xffff8717)
+#define hades_psdm_reg		(*(unsigned char *) 0xffff8741)
+
+#define TRANSFER_SIZE		16
+
+struct m68040_frame {
+	unsigned long  effaddr;  /* effective address */
+	unsigned short ssw;      /* special status word */
+	unsigned short wb3s;     /* write back 3 status */
+	unsigned short wb2s;     /* write back 2 status */
+	unsigned short wb1s;     /* write back 1 status */
+	unsigned long  faddr;    /* fault address */
+	unsigned long  wb3a;     /* write back 3 address */
+	unsigned long  wb3d;     /* write back 3 data */
+	unsigned long  wb2a;     /* write back 2 address */
+	unsigned long  wb2d;     /* write back 2 data */
+	unsigned long  wb1a;     /* write back 1 address */
+	unsigned long  wb1dpd0;  /* write back 1 data/push data 0*/
+	unsigned long  pd1;      /* push data 1*/
+	unsigned long  pd2;      /* push data 2*/
+	unsigned long  pd3;      /* push data 3*/
+};
+
+static void writeback (unsigned short wbs, unsigned long wba,
+		       unsigned long wbd, void *old_buserr)
+{
+	unsigned long fs = get_fs();
+	static void *save_buserr;
+
+	__asm__ __volatile__ ("movec.l	%%vbr,%%a0\n\t"
+			      "move.l	%0,8(%%a0)\n\t"
+			      :
+			      : "r" (&&bus_error)
+			      : "a0" );
+
+	save_buserr = old_buserr;
+
+	set_fs (wbs & WBTM_040);
+
+	switch (wbs & WBSIZ_040) {
+	    case BA_SIZE_BYTE:
+		put_user (wbd & 0xff, (char *)wba);
+		break;
+	    case BA_SIZE_WORD:
+		put_user (wbd & 0xffff, (short *)wba);
+		break;
+	    case BA_SIZE_LONG:
+		put_user (wbd, (int *)wba);
+		break;
+	}
+
+	set_fs (fs);
+	return;
+
+bus_error:
+	__asm__ __volatile__ ("cmp.l	%0,2(%%sp)\n\t"
+			      "bcs.s	.jump_old\n\t"
+			      "cmp.l	%1,2(%%sp)\n\t"
+			      "bls.s	.restore_old\n"
+			".jump_old:\n\t"
+			      "move.l	%2,-(%%sp)\n\t"
+			      "rts\n"
+			".restore_old:\n\t"
+			      "move.l	%%a0,-(%%sp)\n\t"
+			      "movec.l	%%vbr,%%a0\n\t"
+			      "move.l	%2,8(%%a0)\n\t"
+			      "move.l	(%%sp)+,%%a0\n\t"
+			      "rte\n\t"
+			      :
+			      : "i" (writeback), "i" (&&bus_error),
+			        "m" (save_buserr) );
+}
+
+/*
+ * static inline void set_restdata_reg(unsigned char *cur_addr)
+ *
+ * Set the rest data register if necessary.
+ */
+
+static inline void set_restdata_reg(unsigned char *cur_addr)
+{
+	if (((long) cur_addr & ~3) != 0)
+		tt_scsi_dma.dma_restdata =
+			*((unsigned long *) ((long) cur_addr & ~3));
+}
+
+/*
+ * void hades_dma_emulator(int irq, void *dummy, struct pt_regs *fp)
+ * 
+ * This code emulates TT SCSI DMA on the Hades.
+ * 
+ * Note the following:
+ * 
+ * 1. When there is no byte available to read from the SCSI bus, or
+ *    when a byte cannot yet bet written to the SCSI bus, a bus
+ *    error occurs when reading or writing the pseudo DMA data
+ *    register (hades_psdm_reg). We have to catch this bus error
+ *    and try again to read or write the byte. If after several tries
+ *    we still get a bus error, the interrupt handler is left. When
+ *    the byte can be read or written, the interrupt handler is
+ *    called again.
+ * 
+ * 2. The SCSI interrupt must be disabled in this interrupt handler.
+ * 
+ * 3. If we set the EOP signal, the SCSI controller still expects one
+ *    byte to be read or written. Therefore the last byte is transferred
+ *    separately, after setting the EOP signal.
+ * 
+ * 4. When this function is left, the address pointer (start_addr) is
+ *    converted to a physical address. Because it points one byte
+ *    further than the last transfered byte, it can point outside the
+ *    current page. If virt_to_phys() is called with this address we
+ *    might get an access error. Therefore virt_to_phys() is called with
+ *    start_addr - 1 if the count has reached zero. The result is
+ *    increased with one.
+ */
+
+static void hades_dma_emulator(int irq, void *dummy, struct pt_regs *fp)
+{
+	unsigned long dma_base;
+	register unsigned long dma_cnt asm ("d3");
+	static long save_buserr;
+	register unsigned long save_sp asm ("d4");
+	register int tries asm ("d5");
+	register unsigned char *start_addr asm ("a3"), *end_addr asm ("a4");
+	register unsigned char *eff_addr;
+	register unsigned char *psdm_reg;
+	unsigned long rem;
+
+	atari_disable_irq(IRQ_TT_MFP_SCSI);
+
+	/*
+	 * Read the dma address and count registers.
+	 */
+
+	dma_base = SCSI_DMA_READ_P(dma_addr);
+	dma_cnt = SCSI_DMA_READ_P(dma_cnt);
+
+	/*
+	 * Check if DMA is still enabled.
+	 */
+
+	if ((tt_scsi_dma.dma_ctrl & 2) == 0)
+	{
+		atari_enable_irq(IRQ_TT_MFP_SCSI);
+		return;
+	}
+
+	if (dma_cnt == 0)
+	{
+		printk(KERN_NOTICE "DMA emulation: count is zero.\n");
+		tt_scsi_dma.dma_ctrl &= 0xfd;	/* DMA ready. */
+		atari_enable_irq(IRQ_TT_MFP_SCSI);
+		return;
+	}
+
+	/*
+	 * Install new bus error routine.
+	 */
+
+	__asm__ __volatile__ ("movec.l	%%vbr,%%a0\n\t"
+			      "move.l	8(%%a0),%0\n\t"
+			      "move.l	%1,8(%%a0)\n\t"
+			      : "=&r" (save_buserr)
+			      : "r" (&&scsi_bus_error)
+			      : "a0" );
+
+	hades_dma_ctrl &= 0xfc;		/* Bus error and EOP off. */
+
+	/*
+	 * Save the stack pointer.
+	 */
+
+	__asm__ __volatile__ ("move.l	%%sp,%0\n\t"
+			      : "=&r" (save_sp) );
+
+	tries = 100;			/* Maximum number of bus errors. */
+	start_addr = phys_to_virt(dma_base);
+	end_addr = start_addr + dma_cnt;
+
+scsi_loop:
+	dma_cnt--;
+	rem = dma_cnt & (TRANSFER_SIZE - 1);
+	dma_cnt &= ~(TRANSFER_SIZE - 1);
+	psdm_reg = &hades_psdm_reg;
+
+	if (tt_scsi_dma.dma_ctrl & 1)	/* Read or write? */
+	{
+		/*
+		 * SCSI write. Abort when count is zero.
+		 */
+
+		switch (rem)
+		{
+		case 0:
+			while (dma_cnt > 0)
+			{
+				dma_cnt -= TRANSFER_SIZE;
+
+				*psdm_reg = *start_addr++;
+		case 15:
+				*psdm_reg = *start_addr++;
+		case 14:
+				*psdm_reg = *start_addr++;
+		case 13:
+				*psdm_reg = *start_addr++;
+		case 12:
+				*psdm_reg = *start_addr++;
+		case 11:
+				*psdm_reg = *start_addr++;
+		case 10:
+				*psdm_reg = *start_addr++;
+		case 9:
+				*psdm_reg = *start_addr++;
+		case 8:
+				*psdm_reg = *start_addr++;
+		case 7:
+				*psdm_reg = *start_addr++;
+		case 6:
+				*psdm_reg = *start_addr++;
+		case 5:
+				*psdm_reg = *start_addr++;
+		case 4:
+				*psdm_reg = *start_addr++;
+		case 3:
+				*psdm_reg = *start_addr++;
+		case 2:
+				*psdm_reg = *start_addr++;
+		case 1:
+				*psdm_reg = *start_addr++;
+			}
+		}
+
+		hades_dma_ctrl |= 1;	/* Set EOP. */
+		udelay(10);
+		*psdm_reg = *start_addr++;	/* Dummy byte. */
+		tt_scsi_dma.dma_ctrl &= 0xfd;	/* DMA ready. */
+	}
+	else
+	{
+		/*
+		 * SCSI read. Abort when count is zero.
+		 */
+
+		switch (rem)
+		{
+		case 0:
+			while (dma_cnt > 0)
+			{
+				dma_cnt -= TRANSFER_SIZE;
+
+				*start_addr++ = *psdm_reg;
+		case 15:
+				*start_addr++ = *psdm_reg;
+		case 14:
+				*start_addr++ = *psdm_reg;
+		case 13:
+				*start_addr++ = *psdm_reg;
+		case 12:
+				*start_addr++ = *psdm_reg;
+		case 11:
+				*start_addr++ = *psdm_reg;
+		case 10:
+				*start_addr++ = *psdm_reg;
+		case 9:
+				*start_addr++ = *psdm_reg;
+		case 8:
+				*start_addr++ = *psdm_reg;
+		case 7:
+				*start_addr++ = *psdm_reg;
+		case 6:
+				*start_addr++ = *psdm_reg;
+		case 5:
+				*start_addr++ = *psdm_reg;
+		case 4:
+				*start_addr++ = *psdm_reg;
+		case 3:
+				*start_addr++ = *psdm_reg;
+		case 2:
+				*start_addr++ = *psdm_reg;
+		case 1:
+				*start_addr++ = *psdm_reg;
+			}
+		}
+
+		hades_dma_ctrl |= 1;	/* Set EOP. */
+		udelay(10);
+		*start_addr++ = *psdm_reg;
+		tt_scsi_dma.dma_ctrl &= 0xfd;	/* DMA ready. */
+
+		set_restdata_reg(start_addr);
+	}
+
+	if (start_addr != end_addr)
+		printk(KERN_CRIT "DMA emulation: FATAL: Count is not zero at end of transfer.\n");
+
+	dma_cnt = end_addr - start_addr;
+
+scsi_end:
+	dma_base = (dma_cnt == 0) ? virt_to_phys(start_addr - 1) + 1 :  
+				    virt_to_phys(start_addr);
+
+	SCSI_DMA_WRITE_P(dma_addr, dma_base);
+	SCSI_DMA_WRITE_P(dma_cnt, dma_cnt);
+
+	/*
+	 * Restore old bus error routine.
+	 */
+
+	__asm__ __volatile__ ("movec.l	%%vbr,%%a0\n\t"
+			      "move.l	%0,8(%%a0)\n\t"
+			      :
+			      : "r" (save_buserr)
+			      : "a0" );
+
+	atari_enable_irq(IRQ_TT_MFP_SCSI);
+
+	return;
+
+scsi_bus_error:
+	/*
+	 * First check if the bus error is caused by our code.
+	 * If not, call the original handler.
+	 */
+
+	__asm__ __volatile__ ("cmp.l	%0,2(%%sp)\n\t"
+			      "bcs.s	.old_vector\n\t"
+			      "cmp.l	%1,2(%%sp)\n\t"
+			      "bls.s	.scsi_buserr\n"
+			".old_vector:\n\t"
+			      "move.l	%2,-(%%sp)\n\t"
+			      "rts\n"
+			".scsi_buserr:\n\t"
+			      :
+			      : "i" (&&scsi_loop), "i" (&&scsi_end),
+			        "m" (save_buserr) );
+
+	if (CPU_IS_060)
+	{
+		/*
+		 * Get effective address and restore the stack.
+		 */
+
+		__asm__ __volatile__ ("move.l	8(%%sp),%0\n\t"
+				      "move.l	%1,%%sp\n\t"
+				      : "=a&" (eff_addr)
+				      : "r" (save_sp) );
+	}
+	else
+	{
+		register struct m68040_frame *frame;
+
+		__asm__ __volatile__ ("lea	8(%%sp),%0\n\t"
+				      : "=a&" (frame) );
+
+		if (tt_scsi_dma.dma_ctrl & 1)
+		{
+			/*
+			 * Bus error while writing.
+			 */
+
+			if (frame->wb3s & WBV_040)
+			{
+				if (frame->wb3a == (long) &hades_psdm_reg)
+					start_addr--;
+				else
+					writeback(frame->wb3s, frame->wb3a,
+						  frame->wb3d, &&scsi_bus_error);
+			}
+
+			if (frame->wb2s & WBV_040)
+			{
+				if (frame->wb2a == (long) &hades_psdm_reg)
+					start_addr--;
+				else
+					writeback(frame->wb2s, frame->wb2a,
+						  frame->wb2d, &&scsi_bus_error);
+			}
+
+			if (frame->wb1s & WBV_040)
+			{
+				if (frame->wb1a == (long) &hades_psdm_reg)
+					start_addr--;
+			}
+		}
+		else
+		{
+			/*
+			 * Bus error while reading.
+			 */
+
+			if (frame->wb3s & WBV_040)
+				writeback(frame->wb3s, frame->wb3a,
+					  frame->wb3d, &&scsi_bus_error);
+		}
+
+		eff_addr = (unsigned char *) frame->faddr;
+	}
+
+	dma_cnt = end_addr - start_addr;
+
+	if (eff_addr == &hades_psdm_reg)
+	{
+		/*
+		 * Bus error occured while reading the pseudo
+		 * DMA register. Time out.
+		 */
+
+		tries--;
+
+		if (tries <= 0)
+		{
+			if ((tt_scsi_dma.dma_ctrl & 1) == 0)	/* Read or write? */
+				set_restdata_reg(start_addr);
+
+			if (dma_cnt <= 1)
+				printk(KERN_CRIT "DMA emulation: Fatal "
+				       "error while %s the last byte.\n",
+				       (tt_scsi_dma.dma_ctrl & 1)
+				       ? "writing" : "reading");
+
+			goto scsi_end;
+		}
+		else
+			goto scsi_loop;
+	}
+	else
+	{
+		/*
+		 * Bus error during pseudo DMA transfer.
+		 * Terminate the DMA transfer.
+		 */
+
+		hades_dma_ctrl |= 3;	/* Set EOP and bus error. */
+		if ((tt_scsi_dma.dma_ctrl & 1) == 0)	/* Read or write? */
+			set_restdata_reg(start_addr);
+		goto scsi_end;
+	}
+}
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/drivers/scsi/atari_scsi.c linux-2.1.55/drivers/scsi/atari_scsi.c
--- linux-2.1.55.orig/drivers/scsi/atari_scsi.c	Mon Sep 22 21:58:59 1997
+++ linux-2.1.55/drivers/scsi/atari_scsi.c	Mon Sep 15 22:17:16 1997
@@ -255,6 +255,10 @@
 MODULE_PARM(setup_hostid, "i");
 
 
+#if defined(CONFIG_TT_DMA_EMUL)
+#include "atari_dma_emul.c"
+#endif
+
 #if defined(REAL_DMA)
 
 static int scsi_dma_is_ignored_buserr( unsigned char dma_stat )
@@ -682,6 +686,13 @@
 		atari_dma_residual = 0;
 #endif /* REAL_DMA */
 #ifdef REAL_DMA
+#ifdef CONFIG_TT_DMA_EMUL
+		if (is_hades) {
+			request_irq(IRQ_AUTO_2, hades_dma_emulator,
+				    IRQ_TYPE_PRIO, "Hades DMA emulator",
+				    hades_dma_emulator);
+		}
+#endif
 		if (is_medusa || is_hades) {
 			/* While the read overruns (described by Drew Eckhardt in
 			 * NCR5380.c) never happened on TTs, they do in fact on the Medusa
@@ -1003,11 +1014,11 @@
 					int write_flag )
 {
 	unsigned long	possible_len, limit;
-
+#ifndef CONFIG_TT_DMA_EMUL
 	if (is_hades)
 		/* Hades has no SCSI DMA at all :-( Always force use of PIO */
 		return( 0 );
-	
+#endif	
 	if (IS_A_TT())
 		/* TT SCSI DMA can transfer arbitrary #bytes */
 		return( wanted_len );
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/include/asm-m68k/entry.h linux-2.1.55/include/asm-m68k/entry.h
--- linux-2.1.55.orig/include/asm-m68k/entry.h	Mon Sep 22 23:19:11 1997
+++ linux-2.1.55/include/asm-m68k/entry.h	Wed Sep 24 22:19:24 1997
@@ -55,7 +55,7 @@
 LTSS_FPCTXT	= 24
 
 /* the following macro is used when enabling interrupts */
-#if defined(MACH_ATARI_ONLY)
+#if defined(MACH_ATARI_ONLY) && !defined(CONFIG_HADES)
 	/* block out HSYNC on the atari */
 #define ALLOWINT 0xfbff
 #define	MAX_NOINT_IPL	3
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/include/asm-m68k/io.h linux-2.1.55/include/asm-m68k/io.h
--- linux-2.1.55.orig/include/asm-m68k/io.h	Mon Sep 22 21:59:11 1997
+++ linux-2.1.55/include/asm-m68k/io.h	Wed Sep 24 21:48:55 1997
@@ -3,6 +3,14 @@
 
 #ifdef __KERNEL__
 
+#include <asm/byteorder.h>
+
+#ifdef CONFIG_ATARI
+#include <asm/atarihw.h>
+
+#define SLOW_DOWN_IO	MFPDELAY()
+#endif
+
 /*
  * readX/writeX() are used to access memory mapped devices. On some
  * architectures the memory mapped IO stuff needs to be accessed
@@ -33,6 +41,28 @@
 #define outb(x,addr) ((void) writeb(x,addr))
 #define outb_p(x,addr) outb(x,addr)
 
+extern inline unsigned short inw(int port)
+{
+	return le16_to_cpu(readw(port));
+}
+
+extern inline unsigned long inl(int port)
+{
+	return le32_to_cpu(readl(port));
+}
+
+extern inline unsigned short outw(unsigned short val, int port)
+{
+	writew(cpu_to_le16(val), port);
+	return val;
+}
+
+extern inline unsigned long outl(unsigned long val, int port)
+{
+	writel(cpu_to_le32(val), port);
+	return val;
+}
+
 /*
  * Change virtual addresses to physical addresses and vv.
  */
@@ -50,10 +80,16 @@
 }
 
 /*
- * IO bus memory addresses are 1:1 with the physical address
+ * IO bus memory addresses are 1:1 with the physical address,
+ * except on the PCI bus of the Hades.
  */
+#ifdef CONFIG_HADES
+#define virt_to_bus(a) (virt_to_phys(a) + 0x80000000)
+#define bus_to_virt(a) (phys_to_virt((a) - 0x80000000))
+#else
 #define virt_to_bus virt_to_phys
 #define bus_to_virt phys_to_virt
+#endif
 
 #endif /* __KERNEL__ */
 
diff -ruN -x *.o -x *.a -x .*depend -x .config* -x .menuconfig* -x System.map -x .version -x autoconf.h -x compile.h -x vmlinux -x *_MODULES -x *.ver linux-2.1.55.orig/include/asm-m68k/system.h linux-2.1.55/include/asm-m68k/system.h
--- linux-2.1.55.orig/include/asm-m68k/system.h	Mon Sep 22 22:51:37 1997
+++ linux-2.1.55/include/asm-m68k/system.h	Wed Sep 24 21:48:52 1997
@@ -63,7 +63,7 @@
 struct __xchg_dummy { unsigned long a[100]; };
 #define __xg(x) ((volatile struct __xchg_dummy *)(x))
 
-#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC)
+#if defined(CONFIG_ATARI) && !defined(CONFIG_AMIGA) && !defined(CONFIG_MAC) && !defined(CONFIG_HADES)
 /* block out HSYNC on the atari */
 #define __sti() __asm__ __volatile__ ("andiw #0xfbff,%/sr": : : "memory")
 #else /* portable version */


