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

📄 acornscsi.c.2

📁 arm平台上的uclinux系统全部源代码
💻 2
📖 第 1 页 / 共 5 页
字号:
/* * linux/arch/arm/drivers/scsi/acornscsi.c * *  Acorn SCSI 3 driver *  By R.M.King. * * Abandoned using the Select and Transfer command since there were * some nasty races between our software and the target devices that * were not easy to solve, and the device errata had a lot of entries * for this command, some of them quite nasty... * * Changelog: *  26-Sep-1997	RMK	Re-jigged to use the queue module. *			Re-coded state machine to be based on driver *			state not scsi state.  Should be easier to debug. *			Added acornscsi_release to clean up properly. *			Updated proc/scsi reporting. *  05-Oct-1997	RMK	Implemented writing to SCSI devices. *  06-Oct-1997	RMK	Corrected small (non-serious) bug with the connect/ *			reconnect race condition causing a warning message. */#define DEBUG_NO_WRITE	1#define DEBUG_QUEUES	2#define DEBUG_DMA	4#define DEBUG_ABORT	8#define DEBUG_DISCON	16#define DEBUG_CONNECT	32#define DEBUG_PHASES	64#define DEBUG_WRITE	128#define DEBUG_LINK	256#define DEBUG_MESSAGES	512#define DEBUG_RESET	1024#define DEBUG_ALL	(DEBUG_RESET|DEBUG_MESSAGES|DEBUG_LINK|DEBUG_WRITE|\			 DEBUG_PHASES|DEBUG_CONNECT|DEBUG_DISCON|DEBUG_ABORT|\			 DEBUG_DMA|DEBUG_QUEUES|DEBUG_NO_WRITE)/* DRIVER CONFIGURATION * * SCSI-II Tagged queue support. * * I don't have any SCSI devices that support it, so it is totally untested * (except to make sure that it doesn't interfere with any non-tagging * devices).  It is not fully implemented either - what happens when a * tagging device reconnects??? * * You can tell if you have a device that supports tagged queueing my * cating (eg) /proc/scsi/acornscsi/0 and see if the SCSI revision is reported * as '2 TAG'. */#define SCSI2_TAG/* * SCSI-II Linked command support. * * The higher level code doesn't support linked commands yet. */#undef SCSI2_LINK/* * SCSI-II Synchronous transfer support. * * Tried and tested... * * SDTR_SIZE	  - maximum number of un-acknowledged bytes (0 = off, 12 = max) * SDTR_PERIOD	  - period of REQ signal (min=125, max=1020) * DEFAULT_PERIOD - default REQ period. */#define SCSI2_SYNC#define SDTR_SIZE	12#define SDTR_PERIOD	125#define DEFAULT_PERIOD	500/* * Debugging information * * DEBUG	  - bit mask from list above * DEBUG_TARGET   - is defined to the target number if you want to debug *		    a specific target. [only recon/write/dma]. */#define DEBUG (DEBUG_RESET|DEBUG_WRITE|DEBUG_NO_WRITE)/* only allow writing to SCSI device 0 */#define NO_WRITE 0xFE/*#define DEBUG_TARGET 2*//* * Select timeout time (in 10ms units) * * This is the timeout used between the start of selection and the WD33C93 * chip deciding that the device isn't responding. */#define TIMEOUT_TIME 10/* * Define this if you want to have verbose explaination of SCSI * status/messages. */#undef CONFIG_ACORNSCSI_CONSTANTS/* * Define this if you want to use the on board DMAC */#define USE_DMAC/* * List of devices that the driver will recognise */#define ACORNSCSI_LIST { MANU_ACORN, PROD_ACORN_SCSI }/* * ==================================================================================== */#ifdef DEBUG_TARGET#define DBG(cmd,xxx...) \  if (cmd->target == DEBUG_TARGET) { \    xxx; \  }#else#define DBG(cmd,xxx...) xxx#endif#ifndef STRINGIFY#define STRINGIFY(x) #x#endif#define STR(x) STRINGIFY(x)#define NO_WRITE_STR STR(NO_WRITE)#include <linux/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/sched.h>#include <linux/string.h>#include <linux/signal.h>#include <linux/errno.h>#include <linux/proc_fs.h>#include <linux/stat.h>#include <linux/ioport.h>#include <asm/bitops.h>#include <asm/delay.h>#include <asm/system.h>#include <asm/io.h>#include <asm/ecard.h>#include "../block/blk.h"#include "scsi.h"#include "hosts.h"#include "acornscsi.h"#include "constants.h"#define VER_MAJOR 2#define VER_MINOR 0#define VER_PATCH 3#ifndef ABORT_TAG#define ABORT_TAG 0xd#else#error "Yippee!  ABORT TAG is now defined!  Remove this error!"#endif#ifndef NO_IRQ#define NO_IRQ 255#endif/* * DMAC setup parameters */ #define INIT_DEVCON0	(DEVCON0_RQL|DEVCON0_EXW|DEVCON0_CMP)#define INIT_DEVCON1	(DEVCON1_BHLD)#define DMAC_READ	(MODECON_READ)#define DMAC_WRITE	(MODECON_WRITE)#define INIT_SBICDMA	(CTRL_DMABURST)#ifdef SCSI2_LINK#error SCSI2 LINKed commands not supported (yet)!#endif/* * Size of on-board DMA buffer */#define DMAC_BUFFER_SIZE	65536/* * This is used to dump the previous states of the SBIC */static struct status_entry {	unsigned long	when;	unsigned char	ssr;	unsigned char	ph;	unsigned char	irq;	unsigned char	unused;} status[9][16];static unsigned char status_ptr[9];#define ADD_STATUS(_q,_ssr,_ph,_irq) \({							\	status[(_q)][status_ptr[(_q)]].when = jiffies;	\	status[(_q)][status_ptr[(_q)]].ssr  = (_ssr);	\	status[(_q)][status_ptr[(_q)]].ph   = (_ph);	\	status[(_q)][status_ptr[(_q)]].irq  = (_irq);	\	status_ptr[(_q)] = (status_ptr[(_q)] + 1) & 15;	\})unsigned int sdtr_period = SDTR_PERIOD;unsigned int sdtr_size   = SDTR_SIZE;static struct proc_dir_entry proc_scsi_acornscsi = {	PROC_SCSI_EATA, 9, "acornscsi", S_IFDIR | S_IRUGO | S_IXUGO, 2};static void acornscsi_done (AS_Host *host, Scsi_Cmnd **SCpntp, unsigned int result);static int acornscsi_reconnect_finish (AS_Host *host);static void acornscsi_dma_cleanup (AS_Host *host);static void acornscsi_abortcmd (AS_Host *host, unsigned char tag);/* ==================================================================================== * Miscellaneous */static inline voidsbic_arm_write (unsigned int io_port, int reg, int value){    arm_outb (reg, io_port);    arm_outb (value, io_port + 4);}#define sbic_arm_writenext(io,val) \	arm_outb ((val), (io) + 4)static inlineint sbic_arm_read (unsigned int io_port, int reg){    if(reg == ASR)	   return arm_inl(io_port) & 255;    arm_outb(reg, io_port);    return arm_inl(io_port + 4) & 255;}#define sbic_arm_readnext(io) \	arm_inb((io) + 4)#define dmac_read(io_port,reg) \	inb ((io_port) + (reg))#define dmac_write(io_port,reg,value) \	({ outb ((value), (io_port) + (reg)); })#define dmac_clearintr(io_port) \	({ outb (0, (io_port)); })static inlineunsigned int dmac_address (unsigned int io_port){    return dmac_read (io_port, TXADRHI) << 16 |	   dmac_read (io_port, TXADRMD) << 8 |	   dmac_read (io_port, TXADRLO);}staticunsigned long acornscsi_sbic_xfcount (AS_Host *host){    unsigned long length;    length = sbic_arm_read (host->scsi.io_port, TRANSCNTH) << 16;    length |= sbic_arm_readnext (host->scsi.io_port) << 8;    length |= sbic_arm_readnext (host->scsi.io_port);    return length;}static voidacornscsi_csdelay (unsigned int cs){    unsigned long target_jiffies, flags;    target_jiffies = jiffies + 1 + cs * HZ / 100;    save_flags (flags);    sti ();    while (jiffies < target_jiffies) barrier();    restore_flags (flags);}staticvoid acornscsi_resetcard (AS_Host *host){    unsigned int i;    /* assert reset line */    host->card.page_reg = 0x80;    outb (host->card.page_reg, host->card.io_page);    /* wait 3 cs.  SCSI standard says 25ms. */    acornscsi_csdelay (3);    host->card.page_reg = 0;    outb (host->card.page_reg, host->card.io_page);    /*     * Should get a reset from the card     */    while (!(inb (host->card.io_intr) & 8));    sbic_arm_read (host->scsi.io_port, ASR);    sbic_arm_read (host->scsi.io_port, SSR);    /* setup sbic - WD33C93A */    sbic_arm_write (host->scsi.io_port, OWNID, OWNID_EAF | host->host->this_id);    sbic_arm_write (host->scsi.io_port, CMND, CMND_RESET);    /*     * Command should cause a reset interrupt     */    while (!(inb (host->card.io_intr) & 8));    sbic_arm_read (host->scsi.io_port, ASR);    if (sbic_arm_read (host->scsi.io_port, SSR) != 0x01)	printk (KERN_CRIT "scsi%d: WD33C93A didn't give enhanced reset interrupt\n",		host->host->host_no);    sbic_arm_write (host->scsi.io_port, CTRL, INIT_SBICDMA | CTRL_IDI);    sbic_arm_write (host->scsi.io_port, TIMEOUT, TIMEOUT_TIME);    sbic_arm_write (host->scsi.io_port, SYNCHTRANSFER, SYNCHTRANSFER_2DBA);    sbic_arm_write (host->scsi.io_port, SOURCEID, SOURCEID_ER | SOURCEID_DSP);    host->card.page_reg = 0x40;    outb (host->card.page_reg, host->card.io_page);    /* setup dmac - uPC71071 */    dmac_write (host->dma.io_port, INIT, 0);    dmac_write (host->dma.io_port, INIT, INIT_8BIT);    dmac_write (host->dma.io_port, CHANNEL, CHANNEL_0);    dmac_write (host->dma.io_port, DEVCON0, INIT_DEVCON0);    dmac_write (host->dma.io_port, DEVCON1, INIT_DEVCON1);    host->SCpnt = NULL;    host->scsi.phase = PHASE_IDLE;    host->scsi.disconnectable = 0;    for (i = 0; i < 8; i++) {	host->busyluns[i] = 0;	host->device[i].sync_state = SYNC_NEGOCIATE;	host->device[i].disconnect_ok = 1;    }    /* wait 25 cs.  SCSI standard says 250ms. */    acornscsi_csdelay (25);}/*============================================================================================= * Utility routines (eg. debug) */#ifdef CONFIG_ACORNSCSI_CONSTANTSstatic char *acornscsi_interrupttype[] = {  "rst",  "suc",  "p/a",  "3",  "term", "5",	  "6",	  "7",  "serv", "9",	  "a",	  "b",  "c",	  "d",	  "e",	  "f"};static signed char acornscsi_map[] = {  0,  1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1,  2, -1, -1,  -1, -1,  3, -1,   4,	5,  6,	7,   8,  9, 10, 11, 12, 13, 14, -1,  -1, -1, -1, -1,   4,	5,  6,	7,   8,  9, 10, 11, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, 15, 16, 17, 18,  19, -1, -1, 20,   4,	5,  6,	7,   8,  9, 10, 11, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, 21, 22, -1, -1,  -1, 23, -1, -1,   4,	5,  6,	7,   8,  9, 10, 11, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1, -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1,  -1, -1, -1, -1};      static char *acornscsi_interruptcode[] = {    /* 0 */    "reset - normal mode",	/* 00 */    "reset - advanced mode",	/* 01 */    /* 2 */    "sel",			/* 11 */    "sel+xfer", 		/* 16 */    "data-out", 		/* 18 */    "data-in",			/* 19 */    "cmd",			/* 1A */    "stat",			/* 1B */    "??-out",			/* 1C */    "??-in",			/* 1D */    "msg-out",			/* 1E */    "msg-in",			/* 1F */    /* 12 */    "/ACK asserted",		/* 20 */    "save-data-ptr",		/* 21 */    "{re}sel",			/* 22 */    /* 15 */    "inv cmd",			/* 40 */    "unexpected disconnect",	/* 41 */    "sel timeout",		/* 42 */    "P err",			/* 43 */    "P err+ATN",		/* 44 */    "bad status byte",		/* 47 */    /* 21 */    "resel, no id",		/* 80 */    "resel",			/* 81 */    "discon",			/* 85 */};staticvoid print_scsi_status (unsigned int ssr){    if (acornscsi_map[ssr] != -1)	printk ("%s:%s",		acornscsi_interrupttype[(ssr >> 4)],		acornscsi_interruptcode[acornscsi_map[ssr]]);    else	printk ("%X:%X", ssr >> 4, ssr & 0x0f);    }    #endifstaticvoid print_sbic_status (int asr, int ssr, int cmdphase){#ifdef CONFIG_ACORNSCSI_CONSTANTS	printk ("sbic: %c%c%c%c%c%c ",		asr & ASR_INT ? 'I' : 'i',		asr & ASR_LCI ? 'L' : 'l',		asr & ASR_BSY ? 'B' : 'b',		asr & ASR_CIP ? 'C' : 'c',		asr & ASR_PE  ? 'P' : 'p',		asr & ASR_DBR ? 'D' : 'd');	printk ("scsi: ");	print_scsi_status (ssr);	printk (" ph %02X\n", cmdphase);#else	printk ("sbic: %02X scsi: %X:%X ph: %02X\n",		asr, (ssr & 0xf0)>>4, ssr & 0x0f, cmdphase);#endif}staticvoid acornscsi_dumplog (AS_Host *host, int target)

⌨️ 快捷键说明

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