⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sim710.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * sim710.c - Copyright (C) 1999 Richard Hirst <richard@sleepie.demon.co.uk> * *---------------------------------------------------------------------------- *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License as published by  *  the Free Software Foundation; either version 2 of the License, or *  (at your option) any later version. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program; if not, write to the Free Software *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *---------------------------------------------------------------------------- * * MCA card detection code by Trent McNair. * * 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" * * 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. * * Current limitations: * * o  Async only * o  Severely lacking in error recovery * o  Auto detection of IRQs and chip addresses only on MCA architectures * */#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/init.h>#include <linux/mca.h>#include <asm/dma.h>#include <asm/system.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,17)#include <linux/spinlock.h>#elif LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93)#include <asm/spinlock.h>#endif#include <asm/io.h>#include <asm/pgtable.h>#include <asm/byteorder.h>#include <linux/blk.h>#ifdef CONFIG_TP34V_SCSI#include <asm/tp34vhw.h>#define MEM_MAPPED#elif defined(CONFIG_MCA)#define IO_MAPPED/* * 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). */#define MCA_53C710_IDS { 0x01bb, 0x01ba, 0x004f }/* CARD ID 01BB and 01BA use the same pos values */#define MCA_01BB_IO_PORTS { 0x0000, 0x0000, 0x0800, 0x0C00, 0x1000, 0x1400, \			    0x1800, 0x1C00, 0x2000, 0x2400, 0x2800, \			    0x2C00, 0x3000, 0x3400, 0x3800, 0x3C00, \			    0x4000, 0x4400, 0x4800, 0x4C00, 0x5000  }#define MCA_01BB_IRQS { 3, 5, 11, 14 }/* CARD ID 004f */#define MCA_004F_IO_PORTS { 0x0000, 0x0200, 0x0300, 0x0400, 0x0500,  0x0600 }#define MCA_004F_IRQS { 5, 9, 14 }#else/* Assume an Intel platform */#define IO_MAPPED#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) xint sim710_debug = 0;#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 2	/* Increase this and the sizes of the			   arrays below, if you need more.. */#ifdef MODULEchar *sim710;		/* command line passed by insmod */MODULE_AUTHOR("Richard Hirst");MODULE_DESCRIPTION("Simple NCR53C710 driver");MODULE_PARM(sim710, "s");#endifstatic int sim710_errors = 0;	/* Count of error interrupts */static int sim710_intrs = 0;	/* Count of all interrupts */static int ignore_ids = 0;	/* Accept all SCSI IDs */static int opt_nodisc = 0;	/* Allow disconnect on all IDs */static int opt_noneg = 0;	/* Allow SDTR negotiation on all IDs */#ifdef CONFIG_TP34V_SCSI/* Special hardwired case for Tadpole TP34V at the moment, otherwise * boot parameters 'sim710=addr:0x8000,irq:15' (for example) must be given. */static int no_of_boards = 2;static unsigned int bases[MAXBOARDS] = {	TP34V_SCSI0_BASE, TP34V_SCSI1_BASE};static unsigned int irq_vectors[MAXBOARDS] = {	TP34V_SCSI0_VECTOR, TP34V_SCSI1_VECTOR};static unsigned int irq_index[MAXBOARDS] = {	TP34V_SCSI0_IRQ_INDEX, TP34V_SCSI1_IRQ_INDEX};#else/* All other cases use boot/module params, or auto-detect */static int no_of_boards = 0;static unsigned int bases[MAXBOARDS] = {	0};static unsigned int irq_vectors[MAXBOARDS] = {	0};#endif/* 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	1struct sim710_hostdata{    int state;    Scsi_Cmnd * issue_queue;    Scsi_Cmnd * running;    int chip;    u8 negotiate;    u8 reselected_identify;    u8 msgin_buf[MAX_MSGIN];    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: int param_setup(char *str) */#ifdef MODULE#define ARG_SEP ' '#else#define ARG_SEP ','#endifstatic intparam_setup(char *str){    char *cur = str;    char *pc, *pv;    int val;    int base;    int c;    no_of_boards = 0;    while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {	char *pe;	val = 0;	pv = pc;	c = *++pv;	if (c == 'n')	    val = 0;	else if	(c == 'y')	    val = 1;	else {	    base = 0;	    val = (int) simple_strtoul(pv, &pe, base);	}	if (!strncmp(cur, "addr:", 5)) {	    bases[0] = val;	    no_of_boards = 1;	}	else if	(!strncmp(cur, "irq:", 4))	    irq_vectors[0] = val;	else if	(!strncmp(cur, "ignore:", 7))	    ignore_ids = val;	else if	(!strncmp(cur, "nodisc:", 7))	    opt_nodisc = val;	else if	(!strncmp(cur, "noneg:", 6))	    opt_noneg = val;	else if	(!strncmp(cur, "disabled:", 5)) {	    no_of_boards = -1;	    return 1;	}#ifdef DEBUG	else if (!strncmp(cur, "debug:", 6)) {	    sim710_debug = val;	}#endif	else	    printk("sim710: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);	if ((cur = strchr(cur, ARG_SEP)) != NULL)	    ++cur;    }    return 1;}#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)#ifndef MODULE__setup("sim710=", param_setup);#endif#else/* Old boot param syntax support */voidsim710_setup(char *str, int *ints){    param_setup(str);}#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 void disable (struct Scsi_Host *host) */static voiddisable (struct Scsi_Host *host){    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)	host->hostdata[0];    hostdata->state = STATE_DISABLED;    printk (KERN_ALERT "scsi%d : disabled.  Unload and reload\n",		            host->host_no);}/* * 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 intncr_halt (struct Scsi_Host *host){    unsigned long flags;    unsigned char istat, tmp;    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)	host->hostdata[0];    int stage;    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     */    for (stage = 0;;) {	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 {		    printk(KERN_ALERT "scsi%d : could not halt NCR chip\n",			host->host_no);		    disable (host);	    	}    	    }	}	if (!(istat & (ISTAT_SIP|ISTAT_DIP))) {	    if (stage == 0)	    	++stage;	    else if (stage == 3)		break;	}    }    hostdata->state = STATE_HALTED;    restore_flags(flags);    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 voidsim710_soft_reset (struct Scsi_Host *host){    unsigned long flags;#ifdef CONFIG_TP34V_SCSI    struct sim710_hostdata *hostdata = (struct sim710_hostdata *)	host->hostdata[0];#endif    save_flags(flags);    cli();#ifdef CONFIG_TP34V_SCSI    tpvic.loc_icr[irq_index[hostdata->chip]].icr = 0x80;#endif    /*     * 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_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 |

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -