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

📄 53c700.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
		count = ((NCR_700_readb(host, DFIFO_REG) & 0x7f) -			 (NCR_700_readl(host, DBC_REG) & 0x7f)) & 0x7f;	} else {		count = ((NCR_700_readb(host, DFIFO_REG) & 0x3f) -			 (NCR_700_readl(host, DBC_REG) & 0x3f)) & 0x3f;	}		if(hostdata->fast)		synchronous = NCR_700_readb(host, SXFER_REG) & 0x0f;		/* get the data direction */	ddir = NCR_700_readb(host, CTEST0_REG) & 0x01;	if (ddir) {		/* Receive */		if (synchronous) 			count += (NCR_700_readb(host, SSTAT2_REG) & 0xf0) >> 4;		else			if (NCR_700_readb(host, SSTAT1_REG) & SIDL_REG_FULL)				++count;	} else {		/* Send */		__u8 sstat = NCR_700_readb(host, SSTAT1_REG);		if (sstat & SODL_REG_FULL)			++count;		if (synchronous && (sstat & SODR_REG_FULL))			++count;	}#ifdef NCR_700_DEBUG	if(count)		printk("RESIDUAL IS %d (ddir %d)\n", count, ddir);#endif	return count;}/* print out the SCSI wires and corresponding phase from the SBCL register * in the chip */static inline char *sbcl_to_string(__u8 sbcl){	int i;	static char ret[256];	ret[0]='\0';	for(i=0; i<8; i++) {		if((1<<i) & sbcl) 			strcat(ret, NCR_700_SBCL_bits[i]);	}	strcat(ret, NCR_700_SBCL_to_phase[sbcl & 0x07]);	return ret;}static inline __u8bitmap_to_number(__u8 bitmap){	__u8 i;	for(i=0; i<8 && !(bitmap &(1<<i)); i++)		;	return i;}/* Pull a slot off the free list */STATIC struct NCR_700_command_slot *find_empty_slot(struct NCR_700_Host_Parameters *hostdata){	struct NCR_700_command_slot *slot = hostdata->free_list;	if(slot == NULL) {		/* sanity check */		if(hostdata->command_slot_count != NCR_700_COMMAND_SLOTS_PER_HOST)			printk(KERN_ERR "SLOTS FULL, but count is %d, should be %d\n", hostdata->command_slot_count, NCR_700_COMMAND_SLOTS_PER_HOST);		return NULL;	}	if(slot->state != NCR_700_SLOT_FREE)		/* should panic! */		printk(KERN_ERR "BUSY SLOT ON FREE LIST!!!\n");			hostdata->free_list = slot->ITL_forw;	slot->ITL_forw = NULL;	/* NOTE: set the state to busy here, not queued, since this	 * indicates the slot is in use and cannot be run by the IRQ	 * finish routine.  If we cannot queue the command when it	 * is properly build, we then change to NCR_700_SLOT_QUEUED */	slot->state = NCR_700_SLOT_BUSY;	hostdata->command_slot_count++;		return slot;}STATIC void free_slot(struct NCR_700_command_slot *slot,	  struct NCR_700_Host_Parameters *hostdata){	int hash;	struct NCR_700_command_slot **forw, **back;	if((slot->state & NCR_700_SLOT_MASK) != NCR_700_SLOT_MAGIC) {		printk(KERN_ERR "53c700: SLOT %p is not MAGIC!!!\n", slot);	}	if(slot->state == NCR_700_SLOT_FREE) {		printk(KERN_ERR "53c700: SLOT %p is FREE!!!\n", slot);	}	/* remove from queues */	if(slot->tag != NCR_700_NO_TAG) {		hash = hash_ITLQ(slot->cmnd->target, slot->cmnd->lun,				 slot->tag);		if(slot->ITLQ_forw == NULL)			back = &hostdata->ITLQ_Hash_back[hash];		else			back = &slot->ITLQ_forw->ITLQ_back;		if(slot->ITLQ_back == NULL)			forw = &hostdata->ITLQ_Hash_forw[hash];		else			forw = &slot->ITLQ_back->ITLQ_forw;		*forw = slot->ITLQ_forw;		*back = slot->ITLQ_back;	}	hash = hash_ITL(slot->cmnd->target, slot->cmnd->lun);	if(slot->ITL_forw == NULL)		back = &hostdata->ITL_Hash_back[hash];	else		back = &slot->ITL_forw->ITL_back;		if(slot->ITL_back == NULL)		forw = &hostdata->ITL_Hash_forw[hash];	else		forw = &slot->ITL_back->ITL_forw;		*forw = slot->ITL_forw;	*back = slot->ITL_back;		slot->resume_offset = 0;	slot->cmnd = NULL;	slot->state = NCR_700_SLOT_FREE;	slot->ITL_forw = hostdata->free_list;	hostdata->free_list = slot;	hostdata->command_slot_count--;}/* This routine really does very little.  The command is indexed on   the ITL and (if tagged) the ITLQ lists in _queuecommand */STATIC voidsave_for_reselection(struct NCR_700_Host_Parameters *hostdata,		     Scsi_Cmnd *SCp, __u32 dsp){	/* Its just possible that this gets executed twice */	if(SCp != NULL) {		struct NCR_700_command_slot *slot =			(struct NCR_700_command_slot *)SCp->host_scribble;		slot->resume_offset = dsp;	}	hostdata->state = NCR_700_HOST_FREE;	hostdata->cmd = NULL;}/* Most likely nexus is the oldest in each case */STATIC inline struct NCR_700_command_slot *find_ITL_Nexus(struct NCR_700_Host_Parameters *hostdata, __u8 pun, __u8 lun){	int hash = hash_ITL(pun, lun);	struct NCR_700_command_slot *slot = hostdata->ITL_Hash_back[hash];	while(slot != NULL && !(slot->cmnd->target == pun &&				slot->cmnd->lun == lun))		slot = slot->ITL_back;	return slot;}STATIC inline struct NCR_700_command_slot *find_ITLQ_Nexus(struct NCR_700_Host_Parameters *hostdata, __u8 pun,		__u8 lun, __u8 tag){	int hash = hash_ITLQ(pun, lun, tag);	struct NCR_700_command_slot *slot = hostdata->ITLQ_Hash_back[hash];	while(slot != NULL && !(slot->cmnd->target == pun 	      && slot->cmnd->lun == lun && slot->tag == tag))		slot = slot->ITLQ_back;#ifdef NCR_700_TAG_DEBUG	if(slot != NULL) {		struct NCR_700_command_slot *n = slot->ITLQ_back;		while(n != NULL && n->cmnd->target != pun		      && n->cmnd->lun != lun && n->tag != tag)			n = n->ITLQ_back;		if(n != NULL && n->cmnd->target == pun && n->cmnd->lun == lun		   && n->tag == tag) {			printk(KERN_WARNING "53c700: WARNING: DUPLICATE tag %d\n",			       tag);		}	}#endif	return slot;}/* This translates the SDTR message offset and period to a value * which can be loaded into the SXFER_REG. * * NOTE: According to SCSI-2, the true transfer period (in ns) is *       actually four times this period value */STATIC inline __u8NCR_700_offset_period_to_sxfer(struct NCR_700_Host_Parameters *hostdata,			       __u8 offset, __u8 period){	int XFERP;	__u8 min_xferp = (hostdata->chip710			  ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);	__u8 max_offset = (hostdata->chip710			   ? NCR_710_MAX_OFFSET : NCR_700_MAX_OFFSET);	/* NOTE: NCR_700_SDTR_msg[3] contains our offer of the minimum	 * period.  It is set in NCR_700_chip_setup() */	if(period < NCR_700_SDTR_msg[3]) {		printk(KERN_WARNING "53c700: Period %dns is less than this chip's minimum, setting to %d\n", period*4, NCR_700_SDTR_msg[3]*4);		period = NCR_700_SDTR_msg[3];	}	XFERP = (period*4 * hostdata->sync_clock)/1000 - 4;	if(offset > max_offset) {		printk(KERN_WARNING "53c700: Offset %d exceeds chip maximum, setting to %d\n",		       offset, max_offset);		offset = max_offset;	}	if(XFERP < min_xferp) {		printk(KERN_WARNING "53c700: XFERP %d is less than minium, setting to %d\n",		       XFERP,  min_xferp);		XFERP =  min_xferp;	}	return (offset & 0x0f) | (XFERP & 0x07)<<4;}STATIC inline voidNCR_700_unmap(struct NCR_700_Host_Parameters *hostdata, Scsi_Cmnd *SCp,	      struct NCR_700_command_slot *slot){	if(SCp->sc_data_direction != SCSI_DATA_NONE &&	   SCp->sc_data_direction != SCSI_DATA_UNKNOWN) {		int pci_direction = scsi_to_pci_dma_dir(SCp->sc_data_direction);		if(SCp->use_sg) {			pci_unmap_sg(hostdata->pci_dev, SCp->buffer,				     SCp->use_sg, pci_direction);		} else {			pci_unmap_single(hostdata->pci_dev,					 slot->dma_handle,					 SCp->request_bufflen,					 pci_direction);		}	}}STATIC inline voidNCR_700_scsi_done(struct NCR_700_Host_Parameters *hostdata,	       Scsi_Cmnd *SCp, int result){	hostdata->state = NCR_700_HOST_FREE;	hostdata->cmd = NULL;	if(SCp != NULL) {		struct NCR_700_command_slot *slot = 			(struct NCR_700_command_slot *)SCp->host_scribble;				NCR_700_unmap(hostdata, SCp, slot);		pci_unmap_single(hostdata->pci_dev, slot->pCmd,				 sizeof(SCp->cmnd), PCI_DMA_TODEVICE);		if(SCp->cmnd[0] == REQUEST_SENSE && SCp->cmnd[6] == NCR_700_INTERNAL_SENSE_MAGIC) {#ifdef NCR_700_DEBUG			printk(" ORIGINAL CMD %p RETURNED %d, new return is %d sense is\n",			       SCp, SCp->cmnd[7], result);			print_sense("53c700", SCp);#endif			SCp->use_sg = SCp->cmnd[8];			if(result == 0)				result = SCp->cmnd[7];		}		free_slot(slot, hostdata);		SCp->host_scribble = NULL;		SCp->result = result;		SCp->scsi_done(SCp);		if(NCR_700_get_depth(SCp->device) == 0 ||		   NCR_700_get_depth(SCp->device) > NCR_700_MAX_TAGS)			printk(KERN_ERR "Invalid depth in NCR_700_scsi_done(): %d\n",			       NCR_700_get_depth(SCp->device));		NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) - 1);	} else {		printk(KERN_ERR "53c700: SCSI DONE HAS NULL SCp\n");	}}STATIC voidNCR_700_internal_bus_reset(struct Scsi_Host *host){	/* Bus reset */	NCR_700_writeb(ASSERT_RST, host, SCNTL1_REG);	udelay(50);	NCR_700_writeb(0, host, SCNTL1_REG);}STATIC voidNCR_700_chip_setup(struct Scsi_Host *host){	struct NCR_700_Host_Parameters *hostdata = 		(struct NCR_700_Host_Parameters *)host->hostdata[0];	__u32 dcntl_extra = 0;	__u8 min_period;	__u8 min_xferp = (hostdata->chip710 ? NCR_710_MIN_XFERP : NCR_700_MIN_XFERP);	if(hostdata->chip710) {		__u8 burst_disable = hostdata->burst_disable			? BURST_DISABLE : 0;		dcntl_extra = COMPAT_700_MODE;		NCR_700_writeb(dcntl_extra, host, DCNTL_REG);		NCR_700_writeb(BURST_LENGTH_8  | hostdata->dmode_extra,			       host, DMODE_710_REG);		NCR_700_writeb(burst_disable | (hostdata->differential ? 						DIFF : 0), host, CTEST7_REG);		NCR_700_writeb(BTB_TIMER_DISABLE, host, CTEST0_REG);		NCR_700_writeb(FULL_ARBITRATION | ENABLE_PARITY | PARITY			       | AUTO_ATN, host, SCNTL0_REG);	} else {		NCR_700_writeb(BURST_LENGTH_8 | hostdata->dmode_extra,			       host, DMODE_700_REG);		NCR_700_writeb(hostdata->differential ? 			       DIFF : 0, host, CTEST7_REG);		if(hostdata->fast) {			/* this is for 700-66, does nothing on 700 */			NCR_700_writeb(LAST_DIS_ENBL | ENABLE_ACTIVE_NEGATION 				       | GENERATE_RECEIVE_PARITY, host,				       CTEST8_REG);		} else {			NCR_700_writeb(FULL_ARBITRATION | ENABLE_PARITY				       | PARITY | AUTO_ATN, host, SCNTL0_REG);		}	}	NCR_700_writeb(1 << host->this_id, host, SCID_REG);	NCR_700_writeb(0, host, SBCL_REG);	NCR_700_writeb(ASYNC_OPERATION, host, SXFER_REG);	NCR_700_writeb(PHASE_MM_INT | SEL_TIMEOUT_INT | GROSS_ERR_INT | UX_DISC_INT	     | RST_INT | PAR_ERR_INT | SELECT_INT, host, SIEN_REG);	NCR_700_writeb(ABORT_INT | INT_INST_INT | ILGL_INST_INT, host, DIEN_REG);	NCR_700_writeb(ENABLE_SELECT, host, SCNTL1_REG);	if(hostdata->clock > 75) {		printk(KERN_ERR "53c700: Clock speed %dMHz is too high: 75Mhz is the maximum this chip can be driven at\n", hostdata->clock);		/* do the best we can, but the async clock will be out		 * of spec: sync divider 2, async divider 3 */		DEBUG(("53c700: sync 2 async 3\n"));		NCR_700_writeb(SYNC_DIV_2_0, host, SBCL_REG);		NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);		hostdata->sync_clock = hostdata->clock/2;	} else	if(hostdata->clock > 50  && hostdata->clock <= 75) {		/* sync divider 1.5, async divider 3 */		DEBUG(("53c700: sync 1.5 async 3\n"));		NCR_700_writeb(SYNC_DIV_1_5, host, SBCL_REG);		NCR_700_writeb(ASYNC_DIV_3_0 | dcntl_extra, host, DCNTL_REG);		hostdata->sync_clock = hostdata->clock*2;		hostdata->sync_clock /= 3;			} else if(hostdata->clock > 37 && hostdata->clock <= 50) {		/* sync divider 1, async divider 2 */		DEBUG(("53c700: sync 1 async 2\n"));		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);		NCR_700_writeb(ASYNC_DIV_2_0 | dcntl_extra, host, DCNTL_REG);		hostdata->sync_clock = hostdata->clock;	} else if(hostdata->clock > 25 && hostdata->clock <=37) {		/* sync divider 1, async divider 1.5 */		DEBUG(("53c700: sync 1 async 1.5\n"));		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);		NCR_700_writeb(ASYNC_DIV_1_5 | dcntl_extra, host, DCNTL_REG);		hostdata->sync_clock = hostdata->clock;	} else {		DEBUG(("53c700: sync 1 async 1\n"));		NCR_700_writeb(SYNC_DIV_1_0, host, SBCL_REG);		NCR_700_writeb(ASYNC_DIV_1_0 | dcntl_extra, host, DCNTL_REG);		/* sync divider 1, async divider 1 */		hostdata->sync_clock = hostdata->clock;	}	/* Calculate the actual minimum period that can be supported	 * by our synchronous clock speed.  See the 710 manual for	 * exact details of this calculation which is based on a

⌨️ 快捷键说明

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