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

📄 acornscsi.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
/* *  linux/drivers/acorn/scsi/acornscsi.c * *  Acorn SCSI 3 driver *  By R.M.King. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * 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. *  12-Oct-1997	RMK	Added catch for re-entering interrupt routine. *  15-Oct-1997	RMK	Improved handling of commands. *  27-Jun-1998	RMK	Changed asm/delay.h to linux/delay.h. *  13-Dec-1998	RMK	Better abort code and command handling.  Extra state *			transitions added to allow dodgy devices to work. */#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)/* 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'. * * Also note that CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE is normally set in the config * scripts, but disabled here.  Once debugged, remove the #undef, otherwise to debug, * comment out the undef. */#undef CONFIG_SCSI_ACORNSCSI_TAGGED_QUEUE/* * SCSI-II Linked command support. * * The higher level code doesn't support linked commands yet, and so the option * is undef'd here. */#undef CONFIG_SCSI_ACORNSCSI_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 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 [don't remove this option] * If not set, then use PIO mode (not currently supported). */#define USE_DMAC/* * ==================================================================================== */#ifdef DEBUG_TARGET#define DBG(cmd,xxx...) \  if (cmd->device->id == DEBUG_TARGET) { \    xxx; \  }#else#define DBG(cmd,xxx...) xxx#endif#ifndef STRINGIFY#define STRINGIFY(x) #x#endif#define STRx(x) STRINGIFY(x)#define NO_WRITE_STR STRx(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/ioport.h>#include <linux/blkdev.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/init.h>#include <linux/bitops.h>#include <asm/system.h>#include <asm/io.h>#include <asm/irq.h>#include <asm/ecard.h>#include "../scsi.h"#include <scsi/scsi_dbg.h>#include <scsi/scsi_host.h>#include "acornscsi.h"#include "msgqueue.h"#include "scsi.h"#include <scsi/scsicam.h>#define VER_MAJOR 2#define VER_MINOR 0#define VER_PATCH 6#ifndef ABORT_TAG#define ABORT_TAG 0xd#else#error "Yippee!  ABORT TAG is now defined!  Remove this error!"#endif#ifdef CONFIG_SCSI_ACORNSCSI_LINK#error SCSI2 LINKed commands not supported (yet)!#endif#ifdef USE_DMAC/* * 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)#define scsi_xferred	have_data_in/* * Size of on-board DMA buffer */#define DMAC_BUFFER_SIZE	65536#endif#define STATUS_BUFFER_TO_PRINT	24unsigned int sdtr_period = SDTR_PERIOD;unsigned int sdtr_size   = SDTR_SIZE;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){    __raw_writeb(reg, io_port);    __raw_writeb(value, io_port + 4);}#define sbic_arm_writenext(io,val) \	__raw_writeb((val), (io) + 4)static inlineint sbic_arm_read(unsigned int io_port, int reg){    if(reg == SBIC_ASR)	   return __raw_readl(io_port) & 255;    __raw_writeb(reg, io_port);    return __raw_readl(io_port + 4) & 255;}#define sbic_arm_readnext(io) \	__raw_readb((io) + 4)#ifdef USE_DMAC#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, DMAC_TXADRHI) << 16 |	   dmac_read(io_port, DMAC_TXADRMD) << 8 |	   dmac_read(io_port, DMAC_TXADRLO);}staticvoid acornscsi_dumpdma(AS_Host *host, char *where){	unsigned int mode, addr, len;	mode = dmac_read(host->dma.io_port, DMAC_MODECON);	addr = dmac_address(host->dma.io_port);	len  = dmac_read(host->dma.io_port, DMAC_TXCNTHI) << 8 |	       dmac_read(host->dma.io_port, DMAC_TXCNTLO);	printk("scsi%d: %s: DMAC %02x @%06x+%04x msk %02x, ",		host->host->host_no, where,		mode, addr, (len + 1) & 0xffff,		dmac_read(host->dma.io_port, DMAC_MASKREG));	printk("DMA @%06x, ", host->dma.start_addr);	printk("BH @%p +%04x, ", host->scsi.SCp.ptr,		host->scsi.SCp.this_residual);	printk("DT @+%04x ST @+%04x", host->dma.transferred,		host->scsi.SCp.scsi_xferred);	printk("\n");}#endifstaticunsigned long acornscsi_sbic_xfcount(AS_Host *host){    unsigned long length;    length = sbic_arm_read(host->scsi.io_port, SBIC_TRANSCNTH) << 16;    length |= sbic_arm_readnext(host->scsi.io_port) << 8;    length |= sbic_arm_readnext(host->scsi.io_port);    return length;}static intacornscsi_sbic_wait(AS_Host *host, int stat_mask, int stat, int timeout, char *msg){	int asr;	do {		asr = sbic_arm_read(host->scsi.io_port, SBIC_ASR);		if ((asr & stat_mask) == stat)			return 0;		udelay(1);	} while (--timeout);	printk("scsi%d: timeout while %s\n", host->host->host_no, msg);	return -1;}staticint acornscsi_sbic_issuecmd(AS_Host *host, int command){    if (acornscsi_sbic_wait(host, ASR_CIP, 0, 1000, "issuing command"))	return -1;    sbic_arm_write(host->scsi.io_port, SBIC_CMND, command);    return 0;}static voidacornscsi_csdelay(unsigned int cs){    unsigned long target_jiffies, flags;    target_jiffies = jiffies + 1 + cs * HZ / 100;    local_save_flags(flags);    local_irq_enable();    while (time_before(jiffies, target_jiffies)) barrier();    local_irq_restore(flags);}staticvoid acornscsi_resetcard(AS_Host *host){    unsigned int i, timeout;    /* 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     */    timeout = 1000;    do {	if (inb(host->card.io_intr) & 8)	    break;	udelay(1);    } while (--timeout);    if (timeout == 0)	printk("scsi%d: timeout while resetting card\n",		host->host->host_no);    sbic_arm_read(host->scsi.io_port, SBIC_ASR);    sbic_arm_read(host->scsi.io_port, SBIC_SSR);    /* setup sbic - WD33C93A */    sbic_arm_write(host->scsi.io_port, SBIC_OWNID, OWNID_EAF | host->host->this_id);    sbic_arm_write(host->scsi.io_port, SBIC_CMND, CMND_RESET);    /*     * Command should cause a reset interrupt     */    timeout = 1000;    do {	if (inb(host->card.io_intr) & 8)	    break;	udelay(1);    } while (--timeout);    if (timeout == 0)	printk("scsi%d: timeout while resetting card\n",		host->host->host_no);    sbic_arm_read(host->scsi.io_port, SBIC_ASR);    if (sbic_arm_read(host->scsi.io_port, SBIC_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, SBIC_CTRL, INIT_SBICDMA | CTRL_IDI);    sbic_arm_write(host->scsi.io_port, SBIC_TIMEOUT, TIMEOUT_TIME);    sbic_arm_write(host->scsi.io_port, SBIC_SYNCHTRANSFER, SYNCHTRANSFER_2DBA);    sbic_arm_write(host->scsi.io_port, SBIC_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, DMAC_INIT, 0);#ifdef USE_DMAC    dmac_write(host->dma.io_port, DMAC_INIT, INIT_8BIT);    dmac_write(host->dma.io_port, DMAC_CHANNEL, CHANNEL_0);    dmac_write(host->dma.io_port, DMAC_DEVCON0, INIT_DEVCON0);    dmac_write(host->dma.io_port, DMAC_DEVCON1, INIT_DEVCON1);#endif    host->SCpnt = NULL;    host->scsi.phase = PHASE_IDLE;    host->scsi.disconnectable = 0;    memset(host->busyluns, 0, sizeof(host->busyluns));    for (i = 0; i < 8; i++) {	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 */

⌨️ 快捷键说明

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