Resent-Date: Mon, 9 Nov 1998 14:45:22 +0100 (MET)
To: Martin Waschbuesch <Martin@Steininger.com>
Cc: richard@sleepie.demon.co.uk, linux-m68k@phil.uni-sb.de
Subject: Re: 53c7xx SCSI and A4000T
References: <yam7617.284.141200656@mail.munich.netsurf.de>
From: Jes Sorensen <Jes.Sorensen@cern.ch>
Date: 09 Nov 1998 14:35:48 +0100
In-Reply-To: Martin Waschbuesch's message of "Mon, 09 Nov 1998 14:17:05 +0200"
Resent-From: linux-m68k@phil.uni-sb.de

>>>>> "Martin" == Martin Waschbuesch <Martin@Steininger.com> writes:

Martin> Hi Jes!  I finally found the third version (I had a problem
Martin> with my provider's proxy) and it works!  I'll continue testing
Martin> and report any problems that might occur.  Could you please
Martin> release a patch for 2.0.33pl1 so that I can compile a 68060
Martin> only version?

Sure, here you are.

So 2.0.x didn't work for you before, right?

Could someone with a 68040 and a 53c7xx based controller please test
this.

Thanks a lot for testing.

Jes

--- linux20/drivers/scsi/53c7xx.c.orig	Wed Dec 17 16:30:30 1997
+++ linux20/drivers/scsi/53c7xx.c	Mon Nov  9 11:17:05 1998
@@ -2,7 +2,7 @@
  * 53c710 driver.  Modified from Drew Eckhardts driver
  * for 53c810 by Richard Hirst [richard@sleepie.demon.co.uk]
  * Check out PERM_OPTIONS and EXPECTED_CLOCK, which may be defined in the
- * relevant machine specific file (eg. mvme166.[ch], amiga7xx.[ch]).
+ * relevant machine specific file (eg. mvme16x.[ch], amiga7xx.[ch]).
  * There are also currently some defines at the top of 53c7xx.scr.
  * The chip type is #defined in script_asm.pl, as well as the Makefile.
  * Host scsi ID expected to be 7 - see NCR53c7x0_init().
@@ -10,9 +10,9 @@
  * I have removed the PCI code and some of the 53c8xx specific code - 
  * simply to make this file smaller and easier to manage.
  *
- * MVME166 issues:
+ * MVME16x issues:
  *   Problems trying to read any chip registers in NCR53c7x0_init(), as they
- *   may never have been set by 166Bug (eg. If kernel has come in over tftp).
+ *   may never have been set by 16xBug (eg. If kernel has come in over tftp).
  */
 
 /*
@@ -40,11 +40,15 @@
  *
  * Options for the NCR7xx driver
  *
- * nosync:0		-	disables synchronous negotiation
+ * noasync:0		-	disables sync and asynchronous negotiation
+ * nosync:0		-	disables synchronous negotiation (does async)
  * nodisconnect:0	-	disables disconnection
  * validids:0x??	-	Bitmask field that disallows certain ID's.
  *			-	e.g.	0x03	allows ID 0,1
  *			-		0x1F	allows ID 0,1,2,3,4
+ * opthi:n		-	replace top word of options with 'n'
+ * optlo:n		-	replace bottom word of options with 'n'
+ *			-	ALWAYS SPECIFY opthi THEN optlo <<<<<<<<<<
  */
 
 /*
@@ -60,7 +64,7 @@
  *	out brain damaged main boards.
  *
  * Other PERM_OPTIONS settings are listed below.  Note the actual options
- * required are set in the relevant file (mvme166.c, amiga7xx.c, etc):
+ * required are set in the relevant file (mvme16x.c, amiga7xx.c, etc):
  *
  *   OPTION_NO_ASYNC
  *	Don't negotiate for asynchronous transfers on the first command 
@@ -100,8 +104,6 @@
  *  the fourth byte from 50 to 25.
  */
 
-#include <linux/config.h>
-
 /*
  * Sponsored by 
  *	iX Multiuser Multitasking Magazine
@@ -234,6 +236,8 @@
 
 #include <linux/config.h>
 
+#include <linux/types.h>
+#include <asm/setup.h>
 #include <asm/dma.h>
 #include <asm/io.h>
 #include <asm/system.h>
@@ -241,8 +245,6 @@
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/errno.h>
-#include <linux/bios32.h>
-#include <linux/pci.h>
 #include <linux/proc_fs.h>
 #include <linux/string.h>
 #include <linux/malloc.h>
@@ -261,11 +263,22 @@
 #define NO_IO_SPACE
 #endif
 
-#ifdef CONFIG_MVME166
-#include <asm/mvme166hw.h>
+#ifdef CONFIG_MVME16x
+#include <asm/pgtable.h>
+#include <asm/mvme16xhw.h>
+
+#define BIG_ENDIAN
+#define NO_IO_SPACE
+#define VALID_IDS
+#endif
+
+#ifdef CONFIG_BVME6000
+#include <asm/pgtable.h>
+#include <asm/bvme6000hw.h>
 
 #define BIG_ENDIAN
 #define NO_IO_SPACE
+#define VALID_IDS
 #endif
 
 #include "scsi.h"
@@ -276,10 +289,14 @@
 #include <linux/stat.h>
 #include <linux/stddef.h>
 
+#if (PAGE_SIZE != 4096)
+#error "This driver doesn't work on non 4K PAGE machines"
+#endif
+
 #ifdef NO_IO_SPACE
 /*
  * The following make the definitions in 53c7xx.h (write8, etc) smaller,
- * we don't have seperate i/o space anyway.
+ * we don't have separate i/o space anyway.
  */
 #undef inb
 #undef outb
@@ -309,7 +326,8 @@
 static void abnormal_finished (struct NCR53c7x0_cmd *cmd, int result);
 static int disable (struct Scsi_Host *host);
 static int NCR53c7xx_run_tests (struct Scsi_Host *host);
-void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+static void NCR53c7x0_intr(int irq, void *dev_id, struct pt_regs * regs);
+static void NCR53c7x0_intfly (struct Scsi_Host *host);
 static int ncr_halt (struct Scsi_Host *host);
 static void intr_phase_mismatch (struct Scsi_Host *host, struct NCR53c7x0_cmd 
     *cmd);
@@ -341,7 +359,6 @@
 #ifdef FORCE_DSA_ALIGNMENT
 int CmdPageStart = (0 - Ent_dsa_zero - sizeof(struct NCR53c7x0_cmd)) & 0xff;
 #endif
-int flushsize;
 
 static char *setup_strings[] =
 	{"","","","","","","",""};
@@ -638,6 +655,7 @@
     EXTENDED_MESSAGE, 2 /* length */, EXTENDED_WDTR, 1 /* 2^1 bytes */
 };
 
+#if 0
 /*
  * Function : struct Scsi_Host *find_host (int host)
  * 
@@ -663,6 +681,7 @@
     return h;
 }
 
+#if 0
 /*
  * Function : request_synchronous (int host, int target)
  * 
@@ -697,7 +716,7 @@
 	    h->max_id);
 	return -1;
     }
-    hostdata = (struct NCR53c7x0_hostdata *)h->hostdata;
+    hostdata = (struct NCR53c7x0_hostdata *)h->hostdata[0];
 
     save_flags(flags);
     cli();
@@ -710,6 +729,7 @@
     restore_flags(flags);
     return 0;
 }
+#endif
 
 /*
  * Function : request_disconnect (int host, int on_or_off)
@@ -729,13 +749,14 @@
     struct NCR53c7x0_hostdata *hostdata;
     if (!(h = find_host (host)))
 	return -1;
-    hostdata = (struct NCR53c7x0_hostdata *) h->hostdata;
+    hostdata = (struct NCR53c7x0_hostdata *) h->hostdata[0];
     if (on_or_off) 
 	hostdata->options |= OPTION_DISCONNECT;
     else
 	hostdata->options &= ~OPTION_DISCONNECT;
     return 0;
 }
+#endif
 
 /*
  * Function : static void NCR53c7x0_driver_init (struct Scsi_Host *host)
@@ -749,7 +770,7 @@
 static void 
 NCR53c7x0_driver_init (struct Scsi_Host *host) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     int i, j;
     u32 *ncrcurrent;
 
@@ -781,8 +802,6 @@
     	hostdata->initiate_sdtr = 0;
     hostdata->talked_to = 0;
     hostdata->idle = 1;
-
-    cache_push(virt_to_bus(hostdata->script), flushsize);
 }
 
 /* 
@@ -830,8 +849,7 @@
     int i, ccf;
     unsigned char revision;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
-    struct Scsi_Host *search;
+	host->hostdata[0];
     /* 
      * There are some things which we need to know about in order to provide
      * a semblance of support.  Print 'em if they aren't what we expect, 
@@ -849,16 +867,23 @@
 #else
     int expected_mapping = OPTION_IO_MAPPED;
 #endif
+    unsigned long irq;
+
     for (i=0;i<7;i++)
 	hostdata->valid_ids[i] = 1;	/* Default all ID's to scan */
 
     /* Parse commandline flags */
-    if (check_setup_strings("nosync",&flags,&val,buf))
+    if (check_setup_strings("noasync",&flags,&val,buf))
     {
 	hostdata->options |= OPTION_NO_ASYNC;
 	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
     }
 
+    if (check_setup_strings("nosync",&flags,&val,buf))
+    {
+	hostdata->options &= ~(OPTION_SYNCHRONOUS | OPTION_ALWAYS_SYNCHRONOUS);
+    }
+
     if (check_setup_strings("nodisconnect",&flags,&val,buf))
 	hostdata->options &= ~OPTION_DISCONNECT;
 
@@ -874,18 +899,22 @@
 		setup_used[--i] = 1;
     }
 
+    if (check_setup_strings("opthi",&flags,&val,buf))
+	hostdata->options = (long long)val << 32;
+    if (check_setup_strings("optlo",&flags,&val,buf))
+	hostdata->options |= val;
 
     NCR53c7x0_local_setup(host);
-
     switch (hostdata->chip) {
     case 710:
+    case 770:
     	hostdata->dstat_sir_intr = NCR53c7x0_dstat_sir_intr;
     	hostdata->init_save_regs = NULL;
     	hostdata->dsa_fixup = NCR53c7xx_dsa_fixup;
     	hostdata->init_fixup = NCR53c7x0_init_fixup;
     	hostdata->soft_reset = NCR53c7x0_soft_reset;
 	hostdata->run_tests = NCR53c7xx_run_tests;
-	expected_clock = hostdata->scsi_clock = 50000000;
+	expected_clock = hostdata->scsi_clock;
 	expected_id = 7;
     	break;
     default:
@@ -901,7 +930,6 @@
     hostdata->NCR53c7xx_msg_abort = ABORT;
     hostdata->NCR53c7xx_msg_nop = NOP;
     hostdata->NOP_insn = (DCMD_TYPE_TCI|DCMD_TCI_OP_JUMP) << 24;
-
     if (expected_mapping == -1 || 
 	(hostdata->options & (OPTION_MEMORY_MAPPED)) != 
 	(expected_mapping & OPTION_MEMORY_MAPPED))
@@ -914,6 +942,12 @@
     hostdata->istat = ((hostdata->chip / 100) == 8) ? 
     	ISTAT_REG_800 : ISTAT_REG_700;
 
+/* We have to assume that this may be the first access to the chip, so
+ * we must set EA in DCNTL. */
+
+    NCR53c7x0_write8 (DCNTL_REG, DCNTL_10_EA|DCNTL_10_COM);
+
+
 /* Only the ISTAT register is readable when the NCR is running, so make 
    sure it's halted. */
     ncr_halt(host);
@@ -962,32 +996,29 @@
      * default value may not be optimal anyway.
      * Even worse, it may never have been set up since reset.
      */
-	hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE;
-	revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4;
-	switch (revision) {
-		case 1:
-			revision = 0;
-			break;
-		case 2:
-			revision = 1;
-			break;
-		case 4: 
-			revision = 2;
-			break;
-		case 8:
-			revision = 3;
-			break;
-		default:
-			revision = 255;
-			break;
-	}
-	printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
+    hostdata->saved_ctest7 = NCR53c7x0_read8(CTEST7_REG) & CTEST7_SAVE;
+    revision = (NCR53c7x0_read8(CTEST8_REG) & 0xF0) >> 4;
+    switch (revision) {
+	case 1: revision = 0;    break;
+	case 2: revision = 1;    break;
+	case 4: revision = 2;    break;
+	case 8: revision = 3;    break;
+	default: revision = 255; break;
+    }
+    printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
+
+    if ((revision == 0 || revision == 255) && (hostdata->options & (OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS)))
+    {
+	printk ("scsi%d: Disabling sync working and disconnect/reselect\n",
+							host->host_no);
+	hostdata->options &= ~(OPTION_SYNCHRONOUS|OPTION_DISCONNECT|OPTION_ALWAYS_SYNCHRONOUS);
+    }
 
     /*
      * On NCR53c700 series chips, DCNTL controls the SCSI clock divisor,
      * on 800 series chips, it allows for a totem-pole IRQ driver.
      * NOTE saved_dcntl currently overwritten in init function.
-     * The value read here may be garbage anyway, MVME166 board at least
+     * The value read here may be garbage anyway, MVME16x board at least
      * does not initialise chip if kernel arrived via tftp.
      */
 
@@ -996,7 +1027,7 @@
     /*
      * DMODE controls DMA burst length, and on 700 series chips,
      * 286 mode and bus width  
-     * NOTE:  On MVME166, chip may have been reset, so this could be a
+     * NOTE:  On MVME16x, chip may have been reset, so this could be a
      * power-on/reset default value.
      */
     hostdata->saved_dmode = NCR53c7x0_read8(hostdata->dmode);
@@ -1045,42 +1076,19 @@
 
     NCR53c7x0_driver_init (host);
 
-    /*
-     * Set up an interrupt handler if we aren't already sharing an IRQ
-     * with another board.
-     */
-
-#ifdef CONFIG_MVME166
-    if (request_irq(IRQ_MVME166_SCSI, NCR53c7x0_intr, 0, "SCSI-script", NULL))
-	panic ("Couldn't get SCSI IRQ");
-#ifdef MVME166_INTFLY
-    else if (request_irq(IRQ_MVME166_FLY, NCR53c7x0_intr, 0, "SCSI-intfly", NULL))
-	panic ("Couldn't get INT_FLY IRQ");
-#endif
-#else
-    for (search = first_host; search && !(search->hostt == the_template &&
-	search->irq == host->irq && search != host); search=search->next);
-
-    if (!search) {
+    irq = host->irq;
 #ifdef CONFIG_AMIGA
-	if (request_irq(host->irq | IRQ_MACHSPEC, NCR53c7x0_intr, 0, "53c7xx", NCR53c7x0_intr)) {
-#else
-	if (request_irq(host->irq, NCR53c7x0_intr, SA_INTERRUPT, "53c7xx", NULL)) {
+    if (MACH_IS_AMIGA)
+	    irq |= IRQ_MACHSPEC;
 #endif
-	    printk("scsi%d : IRQ%d not free, detaching\n"
-	           "         You have either a configuration problem, or a\n"
-                   "         broken BIOS.  You may wish to manually assign\n"
-	           "         an interrupt to the NCR board rather than using\n"
-                   "         an automatic setting.\n", 
+
+    if (request_irq(irq, NCR53c7x0_intr, 0, "53c7xx", host))
+    {
+	printk("scsi%d : IRQ%d not free, detaching\n",
 		host->host_no, host->irq);
-	    scsi_unregister (host);
-	    return -1;
-	} 
-    } else {
-	printk("scsi%d : using interrupt handler previously installed for scsi%d\n",
-	    host->host_no, search->host_no);
-    }
-#endif
+	scsi_unregister (host);
+	return -1;
+    } 
 
     if ((hostdata->run_tests && hostdata->run_tests(host) == -1) ||
         (hostdata->options & OPTION_DEBUG_TESTS_ONLY)) {
@@ -1102,18 +1110,13 @@
 }
 
 /* 
- * Function : static int normal_init(Scsi_Host_Template *tpnt, int board, 
- *	int chip, u32 base, int io_port, int irq, int dma, int pcivalid,
- *	unsigned char pci_bus, unsigned char pci_device_fn,
- *	long long options);
+ * Function : static int ncr53c7xx_init(Scsi_Host_Template *tpnt, int board, 
+ *	int chip, u32 base, int io_port, int irq, int dma, long long options,
+ *	int clock);
  *
  * Purpose : initializes a NCR53c7,8x0 based on base addresses,
  *	IRQ, and DMA channel.	
  *	
- *	Useful where a new NCR chip is backwards compatible with
- *	a supported chip, but the DEVICE ID has changed so it 
- *	doesn't show up when the autoprobe does a pcibios_find_device.
- *
  * Inputs : tpnt - Template for this SCSI adapter, board - board level
  *	product, chip - 710
  * 
@@ -1203,20 +1206,27 @@
     */
     size += 256;
 #endif
-	flushsize = size;
-    instance = scsi_register (tpnt, size);
+    /* Size should be < 8K, so we can fit it in two pages. */
+    if (size > 16384)
+      panic("53c7xx: hostdata > 16K");
+    instance = scsi_register (tpnt, 4);
     if (!instance)
 	return -1;
+    instance->hostdata[0] = __get_free_pages(GFP_ATOMIC, 2, 1);
+    if (instance->hostdata[0] == 0)
+        panic ("53c7xx: Couldn't get hostdata memory");
+    memset((void *)instance->hostdata[0], 0, 16384);
+    cache_push(virt_to_phys((void *)(instance->hostdata[0])), 16384);
+    cache_clear(virt_to_phys((void *)(instance->hostdata[0])), 16384);
+    kernel_set_cachemode(instance->hostdata[0], 16384, KERNELMAP_NOCACHE_SER);
 
     /* FIXME : if we ever support an ISA NCR53c7xx based board, we
        need to check if the chip is running in a 16 bit mode, and if so 
        unregister it if it is past the 16M (0x1000000) mark */
-   	
-    hostdata = (struct NCR53c7x0_hostdata *) 
-    	instance->hostdata;
+
+    hostdata = (struct NCR53c7x0_hostdata *)instance->hostdata[0];
     hostdata->size = size;
     hostdata->script_count = script_len / sizeof(u32);
-    hostdata = (struct NCR53c7x0_hostdata *) instance->hostdata;
     hostdata->board = board;
     hostdata->chip = chip;
 
@@ -1266,6 +1276,7 @@
     hostdata->dsa_len = dsa_len;
     hostdata->max_cmd_size = max_cmd_size;
     hostdata->num_cmds = 1;
+    hostdata->scsi_clock = clock;
     /* Initialize single command */
     tmp = (hostdata->script + hostdata->script_count);
 #ifdef FORCE_DSA_ALIGNMENT
@@ -1275,10 +1286,12 @@
 	    t = (void *)((u32)t + 255);
 	t = (void *)(((u32)t & ~0xff) + CmdPageStart);
         hostdata->free = t;
+#if 0
 	printk ("scsi: Registered size increased by 256 to %d\n", size);
 	printk ("scsi: CmdPageStart = 0x%02x\n", CmdPageStart);
 	printk ("scsi: tmp = 0x%08x, hostdata->free set to 0x%08x\n",
 			(u32)tmp, (u32)t);
+#endif
     }
 #else
     hostdata->free = ROUNDUP(tmp, void *);
@@ -1333,7 +1346,7 @@
 NCR53c7x0_init_fixup (struct Scsi_Host *host) {
     NCR53c7x0_local_declare();
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     unsigned char tmp;
     int i, ncr_to_memory, memory_to_ncr;
     u32 base;
@@ -1390,8 +1403,8 @@
      * register.  Make sure SCRIPTS start automagically.
      */
 
-#if defined(CONFIG_MVME166)
-    /* We know better what we want than 166Bug does! */
+#if defined(CONFIG_MVME16x) || defined(CONFIG_BVME6000)
+    /* We know better what we want than 16xBug does! */
     tmp = DMODE_10_BL_8 | DMODE_10_FC2;
 #else
     tmp = NCR53c7x0_read8(DMODE_REG_10);
@@ -1540,8 +1553,6 @@
 
     printk("scsi%d : NCR code relocated to 0x%lx (virt 0x%p)\n", host->host_no,
 	virt_to_bus(hostdata->script), hostdata->script);
-
-    cache_push(virt_to_bus(hostdata->script), flushsize);
 }
 
 /*
@@ -1563,7 +1574,7 @@
 NCR53c7xx_run_tests (struct Scsi_Host *host) {
     NCR53c7x0_local_declare();
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     unsigned long timeout;
     u32 start;
     int failed, i;
@@ -1595,13 +1606,12 @@
 	start = virt_to_bus (hostdata->script) + hostdata->E_test_1;
     	hostdata->state = STATE_RUNNING;
 	printk ("scsi%d : test 1", host->host_no);
-	cache_push(virt_to_bus(hostdata->script), flushsize);
 	NCR53c7x0_write32 (DSP_REG, start);
 	if (hostdata->options & OPTION_DEBUG_TRACE)
 	    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl | DCNTL_SSM |
 						DCNTL_STD);
 	printk (" started\n");
-	sti();
+	restore_flags(flags);
 
 	/* 
 	 * This is currently a .5 second timeout, since (in theory) no slow 
@@ -1689,13 +1699,12 @@
 	    hostdata->test_completed = -1;
 	    start = virt_to_bus(hostdata->script) + hostdata->E_test_2;
 	    hostdata->state = STATE_RUNNING;
-	    cache_clear(virt_to_bus(hostdata->script), flushsize);
 	    NCR53c7x0_write32 (DSA_REG, virt_to_bus(dsa));
 	    NCR53c7x0_write32 (DSP_REG, start);
 	    if (hostdata->options & OPTION_DEBUG_TRACE)
 	        NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
 				DCNTL_SSM | DCNTL_STD);
-	    sti();
+	    restore_flags(flags);
 
 	    timeout = jiffies + 5 * HZ;	/* arbitrary */
 	    while ((hostdata->test_completed == -1) && jiffies < timeout)
@@ -1748,7 +1757,7 @@
     Scsi_Cmnd *c = cmd->cmd;
     struct Scsi_Host *host = c->host;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata;
+    	host->hostdata[0];
     int i;
 
     memcpy (cmd->dsa, hostdata->script + (hostdata->E_dsa_code_template / 4),
@@ -1795,9 +1804,6 @@
 
     patch_abs_32 (cmd->dsa, Ent_dsa_code_template / sizeof(u32),
 	dsa_temp_addr_dsa_value, virt_to_bus(&cmd->dsa_addr));
-
-    cache_push(virt_to_bus(hostdata->script), flushsize);
-    cache_push(virt_to_bus(cmd->dsa), flushsize);
 }
 
 /* 
@@ -1849,7 +1855,7 @@
     Scsi_Cmnd *c = cmd->cmd;
     struct Scsi_Host *host = c->host;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata;
+    	host->hostdata[0];
     unsigned long flags;
     int left, found;
     volatile struct NCR53c7x0_cmd * linux_search;
@@ -1969,7 +1975,7 @@
 #endif
     u32 *dsp;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;		
+	host->hostdata[0];		
     unsigned long flags;
     NCR53c7x0_local_setup(host);
 
@@ -2049,7 +2055,7 @@
     int now_connected) {
     NCR53c7x0_local_declare();
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *) 
-	host->hostdata;
+	host->hostdata[0];
     u32 *script;
     NCR53c7x0_local_setup(host);
 
@@ -2124,7 +2130,7 @@
 asynchronous (struct Scsi_Host *host, int target) {
     NCR53c7x0_local_declare();
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     NCR53c7x0_local_setup(host);
     set_synchronous (host, target, /* no offset */ 0, hostdata->saved_scntl3,
 	1);
@@ -2183,7 +2189,7 @@
 static void 
 synchronous (struct Scsi_Host *host, int target, char *msg) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     int desire, divisor, i, limit;
     unsigned char scntl3, sxfer;
 /* The diagnostic message fits on one line, even with max. width integers */
@@ -2245,13 +2251,23 @@
     int print;
     Scsi_Cmnd *c = cmd ? cmd->cmd : NULL;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;		
+	host->hostdata[0];		
     u32 dsps,*dsp;	/* Argument of the INT instruction */
 
     NCR53c7x0_local_setup(host);
     dsps = NCR53c7x0_read32(DSPS_REG);
     dsp = (u32 *) bus_to_virt(NCR53c7x0_read32(DSP_REG));
 
+    /* RGH 150597:  Frig.  Commands which fail with Check Condition are
+     * Flagged as successful - hack dsps to indicate check condition */
+#if 0
+    /* RGH 200597:  Need to disable for BVME6000, as it gets Check Conditions
+     * and then dies.  Seems to handle Check Condition at startup, but
+     * not mid kernel build. */
+    if (dsps == A_int_norm_emulateintfly && cmd && cmd->result == 2)
+        dsps = A_int_err_check_condition;
+#endif
+
     if (hostdata->options & OPTION_DEBUG_INTR) 
 	printk ("scsi%d : DSPS = 0x%x\n", host->host_no, dsps);
 
@@ -2427,12 +2443,23 @@
 
     	patch_dsa_32 (cmd->dsa, dsa_cmdout, 0, 6);
 
-	c->cmnd[0] = REQUEST_SENSE;
-	c->cmnd[1] &= 0xe0;	/* Zero all but LUN */
-	c->cmnd[2] = 0;
-	c->cmnd[3] = 0;
-	c->cmnd[4] = sizeof(c->sense_buffer);
-	c->cmnd[5] = 0; 
+        /*
+         * The CDB is now mirrored in our local non-cached
+         * structure, but keep the old structure up to date as well,
+         * just in case anyone looks at it.
+         */
+
+	/*
+	 * XXX Need to worry about data buffer alignment/cache state
+	 * XXX here, but currently never get A_int_err_check_condition,
+	 * XXX so ignore problem for now.
+         */
+	cmd->cmnd[0] = c->cmnd[0] = REQUEST_SENSE;
+	cmd->cmnd[0] = c->cmnd[1] &= 0xe0;	/* Zero all but LUN */
+	cmd->cmnd[0] = c->cmnd[2] = 0;
+	cmd->cmnd[0] = c->cmnd[3] = 0;
+	cmd->cmnd[0] = c->cmnd[4] = sizeof(c->sense_buffer);
+	cmd->cmnd[0] = c->cmnd[5] = 0; 
 
 	/*
 	 * Disable dataout phase, and program datain to transfer to the 
@@ -2460,7 +2487,7 @@
 	 * status, etc are used.
     	 */
 
-	cmd->cmd->result = 0xffff;		
+	cmd->result = cmd->cmd->result = 0xffff;		
 
 	/* 
 	 * Restart command as a REQUEST SENSE.
@@ -2478,18 +2505,7 @@
 	    abnormal_finished (cmd, DID_ERROR << 16);
 	return SPECIFIC_INT_NOTHING;
     case A_int_norm_emulateintfly:
-	/* I'm not sure this is the right ! thing to do, but it works
-	 * with the A4000T when copyback is disabled, and also the
-	 * WarpEngine with copyback enabled, so it looks as though
-	 * it does work to some extent.
-	 *
-	 * RGH:  I don't really like it - You get an interrupt which
-	 * calls NCR53c7x0_intr(), which calls this function (via
-	 * intr_dma()), which calls NCR53c7x0_intr().....
-	 * Anyway lets see how it goes for now.
-	 */
-	hostdata->emulated_intfly = 1;
-	NCR53c7x0_intr(host->irq, NULL, NULL);
+	NCR53c7x0_intfly(host);
 	return SPECIFIC_INT_NOTHING;
     case A_int_test_1:
     case A_int_test_2:
@@ -2856,8 +2872,6 @@
 	    host->host_no, (unsigned) dsps);
 	return SPECIFIC_INT_PANIC;
     }
-
-    flush_cache_all();
 }
 
 /* 
@@ -2895,11 +2909,8 @@
 NCR53c7x0_soft_reset (struct Scsi_Host *host) {
     NCR53c7x0_local_declare();
     unsigned long flags;
-#ifdef CONFIG_MVME166
-    volatile unsigned long v;
-#endif
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     NCR53c7x0_local_setup(host);
 
     save_flags(flags);
@@ -2907,16 +2918,20 @@
 
     /* Disable scsi chip and s/w level 7 ints */
 
-#ifdef CONFIG_MVME166
-    v = *(volatile unsigned long *)0xfff4006c;
-    v &= ~0x8000;
-    *(volatile unsigned long *)0xfff4006c = v;
-    v = *(volatile unsigned long *)0xfff4202c;
-    v &= ~0x10;
-    *(volatile unsigned long *)0xfff4202c = v;
-#else
-    /* Anything specific for your hardware? */
+#ifdef CONFIG_MVME16x
+    if (MACH_IS_MVME16x)
+    {
+        volatile unsigned long v;
+
+        v = *(volatile unsigned long *)0xfff4006c;
+        v &= ~0x8000;
+        *(volatile unsigned long *)0xfff4006c = v;
+        v = *(volatile unsigned long *)0xfff4202c;
+        v &= ~0x10;
+        *(volatile unsigned long *)0xfff4202c = v;
+    }
 #endif
+    /* Anything specific for your hardware? */
 
     /*
      * Do a soft reset of the chip so that everything is 
@@ -2982,21 +2997,24 @@
 	    SIEN_PAR : 0) | SIEN_700_STO | SIEN_RST | SIEN_UDC |
 		SIEN_SGE | SIEN_MA);
 
-#ifdef CONFIG_MVME166
-    /* Enable scsi chip and s/w level 7 ints */
+#ifdef CONFIG_MVME16x
+    if (MACH_IS_MVME16x)
+    {
+        volatile unsigned long v;
 
-    v = *(volatile unsigned long *)0xfff40080;
-    v = (v & ~(0xf << 28)) | (4 << 28);
-    *(volatile unsigned long *)0xfff40080 = v;
-    v = *(volatile unsigned long *)0xfff4006c;
-    v |= 0x8000;
-    *(volatile unsigned long *)0xfff4006c = v;
-    v = *(volatile unsigned long *)0xfff4202c;
-    v = (v & ~0xff) | 0x10 | 4;
-    *(volatile unsigned long *)0xfff4202c = v;
-#else
-    /* Anything needed for your hardware */
+        /* Enable scsi chip and s/w level 7 ints */
+        v = *(volatile unsigned long *)0xfff40080;
+        v = (v & ~(0xf << 28)) | (4 << 28);
+        *(volatile unsigned long *)0xfff40080 = v;
+        v = *(volatile unsigned long *)0xfff4006c;
+        v |= 0x8000;
+        *(volatile unsigned long *)0xfff4006c = v;
+        v = *(volatile unsigned long *)0xfff4202c;
+        v = (v & ~0xff) | 0x10 | 4;
+        *(volatile unsigned long *)0xfff4202c = v;
+    }
 #endif
+    /* Anything needed for your hardware? */
     restore_flags(flags);
 }
 
@@ -3009,7 +3027,7 @@
  *
  * Side effects : If we haven't yet scheduled allocation of NCR53c7x0_cmd
  *	structures for this device, do so.  Attempt to complete all scheduled
- *	allocations using kmalloc(), putting NCR53c7x0_cmd structures on
+ *	allocations using get_free_page(), putting NCR53c7x0_cmd structures on
  *	the free list.  Teach programmers not to drink and hack.
  *
  * Inputs : cmd - SCSI command
@@ -3018,12 +3036,23 @@
  *	NULL on failure.
  */
 
+static void
+my_free_page (void *addr, int dummy)
+{
+    /* XXX This assumes default cache mode to be KERNELMAP_FULL_CACHING, which
+     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
+     */
+    kernel_set_cachemode((u32)addr, 8192, KERNELMAP_FULL_CACHING);
+    free_page ((u32)addr);
+    free_page ((u32)(addr + 4096));
+}
+
 static struct NCR53c7x0_cmd *
 allocate_cmd (Scsi_Cmnd *cmd) {
     struct Scsi_Host *host = cmd->host;
     struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata;
-    void *real;			/* Real address */
+	(struct NCR53c7x0_hostdata *) host->hostdata[0];
+    u32 real;			/* Real address */
     int size;			/* Size of *tmp */
     struct NCR53c7x0_cmd *tmp;
     unsigned long flags;
@@ -3061,28 +3090,31 @@
 	size += 256;
 #endif
 /* FIXME: for ISA bus '7xx chips, we need to or GFP_DMA in here */
-	real = kmalloc (size, GFP_ATOMIC);
-	if (!real) {
-	    if (hostdata->options & OPTION_DEBUG_ALLOCATION)
-		printk ("scsi%d : kmalloc(%d) failed\n",
-		    host->host_no, size);
-	    break;
-	}
+
+        if (size > 8192)
+            panic ("53c7xx: allocate_cmd size > 8K");
+        real = __get_free_pages(GFP_ATOMIC, 1, 1);
+        if (real == 0)
+            panic ("53c7xx: Couldn't get memory for allocate_cmd");
+        memset((void *)real, 0, 8192);
+        cache_push(virt_to_phys((void *)real), 8192);
+        cache_clear(virt_to_phys((void *)real), 8192);
+        kernel_set_cachemode(real, 8192, KERNELMAP_NOCACHE_SER);
 	tmp = ROUNDUP(real, void *);
 #ifdef FORCE_DSA_ALIGNMENT
 	{
 	    if (((u32)tmp & 0xff) > CmdPageStart)
 		tmp = (struct NCR53c7x0_cmd *)((u32)tmp + 255);
 	    tmp = (struct NCR53c7x0_cmd *)(((u32)tmp & ~0xff) + CmdPageStart);
-#ifdef DEBUG
+#if 0
 	    printk ("scsi: size = %d, real = 0x%08x, tmp set to 0x%08x\n",
-			size, (u32)real, (u32)tmp);
+			size, real, (u32)tmp);
 #endif
 	}
 #endif
-	tmp->real = real;
+	tmp->real = (void *)real;
 	tmp->size = size;			
-	tmp->free = ((void (*)(void *, int)) kfree);
+	tmp->free = ((void (*)(void *, int)) my_free_page);
 	save_flags (flags);
 	cli();
 	tmp->next = hostdata->free;
@@ -3120,7 +3152,7 @@
     NCR53c7x0_local_declare();
     struct Scsi_Host *host = cmd->host;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-        host->hostdata;	
+        host->hostdata[0];	
     struct NCR53c7x0_cmd *tmp; 	/* NCR53c7x0_cmd structure for this command */
     int datain,  		/* Number of instructions per phase */
 	dataout;
@@ -3139,6 +3171,14 @@
     if (!(tmp = allocate_cmd (cmd)))
 	return NULL;
 
+    /*
+     * Copy CDB and initialised result fields from Scsi_Cmnd to NCR53c7x0_cmd.
+     * We do this because NCR53c7x0_cmd may have a special cache mode
+     * selected to cope with lack of bus snooping, etc.
+     */
+
+    memcpy(tmp->cmnd, cmd->cmnd, 12);
+    tmp->result = cmd->result;
 
     /*
      * Decide whether we need to generate commands for DATA IN,
@@ -3153,6 +3193,8 @@
     case READ_10:
     case READ_CAPACITY:
     case REQUEST_SENSE:
+    case READ_BLOCK_LIMITS:
+    case READ_TOC:
 	datain = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
     	dataout = 0;
 	break;
@@ -3180,13 +3222,17 @@
      * interrupt if a data phase is attempted on them.
      */
     case TEST_UNIT_READY:
+    case ALLOW_MEDIUM_REMOVAL:
     	datain = dataout = 0;
 	break;
     /*
      * We don't know about these commands, so generate code to handle
-     * both DATA IN and DATA OUT phases.
+     * both DATA IN and DATA OUT phases.  More efficient to identify them
+     * and add them to the above cases.
      */
     default:
+	printk("scsi%d : datain+dataout for command ", host->host_no);
+	print_command(cmd->cmnd);
 	datain = dataout = 2 * (cmd->use_sg ? cmd->use_sg : 1) + 3;
     }
 
@@ -3268,6 +3314,10 @@
     	hostdata->dsa_fixup(tmp);
 
     patch_dsa_32(tmp->dsa, dsa_next, 0, 0);
+    /*
+     * XXX is this giving 53c710 access to the Scsi_Cmnd in some way?
+     * Do we need to change it for caching reasons?
+     */
     patch_dsa_32(tmp->dsa, dsa_cmnd, 0, virt_to_bus(cmd));
 
     if (hostdata->options & OPTION_DEBUG_SYNCHRONOUS) {
@@ -3329,7 +3379,7 @@
 	IDENTIFY (1, cmd->lun) : IDENTIFY (0, cmd->lun);
     patch_dsa_32(tmp->dsa, dsa_msgout, 1, virt_to_bus(tmp->select));
     patch_dsa_32(tmp->dsa, dsa_cmdout, 0, cmd->cmd_len);
-    patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(cmd->cmnd));
+    patch_dsa_32(tmp->dsa, dsa_cmdout, 1, virt_to_bus(tmp->cmnd));
     patch_dsa_32(tmp->dsa, dsa_dataout, 0, cmd_dataout ? 
     	    virt_to_bus (cmd_dataout)
 	: virt_to_bus (hostdata->script) + hostdata->E_other_transfer);
@@ -3347,13 +3397,13 @@
  *	structure, and assign them to cmd->result when we're done.
  */
 #ifdef BIG_ENDIAN
-    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&cmd->result) + 2);
+    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 2);
     patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
-    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&cmd->result) + 3);
+    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result) + 3);
 #else
-    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&cmd->result) + 1);
+    patch_dsa_32(tmp->dsa, dsa_msgin, 1, virt_to_bus(&tmp->result) + 1);
     patch_dsa_32(tmp->dsa, dsa_status, 0, 1);
-    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&cmd->result));
+    patch_dsa_32(tmp->dsa, dsa_status, 1, virt_to_bus(&tmp->result));
 #endif
     patch_dsa_32(tmp->dsa, dsa_msgout_other, 0, 1);
     patch_dsa_32(tmp->dsa, dsa_msgout_other, 1, 
@@ -3397,16 +3447,58 @@
  * Not bad, not good. We'll see.
  */
 
+    tmp->bounce.len = 0;	/* Assume aligned buffer */
+
     for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; cmd_datain += 4, 
 	cmd_dataout += 4, ++i) {
-	u32 buf = cmd->use_sg ? 
-	    virt_to_bus(((struct scatterlist *)cmd->buffer)[i].address) :
-	    virt_to_bus(cmd->request_buffer);
+	u32 vbuf = cmd->use_sg ? 
+	    (u32)(((struct scatterlist *)cmd->buffer)[i].address) :
+	    (u32)(cmd->request_buffer);
+	u32 bbuf = virt_to_bus((void *)vbuf);
 	u32 count = cmd->use_sg ?
 	    ((struct scatterlist *)cmd->buffer)[i].length :
 	    cmd->request_bufflen;
 
+	/*
+	 * If we have buffers which are not aligned with 16 byte cache
+	 * lines, then we just hope nothing accesses the other parts of
+	 * those cache lines while the transfer is in progress.  That would
+	 * fill the cache, and subsequent reads of the dma data would pick
+	 * up the wrong thing.
+	 * XXX We need a bounce buffer to handle that correctly.
+	 */
+
+	if (((bbuf & 15) || (count & 15)) && (datain || dataout))
+	{
+	    /* Bounce buffer needed */
+	    if (cmd->use_sg)
+		printk ("53c7xx: Non-aligned buffer with use_sg\n");
+	    else if (datain && dataout)
+                printk ("53c7xx: Non-aligned buffer with datain && dataout\n");
+            else if (count > 256)
+		printk ("53c7xx: Non-aligned transfer > 256 bytes\n");
+	    else
+	    {
+		    if (datain)
+		    {
+			tmp->bounce.len = count;
+			tmp->bounce.addr = vbuf;
+			bbuf = virt_to_bus(tmp->bounce.buf);
+			tmp->bounce.buf[0] = 0xff;
+			tmp->bounce.buf[1] = 0xfe;
+			tmp->bounce.buf[2] = 0xfd;
+			tmp->bounce.buf[3] = 0xfc;
+	    	    }
+	    	    if (dataout)
+	    	    {
+			memcpy ((void *)tmp->bounce.buf, (void *)vbuf, count);
+			bbuf = virt_to_bus(tmp->bounce.buf);
+		    }
+	    }
+	}
+
 	if (datain) {
+            cache_clear(virt_to_phys((void *)vbuf), count);
 	    /* CALL other_in, WHEN NOT DATA_IN */  
 	    cmd_datain[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL | 
 		DCMD_TCI_IO) << 24) | 
@@ -3416,13 +3508,14 @@
 	    /* MOVE count, buf, WHEN DATA_IN */
 	    cmd_datain[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I | DCMD_BMI_IO) 
     	    	<< 24) | count;
-	    cmd_datain[3] = buf;
+	    cmd_datain[3] = bbuf;
 #if 0
 	    print_insn (host, cmd_datain, "dynamic ", 1);
 	    print_insn (host, cmd_datain + 2, "dynamic ", 1);
 #endif
 	}
 	if (dataout) {
+            cache_push(virt_to_phys((void *)vbuf), count);
 	    /* CALL other_out, WHEN NOT DATA_OUT */
 	    cmd_dataout[0] = ((DCMD_TYPE_TCI | DCMD_TCI_OP_CALL) << 24) | 
 		DBC_TCI_WAIT_FOR_VALID | DBC_TCI_COMPARE_PHASE;
@@ -3431,7 +3524,7 @@
 	    /* MOVE count, buf, WHEN DATA+OUT */
 	    cmd_dataout[2] = ((DCMD_TYPE_BMI | DCMD_BMI_OP_MOVE_I) << 24) 
 		| count;
-	    cmd_dataout[3] = buf;
+	    cmd_dataout[3] = bbuf;
 #if 0
 	    print_insn (host, cmd_dataout, "dynamic ", 1);
 	    print_insn (host, cmd_dataout + 2, "dynamic ", 1);
@@ -3501,7 +3594,7 @@
 NCR53c7xx_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) {
     struct Scsi_Host *host = cmd->host;
     struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata;
+	(struct NCR53c7x0_hostdata *) host->hostdata[0];
     unsigned long flags;
     Scsi_Cmnd *tmp;
 
@@ -3679,8 +3772,6 @@
      * soon as it is idle.
      */
 
-    flush_cache_all();
-
     if (hostdata->idle) {
 	hostdata->idle = 0;
 	hostdata->state = STATE_RUNNING;
@@ -3754,7 +3845,7 @@
 	done = 1;
 	for (host = first_host; host && host->hostt == the_template;
 	    host = host->next) {
-	    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata;
+	    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
 	    cli();
 	    if (hostdata->issue_queue) {
 	    	if (hostdata->state == STATE_DISABLED) {
@@ -3826,7 +3917,7 @@
 intr_scsi (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
     NCR53c7x0_local_declare();
     struct NCR53c7x0_hostdata *hostdata = 
-    	(struct NCR53c7x0_hostdata *) host->hostdata;
+    	(struct NCR53c7x0_hostdata *) host->hostdata[0];
     unsigned char sstat0_sist0, sist1, 		/* Registers */
 	    fatal; 				/* Did a fatal interrupt 
 						   occur ? */
@@ -4017,7 +4108,7 @@
 	struct Scsi_Host *host = first_host;
 
 	while (cnt < 4096) {
-		printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata)->script))/4);
+		printk ("%08x (+%6x): ", insn_log[i], (insn_log[i] - (u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4);
 		if (++i == 4096)
 			i = 0;
 		cnt++;
@@ -4036,282 +4127,235 @@
 }
 #endif
 
+
 /*
- * Function : static void NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
+ * Function : static void NCR53c7x0_intfly (struct Scsi_Host *host)
  *
- * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
- *	the same IRQ line.  
+ * Purpose : Scan command queue for specified host, looking for completed
+ *           commands.
  * 
- * Inputs : Since we're using the SA_INTERRUPT interrupt handler
- *	semantics, irq indicates the interrupt which invoked 
- *	this handler.  
+ * Inputs : Scsi_Host pointer.
  *
- * On the 710 we simualte an INTFLY with a script interrupt, and the
- * script interrupt handler will call back to this function.
+ * 	This is called from the interrupt handler, when a simulated INTFLY
+ * 	interrupt occurs.
  */
 
-void 
-NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) {
+static void
+NCR53c7x0_intfly (struct Scsi_Host *host)
+{
     NCR53c7x0_local_declare();
-    struct Scsi_Host *host;			/* Host we are looking at */
-    unsigned char istat; 			/* Values of interrupt regs */
-    struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata */
+    struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
     struct NCR53c7x0_cmd *cmd,			/* command which halted */
 	**cmd_prev_ptr;
-    u32 *dsa;					/* DSA */
-    int done = 1;				/* Indicates when handler 
-						   should terminate */
-    int interrupted = 0;			/* This HA generated 
-						   an interrupt */
-    int have_intfly;				/* Don't print warning 
-						   messages when we stack
-						   INTFLYs */
     unsigned long flags;				
+    char search_found = 0;			/* Got at least one ? */
 
-#ifdef NCR_DEBUG
-    char buf[80];				/* Debugging sprintf buffer */
-    size_t buflen;				/* Length of same */
-#endif
-
-#if defined(CONFIG_AMIGA)
-    irq = irq & ~IRQ_MACHSPEC;
-
-    custom.intena = IF_PORTS;
-#endif
-
-    do {
-	done = 1;
-	for (host = first_host; host; host = host->next) 
-	    if (host->hostt == the_template
-#if defined(MVME166_INTFLY)
-			/* We have two different interrupts pointing
-			 * at this routine, so remove this check */
-#else
-				&& host->irq == irq
-#endif
-							) {
-    	    NCR53c7x0_local_setup(host);
+    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
+    NCR53c7x0_local_setup(host);
 
-	    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata;
-	    hostdata->dsp_changed = 0;
-	    interrupted = 0;
-	    have_intfly = 0;
-
-	    do {
-		hostdata->dstat_valid = 0;
-		interrupted = 0;
-		/*
-		 * Only read istat once, since reading it again will unstack
-		 * interrupts?
-		 */
-		istat = NCR53c7x0_read8(hostdata->istat);
-
-		if ((hostdata->options & OPTION_INTFLY) && 
-#ifdef MVME166_INTFLY
-                    /* the bit is set which indicates an on-the-fly int */
-                        (*(volatile unsigned long *)0xfff40068 & 0x8000))
-#else
-		    (hostdata->emulated_intfly != 0))
-#endif
-		{
-		    char search_found = 0;	/* Got at least one ? */
-		    done = 0;
-		    interrupted = 1;
+    if (hostdata->options & OPTION_DEBUG_INTR)
+    printk ("scsi%d : INTFLY\n", host->host_no); 
 
-#ifdef MVME166_INTFLY
-                    /* clear the INTFLY bit */
-                    *(volatile unsigned long *)0xfff40074 = 0x8000;
-#endif
+    /*
+    * Traverse our list of running commands, and look
+    * for those with valid (non-0xff ff) status and message
+    * bytes encoded in the result which signify command
+    * completion.
+    */
 
-		    if (hostdata->options & OPTION_DEBUG_INTR)
-			printk ("scsi%d : INTFLY\n", host->host_no); 
+    save_flags(flags);
+    cli();
+restart:
+    for (cmd_prev_ptr = (struct NCR53c7x0_cmd **)&(hostdata->running_list),
+	cmd = (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
+	cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
+    	cmd = (struct NCR53c7x0_cmd *) cmd->next)
+    {
+	Scsi_Cmnd *tmp;
 
-		    /*
-		     * Traverse our list of running commands, and look
-		     * for those with valid (non-0xff ff) status and message
-		     * bytes encoded in the result which signify command
-		     * completion.
-		     */
+	if (!cmd) {
+	    printk("scsi%d : very weird.\n", host->host_no);
+	    break;
+	}
 
+	if (!(tmp = cmd->cmd)) {
+	    printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
+		    host->host_no);
+	    continue;
+	}
+	/* Copy the result over now; may not be complete,
+	 * but subsequent tests may as well be done on
+	 * cached memory.
+	 */
+	tmp->result = cmd->result;
 
-		    save_flags(flags);
-		    cli();
-restart:
-		    for (cmd_prev_ptr = (struct NCR53c7x0_cmd **) 
-			 &(hostdata->running_list), cmd = 
-			 (struct NCR53c7x0_cmd *) hostdata->running_list; cmd ;
-			 cmd_prev_ptr = (struct NCR53c7x0_cmd **) &(cmd->next), 
-    	    	    	 cmd = (struct NCR53c7x0_cmd *) cmd->next) {
-			Scsi_Cmnd *tmp;
-
-			if (!cmd) {
-			    printk("scsi%d : very weird.\n", host->host_no);
-			    break;
-			}
-
-			if (!(tmp = cmd->cmd)) {
-			    printk("scsi%d : weird.  NCR53c7x0_cmd has no Scsi_Cmnd\n",
-				host->host_no);
-				continue;
-			}
-#if 0
-			printk ("scsi%d : looking at result of 0x%x\n",
-			    host->host_no, cmd->cmd->result);
-#endif
-		
-			if (((tmp->result & 0xff) == 0xff) ||
+	if (((tmp->result & 0xff) == 0xff) ||
 			    ((tmp->result & 0xff00) == 0xff00))
-			    continue;
+	    continue;
 
-			search_found = 1;
+	search_found = 1;
 
-			/* Important - remove from list _before_ done is called */
-			if (cmd_prev_ptr)
-			    *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next;
+	if (cmd->bounce.len)
+	    memcpy ((void *)cmd->bounce.addr,
+				(void *)cmd->bounce.buf, cmd->bounce.len);
+
+	/* Important - remove from list _before_ done is called */
+	if (cmd_prev_ptr)
+	    *cmd_prev_ptr = (struct NCR53c7x0_cmd *) cmd->next;
 
-			--hostdata->busy[tmp->target][tmp->lun];
-    	    	    	cmd->next = hostdata->free;
-    	    	    	hostdata->free = cmd;
+	--hostdata->busy[tmp->target][tmp->lun];
+	cmd->next = hostdata->free;
+	hostdata->free = cmd;
 
-    	    	    	tmp->host_scribble = NULL;
+	tmp->host_scribble = NULL;
 
-			if (hostdata->options & OPTION_DEBUG_INTR) {
-			    printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", 
-				host->host_no, tmp->pid, tmp->target, tmp->lun, tmp->result);
-			    print_command (tmp->cmnd);
-			}
+	if (hostdata->options & OPTION_DEBUG_INTR) {
+	    printk ("scsi%d : command complete : pid %lu, id %d,lun %d result 0x%x ", 
+		  host->host_no, tmp->pid, tmp->target, tmp->lun, tmp->result);
+	    print_command (tmp->cmnd);
+	}
 
-#if 0
-			hostdata->options &= ~OPTION_DEBUG_INTR;
-#endif
-			tmp->scsi_done(tmp);
-			goto restart;
+	tmp->scsi_done(tmp);
+	goto restart;
+    }
+    restore_flags(flags);
 
-		    }
-		    restore_flags(flags);
-		   
-		    if (!search_found && !have_intfly)  {
-			printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
+    if (!search_found)  {
+	printk ("scsi%d : WARNING : INTFLY with no completed commands.\n",
 			    host->host_no);
-		    } else if (!have_intfly)  {
-			have_intfly = 1; 
-    		    	run_process_issue_queue();
-		    }
-		}
+    } else {
+	run_process_issue_queue();
+    }
+    return;
+}
 
-		if (hostdata->emulated_intfly)
-		{
-			hostdata->emulated_intfly = 0;
-			return;
-		}
+/*
+ * Function : static void NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs)
+ *
+ * Purpose : handle NCR53c7x0 interrupts for all NCR devices sharing
+ *	the same IRQ line.  
+ * 
+ * Inputs : Since we're using the SA_INTERRUPT interrupt handler
+ *	semantics, irq indicates the interrupt which invoked 
+ *	this handler.  
+ *
+ * On the 710 we simualte an INTFLY with a script interrupt, and the
+ * script interrupt handler will call back to this function.
+ */
 
-		if (istat & (ISTAT_SIP|ISTAT_DIP)) {
-		    done = 0;
-		    interrupted = 1;
-    	    	    hostdata->state = STATE_HALTED;
+static void 
+NCR53c7x0_intr (int irq, void *dev_id, struct pt_regs * regs) {
+    NCR53c7x0_local_declare();
+    struct Scsi_Host *host;			/* Host we are looking at */
+    unsigned char istat; 			/* Values of interrupt regs */
+    struct NCR53c7x0_hostdata *hostdata;	/* host->hostdata[0] */
+    struct NCR53c7x0_cmd *cmd;			/* command which halted */
+    u32 *dsa;					/* DSA */
 
-		    if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) 
-			printk ("scsi%d : SCSI FIFO not empty\n", 
-			    host->host_no);
+#ifdef NCR_DEBUG
+    char buf[80];				/* Debugging sprintf buffer */
+    size_t buflen;				/* Length of same */
+#endif
 
-		    /*
-		     * NCR53c700 and NCR53c700-66 change the current SCSI
-		     * process, hostdata->ncrcurrent, in the Linux driver so
-		     * cmd = hostdata->ncrcurrent.
-		     *
-		     * With other chips, we must look through the commands
-		     * executing and find the command structure which 
-		     * corresponds to the DSA register.
-		     */
-
-		    if (hostdata->options & OPTION_700) {
-			cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent;
-		    } else {
-			dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
-			for (cmd = (struct NCR53c7x0_cmd *) 
-			    hostdata->running_list; cmd &&
-    	    	    	    (dsa + (hostdata->dsa_start / sizeof(u32))) != 
-    	    	    	    	cmd->dsa;
-			    cmd = (struct NCR53c7x0_cmd *)(cmd->next));
-		    }
-		    if (hostdata->options & OPTION_DEBUG_INTR) {
-			if (cmd) {
-			    printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", 
-				host->host_no, cmd->cmd->pid, (int) cmd->cmd->target,
-				(int) cmd->cmd->lun);
-			    print_command (cmd->cmd->cmnd);
-			} else {
-			    printk("scsi%d : no active command\n", host->host_no);
-			}
-		    }
+#if defined(CONFIG_AMIGA)
+    if (MACH_IS_AMIGA)
+        irq = irq & ~IRQ_MACHSPEC;
+#endif
 
-		    if (istat & ISTAT_SIP) {
-			if (hostdata->options & OPTION_DEBUG_INTR) 
-			    printk ("scsi%d : ISTAT_SIP\n", host->host_no);
-			intr_scsi (host, cmd);
-		    }
-		
-		    if (istat & ISTAT_DIP) {
-			if (hostdata->options & OPTION_DEBUG_INTR) 
-			    printk ("scsi%d : ISTAT_DIP\n", host->host_no);
-			intr_dma (host, cmd);
-		    }
+    host     = (struct Scsi_Host *)dev_id;
+    hostdata = (struct NCR53c7x0_hostdata *) host->hostdata[0];
+    NCR53c7x0_local_setup(host);
 
-		    if (!hostdata->dstat_valid) {
-			hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
-			hostdata->dstat_valid = 1;
-		    }
+    /*
+     * Only read istat once per loop, since reading it again will unstack
+     * interrupts
+     */
 
-		    if (!(hostdata->dstat & DSTAT_DFE)) {
-		      printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
-		      /* Really need to check this out for 710 RGH */
-                      NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
-                      while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF);
-		      hostdata->dstat |= DSTAT_DFE;
-		    }
-		}
-	    } while (interrupted);
+    while ((istat = NCR53c7x0_read8(hostdata->istat)) & (ISTAT_SIP|ISTAT_DIP)) {
+	hostdata->dsp_changed = 0;
+	hostdata->dstat_valid = 0;
+    	hostdata->state = STATE_HALTED;
 
+	if (NCR53c7x0_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) 
+	    printk ("scsi%d : SCSI FIFO not empty\n", host->host_no);
 
+	/*
+	 * NCR53c700 and NCR53c700-66 change the current SCSI
+	 * process, hostdata->ncrcurrent, in the Linux driver so
+	 * cmd = hostdata->ncrcurrent.
+	 *
+	 * With other chips, we must look through the commands
+	 * executing and find the command structure which 
+	 * corresponds to the DSA register.
+	 */
 
-	    if (hostdata->intrs != -1)
-		hostdata->intrs++;
-#if 0
-	    if (hostdata->intrs > 40) {
-		printk("scsi%d : too many interrupts, halting", host->host_no);
-		disable(host);
+	if (hostdata->options & OPTION_700) {
+	    cmd = (struct NCR53c7x0_cmd *) hostdata->ncrcurrent;
+	} else {
+	    dsa = bus_to_virt(NCR53c7x0_read32(DSA_REG));
+	    for (cmd = (struct NCR53c7x0_cmd *) hostdata->running_list;
+		cmd && (dsa + (hostdata->dsa_start / sizeof(u32))) != cmd->dsa;
+		    cmd = (struct NCR53c7x0_cmd *)(cmd->next))
+		;
+	}
+	if (hostdata->options & OPTION_DEBUG_INTR) {
+	    if (cmd) {
+		printk("scsi%d : interrupt for pid %lu, id %d, lun %d ", 
+		    host->host_no, cmd->cmd->pid, (int) cmd->cmd->target,
+		    (int) cmd->cmd->lun);
+		print_command (cmd->cmd->cmnd);
+	    } else {
+		printk("scsi%d : no active command\n", host->host_no);
 	    }
-#endif
+	}
+	
+	if (istat & ISTAT_SIP) {
+	    if (hostdata->options & OPTION_DEBUG_INTR) 
+		printk ("scsi%d : ISTAT_SIP\n", host->host_no);
+	    intr_scsi (host, cmd);
+	}
+	
+	if (istat & ISTAT_DIP) {
+	    if (hostdata->options & OPTION_DEBUG_INTR) 
+		printk ("scsi%d : ISTAT_DIP\n", host->host_no);
+	    intr_dma (host, cmd);
+	}
+	
+	if (!hostdata->dstat_valid) {
+	    hostdata->dstat = NCR53c7x0_read8(DSTAT_REG);
+	    hostdata->dstat_valid = 1;
+	}
+	
+	if (!(hostdata->dstat & DSTAT_DFE)) {
+	    printk ("scsi%d : DMA FIFO not empty\n", host->host_no);
+	    /* Really need to check this out for 710 RGH */
+	    NCR53c7x0_write8 (CTEST8_REG, CTEST8_10_CLF);
+	    while (NCR53c7x0_read8 (CTEST8_REG) & CTEST8_10_CLF)
+		;
+	    hostdata->dstat |= DSTAT_DFE;
+	}
 
-	    if (!hostdata->idle && hostdata->state == STATE_HALTED) {
-		if (!hostdata->dsp_changed) {
-		    hostdata->dsp = (u32 *) 
-			bus_to_virt(NCR53c7x0_read32(DSP_REG));
-		}
-			
+	if (!hostdata->idle && hostdata->state == STATE_HALTED) {
+	    if (!hostdata->dsp_changed)
+		hostdata->dsp = (u32 *)bus_to_virt(NCR53c7x0_read32(DSP_REG));
 #if 0
-		printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n",
-		    host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp);
+	    printk("scsi%d : new dsp is 0x%lx (virt 0x%p)\n",
+		host->host_no,  virt_to_bus(hostdata->dsp), hostdata->dsp);
 #endif
 		
-		hostdata->state = STATE_RUNNING;
-		flush_cache_all();
-		NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp));
-		if (hostdata->options & OPTION_DEBUG_TRACE) {
+	    hostdata->state = STATE_RUNNING;
+	    NCR53c7x0_write32 (DSP_REG, virt_to_bus(hostdata->dsp));
+	    if (hostdata->options & OPTION_DEBUG_TRACE) {
 #ifdef CYCLIC_TRACE
-		    log_insn (hostdata->dsp);
+		log_insn (hostdata->dsp);
 #else
-	    	    print_insn (host, hostdata->dsp, "t ", 1);
+	    	print_insn (host, hostdata->dsp, "t ", 1);
 #endif
-		    NCR53c7x0_write8 (DCNTL_REG, hostdata->saved_dcntl |
-				DCNTL_SSM | DCNTL_STD);
-		}
+		NCR53c7x0_write8 (DCNTL_REG,
+			hostdata->saved_dcntl | DCNTL_SSM | DCNTL_STD);
 	    }
 	}
-    } while (!done);
-#ifdef CONFIG_AMIGA
-	custom.intena = IF_SETCLR | IF_PORTS;
-#endif
+    }
 }
 
 
@@ -4333,7 +4377,7 @@
     NCR53c7x0_local_declare();
 #endif
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
 /* FIXME : this probably should change for production kernels; at the 
    least, counter should move to a per-host structure. */
     static int counter = 5;
@@ -4510,7 +4554,7 @@
     u32 dbc_dcmd, *dsp, *dsp_next;
     unsigned char dcmd, sbcl;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-    	host->hostdata;
+    	host->hostdata[0];
     int residual;
     enum {ACTION_ABORT, ACTION_ABORT_PRINT, ACTION_CONTINUE} action = 
 	ACTION_ABORT_PRINT;
@@ -4620,7 +4664,9 @@
 	    where = "non-BMI dynamic DSA code";
 	    action = ACTION_ABORT_PRINT;
 	}
-    } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4)) {
+    } else if (dsp == (hostdata->script + hostdata->E_select_msgout / 4 + 2)) {
+	/* RGH 290697:  Added +2 above, to compensate for the script
+	 * instruction which disables the selection timer. */
 	/* Release ATN */
 	NCR53c7x0_write8 (SOCL_REG, 0);
 	switch (sbcl) {
@@ -4702,8 +4748,6 @@
 	print_insn (host, hostdata->dsp, "", 1);
     }
 #endif
-    
-    cache_push(virt_to_bus(hostdata->script), flushsize);
 }
 
 /*
@@ -4777,7 +4821,7 @@
      */
 
     if (retry == NEVER) {
-    	printk(KERN_ALERT "          mail drew@PoohSticks.ORG\n");
+    	printk(KERN_ALERT "          mail richard@sleepie.demon.co.uk\n");
     	FATAL (host);
     }
 }
@@ -4797,7 +4841,7 @@
 intr_dma (struct Scsi_Host *host, struct NCR53c7x0_cmd *cmd) {
     NCR53c7x0_local_declare();
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     unsigned char dstat;	/* DSTAT */	
     u32 *dsp,
 	*next_dsp,		/* Current dsp */
@@ -5048,7 +5092,7 @@
  * FIXME : (void *) cast in virt_to_bus should be unnecessary, because
  * 	it should take const void * as argument.
  */
-#ifndef CONFIG_MVME166
+#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
 	sprintf(buf, "%s0x%lx (virt 0x%p) : 0x%08x 0x%08x (virt 0x%p)", 
 	    (prefix ? prefix : ""), virt_to_bus((void *) insn), insn,  
 	    insn[0], insn[1], bus_to_virt (insn[1]));
@@ -5056,12 +5100,12 @@
 	/* Remove virtual addresses to reduce output, as they are the same */
 	sprintf(buf, "%s0x%x (+%x) : 0x%08x 0x%08x", 
 	    (prefix ? prefix : ""), (u32)insn, ((u32)insn -
-		(u32)&(((struct NCR53c7x0_hostdata *)host->hostdata)->script))/4, 
+		(u32)&(((struct NCR53c7x0_hostdata *)host->hostdata[0])->script))/4, 
 	    insn[0], insn[1]);
 #endif
 	tmp = buf + strlen(buf);
 	if ((dcmd & DCMD_TYPE_MASK) == DCMD_TYPE_MMI)  {
-#ifndef CONFIG_MVME166
+#if !defined(CONFIG_MVME16x) && !defined(CONFIG_BVME6000)
 	    sprintf (tmp, " 0x%08x (virt 0x%p)\n", insn[2], 
 		bus_to_virt(insn[2]));
 #else
@@ -5103,7 +5147,7 @@
     NCR53c7x0_local_declare();
     struct Scsi_Host *host = cmd->host;
     struct NCR53c7x0_hostdata *hostdata = host ? (struct NCR53c7x0_hostdata *) 
-	host->hostdata : NULL;
+	host->hostdata[0] : NULL;
     unsigned long flags;
     struct NCR53c7x0_cmd *curr, **prev;
     Scsi_Cmnd *me, **last;
@@ -5194,7 +5238,8 @@
          &(curr->next), curr = (struct NCR53c7x0_cmd *) curr->next);
 
     if (curr) {
-	if ((cmd->result & 0xff) != 0xff && (cmd->result & 0xff00) != 0xff00) {
+	if ((curr->result & 0xff) != 0xff && (curr->result & 0xff00) != 0xff00) {
+            cmd->result = curr->result;
 	    if (prev)
 		*prev = (struct NCR53c7x0_cmd *) curr->next;
 	    curr->next = (struct NCR53c7x0_cmd *) hostdata->free;
@@ -5225,13 +5270,14 @@
 	cmd->host_scribble = NULL;
     }
 
-    if (((cmd->result & 0xff00) == 0xff00) ||
-	((cmd->result & 0xff) == 0xff)) {
+    if (curr == NULL || ((curr->result & 0xff00) == 0xff00) ||
+		((curr->result & 0xff) == 0xff)) {
 	printk ("scsi%d : did this command ever run?\n", host->host_no);
-	cmd->result = DID_ABORT << 16;
+	    cmd->result = DID_ABORT << 16;
     } else {
 	printk ("scsi%d : probably lost INTFLY, normal completion\n", 
 	    host->host_no);
+        cmd->result = curr->result;
 /* 
  * FIXME : We need to add an additional flag which indicates if a 
  * command was ever counted as BUSY, so if we end up here we can
@@ -5284,7 +5330,7 @@
     Scsi_Cmnd *nuke_list = NULL;
     struct Scsi_Host *host = cmd->host;
     struct NCR53c7x0_hostdata *hostdata = 
-    	(struct NCR53c7x0_hostdata *) host->hostdata;
+    	(struct NCR53c7x0_hostdata *) host->hostdata[0];
 
     NCR53c7x0_local_setup(host);
     save_flags(flags);
@@ -5322,7 +5368,7 @@
 	disable(host);
     else if (hostdata->resets != -1)
 	--hostdata->resets;
-    sti();
+    restore_flags(flags);
     for (; nuke_list; nuke_list = tmp) {
 	tmp = (Scsi_Cmnd *) nuke_list->SCp.buffer;
     	nuke_list->result = DID_RESET << 16;
@@ -5353,7 +5399,7 @@
 static int 
 insn_to_offset (Scsi_Cmnd *cmd, u32 *insn) {
     struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) cmd->host->hostdata;
+	(struct NCR53c7x0_hostdata *) cmd->host->hostdata[0];
     struct NCR53c7x0_cmd *ncmd = 
 	(struct NCR53c7x0_cmd *) cmd->host_scribble;
     int offset = 0, buffers;
@@ -5422,6 +5468,16 @@
     char *where;
     u32 *ptr;
     NCR53c7x0_local_setup (cmd->host);
+
+    if (check_address ((unsigned long) ncmd,sizeof (struct NCR53c7x0_cmd)) == 0)
+    {
+	printk("\nNCR53c7x0_cmd fields:\n");
+	printk("  bounce.len=0x%x, addr=0x%0x, buf[]=0x%02x %02x %02x %02x\n",
+	    ncmd->bounce.len, ncmd->bounce.addr, ncmd->bounce.buf[0],
+	    ncmd->bounce.buf[1], ncmd->bounce.buf[2], ncmd->bounce.buf[3]);
+	printk("  result=%04x, cdb[0]=0x%02x\n", ncmd->result, ncmd->cmnd[0]);
+    }
+
     for (i = 0; i < 2; ++i) {
 	if (check_address ((unsigned long) ncmd, 
 	    sizeof (struct NCR53c7x0_cmd)) == -1) 
@@ -5459,7 +5515,7 @@
 static void 
 print_dsa (struct Scsi_Host *host, u32 *dsa, const char *prefix) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     int i, len;
     char *ptr;
     Scsi_Cmnd *cmd;
@@ -5501,6 +5557,7 @@
     cmd = (Scsi_Cmnd *) bus_to_virt(dsa[hostdata->dsa_cmnd / sizeof(u32)]);
     printk("        + %d : dsa_cmnd = 0x%x ", hostdata->dsa_cmnd,
 	   (u32) virt_to_bus(cmd));
+    /* XXX Maybe we should access cmd->host_scribble->result here. RGH */
     if (cmd) {
 	printk("               result = 0x%x, target = %d, lun = %d, cmd = ",
 	    cmd->result, cmd->target, cmd->lun);
@@ -5533,7 +5590,7 @@
 static void 
 print_queues (struct Scsi_Host *host) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     u32 *dsa, *next_dsa;
     volatile u32 *ncrcurrent;
     int left;
@@ -5616,7 +5673,7 @@
 print_lots (struct Scsi_Host *host) {
     NCR53c7x0_local_declare();
     struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata;
+	(struct NCR53c7x0_hostdata *) host->hostdata[0];
     u32 *dsp_next, *dsp, *dsa, dbc_dcmd;
     unsigned char dcmd, sbcl;
     int i, size;
@@ -5631,14 +5688,14 @@
 	    
 	/*
 	 * For the 53c710, the following will report value 0 for SCNTL3
-	 * and STEST0 - we dont have these registers.
+	 * and STEST0 - we don't have these registers.
 	 */
     	printk ("scsi%d : DCMD|DBC=0x%x, DNAD=0x%x (virt 0x%p)\n"
 		"         DSA=0x%lx (virt 0x%p)\n"
 	        "         DSPS=0x%x, TEMP=0x%x (virt 0x%p), DMODE=0x%x\n"
 		"         SXFER=0x%x, SCNTL3=0x%x\n"
 		"         %s%s%sphase=%s, %d bytes in SCSI FIFO\n"
-		"         STEST0=0x%x\n",
+		"         SCRATCH=0x%x, saved2_dsa=0x%0lx\n",
 	    host->host_no, dbc_dcmd, NCR53c7x0_read32(DNAD_REG),
 		bus_to_virt(NCR53c7x0_read32(DNAD_REG)),
 	    virt_to_bus(dsa), dsa,
@@ -5655,8 +5712,9 @@
 	    	SSTAT1_REG : SSTAT2_REG)),
 	    (NCR53c7x0_read8 ((hostdata->chip / 100) == 8 ? 
 		SSTAT1_REG : SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT,
-	    ((hostdata->chip / 100) == 8) ?
-		NCR53c7x0_read8 (STEST0_REG_800) : 0);
+	    ((hostdata->chip / 100) == 8) ? NCR53c7x0_read8 (STEST0_REG_800) :
+		NCR53c7x0_read32(SCRATCHA_REG_800),
+	    hostdata->saved2_dsa);
 	printk ("scsi%d : DSP 0x%lx (virt 0x%p) ->\n", host->host_no, 
 	    virt_to_bus(dsp), dsp);
     	for (i = 6; i > 0; --i, dsp += size)
@@ -5691,7 +5749,7 @@
     NCR53c7x0_local_declare();
     unsigned long flags;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     NCR53c7x0_local_setup(host);
     save_flags (flags);
     cli();
@@ -5732,7 +5790,7 @@
 static void 
 hard_reset (struct Scsi_Host *host) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     unsigned long flags;
     save_flags (flags);
     cli();
@@ -5767,7 +5825,7 @@
 static Scsi_Cmnd *
 return_outstanding_commands (struct Scsi_Host *host, int free, int issue) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     struct NCR53c7x0_cmd *c;
     int i;
     u32 *ncrcurrent;
@@ -5778,7 +5836,7 @@
 	    printk ("scsi%d : loop detected in running list!\n", host->host_no);
 	    break;
 	} else {
-	    printk ("The sti() implicit in a printk() prevents hangs\n");
+	    printk ("Duh? Bad things happening in the NCR driver\n");
 	    break;
 	}
 
@@ -5833,7 +5891,7 @@
 static int 
 disable (struct Scsi_Host *host) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     unsigned long flags;
     Scsi_Cmnd *nuke_list, *tmp;
     save_flags(flags);
@@ -5872,7 +5930,7 @@
     unsigned long flags;
     unsigned char istat, tmp;
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     int stage;
     NCR53c7x0_local_setup(host);
 
@@ -5950,7 +6008,7 @@
 static void
 dump_events (struct Scsi_Host *host, int count) {
     struct NCR53c7x0_hostdata *hostdata = (struct NCR53c7x0_hostdata *)
-	host->hostdata;
+	host->hostdata[0];
     struct NCR53c7x0_event event;
     int i;
     unsigned long flags;
@@ -6014,7 +6072,7 @@
 NCR53c7x0_release(struct Scsi_Host *host) {
 #ifdef MODULE
     struct NCR53c7x0_hostdata *hostdata = 
-	(struct NCR53c7x0_hostdata *) host->hostdata;
+	(struct NCR53c7x0_hostdata *) host->hostdata[0];
     struct NCR53c7x0_cmd *cmd, *tmp;
     shutdown (host);
     if (host->irq != IRQ_NONE)
@@ -6024,12 +6082,14 @@
 	    for (irq_count = 0, tmp = first_host; tmp; tmp = tmp->next)
 		if (tmp->hostt == the_template && tmp->irq == host->irq)
 		    ++irq_count;
-	    if (irq_count == 1)
+	    if (irq_count == 1){
+		unsigned long irq = host->irq;
 #ifdef CONFIG_AMIGA
-		free_irq(host->irq | IRQ_MACHSPEC, NULL);
-#else
-		free_irq(host->irq, NULL);
+		if (MACH_IS_AMIGA)
+		    irq |= IRQ_MACHSPEC;
 #endif
+		free_irq(irq, NULL);
+	    }
 	}
     if (host->dma_channel != DMA_NONE)
 	free_dma(host->dma_channel);
@@ -6052,6 +6112,12 @@
 	    host->host_no, hostdata->num_cmds);
     if (hostdata->events) 
 	vfree ((void *)hostdata->events);
+
+    /* XXX This assumes default cache mode to be KERNELMAP_FULL_CACHING, which
+     * XXX may be invalid (CONFIG_060_WRITETHROUGH)
+     */
+    kernel_set_cachemode((u32)hostdata, 8192, KERNELMAP_FULL_CACHING);
+    free_pages ((u32)hostdata, 1);
 #endif
     return 1;
 }
--- linux20/drivers/scsi/53c7xx.h.orig	Fri Apr 10 13:33:01 1998
+++ linux20/drivers/scsi/53c7xx.h	Sun Nov  8 16:17:14 1998
@@ -852,7 +852,7 @@
 					 * NCR53c710, this bit moved to CTEST8
 					 */
 #define DCNTL_10_COM		0x01	/* 700 software compatibility mode */
-#define DCNTL_10_EA		0x20	/* Enable Ack - needed for MVME166 */
+#define DCNTL_10_EA		0x20	/* Enable Ack - needed for MVME16x */
 
 #define DCNTL_700_SAVE ( DCNTL_CF_MASK | DCNTL_S16)
 
@@ -1084,6 +1084,15 @@
 
     int flags;				/* CMD_* flags */
 
+    unsigned char      cmnd[12];	/* CDB, copied from Scsi_Cmnd */
+    int                result;		/* Copy to Scsi_Cmnd when done */
+
+    struct {				/* Private non-cached bounce buffer */
+        unsigned char buf[256];
+	u32	      addr;
+        u32           len;
+    } bounce;
+
 /*
  * SDTR and WIDE messages are an either/or affair
  * in this message, since we will go into message out and send
@@ -1206,14 +1215,6 @@
 					   digits of part number */
 
     char valid_ids[8];			/* Valid SCSI ID's for adapter */
-    /*
-     * PCI bus, device, function, only for NCR53c8x0 chips.
-     * pci_valid indicates that the PCI configuration information
-     * is valid, and we can twiddle MAX_LAT, etc. as recommended
-     * for maximum performance in the NCR documentation.
-     */
-    unsigned char pci_bus, pci_device_fn;
-    unsigned pci_valid:1;
 
     u32 *dsp;				/* dsp to restart with after
 					   all stacked interrupts are
@@ -1514,7 +1515,7 @@
     NCR53c7x0_address_memory = (void *) (host)->base;			\
     NCR53c7x0_address_io = (unsigned int) (host)->io_port;		\
     NCR53c7x0_memory_mapped = ((struct NCR53c7x0_hostdata *) 		\
-	host->hostdata)-> options & OPTION_MEMORY_MAPPED 
+	host->hostdata[0])-> options & OPTION_MEMORY_MAPPED 
 
 #ifdef BIG_ENDIAN
 /* These could be more efficient, given that we are always memory mapped,
@@ -1547,7 +1548,7 @@
 
 #ifdef BIG_ENDIAN
 /* If we are big-endian, then we are not Intel, so probably don't have
- * an i/o map as well as a memory map.  So, lets assume memory mapped.
+ * an i/o map as well as a memory map.  So, let's assume memory mapped.
  * Also, I am having terrible problems trying to persuade the compiler
  * not to lay down code which does a read after write for these macros.
  * If you remove 'volatile' from writeb() and friends it is ok....

