# 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 - 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 . 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 #include -#include -#include -#include -#include -#include -#include -#include -#include +#include +#include #include +#ifdef CONFIG_MCA #include -#include -#include -#include -#include -#include -#include -#include -#include +#endif +#ifdef CONFIG_EISA +#include +#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 - -#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<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 001010 0x2800 - * 000001 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 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 001010 0x2800 + * 000001 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 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"