[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Hardware not detected (9000/801/D200)



On Fri, 2003-02-07 at 09:35, Matthew Wilcox wrote:
> > I do actually have plans to add it in in the future.  I talked to
> > Richard Hirst about getting sim710 working again (migration to the
> > device model, DMA model and cli/sti removal).  The upshot is that we're
> > going to gut it and make it use the 53c700 chip driver.
> 
> That makes a certain amount of sense.  It's a little bit of a shame not
> to use the features of the 710 chip, but maintaining fewer drivers is
> clearly a Good Thing.

OK, attached is the sim710 modified to work for the card I have
(HWP0C80, a SE 710).  It should be fairly easy to add support for
others, we just have to decode their eisa config files.

I've tested mine on x86, and it seems to work.  Unfortunately, I don't
actually have the connectors to cable it up to a non differential narrow
drive, so if someone else wants to test it, I'd be grateful.

James

# This is a BitKeeper generated patch for the following project:
# Project Name: Linux kernel tree
# This patch format is intended for GNU patch command version 2.5 or higher.
# This patch includes the following deltas:
#	           ChangeSet	1.956   -> 1.957  
#	drivers/scsi/Makefile	1.34    -> 1.35   
#	drivers/scsi/sim710.c	1.6     -> 1.7    
#	drivers/scsi/Kconfig	1.9     -> 1.10   
#
# The following is the BitKeeper ChangeSet Log
# --------------------------------------------
# 03/02/07	jejb@raven.il.steeleye.com	1.957
# Fix sim710 driver
# 
# Make it use the 53c700 chip driver.   This should give conversion
# to the DMA API, synchronous operation and tag command queueing
# --------------------------------------------
#
diff -Nru a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
--- a/drivers/scsi/Kconfig	Fri Feb  7 21:52:42 2003
+++ b/drivers/scsi/Kconfig	Fri Feb  7 21:52:42 2003
@@ -1372,24 +1372,16 @@
 # definitely looks note 64bit safe:
 config SCSI_SIM710
 	tristate "Simple 53c710 SCSI support (Compaq, NCR machines)"
-	depends on (ISA || MCA && !X86_64) && SCSI
+	depends on (EISA || MCA && !X86_64) && SCSI
 	---help---
-	  This is a simple driver for NCR53c710 based SCSI host adapters.
+	  This driver for NCR53c710 based SCSI host adapters.
 
-	  More complex drivers for this chip are available ("NCR53c7,8xx SCSI
-	  support", above), but they require that the scsi chip be able to do
-	  DMA block moves between memory and on-chip registers, which can
-	  cause problems under certain conditions.  This driver is designed to
-	  avoid these problems and is intended to work with any Intel machines
-	  using 53c710 chips, including various Compaq and NCR machines.
+	  It currently supports Compaq EISA cards and NCR MCA cards
 
-	  Please read the comments at the top of the file
-	  <file:drivers/scsi/sim710.c> for more information.
-
-	  If you want to compile this driver as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want),
-	  say M here and read <file:Documentation/modules.txt>.  The module
-	  will be called sim710.o.
+config 53C700_IO_MAPPED
+	bool
+	depends on SCSI_SIM710
+	default y
 
 config SCSI_SYM53C416
 	tristate "Symbios 53c416 SCSI support"
diff -Nru a/drivers/scsi/Makefile b/drivers/scsi/Makefile
--- a/drivers/scsi/Makefile	Fri Feb  7 21:52:42 2003
+++ b/drivers/scsi/Makefile	Fri Feb  7 21:52:42 2003
@@ -45,7 +45,7 @@
 obj-$(CONFIG_SUN3_SCSI)		+= sun3_scsi.o  sun3_scsi_vme.o
 obj-$(CONFIG_MVME16x_SCSI)	+= mvme16x.o	53c7xx.o
 obj-$(CONFIG_BVME6000_SCSI)	+= bvme6000.o	53c7xx.o
-obj-$(CONFIG_SCSI_SIM710)	+= sim710.o
+obj-$(CONFIG_SCSI_SIM710)	+= sim710.o	53c700.o
 obj-$(CONFIG_SCSI_ADVANSYS)	+= advansys.o
 obj-$(CONFIG_SCSI_PCI2000)	+= pci2000.o
 obj-$(CONFIG_SCSI_PCI2220I)	+= pci2220i.o
diff -Nru a/drivers/scsi/sim710.c b/drivers/scsi/sim710.c
--- a/drivers/scsi/sim710.c	Fri Feb  7 21:52:42 2003
+++ b/drivers/scsi/sim710.c	Fri Feb  7 21:52:42 2003
@@ -22,96 +22,41 @@
  * Some multiboard fixes from Rolf Eike Beer.
  * Auto probing of EISA config space from Trevor Hemsley.
  *
- * Various bits of code in this driver have been copied from 53c7,8xx,c,
- * which is coyright Drew Eckhardt.  The scripts for the SCSI chip are
- * compiled with the script compiler written by Drew.
- *
- * This is a simple driver for the NCR53c710.  More complex drivers
- * for this chip (e.g. 53c7xx.c) require that the scsi chip be able to
- * do DMA block moves between memory and on-chip registers, which can
- * be a problem if those registers are in the I/O address space.  There
- * can also be problems on hardware where the registers are memory
- * mapped, if the design is such that memory-to-memory transfers initiated
- * by the scsi chip cannot access the chip registers.
- *
- * This driver is designed to avoid these problems and is intended to
- * work with any Intel machines using 53c710 chips, including various
- * Compaq and NCR machines.  It was initially written for the Tadpole
- * TP34V VME board which is 68030 based.
- *
- * The driver supports boot-time parameters similar to
- *	sim710=addr:0x9000,irq:15
- * and insmod parameters similar to
- *	sim710="addr:0x9000 irq:15"
- *
- * Multiple controllers can also be set up by command line, provided the
- * addr: parameter is specified first for each controller.  e.g.
- *      sim710="addr:0x9000 irq:15 addr:0x8000 irq:14"
- *
- * To seperate the different options, ' ', '+', and ',' can be used, except
- * that ',' can not be used in module parameters.  ' ' can be a pain, because
- * it needs to be quoted, which causes problems with some installers.
- * The command line above is completely equivalent to
- *      sim710="addr:0x9000+irq:15+addr:0x8000+irq:14"
- *
- * The complete list of options are:
- *
- * addr:0x9000		Specifies the base I/O port (or address) of the 53C710.
- * irq:15		Specifies the IRQ number used by the 53c710.
- * debug:0xffff		Generates lots of debug output.
- * ignore:0x0a		Makes the driver ignore SCSI IDs 0 and 2.
- * nodisc:0x70		Prevents disconnects from IDs 6, 5 and 4.
- * noneg:0x10		Prevents SDTR negotiation on ID 4.
- * disabled:1		Completely disables the driver. When present, overrides
- *			all other options.
- *
- * The driver will auto-probe chip addresses and IRQs now, so typically no
- * parameters are needed.  Auto-probing of addresses is disabled if any addr:
- * parameters are specified.
- *
- * Current limitations:
- *
- * o  Async only
- * o  Severely lacking in error recovery
- * o  'debug:' should be per host really.
+ * Rewritten to use 53c700.c by James.Bottomley@SteelEye.com
  *
  */
 
 #include <linux/config.h>
 #include <linux/module.h>
 
-#include <linux/version.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/string.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/proc_fs.h>
+#include <linux/blk.h>
+#include <linux/device.h>
 #include <linux/init.h>
+#ifdef CONFIG_MCA
 #include <linux/mca.h>
-#include <linux/interrupt.h>
-#include <asm/dma.h>
-#include <asm/system.h>
-#include <linux/spinlock.h>
-#include <asm/io.h>
-#include <asm/pgtable.h>
-#include <asm/byteorder.h>
-#include <linux/blk.h>
+#endif
+#ifdef CONFIG_EISA
+#include <linux/eisa.h>
+#endif
 
-/* All targets are I/O mapped at the moment */
-#define IO_MAPPED
+#include "scsi.h"
+#include "hosts.h"
+#include "53c700.h"
 
-#if defined(CONFIG_MCA)
+/* Must be enough for both EISA and MCA */
+#define MAX_SLOTS 8
+static __u8 __initdata id_array[MAX_SLOTS] = { [0 ... MAX_SLOTS-1] = 7 };
+
+/* info is used to communicate global data across the driver register
+ * because the struct device_driver doesn't have any info fields.  Sigh */
+struct sim710_info {
+	Scsi_Host_Template *tpnt;
+	int found;
+};
 
-/*
- * For each known microchannel card using the 53c710 we need a list
- * of possible IRQ and IO settings, as well as their corresponding
- * bit assignment in pos[].  This might get cumbersome if there
- * are more than a few cards (I only know of 2 at this point).
- */
+static __initdata struct sim710_info sim710_global_info;
 
-#define MCA_53C710_IDS { 0x01bb, 0x01ba, 0x004f }
+#if defined(CONFIG_MCA)
 
 /* CARD ID 01BB and 01BA use the same pos values */
 
@@ -130,63 +75,6 @@
 
 #endif
 
-#include "scsi.h"
-#include "hosts.h"
-#include "sim710.h"
-
-#include<linux/stat.h>
-
-#define DEBUG
-#undef DEBUG_LIMIT_INTS		/* Define to 10 to hang driver after 10 ints */
-
-/* Debug options available via the "debug:0x1234" parameter		*/
-
-#define DEB_NONE	0x0000	/* Nothing				*/
-#define DEB_HALT	0x0001	/* Detailed trace of chip halt funtion	*/
-#define DEB_REGS	0x0002	/* All chip register read/writes	*/
-#define DEB_SYNC	0x0004	/* Sync/async negotiation		*/
-#define DEB_PMM		0x0008	/* Phase mis-match handling		*/
-#define DEB_INTS	0x0010	/* General interrupt trace		*/
-#define DEB_TOUT	0x0020	/* Selection timeouts			*/
-#define DEB_RESUME	0x0040	/* Resume addresses for the script	*/
-#define DEB_CMND	0x0080	/* Commands and status returned		*/
-#define DEB_FIXUP	0x0100	/* Fixup of scsi addresses		*/
-#define DEB_DISC	0x0200	/* Disconnect/reselect handling		*/
-
-#define DEB_ANY		0xffff	/* Any and all debug options		*/
-
-#ifdef DEBUG
-#define DEB(m,x) if (sim710_debug & m) x
-int sim710_debug;
-#else
-#define DEB(m,x)
-#endif
-
-/* Redefine scsi_done to force renegotiation of (a)sync transfers
- * following any failed command.
- */
-
-#define SCSI_DONE(cmd)	{ \
-	DEB(DEB_CMND, printk("scsi%d: Complete %08x\n", \
-		host->host_no, cmd->result)); \
-	if (cmd->result) \
-	    hostdata->negotiate |= (1 << cmd->target); \
-	cmd->scsi_done(cmd); \
-    }
-
-#ifndef offsetof
-#define offsetof(t, m)      ((size_t) (&((t *)0)->m))
-#endif
-
-#define STATE_INITIALISED	0
-#define STATE_HALTED		1
-#define STATE_IDLE		2
-#define STATE_BUSY		3
-#define STATE_DISABLED		4
-
-#define MAXBOARDS 4	/* Increase this and the sizes of the
-			   arrays below, if you need more.. */
-
 #ifdef MODULE
 
 char *sim710;		/* command line passed by insmod */
@@ -199,1583 +87,295 @@
 
 #endif
 
-static int sim710_errors;		/* Count of error interrupts */
-static int sim710_intrs;		/* Count of all interrupts */
-static int ignore_ids[MAXBOARDS];	/* Accept all SCSI IDs */
-static int opt_nodisc[MAXBOARDS];	/* Allow disconnect on all IDs */
-static int opt_noneg[MAXBOARDS];	/* Allow SDTR negotiation on all IDs */
-static int hostdata_order;		/* Encoded size of hostdata for free_pages() */
-static int no_of_boards;		/* Actual number of boards/chips */
-static unsigned int bases[MAXBOARDS];	/* Base addresses of chips */
-static unsigned int irq_vectors[MAXBOARDS]; /* IRQ vectors used by chips */
-
-/* The SCSI Script!!! */
-
-#include "sim710_d.h"
-
-/* Now define offsets in the DSA, as (A_dsa_xxx/4) */
-
-#define DSA_SELECT	(A_dsa_select/4)
-#define DSA_MSGOUT	(A_dsa_msgout/4)
-#define DSA_CMND	(A_dsa_cmnd/4)
-#define DSA_STATUS	(A_dsa_status/4)
-#define DSA_MSGIN	(A_dsa_msgin/4)
-#define DSA_DATAIN	(A_dsa_datain/4)
-#define DSA_DATAOUT	(A_dsa_dataout/4)
-#define DSA_SIZE	(A_dsa_size/4)
-
-#define MAX_SG		128	/* Scatter/Gather elements */
-
-#define MAX_MSGOUT	8
-#define MAX_MSGIN	8
-#define MAX_CMND	12
-#define MAX_STATUS	1
-
-struct sim710_hostdata{
-    int state;
-    Scsi_Cmnd * issue_queue;
-    Scsi_Cmnd * running;
-    int chip;
-    u8 negotiate;
-    u8 reselected_identify;
-    u8 msgin_buf[MAX_MSGIN];
-    u8 msg_reject;
-    u32 test1_src __attribute__ ((aligned (4)));
-    u32 test1_dst;
-
-    struct sim710_target {
-	Scsi_Cmnd *cur_cmd;
-	u32 resume_offset;
-	u32 data_in_jump;
-	u32 data_out_jump;
-	u32 dsa[DSA_SIZE];		/* SCSI Script DSA area */
-	u8  dsa_msgout[MAX_MSGOUT];
-	u8  dsa_msgin[MAX_MSGIN];
-	u8  dsa_cdb[MAX_CMND];
-	u8  dsa_status[MAX_STATUS];
-    } target[8];
-
-    u32 script[sizeof(SCRIPT)/4] __attribute__ ((aligned (4)));
-};
-
-
-/* Template to request asynchronous transfers */
-
-static const unsigned char async_message[] = {
-    EXTENDED_MESSAGE, 3 /* length */, EXTENDED_SDTR, 0, 0 /* asynchronous */};
-
-
-static void sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs);
-static void do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs);
-static __inline__ void run_process_issue_queue(struct sim710_hostdata *);
-static void process_issue_queue (struct sim710_hostdata *, unsigned long flags);
-static int full_reset(struct Scsi_Host * host);
-
-
-/*
- * Function : static void ncr_dump (struct Scsi_Host *host)
- *
- * Purpose :  Dump (possibly) useful info
- *
- * Inputs : host - pointer to this host adapter's structure
- */
-
-static void
-ncr_dump (struct Scsi_Host *host)
-{
-    unsigned long flags;
-    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
-       host->hostdata[0];
-
-    save_flags(flags);
-    cli();
-    printk("scsi%d: Chip register contents:\n", host->host_no);
-    printk(" (script at virt %p, bus %lx)\n",
-           hostdata->script, virt_to_bus(hostdata->script));
-    printk(" 00  sien:  %02x  sdid:  %02x  scntl1:%02x  scntl0:%02x\n"
-	   " 04  socl:  %02x  sodl:  %02x  sxfer: %02x  scid:  %02x\n"
-	   " 08  sbcl:  %02x  sbdl:  %02x  sidl:  %02x  sfbr:  %02x\n"
-	   " 0C  sstat2:%02x  sstat1:%02x  sstat0:%02x  dstat: %02x\n"
-	   " 10  dsa:   %08x\n"
-	   " 14  ctest3:%02x  ctest2:%02x  ctest1:%02x  ctest0:%02x\n"
-	   " 18  ctest7:%02x  ctest6:%02x  ctest5:%02x  ctest4:%02x\n"
-	   " 1C  temp:  %08x\n"
-	   " 20  lcrc:  %02x  ctest8:%02x  istat: %02x  dfifo: %02x\n"
-	   " 24  dbc:   %08x  dnad:  %08x  dsp:   %08x\n"
-	   " 30  dsps:  %08x  scratch:%08x\n"
-	   " 38  dcntl: %02x  dwt:   %02x  dien:  %02x  dmode: %02x\n"
-	   " 3C  adder: %08x\n",
-	  NCR_read8(SIEN_REG), NCR_read8(SDID_REG), NCR_read8(SCNTL1_REG),
-	  NCR_read8(SCNTL0_REG), NCR_read8(SOCL_REG), NCR_read8(SODL_REG),
-	  NCR_read8(SXFER_REG), NCR_read8(SCID_REG), NCR_read8(SBCL_REG),
-	  NCR_read8(SBDL_REG), NCR_read8(SIDL_REG), NCR_read8(SFBR_REG),
-	  NCR_read8(SSTAT2_REG), NCR_read8(SSTAT1_REG), NCR_read8(SSTAT0_REG),
-	  NCR_read8(DSTAT_REG), NCR_read32(DSA_REG), NCR_read8(CTEST3_REG),
-	  NCR_read8(CTEST2_REG), NCR_read8(CTEST1_REG), NCR_read8(CTEST0_REG),
-	  NCR_read8(CTEST7_REG), NCR_read8(CTEST6_REG), NCR_read8(CTEST5_REG),
-	  NCR_read8(CTEST4_REG), NCR_read8(TEMP_REG), NCR_read8(LCRC_REG),
-	  NCR_read8(CTEST8_REG), NCR_read8(ISTAT_REG), NCR_read8(DFIFO_REG),
-	  NCR_read32(DBC_REG), NCR_read32(DNAD_REG), NCR_read32(DSP_REG),
-	  NCR_read32(DSPS_REG), NCR_read32(SCRATCH_REG), NCR_read8(DCNTL_REG),
-	  NCR_read8(DWT_REG), NCR_read8(DIEN_REG), NCR_read8(DMODE_REG),
-	  NCR_read32(ADDER_REG));
-
-    restore_flags(flags);
-}
-
-
-/*
- * Function: int param_setup(char *str)
- */
+#ifdef MODULE
+#define ARG_SEP ' '
+#else
+#define ARG_SEP ','
+#endif
 
 __init int
 param_setup(char *str)
 {
-    char *cur = str;
-    char *p, *pc, *pv;
-    int val;
-    int c;
-
-    no_of_boards = 0;
-    while (no_of_boards < MAXBOARDS && cur != NULL &&
-		(pc = strchr(cur, ':')) != NULL) {
-	char *pe;
-
-	val = 0;
-	pv = pc;
-	c = *++pv;
+	char *pos = str, *next;
+	int slot = -1;
 
-	val = (int) simple_strtoul(pv, &pe, 0);
+	while(pos != NULL && (next = strchr(pos, ':')) != NULL) {
+		int val = (int)simple_strtoul(++next, NULL, 0);
 
-	if (!strncmp(cur, "addr:", 5)) {
-	    bases[no_of_boards++] = val;
-	}
-#ifdef DEBUG
-	else if (!strncmp(cur, "debug:", 6)) {
-	    sim710_debug = val;
-	}
-#endif
-	else if (no_of_boards == 0) {
-	    printk("sim710: Invalid parameters, addr: must come first\n");
-	    no_of_boards = -1;
-	    return 1;
-	}
-	else if	(!strncmp(cur, "irq:", 4))
-	    irq_vectors[no_of_boards-1] = val;
-	else if	(!strncmp(cur, "ignore:", 7))
-	    ignore_ids[no_of_boards-1] = val;
-	else if	(!strncmp(cur, "nodisc:", 7))
-	    opt_nodisc[no_of_boards-1] = val;
-	else if	(!strncmp(cur, "noneg:", 6))
-	    opt_noneg[no_of_boards-1] = val;
-	else if	(!strncmp(cur, "disabled:", 9)) {
-	    no_of_boards = -1;
-	    return 1;
-	}
-	else {
-	    printk("sim710: unexpected boot option '%.*s'\n", (int)(pc-cur+1), cur);
-	    no_of_boards = -1;
-	    return 1;
+		if(!strncmp(pos, "slot:", 5))
+			slot = val;
+		else if(!strncmp(pos, "id:", 3)) {
+			if(slot == -1) {
+				printk(KERN_WARNING "sim710: Must specify slot for id parameter\n");
+			} else if(slot > MAX_SLOTS) {
+				printk(KERN_WARNING "sim710: Illegal slot %d for id %d\n", slot, val);
+			} else {
+				id_array[slot] = val;
+			}
+		}
+		if((pos = strchr(pos, ARG_SEP)) != NULL)
+			pos++;
 	}
-
-	/* Allow ',', ' ', or '+' seperators.  Used to be ',' at boot and
-	 * ' ' for module load, some installers crap out on the space and
-	 * insmod doesn't like the comma.
-	 */
-       if ((p = strchr(cur, ',')) || (p = strchr(cur, ' ')) ||
-               (p = strchr(cur, '+')))
-           cur = p + 1;
-        else
-           break;
-    }
-    return 1;
+	return 1;
 }
 
 #ifndef MODULE
 __setup("sim710=", param_setup);
 #endif
 
-
-/*
- * Function: static const char *sbcl_to_phase (int sbcl)
- */
-
-static const char *
-sbcl_to_phase (int sbcl) {
-    switch (sbcl & SBCL_PHASE_MASK) {
-    case SBCL_PHASE_DATAIN:
-	return "DATAIN";
-    case SBCL_PHASE_DATAOUT:
-	return "DATAOUT";
-    case SBCL_PHASE_MSGIN:
-	return "MSGIN";
-    case SBCL_PHASE_MSGOUT:
-	return "MSGOUT";
-    case SBCL_PHASE_CMDOUT:
-	return "CMDOUT";
-    case SBCL_PHASE_STATIN:
-	return "STATUSIN";
-    default:
-	return "unknown";
-    }
-}
-
-
-/*
- * Function : static int ncr_halt (struct Scsi_Host *host)
- *
- * Purpose : halts the SCSI SCRIPTS(tm) processor on the NCR chip
- *
- * Inputs : host - SCSI chip to halt
- *
- * Returns : 0 on success
- */
-
-static int
-ncr_halt (struct Scsi_Host *host)
-{
-    unsigned long flags;
-    unsigned char istat, tmp;
-    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
-	host->hostdata[0];
-    int stage;
-    int timeout;
-    int res = 0;
-
-    save_flags(flags);
-    cli();
-    /* Stage 0 : eat all interrupts
-       Stage 1 : set ABORT
-       Stage 2 : eat all but abort interrupts
-       Stage 3 : eat all interrupts
-       We loop for 50000 times with a delay of 10us which should give us
-       about half a second.
-     */
-    for (stage = 0, timeout = 50000; timeout; timeout--) {
-	if (stage == 1) {
-	    DEB(DEB_HALT, printk("ncr_halt: writing ISTAT_ABRT\n"));
-	    NCR_write8(ISTAT_REG, ISTAT_ABRT);
-	    ++stage;
-	}
-	istat = NCR_read8 (ISTAT_REG);
-	if (istat & ISTAT_SIP) {
-	    DEB(DEB_HALT, printk("ncr_halt: got ISTAT_SIP, istat=%02x\n", istat));
-	    tmp = NCR_read8(SSTAT0_REG);
-	    DEB(DEB_HALT, printk("ncr_halt: got SSTAT0_REG=%02x\n", tmp));
-	} else if (istat & ISTAT_DIP) {
-	    DEB(DEB_HALT, printk("ncr_halt: got ISTAT_DIP, istat=%02x\n", istat));
-	    tmp = NCR_read8(DSTAT_REG);
-	    DEB(DEB_HALT, printk("ncr_halt: got DSTAT_REG=%02x\n", tmp));
-	    if (stage == 2) {
-		if (tmp & DSTAT_ABRT) {
-	    	    DEB(DEB_HALT, printk("ncr_halt: got DSTAT_ABRT, clearing istat\n"));
-		    NCR_write8(ISTAT_REG, 0);
-		    ++stage;
-		} else {
-		    res = 1;
-		    break;
-	    	}
-    	    }
-	}
-	if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {
-	    if (stage == 0)
-	    	++stage;
-	    else if (stage == 3)
-		break;
-	}
-	udelay(10);
-    }
-    restore_flags(flags);
-
-    if (timeout == 0 || res) {
-	printk(KERN_ALERT "scsi%d: could not halt NCR chip\n", host->host_no);
-	return 1;
-    }
-    else {
-	hostdata->state = STATE_HALTED;
-	return 0;
-    }
-}
-
-/*
- * Function : static void sim710_soft_reset (struct Scsi_Host *host)
- *
- * Purpose :  perform a soft reset of the NCR53c7xx chip
- *
- * Inputs : host - pointer to this host adapter's structure
- *
- * Preconditions : sim710_init must have been called for this
- *      host.
- *
- */
-
-static void
-sim710_soft_reset (struct Scsi_Host *host)
-{
-    unsigned long flags;
-
-    save_flags(flags);
-    cli();
-    /*
-     * Do a soft reset of the chip so that everything is
-     * reinitialized to the power-on state.
-     *
-     * Basically follow the procedure outlined in the NCR53c700
-     * data manual under Chapter Six, How to Use, Steps Necessary to
-     * Start SCRIPTS, with the exception of actually starting the
-     * script and setting up the synchronous transfer gunk.
-     */
-
-    /* XXX Should we reset the scsi bus here? */
-
-    NCR_write8(SCNTL1_REG, SCNTL1_RST);		/* Reset the bus */
-    udelay(50);
-    NCR_write8(SCNTL1_REG, 0);
-
-    udelay(500);
-
-    NCR_write8(ISTAT_REG, ISTAT_10_SRST);	/* Reset the chip */
-    udelay(50);
-    NCR_write8(ISTAT_REG, 0);
-
-    mdelay(1000);				/* Let devices recover */
-
-    NCR_write32(SCRATCH_REG, 0);
-    NCR_write8(DCNTL_REG, DCNTL_10_COM | DCNTL_700_CF_3);
-    NCR_write8(CTEST7_REG, CTEST7_10_CDIS|CTEST7_STD);
-    NCR_write8(DMODE_REG, DMODE_10_BL_8 | DMODE_10_FC2);
-    NCR_write8(SCID_REG, 1 << host->this_id);
-    NCR_write8(SBCL_REG, 0);
-    NCR_write8(SXFER_REG, 0);
-    NCR_write8(SCNTL1_REG, SCNTL1_ESR_700);
-    NCR_write8(SCNTL0_REG, SCNTL0_EPC | SCNTL0_EPG_700 | SCNTL0_ARB1 |
-		SCNTL0_ARB2);
-
-    NCR_write8(DIEN_REG, DIEN_700_BF |
-		DIEN_ABRT | DIEN_SSI | DIEN_SIR | DIEN_700_OPC);
-
-    NCR_write8(SIEN_REG_700,
-	    SIEN_PAR | SIEN_700_STO | SIEN_RST | SIEN_UDC | SIEN_SGE | SIEN_MA);
-
-    restore_flags(flags);
-}
-
-
-/*
- * Function : static void sim710_driver_init (struct Scsi_Host *host)
- *
- * Purpose : Initialize internal structures, as required on startup, or
- *	after a SCSI bus reset.
- *
- * Inputs : host - pointer to this host adapter's structure
- */
-
-static void
-sim710_driver_init (struct Scsi_Host *host)
-{
-    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
-	host->hostdata[0];
-    int i;
-
-    hostdata->running = NULL;
-    memcpy (hostdata->script, SCRIPT, sizeof(SCRIPT));
-    for (i = 0; i < PATCHES; i++)
-	hostdata->script[LABELPATCHES[i]] += isa_virt_to_bus(hostdata->script);
-    patch_abs_32 (hostdata->script, 0, reselected_identify, 
-    	isa_virt_to_bus((void *)&(hostdata->reselected_identify)));
-    patch_abs_32 (hostdata->script, 0, msgin_buf, 
-    	isa_virt_to_bus((void *)&(hostdata->msgin_buf[0])));
-    patch_abs_32 (hostdata->script, 0, msg_reject,
-	isa_virt_to_bus((void *)&(hostdata->msg_reject)));
-    patch_abs_32 (hostdata->script, 0, test1_src,
-	isa_virt_to_bus((void *)&(hostdata->test1_src)));
-    patch_abs_32 (hostdata->script, 0, test1_dst,
-	isa_virt_to_bus((void *)&(hostdata->test1_dst)));
-    hostdata->state = STATE_INITIALISED;
-    hostdata->negotiate = 0xff;
-}
-
-
-/* Handle incoming Synchronous data transfer request.  If our negotiate
- * flag is set then this is a response to our request, otherwise it is
- * spurious request from the target.  Don't really expect target initiated
- * SDTRs, because we always negotiate on the first command.  Could still
- * get them though..
- * The chip is currently paused with ACK asserted on the last byte of the
- * SDTR.
- * resa is the resume address if the message is in response to our outgoing
- * SDTR.  Only possible on initial identify.
- * resb is the resume address if the message exchange is initiated by the
- * target.
- */
-
-static u32
-handle_sdtr (struct Scsi_Host * host, Scsi_Cmnd * cmd, u32 resa, u32 resb)
-{
-    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
-    struct sim710_target *targdata = hostdata->target + cmd->target;
-    u32 resume_offset;
-
-    if (resa && hostdata->negotiate & (1 << cmd->target)) {
-	DEB(DEB_SYNC, printk("scsi%d: Response to host SDTR = %02x %02x\n",
-		host->host_no, hostdata->msgin_buf[3], hostdata->msgin_buf[4]));
-	/* We always issue an SDTR with the identify, so we must issue
-	 * the CDB next.
-	 */
-	resume_offset = resa;
-	hostdata->negotiate &= ~(1 << cmd->target);
-    }
-    else {
-	DEB(DEB_SYNC, printk("scsi%d: Target initiated SDTR = %02x %02x\n",
-		host->host_no, hostdata->msgin_buf[3], hostdata->msgin_buf[4]));
-	memcpy(targdata->dsa_msgout, async_message, sizeof(async_message));
-	targdata->dsa[DSA_MSGOUT] = sizeof(async_message);
-	/* I guess the target could do this anytime; we have to send our
-	 * response, and then continue (sending the CDB if not already done).
-	 */
-	resume_offset = resb;
-    }
-    return resume_offset;
-}
-
-
-/*
- * Function : static int datapath_residual (Scsi_Host *host)
- *
- * Purpose : return residual data count of what's in the chip.
- *
- * Inputs : host - SCSI host
- */
-
-static int
-datapath_residual (struct Scsi_Host *host) {
-    int count, synchronous, sstat;
-    unsigned int ddir;
-
-    count = ((NCR_read8 (DFIFO_REG) & DFIFO_10_BO_MASK) -
-	(NCR_read32 (DBC_REG) & DFIFO_10_BO_MASK)) & DFIFO_10_BO_MASK;
-    synchronous = NCR_read8 (SXFER_REG) & SXFER_MO_MASK;
-    ddir = NCR_read8 (CTEST0_REG_700) & CTEST0_700_DDIR;
-
-    if (ddir) {
-    /* Receive */
-	if (synchronous) 
-	    count += (NCR_read8 (SSTAT2_REG) & SSTAT2_FF_MASK) >> SSTAT2_FF_SHIFT;
-	else
-	    if (NCR_read8 (SSTAT1_REG) & SSTAT1_ILF)
-		++count;
-    } else {
-    /* Send */
-	sstat = NCR_read8 (SSTAT1_REG);
-	if (sstat & SSTAT1_OLF)
-	    ++count;
-	if (synchronous && (sstat & SSTAT1_ORF))
-	    ++count;
-    }
-    return count;
-}
-
-
-static u32
-handle_idd (struct Scsi_Host * host, Scsi_Cmnd * cmd)
+__init int
+sim710_probe_common(struct device *dev, unsigned long base_addr,
+		    int irq, int clock, int differential, int scsi_id)
 {
-    struct sim710_hostdata *hostdata =
-		(struct sim710_hostdata *)host->hostdata[0];
-    struct sim710_target *targdata = hostdata->target + cmd->target;
-    u32 resume_offset = 0, index;
-
-    index = (u32)((u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
-
-    switch (index) {
-    case Ent_wait_disc_complete/4 + 2:
-	cmd->result = targdata->dsa_status[0];
-        SCSI_DONE(cmd);
-	targdata->cur_cmd = NULL;
-	resume_offset = Ent_reselect;
-	break;
-    case Ent_wait_disc2/4 + 2:
-	/* Disconnect after command - just wait for a reselect */
-	targdata->resume_offset = Ent_resume_msgin2a;
-	resume_offset = Ent_reselect;
-	break;
-    case Ent_wait_disc3/4 + 2:
-	/* Disconnect after the data phase */
-	targdata->resume_offset = Ent_resume_msgin3a;
-	resume_offset = Ent_reselect;
-	break;
-    case Ent_wait_disc1/4 + 2:
-	/* Disconnect before command - not expected */
-	targdata->resume_offset = Ent_resume_msgin1a;
-	resume_offset = Ent_reselect;
-	break;
-    default:
-	printk("scsi%d: Unexpected Illegal Instruction, script[%04x]\n",
-		host->host_no, index);
-	sim710_errors++;
-	/* resume_offset is zero, which will cause host reset */
-    }
-    return resume_offset;
-}
+	struct Scsi_Host * host = NULL;
+	struct NCR_700_Host_Parameters *hostdata =
+		kmalloc(sizeof(struct NCR_700_Host_Parameters),	GFP_KERNEL);
 
+	printk(KERN_NOTICE "sim710: %s\n", dev->name);
+	printk(KERN_NOTICE "sim710: irq = %d, clock = %d, base = 0x%lx, scsi_id = %d\n",
+	       irq, clock, base_addr, scsi_id);
 
-/* Handle a phase mismatch.
- */
-
-static u32
-handle_phase_mismatch (struct Scsi_Host * host, Scsi_Cmnd * cmd)
-{
-    struct sim710_hostdata *hostdata =
-		(struct sim710_hostdata *)host->hostdata[0];
-    struct sim710_target *targdata = hostdata->target + cmd->target;
-    u32 resume_offset = 0, index;
-    unsigned char sbcl;
-
-    sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
-    index = (u32)((u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script);
-
-    DEB(DEB_PMM, printk("scsi%d: Phase mismatch, phase %s (%x) at script[0x%x]\n",
-	host->host_no, sbcl_to_phase(sbcl), sbcl, index));
-    DEB(DEB_PMM, print_command(cmd->cmnd));
-
-    if (index == Ent_done_ident/4) {
-	/* Sending initial message out - probably rejecting our sync
-	 * negotiation request.
-	 */
-	NCR_write8(SOCL_REG, 0);	/* Negate ATN */
-	if (sbcl == SBCL_PHASE_MSGIN)
-	    resume_offset = Ent_resume_rej_ident;
-	else if (sbcl == SBCL_PHASE_CMDOUT) {
-	    /* Some old devices (SQ555) switch to cmdout after the first
-	     * byte of an identify message, regardless of whether we
-	     * have more bytes to send!
-	     */
-	    printk("scsi%d: Unexpected switch to CMDOUT during IDENTIFY\n",
-		host->host_no);
-	    resume_offset = Ent_resume_cmd;
+	if(hostdata == NULL) {
+		printk(KERN_ERR "sim710: Failed to allocate host data\n");
+		goto out;
 	}
-	else if (sbcl == SBCL_PHASE_STATIN) {
-	    /* Some devices do this on parity error, at least */
-	    printk("scsi%d: Unexpected switch to STATUSIN on initial message out\n",
-		host->host_no);
-	    resume_offset = Ent_end_data_trans;
-	}
-	else {
-	    printk("scsi%d: Unexpected phase change to %s on initial msgout\n",
-		host->host_no, sbcl_to_phase(sbcl));
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-	hostdata->negotiate &= ~(1 << cmd->target);
-    }
-    else if (index > Ent_patch_input_data/4 &&
-		index < Ent_patch_output_data/4) {
-	/* DataIn transfer phase */
-	u32 sg_id, oaddr, olen, naddr, nlen;
-	int residual;
-
-	sg_id = (index - Ent_patch_input_data/4 - 4) / 2;
-	targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
-		isa_virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_id * 2 + 2);
-	olen  = targdata->dsa[DSA_DATAIN + sg_id * 2];
-	oaddr = targdata->dsa[DSA_DATAIN + sg_id * 2 + 1];
-	residual = datapath_residual (host);
-	if (residual)
-	    printk("scsi%d: Residual count %d on DataIn - NOT expected!!!",
-		host->host_no, residual);
-	naddr = NCR_read32(DNAD_REG) - residual;
-	nlen  = (NCR_read32(DBC_REG) & 0x00ffffff) + residual;
-	DEB(DEB_PMM, printk("scsi%d: DIN sg %d, old %08x/%08x, new %08x/%08x (%d)\n",
-		host->host_no, sg_id, oaddr, olen, naddr, nlen, residual));
-	if (oaddr+olen != naddr+nlen) {
-	    printk("scsi%d: PMM DIN counts error: 0x%x + 0x%x != 0x%x + 0x%x",
-		host->host_no, oaddr, olen, naddr, nlen);
-	}
-	else {
-	    targdata->dsa[DSA_DATAIN + sg_id * 2]     = nlen;
-	    targdata->dsa[DSA_DATAIN + sg_id * 2 + 1] = naddr;
-	    resume_offset = Ent_resume_pmm;
-	}
-    }
-    else if (index > Ent_patch_output_data/4 &&
-		index <= Ent_end_data_trans/4) {
-	/* Dataout transfer phase */
-	u32 sg_id, oaddr, olen, naddr, nlen;
-	int residual;
-
-	sg_id = (index - Ent_patch_output_data/4 - 4) / 2;
-	targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
-		isa_virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_id * 2 + 2);
-	olen  = targdata->dsa[DSA_DATAOUT + sg_id * 2];
-	oaddr = targdata->dsa[DSA_DATAOUT + sg_id * 2 + 1];
-	residual = datapath_residual (host);
-	naddr = NCR_read32(DNAD_REG) - residual;
-	nlen  = (NCR_read32(DBC_REG) & 0x00ffffff) + residual;
-	DEB(DEB_PMM, printk("scsi%d: DOUT sg %d, old %08x/%08x, new %08x/%08x (%d)\n",
-		host->host_no, sg_id, oaddr, olen, naddr, nlen, residual));
-	if (oaddr+olen != naddr+nlen) {
-	    printk("scsi%d: PMM DOUT counts error: 0x%x + 0x%x != 0x%x + 0x%x",
-		host->host_no, oaddr, olen, naddr, nlen);
-	}
-	else {
-	    targdata->dsa[DSA_DATAOUT + sg_id * 2]     = nlen;
-	    targdata->dsa[DSA_DATAOUT + sg_id * 2 + 1] = naddr;
-	    resume_offset = Ent_resume_pmm;
-	}
-    }
-    else if (sbcl == SBCL_PHASE_STATIN) {
-	/* Change to Status In at some random point; probably wants to report a
-	 * parity error or similar.
-	 */
-	printk("scsi%d: Unexpected phase change to STATUSIN at index 0x%x\n",
-		host->host_no, index);
-	resume_offset = Ent_end_data_trans;
-    }
-    else {
-	printk("scsi%d: Unexpected phase change to %s at index 0x%x\n",
-		host->host_no, sbcl_to_phase(sbcl), index);
-	/* resume_offset is zero, which will cause a host reset */
-    }
-    /* Flush DMA FIFO */
-    NCR_write8 (CTEST8_REG, CTEST8_10_CLF);
-    while (NCR_read8 (CTEST8_REG) & CTEST8_10_CLF);
-
-    return resume_offset;
-}
-
-
-static u32
-handle_script_int(struct Scsi_Host * host, Scsi_Cmnd * cmd)
-{
-    struct sim710_hostdata *hostdata =
-		(struct sim710_hostdata *)host->hostdata[0];
-    struct sim710_target *targdata = hostdata->target + cmd->target;
-    u32 dsps, resume_offset = 0;
-    unsigned char sbcl;
-
-    dsps = NCR_read32(DSPS_REG);
-
-    switch (dsps) {
-    case A_int_cmd_complete:
-	cmd->result = targdata->dsa_status[0];
-        SCSI_DONE(cmd);
-	targdata->cur_cmd = NULL;
-	resume_offset = Ent_reselect;
-	break;
-    case A_int_msg_sdtr1:
-	resume_offset = handle_sdtr(host, cmd,
-		Ent_resume_msgin1a, Ent_resume_msgin1b);
-	break;
-    case A_int_msg_sdtr2:
-	resume_offset = handle_sdtr(host, cmd, 0, Ent_resume_msgin2b);
-	break;
-    case A_int_msg_sdtr3:
-	resume_offset = handle_sdtr(host, cmd, 0, Ent_resume_msgin3b);
-	break;
-    case A_int_disc1:
-	/* Disconnect before command - not expected */
-	targdata->resume_offset = Ent_resume_msgin1a;
-	resume_offset = Ent_reselect;
-	break;
-    case A_int_disc2:
-	/* Disconnect after command - just wait for a reselect */
-	targdata->resume_offset = Ent_resume_msgin2a;
-	resume_offset = Ent_reselect;
-	break;
-    case A_int_disc3:
-	/* Disconnect after the data phase */
-	targdata->resume_offset = Ent_resume_msgin3a;
-	resume_offset = Ent_reselect;
-	break;
-    case A_int_reselected:
-	hostdata->script[Ent_patch_output_data/4+1] = targdata->data_out_jump;
-	hostdata->script[Ent_patch_input_data/4+1] = targdata->data_in_jump;
-	NCR_write32(DSA_REG, isa_virt_to_bus(targdata->dsa));
-	resume_offset = targdata->resume_offset;
-	break;
-    case A_int_data_bad_phase:
-	sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
-	printk("scsi%d: int_data_bad_phase, phase %s (%x)\n",
-		host->host_no, sbcl_to_phase(sbcl), sbcl);
-	break;
-    case A_int_bad_msg1:
-    case A_int_bad_msg2:
-    case A_int_bad_msg3:
-    case A_int_cmd_bad_phase:
-    case A_int_no_msgout1:
-    case A_int_no_msgout2:
-    case A_int_no_msgout3:
-    case A_int_not_cmd_complete:
-    case A_int_sel_no_ident:
-    case A_int_sel_not_cmd:
-    case A_int_status_not_msgin:
-    case A_int_resel_not_msgin:
-    case A_int_selected:
-    case A_int_not_rej:
-    default:
-	sbcl = NCR_read8(SBCL_REG) & SBCL_PHASE_MASK;
-	printk("scsi%d: Unimplemented script interrupt: %08x, phase %s\n",
-		host->host_no, dsps, sbcl_to_phase(sbcl));
-	sim710_errors++;
-	/* resume_offset is zero, which will cause a host reset */
-    }
-    return resume_offset;
-}
-
-
-/* A quick wrapper for sim710_intr_handle to grab the spin lock */
-
-static void
-do_sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
-{
-    struct Scsi_Host *host = dev_id;
-    unsigned long flags;
+	memset(hostdata, 0, sizeof(struct NCR_700_Host_Parameters));
 
-    spin_lock_irqsave(host->host_lock, flags);
-    sim710_intr_handle(irq, host, regs);
-    spin_unlock_irqrestore(host->host_lock, flags);
-}
-
-
-/* A "high" level interrupt handler */
-
-static void
-sim710_intr_handle(int irq, void *dev_id, struct pt_regs *regs)
-{
-    struct Scsi_Host * host = (struct Scsi_Host *)dev_id;
-    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
-    Scsi_Cmnd * cmd;
-    unsigned char istat, dstat;
-    unsigned char sstat0;
-    u32 scratch, dsps, resume_offset = 0;
-
-    istat = NCR_read8(ISTAT_REG);
-    if (!(istat & (ISTAT_SIP|ISTAT_DIP)))
-	return;
-    else {
-	sim710_intrs++;
-	dsps = NCR_read32(DSPS_REG);
-	hostdata->state = STATE_HALTED;
-	sstat0 = dstat = 0;
-	scratch = NCR_read32(SCRATCH_REG);
-	if (istat & ISTAT_SIP) {
-	    sstat0 = NCR_read8(SSTAT0_REG);
-	}
-	if (istat & ISTAT_DIP) {
-	    udelay(10);		/* Some comment somewhere about 10cycles
-				 * between accesses to sstat0 and dstat ??? */
-	    dstat = NCR_read8(DSTAT_REG);
-	}
-	DEB(DEB_INTS, printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
-		"dstat %02x, dsp [%04x], scratch %02x\n",
-	    host->host_no, sim710_intrs, istat, sstat0, dstat,
-	    (u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
-	    scratch));
-	if (scratch & 0x100) {
-	    u8 *p = hostdata->msgin_buf;
-	    
-	    DEB(DEB_INTS, printk("  msgin_buf: %02x %02x %02x %02x\n",
-			p[0], p[1], p[2], p[3]));
-	}
-	if ((dstat & DSTAT_SIR) && dsps == A_int_reselected) {
-	    /* Reselected.  Identify the target from LCRC_REG, and
-	     * update current command.  If we were trying to select
-	     * a device, then that command needs to go back on the
-	     * issue_queue for later.
-	     */
-	    unsigned char lcrc = NCR_read8(LCRC_REG_10);
-	    int id = 0;
-
-	    if (!(lcrc & 0x7f)) {
-		printk("scsi%d: Reselected with LCRC = %02x\n",
-			host->host_no, lcrc);
-		cmd = NULL;
-	    }
-	    else {
-		while (!(lcrc & 1)) {
-		    id++;
-		    lcrc >>= 1;
-		}
-		DEB(DEB_DISC, printk("scsi%d: Reselected by ID %d\n",
-			host->host_no, id));
-		if (hostdata->running) {
-		    /* Clear SIGP */
-		    (void)NCR_read8(CTEST2_REG_700);
-
-		    DEB(DEB_DISC, printk("scsi%d: Select of %d interrupted "
-				"by reselect from %d (%p)\n",
-				host->host_no, hostdata->running->target,
-				id, hostdata->target[id].cur_cmd));
-		    cmd = hostdata->running;
-		    hostdata->target[cmd->target].cur_cmd = NULL;
-		    cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
-		    hostdata->issue_queue = cmd;
-		}
-		cmd = hostdata->running = hostdata->target[id].cur_cmd;
-	    }
+	if(request_region(base_addr, 64, "sim710") == NULL) {
+		printk(KERN_ERR "sim710: Failed to reserve IO region 0x%lx\n",
+		       base_addr);
+		goto out_free;
 	}
-	else
-	    cmd = hostdata->running;
 
-	if (!cmd) {
-	    printk("scsi%d: No active command!\n", host->host_no);
-	    printk("scsi%d: Int %d, istat %02x, sstat0 %02x "
-		"dstat %02x, dsp [%04x], scratch %02x, dsps %08x\n",
-		host->host_no, sim710_intrs, istat, sstat0, dstat,
-		(u32 *)(isa_bus_to_virt(NCR_read32(DSP_REG))) - hostdata->script,
-		NCR_read32(SCRATCH_REG), dsps);
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-	else if (sstat0 & SSTAT0_700_STO) {
-	    DEB(DEB_TOUT, printk("scsi%d: Selection timeout\n", host->host_no));
-	    cmd->result = DID_NO_CONNECT << 16;
-	    SCSI_DONE(cmd);
-	    hostdata->target[cmd->target].cur_cmd = NULL;
-	    resume_offset = Ent_reselect;
-	}
-	else if (sstat0 & (SSTAT0_SGE|SSTAT0_UDC|SSTAT0_RST|SSTAT0_PAR)) {
-	    printk("scsi%d: Serious error, sstat0 = %02x\n", host->host_no,
-			    sstat0);
-	    sim710_errors++;
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-	else if (dstat & (DSTAT_BF|DSTAT_ABRT|DSTAT_SSI|DSTAT_WTD)) {
-	    printk("scsi%d: Serious error, dstat = %02x\n", host->host_no,
-			    dstat);
-	    sim710_errors++;
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-	else if (dstat & DSTAT_SIR)
-	    resume_offset = handle_script_int(host, cmd);
-	else if (sstat0 & SSTAT0_MA)
-	    resume_offset = handle_phase_mismatch(host, cmd);
-	else if (dstat & DSTAT_IID) {
-	    /* This can be due to a quick reselect while doing a WAIT
-	     * DISCONNECT.
-	     */
-	    resume_offset = handle_idd(host, cmd);
-	}
-	else {
-	    sim710_errors++;
-	    printk("scsi%d: Spurious interrupt!\n", host->host_no);
-	    /* resume_offset is zero, which will cause a host reset */
-	}
-    }
+	/* Fill in the three required pieces of hostdata */
+	hostdata->base = base_addr;
+	hostdata->differential = differential;
+	hostdata->clock = clock;
+	hostdata->chip710 = 1;
 
-    if (resume_offset) {
-	if (resume_offset == Ent_reselect) {
-	    hostdata->running = NULL;
-	    hostdata->state = STATE_IDLE;
+	/* and register the chip */
+	if((host = NCR_700_detect(sim710_global_info.tpnt, hostdata)) == NULL) {
+		printk(KERN_ERR "sim710: No host detected; card configuration problem?\n");
+		goto out_release;
 	}
-	else
-	    hostdata->state = STATE_BUSY;
-	DEB(DEB_RESUME, printk("scsi%d: Resuming at script[0x%x]\n",
-		host->host_no, resume_offset/4));
-#ifdef DEBUG_LIMIT_INTS
-	if (sim710_intrs < DEBUG_LIMIT_INTS)
-#endif
-	{
-	    NCR_write32(SCRATCH_REG, 0);
-	    NCR_write32(DSP_REG,
-		    isa_virt_to_bus(hostdata->script+resume_offset/4));
-	}
-	if (resume_offset == Ent_reselect)
-	    run_process_issue_queue(hostdata);
-    }
-    else {
-	printk("scsi%d: Failed to handle interrupt.  Failing commands "
-		"and resetting SCSI bus and chip\n", host->host_no);
-	mdelay(1000);		/* Give chance to read screen!! */
-	full_reset(host);
-    }
-
-}
 
+	host->irq = irq;
+	host->this_id = scsi_id;
 
-static void
-run_command (struct sim710_hostdata *hostdata, Scsi_Cmnd *cmd)
-{
-    struct Scsi_Host *host = cmd->host;
-    struct sim710_target *targdata = hostdata->target + cmd->target;
-    int i, datain, dataout, sg_start;
-    u32 *dip, *dop, dsa;
-
-    DEB(DEB_CMND, printk("scsi%d: id%d starting ", host->host_no,
-		cmd->target));
-    DEB(DEB_CMND, print_command(cmd->cmnd));
-
-    switch (cmd->cmnd[0]) {
-    case INQUIRY:
-    case MODE_SENSE:
-    case READ_6:
-    case READ_10:
-    case READ_CAPACITY:
-    case REQUEST_SENSE:
-    case READ_BLOCK_LIMITS:
-    case READ_TOC:
-        datain = 1;
-	dataout = 0;
-        break;
-    case MODE_SELECT:
-    case WRITE_6:
-    case WRITE_10:
-        datain = 0;
-        dataout = 1;
-        break;
-    case TEST_UNIT_READY:
-    case ALLOW_MEDIUM_REMOVAL:
-    case START_STOP:
-        datain = dataout = 0;
-        break;
-    default:
-        datain = dataout = 1;
-    }
-
-    memcpy(targdata->dsa_cdb, cmd->cmnd, MAX_CMND);
-
-    targdata->dsa_msgout[0] =
-		IDENTIFY((opt_nodisc[hostdata->chip] & (1<<cmd->target)) ? 0 : 1 ,0);
-    if (hostdata->negotiate & (1 << cmd->target)) {
-	if (opt_noneg[hostdata->chip] & (1 << cmd->target)) {
-	    hostdata->negotiate ^= (1 << cmd->target);
-	    targdata->dsa[DSA_MSGOUT] = 1;
-	}
-	else {
-	    DEB(DEB_SYNC, printk("scsi%d: Negotiating async transfers "
-		"for ID %d\n",
-		host->host_no, cmd->target));
-	    memcpy(targdata->dsa_msgout+1, async_message, sizeof(async_message));
-	    targdata->dsa[DSA_MSGOUT] = sizeof(async_message) + 1;
-	}
-    }
-    else
-	targdata->dsa[DSA_MSGOUT] = 1;
-
-    targdata->dsa_msgin[0] = 0xff;
-    targdata->dsa_status[0] = 0xff;
-
-    targdata->dsa[DSA_SELECT]		= (1 << cmd->target) << 16;
-    targdata->dsa[DSA_MSGOUT+1]		= isa_virt_to_bus(targdata->dsa_msgout);
-    targdata->dsa[DSA_CMND]		= cmd->cmd_len;
-    targdata->dsa[DSA_CMND+1]		= isa_virt_to_bus(targdata->dsa_cdb);
-    targdata->dsa[DSA_STATUS]		= 1;
-    targdata->dsa[DSA_STATUS+1]		= isa_virt_to_bus(targdata->dsa_status);
-    targdata->dsa[DSA_MSGIN]		= 1;
-    targdata->dsa[DSA_MSGIN+1]		= isa_virt_to_bus(targdata->dsa_msgin);
-
-    sg_start = (MAX_SG - (cmd->use_sg ? cmd->use_sg : 1)) * 2;
-    dip = targdata->dsa + DSA_DATAIN + sg_start;
-    dop = targdata->dsa + DSA_DATAOUT + sg_start;
-
-    for (i = 0; cmd->use_sg ? (i < cmd->use_sg) : !i; i++) {
-	struct scatterlist *sgl = &((struct scatterlist *)cmd->buffer)[i];
-	void *vbuf = cmd->use_sg ?
-		(page_address(sgl->page) + sgl->offset) :
-		(cmd->request_buffer);
-	u32 bbuf = isa_virt_to_bus(vbuf);
-	u32 cnt = cmd->use_sg ? sgl->length : cmd->request_bufflen;
-
-	if (datain) {
-	    *dip++	= cnt;
-	    *dip++	= bbuf;
-	}
-	if (dataout) {
-	    *dop++	= cnt;
-	    *dop++	= bbuf;
+	if(request_irq(irq, NCR_700_intr, SA_SHIRQ, "sim710", host)) {
+		printk(KERN_ERR "sim710: irq problem with %d, detaching\n",
+		       irq);
+		goto out_unregister;
 	}
-    }
-    targdata->data_out_jump = hostdata->script[Ent_patch_output_data/4+1] =
-	isa_virt_to_bus(hostdata->script + Ent_patch_output_data/4 + sg_start + 2);
-    targdata->data_in_jump = hostdata->script[Ent_patch_input_data/4+1] =
-	isa_virt_to_bus(hostdata->script + Ent_patch_input_data/4 + sg_start + 2);
-
-    for (i = 0, dsa = isa_virt_to_bus(targdata->dsa); i < 4; i++) {
-	u32 v = hostdata->script[Ent_patch_new_dsa/4 + i * 2];
-
-	v &= ~0x0000ff00;
-	v |= (dsa & 0xff) << 8;
-	hostdata->script[Ent_patch_new_dsa/4 + i * 2] = v;
-	dsa >>= 8;
-    }
-    hostdata->running = targdata->cur_cmd = cmd;
-    hostdata->state = STATE_BUSY;
 
-    NCR_write8(ISTAT_REG, ISTAT_10_SIGP);
-}
-
-
-static volatile int process_issue_queue_running = 0;
- 
-static __inline__ void 
-run_process_issue_queue(struct sim710_hostdata *hostdata)
-{
-    unsigned long flags;
-    save_flags (flags);
-    cli();
-    if (!process_issue_queue_running) {
-	process_issue_queue_running = 1;
-	process_issue_queue(hostdata, flags);
-	/*
-	 * process_issue_queue_running is cleared in process_issue_queue
-	 * once it can't do more work, and process_issue_queue exits with
-	 * interrupts disabled.
-	 */
-    }
-    restore_flags (flags);
-}
+	scsi_set_device(host, dev);
+	hostdata->dev = dev;
 
+	sim710_global_info.found++;
 
-/*
- * Function : process_issue_queue (hostdata, flags)
- *
- * Purpose : Start next command for any idle target.
- * 
- * NOTE : process_issue_queue exits with interrupts *disabled*, so the 
- *	caller must reenable them if it desires.
- * 
- * NOTE : process_issue_queue should be called from both 
- *	sim710_queue_command() and from the interrupt handler 
- *	after command completion.
- */
-
-static void 
-process_issue_queue (struct sim710_hostdata *hostdata, unsigned long flags)
-{
-    Scsi_Cmnd *tmp, *prev;
-    int done;
-
-    /*
-     * We run (with interrupts disabled) until we're sure that none of 
-     * the host adapters have anything that can be done, at which point 
-     * we set process_issue_queue_running to 0 and exit.
-     *
-     * Interrupts are enabled before doing various other internal 
-     * instructions, after we've decided that we need to run through
-     * the loop again.
-     *
-     */
-
-    do {
-	cli(); /* Freeze request queues */
-	done = 1;
-	if (hostdata->issue_queue) {
-	    if (hostdata->state == STATE_DISABLED) {
-		tmp = (Scsi_Cmnd *) hostdata->issue_queue;
-		hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
-		tmp->result = (DID_BAD_TARGET << 16);
-		tmp->scsi_done (tmp);
-		done = 0;
-	    }
-	    else if (hostdata->state == STATE_IDLE) {
-		for (tmp = hostdata->issue_queue, prev = NULL; tmp;
-				prev = tmp, tmp = (Scsi_Cmnd *) tmp->SCp.ptr) {
-		    if (hostdata->target[tmp->target].cur_cmd == NULL) {
-			if (prev)
-			    prev->SCp.ptr = tmp->SCp.ptr;
-			else
-			    hostdata->issue_queue = (Scsi_Cmnd *) tmp->SCp.ptr;
-			tmp->SCp.ptr = NULL;
-			run_command (hostdata, tmp);
-			done = 0;
-		    } /* if target/lun is not busy */
-		} /* scan issue queue for work */
-	    } /* host is idle */
-	} /* if hostdata->issue_queue */
-	if (!done)
-	    restore_flags (flags);
-    } while (!done);
-    process_issue_queue_running = 0;
-}
-
-
-int
-sim710_queuecommand(Scsi_Cmnd * cmd, void (*done)(Scsi_Cmnd *))
-{
-    struct Scsi_Host *host = cmd->host;
-    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)host->hostdata[0];
-    Scsi_Cmnd *tmp;
-    unsigned long flags;
-
-    if (cmd->lun) {
-	/* Silently ignore luns other than zero! */
-	cmd->result = (DID_BAD_TARGET << 16);
-	done(cmd);
-	return 0;
-    }
-
-    DEB(DEB_CMND, printk("scsi%d: id%d queuing ", host->host_no,
-		cmd->target));
-    DEB(DEB_CMND, print_command(cmd->cmnd));
-
-    cmd->scsi_done = done;
-    cmd->host_scribble = NULL;
-    cmd->SCp.ptr = NULL;
-    cmd->SCp.buffer = NULL;
-
-    save_flags(flags);
-    cli();
-
-    if (ignore_ids[hostdata->chip] & (1 << cmd->target)) {
-	printk("scsi%d: ignoring target %d\n", host->host_no, cmd->target);
-	cmd->result = (DID_BAD_TARGET << 16);
-	done(cmd);
-	restore_flags (flags);
-	return 0;
-    }
-#ifdef DEBUG_LIMIT_INTS
-    if (sim710_intrs > DEBUG_LIMIT_INTS) {
-	cmd->result = (DID_BAD_TARGET << 16);
-	done(cmd);
-	restore_flags (flags);
 	return 0;
-    }
-#endif
-    if (cmd->use_sg > MAX_SG)
-	panic ("cmd->use_sg = %d\n", cmd->use_sg);
 
-    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {
-        cmd->SCp.ptr = (unsigned char *) hostdata->issue_queue;
-        hostdata->issue_queue = cmd;
-    } else {
-        for (tmp = hostdata->issue_queue; tmp->SCp.ptr;
-                tmp = (Scsi_Cmnd *) tmp->SCp.ptr);
-        tmp->SCp.ptr = (unsigned char *) cmd;
-    }
-    restore_flags (flags);
-    run_process_issue_queue(hostdata);
-    return 0;
+ out_unregister:
+	scsi_unregister(host);
+ out_release:
+	release_region(host->base, 64);
+ out_free:
+	kfree(hostdata);
+ out:
+	return -ENODEV;
 }
 
+#ifdef CONFIG_MCA
+static short sim710_mca_id_table[] = { 0x01bb, 0x01ba, 0x004f, 0};
 
 __init int
-sim710_detect(Scsi_Host_Template * tpnt)
+sim710_mca_probe(struct device *dev)
 {
-    unsigned char scsi_id;
-    unsigned int base_addr;
-    struct Scsi_Host * host = NULL;
-    struct sim710_hostdata *hostdata;
-    unsigned long timeout;
-    unsigned long irq_mask;
-    int requested_irq;
-    int probed_irq;
-    u32 dsps;
-    int chips = 0;
-    int limit;
-    int indx;
-    int revision;
-    int size;
-    volatile u8 tmp;
-    struct Scsi_Host *our_hosts[MAXBOARDS+1];
-
-#ifdef MODULE
-    if (sim710)
-	param_setup(sim710);
-#endif
-
-    if (no_of_boards < 0) {
-	printk("sim710: NCR53C710 driver disabled\n");
-	return 0;
-    }
-
-#ifdef CONFIG_MCA
-    /* If board details have been specified via boot/module parameters,
-     * then don't bother probing.
-     */
-    if (no_of_boards == 0) {
-	int slot;
+	struct mca_device *mca_dev = to_mca_device(dev);
+	int slot = mca_dev->slot;
 	int pos[3];
-	int mca_53c710_ids[] = MCA_53C710_IDS;
-	int *id_to_check = mca_53c710_ids;
+	unsigned int base;
+	int irq_vector;
+	short id = sim710_mca_id_table[mca_dev->index];
 	static int io_004f_by_pos[] = MCA_004F_IO_PORTS;
 	static int irq_004f_by_pos[] = MCA_004F_IRQS;
 	static int io_01bb_by_pos[] = MCA_01BB_IO_PORTS;
 	static int irq_01bb_by_pos[] = MCA_01BB_IRQS;
+	char *name;
+	int clock;
 
-	while ( *id_to_check && no_of_boards < MAXBOARDS) {
-	    if (!MCA_bus)
-		return 0;
-
-	    if ((slot = mca_find_adapter(*id_to_check, 0)) != MCA_NOTFOUND) {
-
-		pos[0] = mca_read_stored_pos(slot, 2);
-		pos[1] = mca_read_stored_pos(slot, 3);
-		pos[2] = mca_read_stored_pos(slot, 4);
-
-		/*
-		 * 01BB & 01BA port base by bits 7,6,5,4,3,2 in pos[2]
-		 *
-		 *    000000  <disabled>   001010  0x2800
-		 *    000001  <invalid>    001011  0x2C00
-		 *    000010  0x0800       001100  0x3000
-		 *    000011  0x0C00       001101  0x3400
-		 *    000100  0x1000       001110  0x3800
-		 *    000101  0x1400       001111  0x3C00
-		 *    000110  0x1800       010000  0x4000
-		 *    000111  0x1C00       010001  0x4400
-		 *    001000  0x2000       010010  0x4800
-		 *    001001  0x2400       010011  0x4C00
-		 *                         010100  0x5000
-		 *
-		 * 00F4 port base by bits 3,2,1 in pos[0]
-		 *
-		 *    000  <disabled>      001    0x200
-		 *    010  0x300           011    0x400
-		 *    100  0x500           101    0x600
-		 *
-		 * 01BB & 01BA IRQ is specified in pos[0] bits 7 and 6:
-		 *
-		 *    00   3               10   11
-		 *    01   5               11   14
-		 *
-		 * 00F4 IRQ specified by bits 6,5,4 in pos[0]
-		 *
-		 *    100   5              101    9
-		 *    110   14
-		 */
-
-		if ( *id_to_check == 0x01bb || *id_to_check == 0x01ba ) {
-		    bases[no_of_boards] = io_01bb_by_pos[(pos[2] & 0xFC) >> 2];
-		    irq_vectors[no_of_boards] =
-				irq_01bb_by_pos[((pos[0] & 0xC0) >> 6)];
-		    if (bases[no_of_boards] == 0x0000)
-			printk("sim710: NCR53C710 Adapter ID 0x01bb is disabled.\n");
-		    else {
-			no_of_boards++;
-			if ( *id_to_check == 0x01bb )
-			    mca_set_adapter_name( slot,
-				    "NCR 3360/3430 SCSI SubSystem" );
-			else
-			    mca_set_adapter_name(slot,
-				    "NCR Dual SIOP SCSI Host Adapter Board");
-		    }
-		}
-		else if ( *id_to_check == 0x004f ) {
-		    bases[no_of_boards] = io_004f_by_pos[((pos[0] & 0x0E) >> 1)];
-		    irq_vectors[no_of_boards] =
-				irq_004f_by_pos[((pos[0] & 0x70) >> 4) - 4];
-		    if (bases[no_of_boards] == 0x0000)
-			printk("sim710: NCR53C710 Adapter ID 0x004f is disabled.\n");
-		    else {
-			no_of_boards++;
-			mca_set_adapter_name(slot,
-				"NCR 53c710 SCSI Host Adapter Board");
-		    }
-		}
-	    }
-	    id_to_check++;
-	}
-    }
-#endif
+	pos[0] = mca_device_read_stored_pos(mca_dev, 2);
+	pos[1] = mca_device_read_stored_pos(mca_dev, 3);
+	pos[2] = mca_device_read_stored_pos(mca_dev, 4);
 
-#ifdef CONFIG_EISA
-    /* Auto probe, if no boards specified in boot parameters */
-    if (no_of_boards == 0) {
-	int io_addr;
-	/* reverse probe, so my on-board controller at 0x9000 is always scsi0 */
-	for (io_addr = 0x9000; no_of_boards < MAXBOARDS && io_addr >= 0x1000; io_addr -= 0x1000) {
-	    if (request_region(io_addr, 0x40, "sim710") != NULL) {
-		int id0 = inw(io_addr + 0xc80);
-		int id1 = inw(io_addr + 0xc82);
-		/* The on-board controller on my Proliant 2000 is 0x1044,
-		 * my EISA card is 0x1144.
-		 */
-		if (id0 == 0x110e && (id1 == 0x1044 || id1 == 0x1144)) {
-		    bases[no_of_boards] = io_addr;
-#if 0
-		    /* This should detect the IRQ, but I havn't proved it for
-		     * myself.  Leave the old probe code active for now, as
-		     * no-one has reported problems with it.
-		     */
-		    switch (inb(io_addr + 0xc88)) {
-			case (0x00):
-			    irq_vectors[no_of_boards] = 11;
-			    break;
-			case (0x01):
-			    irq_vectors[no_of_boards] = 14;
-			    break;
-			case (0x02):
-			    irq_vectors[no_of_boards] = 15;
-			    break;
-			case (0x03):
-			    irq_vectors[no_of_boards] = 10;
-			    break;
-			case (0x04):
-			    irq_vectors[no_of_boards] = 9;
-			    break;
-			default:
-			    printk("sim710.c: irq nasty\n");
-		    }
-#endif
-		    no_of_boards++;
-		}
-		release_region(io_addr, 64);
-	    }
-	}
-    }
-#endif
-      
-    if (!no_of_boards) {
-	printk("sim710: No NCR53C710 adapter found.\n");
-	return 0;
-    }
-
-    size = sizeof(struct sim710_hostdata);
-    hostdata_order = 0;
-    while (size > (PAGE_SIZE << hostdata_order))
-	hostdata_order++;
-    size = PAGE_SIZE << hostdata_order;
-
-    DEB(DEB_ANY, printk("sim710: hostdata %d bytes, size %d, order %d\n",
-	sizeof(struct sim710_hostdata), size, hostdata_order));
-
-    tpnt->proc_name = "sim710";
-
-    memset(our_hosts, 0, sizeof(our_hosts));
-    for (indx = 0; indx < no_of_boards; indx++) {
-        unsigned long page = __get_free_pages(GFP_ATOMIC, hostdata_order);
-        if(page == 0UL)
-        {
-		printk(KERN_WARNING "sim710: out of memory registering board %d.\n", indx);
-		break;
-        }
-	host = scsi_register(tpnt, 4);
-	if(host == NULL) {
-	    free_pages(host->hostdata[0], hostdata_order);
-	    break;
-	}
-	our_hosts[chips] = host;
-	host->hostdata[0] = page;
-	hostdata = (struct sim710_hostdata *)host->hostdata[0];
-	memset(hostdata, 0, size);
-	scsi_id = 7;
-	base_addr = bases[indx];
-	requested_irq = irq_vectors[indx];
-	printk("scsi%d: Configuring Sim710 (SCSI-ID %d) at %x, IRQ %d\n",
-			host->host_no, scsi_id, base_addr, requested_irq);
-	DEB(DEB_ANY, printk("sim710: hostdata = %p (%d bytes), dsa0 = %p\n",
-			hostdata, sizeof(struct sim710_hostdata),
-			 hostdata->target[0].dsa));
-	hostdata->chip = indx;
-	host->irq = requested_irq;
-	host->this_id = scsi_id;
-	host->unique_id = base_addr;
-	host->base = base_addr;
-	hostdata->msg_reject = MESSAGE_REJECT;
-
-	if (ncr_halt(host)) {
-	    free_pages(host->hostdata[0], hostdata_order);
-	    scsi_unregister (host);
-	    printk("scsi%d: Failed to initialise 53c710 at address %x\n",
-			host->host_no, base_addr);
-	    continue;
-	}
-	DEB(DEB_ANY,ncr_dump(host));
-	revision = (NCR_read8(CTEST8_REG) & 0xF0) >> 4;
-	printk("scsi%d: Revision 0x%x\n",host->host_no,revision);
-	sim710_soft_reset(host);
-
-	sim710_driver_init(host);
-
-	request_region((u32)host->base, 64, "sim710");
-	/* Now run test1 */
-	hostdata->test1_src = 0x53c710aa;
-	hostdata->test1_dst = 0x76543210;
-	NCR_write32(DSPS_REG, 0x89abcdef);
-	irq_mask = probe_irq_on();
-	NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_test1/4));
-	timeout = 5;
-	while (hostdata->test1_dst != hostdata->test1_src && timeout--)
-	    mdelay(100);
-	tmp = NCR_read8(ISTAT_REG);
-	tmp = NCR_read8(SSTAT0_REG);
-	udelay(10);
-	tmp = NCR_read8(DSTAT_REG);
-	probed_irq = probe_irq_off(irq_mask);
-	if (requested_irq == 0) {
-	    if (probed_irq > 0) {
-		printk("scsi%d: Chip is using IRQ %d\n", host->host_no,
-			probed_irq);
-		requested_irq = host->irq = probed_irq;
-	    }
-	    else {
-		printk("scsi%d: Failed to probe for IRQ (returned %d)\n",
-			host->host_no, probed_irq);
-		ncr_halt(host);
-		free_pages(host->hostdata[0], hostdata_order);
-		scsi_unregister (host);
-		release_region((u32)host->base, 64);
-		continue;
-	    }
-	}
-	else if (probed_irq > 0 && probed_irq != requested_irq)
-	    printk("scsi%d: WARNING requested IRQ %d, but probed as %d\n",
-			host->host_no, requested_irq, probed_irq);
-	else if (probed_irq <= 0)
-	    printk("scsi%d: WARNING IRQ probe failed, (returned %d)\n",
-			host->host_no, probed_irq);
-	
-	dsps = NCR_read32(DSPS_REG);
-	if (hostdata->test1_dst != 0x53c710aa || dsps != A_int_test1) {
-	    if (hostdata->test1_dst != 0x53c710aa)
-		printk("scsi%d: test 1 FAILED: data: exp 0x53c710aa, got 0x%08x\n",
-			host->host_no, hostdata->test1_dst);
-	    if (dsps != A_int_test1)
-		printk("scsi%d: test 1 FAILED: dsps: exp 0x%08x, got 0x%08x\n",
-			host->host_no, A_int_test1, dsps);
-	    ncr_dump(host);
-	    ncr_halt(host);
-	    free_pages(host->hostdata[0], hostdata_order);
-	    scsi_unregister (host);
-	    release_region((u32)host->base, 64);
-	    continue;
-	}
-	printk("scsi%d: test 1 completed ok.\n", host->host_no);
-
-	NCR_write32(DSP_REG, virt_to_bus(hostdata->script+Ent_reselect/4));
-	hostdata->state = STATE_IDLE;
-	chips++;
-    }
-    /* OK, now run down our_hosts[] calling request_irq(... SA_SHIRQ ...).
-     * Couldn't call request_irq earlier, as probing would have failed.
-     */
-    for (indx = 0, limit = chips; indx < limit; indx++) {
-	host = our_hosts[indx];
-	if (request_irq(host->irq, do_sim710_intr_handle,
-                       SA_INTERRUPT | SA_SHIRQ, "sim710", host))
-	{
-	    printk("scsi%d : IRQ%d not free, detaching\n",
-			host->host_no, host->irq);
-	    ncr_halt(host);
-	    free_pages(host->hostdata[0], hostdata_order);
-	    scsi_unregister (host);
-	    chips--;
-	}
-    }
-
-    return chips;
-}
+	/*
+	 * 01BB & 01BA port base by bits 7,6,5,4,3,2 in pos[2]
+	 *
+	 *    000000  <disabled>   001010  0x2800
+	 *    000001  <invalid>    001011  0x2C00
+	 *    000010  0x0800       001100  0x3000
+	 *    000011  0x0C00       001101  0x3400
+	 *    000100  0x1000       001110  0x3800
+	 *    000101  0x1400       001111  0x3C00
+	 *    000110  0x1800       010000  0x4000
+	 *    000111  0x1C00       010001  0x4400
+	 *    001000  0x2000       010010  0x4800
+	 *    001001  0x2400       010011  0x4C00
+	 *                         010100  0x5000
+	 *
+	 * 00F4 port base by bits 3,2,1 in pos[0]
+	 *
+	 *    000  <disabled>      001    0x200
+	 *    010  0x300           011    0x400
+	 *    100  0x500           101    0x600
+	 *
+	 * 01BB & 01BA IRQ is specified in pos[0] bits 7 and 6:
+	 *
+	 *    00   3               10   11
+	 *    01   5               11   14
+	 *
+	 * 00F4 IRQ specified by bits 6,5,4 in pos[0]
+	 *
+	 *    100   5              101    9
+	 *    110   14
+	 */
 
-int
-sim710_abort(Scsi_Cmnd * cmd)
-{
-    struct Scsi_Host * host = cmd->host;
+	if (id == 0x01bb || id == 0x01ba) {
+		base = io_01bb_by_pos[(pos[2] & 0xFC) >> 2];
+		irq_vector =
+			irq_01bb_by_pos[((pos[0] & 0xC0) >> 6)];
+
+		clock = 50;
+		if (id == 0x01bb)
+			name = "NCR 3360/3430 SCSI SubSystem";
+		else
+			name = "NCR Dual SIOP SCSI Host Adapter Board";
+	} else if ( id == 0x004f ) {
+		base = io_004f_by_pos[((pos[0] & 0x0E) >> 1)];
+		irq_vector =
+			irq_004f_by_pos[((pos[0] & 0x70) >> 4) - 4];
+		clock = 50;
+		name = "NCR 53c710 SCSI Host Adapter Board";
+	} else {
+		return -ENODEV;
+	}
+	strncpy(dev->name, name, sizeof(dev->name));
+	mca_device_set_claim(mca_dev, 1);
+	base = mca_device_transform_ioport(mca_dev, base);
+	irq_vector = mca_device_transform_irq(mca_dev, irq_vector);
+
+	return sim710_probe_common(dev, base, irq_vector, clock,
+				   0, id_array[slot]);
+}
+
+struct mca_driver sim710_mca_driver = {
+	.id_table = sim710_mca_id_table,
+	.driver = {
+		.name = "sim710",
+		.bus = &mca_bus_type,
+		.probe = sim710_mca_probe,
+	},
+};
 
-    printk("scsi%d: Unable to abort command for target %d\n",
-	   host->host_no, cmd->target);
-    return FAILED;
-}
+#endif /* CONFIG_MCA */
 
-/*
- * This is a device reset.  Need to select and send a Bus Device Reset msg.
- */
+#ifdef CONFIG_EISA
+struct eisa_device_id sim710_eisa_ids[] = {
+	{ "CPQ4410" },
+	{ "CPQ4411" },
+	{ "HWP0C80" },
+	{ "" }
+};
 
-int
-sim710_dev_reset(Scsi_Cmnd * SCpnt)
+__init int
+sim710_eisa_probe(struct device *dev)
 {
-    struct Scsi_Host * host = SCpnt->host;
+	struct eisa_device *edev = to_eisa_device(dev);
+	unsigned long io_addr = edev->base_addr;
+	char eisa_cpq_irqs[] = { 11, 14, 15, 10, 9, 0 };
+	char eisa_hwp_irqs[] = { 3, 4, 5, 7, 12, 10, 11, 0};
+	char *eisa_irqs;
+	unsigned char irq_index;
+	unsigned char irq, differential = 0, scsi_id = 7;
+
+	if(strcmp(edev->id.sig, "HWP0C80") == 0) {
+		printk(KERN_NOTICE "sim710: FOUND HP CARD!\n");
+		eisa_irqs =  eisa_hwp_irqs;
+		irq_index = (inb(io_addr + 0xc85) & 0x7) - 1;
+		scsi_id = ffs(inb(io_addr + 0x4));
+	} else {
+		eisa_irqs = eisa_cpq_irqs;
+		irq_index = inb(io_addr + 0xc88);
+	}
+
+	printk(KERN_NOTICE "IRQ_INDEX %d, %d\n", irq_index,
+	       strlen(eisa_irqs));
+		
+	if(irq_index >= strlen(eisa_irqs)) {
+		printk("sim710.c: irq nasty\n");
+		return -ENODEV;
+	}
+
+	irq = eisa_irqs[irq_index];
+		
+	return sim710_probe_common(dev, io_addr, irq, 50,
+				   differential, scsi_id);
+}
+
+struct eisa_driver sim710_eisa_driver = {
+	.id_table = sim710_eisa_ids,
+	.driver = {
+		.name =		"sim710",
+		.probe =	sim710_eisa_probe,
+		.remove =	__devexit_p(sim710_device_remove),
+	},
+};
 
-    printk("scsi%d: Unable to send Bus Device Reset for target %d\n",
-	   host->host_no, SCpnt->target);
-    return FAILED;
-}
+#endif /* CONFIG_EISA */
 
-/*
- * This is bus reset.  We need to reset the bus and fail any active commands.
- */
 
 int
-sim710_bus_reset(Scsi_Cmnd * SCpnt)
-{
-    struct Scsi_Host * host = SCpnt->host;
-
-    printk("scsi%d: Unable to do SCSI bus reset\n", host->host_no);
-    return FAILED;
-}
-
-static int
-full_reset(struct Scsi_Host * host)
+sim710_release(struct Scsi_Host *host)
 {
-    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)
-	    host->hostdata[0];
-    int target;
-    Scsi_Cmnd *cmd;
-
-    u32 istat, dstat = 0, sstat0 = 0, sstat1 = 0, dsp, dsps, scratch;
-    unsigned long flags;
-
-    save_flags(flags);
-    cli();
-
-    istat = NCR_read8(ISTAT_REG);
-    if (istat & ISTAT_SIP) {
-	sstat0 = NCR_read8(SSTAT0_REG);
-	sstat1 = NCR_read8(SSTAT1_REG);
-	udelay(10);
-    }
-    if (istat & ISTAT_DIP)
-	dstat = NCR_read8(DSTAT_REG);
-
-    if (ncr_halt(host)) {
-	restore_flags(flags);
-	return FAILED;
-    }
-    restore_flags(flags);
-    dsp = NCR_read32(DSP_REG);
-    dsps = NCR_read32(DSPS_REG);
-    scratch = NCR_read32(SCRATCH_REG);
-    printk("scsi%d: istat = %02x, sstat0 = %02x, sstat1 = %02x, dstat = %02x\n",
-		host->host_no, istat, sstat0, sstat1, dstat);
-    printk("scsi%d: dsp = %08x (script[0x%04x]), dsps = %08x, scratch = %08x\n",
-		host->host_no, dsp,
-		((u32)bus_to_virt(dsp) - (u32)hostdata->script)/4, dsps, scratch);
-
-    for (target = 0; target < 7; target++) {
-	if ((cmd = hostdata->target[target].cur_cmd)) {
-	    printk("scsi%d: Failing command for ID%d\n",
-			host->host_no, target);
-	    cmd->result = DID_RESET << 16;
-	    cmd->scsi_done(cmd);
-	    hostdata->target[target].cur_cmd = NULL;
-	}
-    }
+	struct D700_Host_Parameters *hostdata = 
+		(struct D700_Host_Parameters *)host->hostdata[0];
 
-    sim710_soft_reset(host);
-    sim710_driver_init(host);
-
-    NCR_write32(DSP_REG, isa_virt_to_bus(hostdata->script+Ent_reselect/4));
-    hostdata->state = STATE_IDLE;
-
-    run_process_issue_queue(hostdata);
-
-    return SUCCESS;
+	NCR_700_release(host);
+	kfree(hostdata);
+	free_irq(host->irq, host);
+	/* should do a refcount here and unregister the drivers when
+	 * it reaches zero */
+	return 1;
 }
 
-/*
- * This is host reset.  We need to reset the chip and the bus.
- */
-
-int
-sim710_host_reset(Scsi_Cmnd * SCpnt)
+int __init
+sim710_detect(Scsi_Host_Template *tpnt)
 {
-    struct Scsi_Host * host = SCpnt->host;
-
-    printk("scsi%d: >>>>>>>>>>>> Host reset <<<<<<<<<<<<\n", host->host_no);
-
-    return full_reset(host);
-}
+	sim710_global_info.tpnt = tpnt;
+	sim710_global_info.found = 0;
 
 #ifdef MODULE
+	if (sim710)
+		param_setup(sim710);
+#endif
 
-int
-sim710_release(struct Scsi_Host *host)
-{
-    ncr_halt(host);
-    free_pages(host->hostdata[0], hostdata_order);
-    free_irq(host->irq, host);
-    release_region((u32)host->base, 64);
-    return 1;
-}
+#ifdef CONFIG_MCA
+	if(MCA_bus)
+		mca_register_driver(&sim710_mca_driver);
+#endif
 
+#ifdef CONFIG_EISA
+	eisa_driver_register(&sim710_eisa_driver);
 #endif
+	return sim710_global_info.found;
+}
 
-static Scsi_Host_Template driver_template = SIM710_SCSI;
+static Scsi_Host_Template driver_template = {
+	.name =			"LSI (Symbios) 710 MCA/EISA",
+	.proc_name =		"sim710",
+	.detect =		sim710_detect,
+	.release =		sim710_release,
+	.this_id =		7,
+};
 
 #include "scsi_module.c"

Reply to: