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

📄 53c700.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/* -*- mode: c; c-basic-offset: 8 -*- *//* NCR (or Symbios) 53c700 and 53c700-66 Driver * * Copyright (C) 2001 by James.Bottomley@HansenPartnership.com**-----------------------------------------------------------------------------**  **  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.****----------------------------------------------------------------------------- *//* Notes: * * This driver is designed exclusively for these chips (virtually the * earliest of the scripts engine chips).  They need their own drivers * because they are missing so many of the scripts and snazzy register * features of their elder brothers (the 710, 720 and 770). * * The 700 is the lowliest of the line, it can only do async SCSI. * The 700-66 can at least do synchronous SCSI up to 10MHz. *  * The 700 chip has no host bus interface logic of its own.  However, * it is usually mapped to a location with well defined register * offsets.  Therefore, if you can determine the base address and the * irq your board incorporating this chip uses, you can probably use * this driver to run it (although you'll probably have to write a * minimal wrapper for the purpose---see the NCR_D700 driver for * details about how to do this). * * * TODO List: * * 1. Better statistics in the proc fs * * 2. Implement message queue (queues SCSI messages like commands) and make *    the abort and device reset functions use them. * *//* CHANGELOG * * Version 2.7 * * Fixed scripts problem which caused certain devices (notably CDRWs) * to hang on initial INQUIRY.  Updated NCR_700_readl/writel to use * __raw_readl/writel for parisc compatibility (Thomas * Bogendoerfer). Added missing SCp->request_bufflen initialisation * for sense requests (Ryan Bradetich). * * Version 2.6 * * Following test of the 64 bit parisc kernel by Richard Hirst, * several problems have now been corrected.  Also adds support for * consistent memory allocation. * * Version 2.5 *  * More Compatibility changes for 710 (now actually works).  Enhanced * support for odd clock speeds which constrain SDTR negotiations. * correct cacheline separation for scsi messages and status for * incoherent architectures.  Use of the pci mapping functions on * buffers to begin support for 64 bit drivers. * * Version 2.4 * * Added support for the 53c710 chip (in 53c700 emulation mode only---no  * special 53c710 instructions or registers are used). * * Version 2.3 * * More endianness/cache coherency changes. * * Better bad device handling (handles devices lying about tag * queueing support and devices which fail to provide sense data on * contingent allegiance conditions) * * Many thanks to Richard Hirst <rhirst@linuxcare.com> for patiently * debugging this driver on the parisc architecture and suggesting * many improvements and bug fixes. * * Thanks also go to Linuxcare Inc. for providing several PARISC * machines for me to debug the driver on. * * Version 2.2 * * Made the driver mem or io mapped; added endian invariance; added * dma cache flushing operations for architectures which need it; * added support for more varied clocking speeds. * * Version 2.1 * * Initial modularisation from the D700.  See NCR_D700.c for the rest of * the changelog. * */#define NCR_700_VERSION "2.7"#include <linux/config.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/spinlock.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>#include <asm/io.h>#include <asm/pgtable.h>#include <asm/byteorder.h>#include <linux/blk.h>#include <linux/module.h>#include <linux/pci.h>#include "scsi.h"#include "hosts.h"#include "constants.h"#include "53c700.h"/* NOTE: For 64 bit drivers there are points in the code where we use * a non dereferenceable pointer to point to a structure in dma-able * memory (which is 32 bits) so that we can use all of the structure * operations but take the address at the end.  This macro allows us * to truncate the 64 bit pointer down to 32 bits without the compiler * complaining */#define to32bit(x)	((__u32)((unsigned long)(x)))#ifdef NCR_700_DEBUG#define STATIC#else#define STATIC static#endifMODULE_AUTHOR("James Bottomley");MODULE_DESCRIPTION("53c700 and 53c700-66 Driver");MODULE_LICENSE("GPL");/* This is the script */#include "53c700_d.h"STATIC int NCR_700_queuecommand(Scsi_Cmnd *, void (*done)(Scsi_Cmnd *));STATIC int NCR_700_abort(Scsi_Cmnd * SCpnt);STATIC int NCR_700_bus_reset(Scsi_Cmnd * SCpnt);STATIC int NCR_700_dev_reset(Scsi_Cmnd * SCpnt);STATIC int NCR_700_host_reset(Scsi_Cmnd * SCpnt);STATIC int NCR_700_proc_directory_info(char *, char **, off_t, int, int, int);STATIC void NCR_700_chip_setup(struct Scsi_Host *host);STATIC void NCR_700_chip_reset(struct Scsi_Host *host);static char *NCR_700_phase[] = {	"",	"after selection",	"before command phase",	"after command phase",	"after status phase",	"after data in phase",	"after data out phase",	"during data phase",};static char *NCR_700_condition[] = {	"",	"NOT MSG_OUT",	"UNEXPECTED PHASE",	"NOT MSG_IN",	"UNEXPECTED MSG",	"MSG_IN",	"SDTR_MSG RECEIVED",	"REJECT_MSG RECEIVED",	"DISCONNECT_MSG RECEIVED",	"MSG_OUT",	"DATA_IN",	};static char *NCR_700_fatal_messages[] = {	"unexpected message after reselection",	"still MSG_OUT after message injection",	"not MSG_IN after selection",	"Illegal message length received",};static char *NCR_700_SBCL_bits[] = {	"IO ",	"CD ",	"MSG ",	"ATN ",	"SEL ",	"BSY ",	"ACK ",	"REQ ",};static char *NCR_700_SBCL_to_phase[] = {	"DATA_OUT",	"DATA_IN",	"CMD_OUT",	"STATE",	"ILLEGAL PHASE",	"ILLEGAL PHASE",	"MSG OUT",	"MSG IN",};static __u8 NCR_700_SDTR_msg[] = {	0x01,			/* Extended message */	0x03,			/* Extended message Length */	0x01,			/* SDTR Extended message */	NCR_700_MIN_PERIOD,	NCR_700_MAX_OFFSET};struct Scsi_Host * __initNCR_700_detect(Scsi_Host_Template *tpnt,	       struct NCR_700_Host_Parameters *hostdata){	dma_addr_t pScript, pMemory, pSlots;	__u8 *memory;	__u32 *script;	struct Scsi_Host *host;	static int banner = 0;	int j;#ifdef CONFIG_53C700_USE_CONSISTENT	memory = pci_alloc_consistent(hostdata->pci_dev, TOTAL_MEM_SIZE,				      &pMemory);	hostdata->consistent = 1;	if(memory == NULL ) {		printk(KERN_WARNING "53c700: consistent memory allocation failed\n");#endif		memory = kmalloc(TOTAL_MEM_SIZE, GFP_KERNEL);		if(memory == NULL) {			printk(KERN_ERR "53c700: Failed to allocate memory for driver, detatching\n");			return NULL;		}		pMemory = pci_map_single(hostdata->pci_dev, memory,					 TOTAL_MEM_SIZE, PCI_DMA_BIDIRECTIONAL);#ifdef CONFIG_53C700_USE_CONSISTENT		hostdata->consistent = 0;	}#endif	script = (__u32 *)memory;	pScript = pMemory;	hostdata->msgin = memory + MSGIN_OFFSET;	hostdata->msgout = memory + MSGOUT_OFFSET;	hostdata->status = memory + STATUS_OFFSET;	hostdata->slots = (struct NCR_700_command_slot *)(memory + SLOTS_OFFSET);			pSlots = pMemory + SLOTS_OFFSET;	/* Fill in the missing routines from the host template */	tpnt->queuecommand = NCR_700_queuecommand;	tpnt->eh_abort_handler = NCR_700_abort;	tpnt->eh_device_reset_handler = NCR_700_dev_reset;	tpnt->eh_bus_reset_handler = NCR_700_bus_reset;	tpnt->eh_host_reset_handler = NCR_700_host_reset;	tpnt->can_queue = NCR_700_COMMAND_SLOTS_PER_HOST;	tpnt->sg_tablesize = NCR_700_SG_SEGMENTS;	tpnt->cmd_per_lun = NCR_700_MAX_TAGS;	tpnt->use_clustering = DISABLE_CLUSTERING;	tpnt->use_new_eh_code = 1;	tpnt->proc_info = NCR_700_proc_directory_info;		if(tpnt->name == NULL)		tpnt->name = "53c700";	if(tpnt->proc_name == NULL)		tpnt->proc_name = "53c700";		if((host = scsi_register(tpnt, 4)) == NULL)		return NULL;	memset(hostdata->slots, 0, sizeof(struct NCR_700_command_slot)	       * NCR_700_COMMAND_SLOTS_PER_HOST);	for(j = 0; j < NCR_700_COMMAND_SLOTS_PER_HOST; j++) {		dma_addr_t offset = (dma_addr_t)((unsigned long)&hostdata->slots[j].SG[0]					  - (unsigned long)&hostdata->slots[0].SG[0]);		hostdata->slots[j].pSG = (struct NCR_700_SG_List *)((unsigned long)(pSlots + offset));		if(j == 0)			hostdata->free_list = &hostdata->slots[j];		else			hostdata->slots[j-1].ITL_forw = &hostdata->slots[j];		hostdata->slots[j].state = NCR_700_SLOT_FREE;	}	for(j = 0; j < sizeof(SCRIPT)/sizeof(SCRIPT[0]); j++) {		script[j] = bS_to_host(SCRIPT[j]);	}	/* adjust all labels to be bus physical */	for(j = 0; j < PATCHES; j++) {		script[LABELPATCHES[j]] = bS_to_host(pScript + SCRIPT[LABELPATCHES[j]]);	}	/* now patch up fixed addresses. */	script_patch_32(script, MessageLocation,			pScript + MSGOUT_OFFSET);	script_patch_32(script, StatusAddress,			pScript + STATUS_OFFSET);	script_patch_32(script, ReceiveMsgAddress,			pScript + MSGIN_OFFSET);	hostdata->script = script;	hostdata->pScript = pScript;	NCR_700_dma_cache_wback((unsigned long)script, sizeof(SCRIPT));	hostdata->state = NCR_700_HOST_FREE;	spin_lock_init(&hostdata->lock);	hostdata->cmd = NULL;	host->max_id = 7;	host->max_lun = NCR_700_MAX_LUNS;	host->unique_id = hostdata->base;	host->base = hostdata->base;	host->hostdata[0] = (unsigned long)hostdata;	/* kick the chip */	NCR_700_writeb(0xff, host, CTEST9_REG);	if(hostdata->chip710) 		hostdata->rev = (NCR_700_readb(host, CTEST8_REG)>>4) & 0x0f;	else		hostdata->rev = (NCR_700_readb(host, CTEST7_REG)>>4) & 0x0f;	hostdata->fast = (NCR_700_readb(host, CTEST9_REG) == 0);	if(banner == 0) {		printk(KERN_NOTICE "53c700: Version " NCR_700_VERSION " By James.Bottomley@HansenPartnership.com\n");		banner = 1;	}	printk(KERN_NOTICE "scsi%d: %s rev %d %s\n", host->host_no,	       hostdata->chip710 ? "53c710" : 	       (hostdata->fast ? "53c700-66" : "53c700"),	       hostdata->rev, hostdata->differential ?	       "(Differential)" : "");	/* reset the chip */	NCR_700_chip_reset(host);	return host;}intNCR_700_release(struct Scsi_Host *host){	struct NCR_700_Host_Parameters *hostdata = 		(struct NCR_700_Host_Parameters *)host->hostdata[0];#ifdef CONFIG_53C700_USE_CONSISTENT	if(hostdata->consistent) {		pci_free_consistent(hostdata->pci_dev, TOTAL_MEM_SIZE,				    hostdata->script, hostdata->pScript);	} else {#endif		pci_unmap_single(hostdata->pci_dev, hostdata->pScript,				 TOTAL_MEM_SIZE, PCI_DMA_BIDIRECTIONAL);		kfree(hostdata->script);#ifdef CONFIG_53C700_USE_CONSISTENT	}#endif	return 1;}static inline __u8NCR_700_identify(int can_disconnect, __u8 lun){	return IDENTIFY_BASE |		((can_disconnect) ? 0x40 : 0) |		(lun & NCR_700_LUN_MASK);}/* * Function : static int data_residual (Scsi_Host *host) * * Purpose : return residual data count of what's in the chip.  If you * really want to know what this function is doing, it's almost a * direct transcription of the algorithm described in the 53c710 * guide, except that the DBC and DFIFO registers are only 6 bits * wide on a 53c700. * * Inputs : host - SCSI host */static inline intNCR_700_data_residual (struct Scsi_Host *host) {	struct NCR_700_Host_Parameters *hostdata = 		(struct NCR_700_Host_Parameters *)host->hostdata[0];	int count, synchronous = 0;	unsigned int ddir;	if(hostdata->chip710) {

⌨️ 快捷键说明

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