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

📄 53c700.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
					continue;								SCp = slot->cmnd;				printk(KERN_ERR " failing command because of reset, slot %p, cmnd %p\n",				       slot, SCp);				free_slot(slot, hostdata);				SCp->host_scribble = NULL;				NCR_700_set_depth(SCp->device, 0);				/* NOTE: deadlock potential here: we				 * rely on mid-layer guarantees that				 * scsi_done won't try to issue the				 * command again otherwise we'll				 * deadlock on the				 * hostdata->state_lock */				SCp->result = DID_RESET << 16;				SCp->scsi_done(SCp);			}			mdelay(25);			NCR_700_chip_setup(host);			hostdata->state = NCR_700_HOST_FREE;			hostdata->cmd = NULL;			goto out_unlock;		} else if(sstat0 & SELECTION_TIMEOUT) {			DEBUG(("scsi%d: (%d:%d) selection timeout\n",			       host->host_no, pun, lun));			NCR_700_scsi_done(hostdata, SCp, DID_NO_CONNECT<<16);		} else if(sstat0 & PHASE_MISMATCH) {			struct NCR_700_command_slot *slot = (SCp == NULL) ? NULL :				(struct NCR_700_command_slot *)SCp->host_scribble;			if(dsp == Ent_SendMessage + 8 + hostdata->pScript) {				/* It wants to reply to some part of				 * our message */#ifdef NCR_700_DEBUG				__u32 temp = NCR_700_readl(host, TEMP_REG);				int count = (hostdata->script[Ent_SendMessage/4] & 0xffffff) - ((NCR_700_readl(host, DBC_REG) & 0xffffff) + NCR_700_data_residual(host));				printk("scsi%d (%d:%d) PHASE MISMATCH IN SEND MESSAGE %d remain, return %p[%04x], phase %s\n", host->host_no, pun, lun, count, (void *)temp, temp - hostdata->pScript, sbcl_to_string(NCR_700_readb(host, SBCL_REG)));#endif				resume_offset = hostdata->pScript + Ent_SendMessagePhaseMismatch;			} else if(dsp >= to32bit(&slot->pSG[0].ins) &&				  dsp <= to32bit(&slot->pSG[NCR_700_SG_SEGMENTS].ins)) {				int data_transfer = NCR_700_readl(host, DBC_REG) & 0xffffff;				int SGcount = (dsp - to32bit(&slot->pSG[0].ins))/sizeof(struct NCR_700_SG_List);				int residual = NCR_700_data_residual(host);				int i;#ifdef NCR_700_DEBUG				__u32 naddr = NCR_700_readl(host, DNAD_REG);				printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x\n",				       host->host_no, pun, lun,				       SGcount, data_transfer);				print_command(SCp->cmnd);				if(residual) {					printk("scsi%d: (%d:%d) Expected phase mismatch in slot->SG[%d], transferred 0x%x, residual %d\n",				       host->host_no, pun, lun,				       SGcount, data_transfer, residual);				}#endif				data_transfer += residual;				if(data_transfer != 0) {					int count; 					__u32 pAddr;					SGcount--;					count = (bS_to_cpu(slot->SG[SGcount].ins) & 0x00ffffff);					DEBUG(("DATA TRANSFER MISMATCH, count = %d, transferred %d\n", count, count-data_transfer));					slot->SG[SGcount].ins &= bS_to_host(0xff000000);					slot->SG[SGcount].ins |= bS_to_host(data_transfer);					pAddr = bS_to_cpu(slot->SG[SGcount].pAddr);					pAddr += (count - data_transfer);#ifdef NCR_700_DEBUG					if(pAddr != naddr) {						printk("scsi%d (%d:%d) transfer mismatch pAddr=%lx, naddr=%lx, data_transfer=%d, residual=%d\n", host->host_no, pun, lun, (unsigned long)pAddr, (unsigned long)naddr, data_transfer, residual);					}#endif					slot->SG[SGcount].pAddr = bS_to_host(pAddr);				}				/* set the executed moves to nops */				for(i=0; i<SGcount; i++) {					slot->SG[i].ins = bS_to_host(SCRIPT_NOP);					slot->SG[i].pAddr = 0;				}				NCR_700_dma_cache_wback((unsigned long)slot->SG, sizeof(slot->SG));				/* and pretend we disconnected after				 * the command phase */				resume_offset = hostdata->pScript + Ent_MsgInDuringData;				/* make sure all the data is flushed */				NCR_700_flush_fifo(host);			} else {				__u8 sbcl = NCR_700_readb(host, SBCL_REG);				printk(KERN_ERR "scsi%d: (%d:%d) phase mismatch at %04x, phase %s\n",				       host->host_no, pun, lun, dsp - hostdata->pScript, sbcl_to_string(sbcl));				NCR_700_internal_bus_reset(host);			}		} else if(sstat0 & SCSI_GROSS_ERROR) {			printk(KERN_ERR "scsi%d: (%d:%d) GROSS ERROR\n",			       host->host_no, pun, lun);			NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16);		} else if(sstat0 & PARITY_ERROR) {			printk(KERN_ERR "scsi%d: (%d:%d) PARITY ERROR\n",			       host->host_no, pun, lun);			NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16);		} else if(dstat & SCRIPT_INT_RECEIVED) {			DEBUG(("scsi%d: (%d:%d) ====>SCRIPT INTERRUPT<====\n",			       host->host_no, pun, lun));			resume_offset = process_script_interrupt(dsps, dsp, SCp, host, hostdata);		} else if(dstat & (ILGL_INST_DETECTED)) {			printk(KERN_ERR "scsi%d: (%d:%d) Illegal Instruction detected at 0x%08x[0x%x]!!!\n"			       "         Please email James.Bottomley@HansenPartnership.com with the details\n",			       host->host_no, pun, lun,			       dsp, dsp - hostdata->pScript);			NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16);		} else if(dstat & (WATCH_DOG_INTERRUPT|ABORTED)) {			printk(KERN_ERR "scsi%d: (%d:%d) serious DMA problem, dstat=%02x\n",			       host->host_no, pun, lun, dstat);			NCR_700_scsi_done(hostdata, SCp, DID_ERROR<<16);		}				/* NOTE: selection interrupt processing MUST occur		 * after script interrupt processing to correctly cope		 * with the case where we process a disconnect and		 * then get reselected before we process the		 * disconnection */		if(sstat0 & SELECTED) {			/* FIXME: It currently takes at least FOUR			 * interrupts to complete a command that			 * disconnects: one for the disconnect, one			 * for the reselection, one to get the			 * reselection data and one to complete the			 * command.  If we guess the reselected			 * command here and prepare it, we only need			 * to get a reselection data interrupt if we			 * guessed wrongly.  Since the interrupt			 * overhead is much greater than the command			 * setup, this would be an efficient			 * optimisation particularly as we probably			 * only have one outstanding command on a			 * target most of the time */			resume_offset = process_selection(host, dsp);		}	}	if(resume_offset) {		if(hostdata->state != NCR_700_HOST_BUSY) {			printk(KERN_ERR "scsi%d: Driver error: resume at 0x%08x [0x%04x] with non busy host!\n",			       host->host_no, resume_offset, resume_offset - hostdata->pScript);			hostdata->state = NCR_700_HOST_BUSY;		}		DEBUG(("Attempting to resume at %x\n", resume_offset));		NCR_700_clear_fifo(host);		NCR_700_writel(resume_offset, host, DSP_REG);	} 	/* There is probably a technical no-no about this: If we're a	 * shared interrupt and we got this interrupt because the	 * other device needs servicing not us, we're still going to	 * check our queued commands here---of course, there shouldn't	 * be any outstanding.... */	if(hostdata->state == NCR_700_HOST_FREE) {		int i;		for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) {			/* fairness: always run the queue from the last			 * position we left off */			int j = (i + hostdata->saved_slot_position)				% NCR_700_COMMAND_SLOTS_PER_HOST;						if(hostdata->slots[j].state != NCR_700_SLOT_QUEUED)				continue;			if(NCR_700_start_command(hostdata->slots[j].cmnd)) {				DEBUG(("scsi%d: Issuing saved command slot %p, cmd %p\t\n",				       host->host_no, &hostdata->slots[j],				       hostdata->slots[j].cmnd));				hostdata->saved_slot_position = j + 1;			}			break;		}	} out_unlock:	spin_unlock_irqrestore(&io_request_lock, flags);}/* FIXME: Need to put some proc information in and plumb it * into the scsi proc system */STATIC intNCR_700_proc_directory_info(char *proc_buf, char **startp,			 off_t offset, int bytes_available,			 int host_no, int write){	static char buf[4096];	/* 1 page should be sufficient */	int len = 0;	struct Scsi_Host *host = scsi_hostlist;	struct NCR_700_Host_Parameters *hostdata;	Scsi_Device *SDp;	while(host != NULL && host->host_no != host_no)		host = host->next;	if(host == NULL)		return 0;	if(write) {		/* FIXME: Clear internal statistics here */		return 0;	}	hostdata = (struct NCR_700_Host_Parameters *)host->hostdata[0];	len += sprintf(&buf[len], "Total commands outstanding: %d\n", hostdata->command_slot_count);	len += sprintf(&buf[len],"\Target	Depth  Active  Next Tag\n\======	=====  ======  ========\n");	for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next) {		len += sprintf(&buf[len]," %2d:%2d   %4d    %4d      %4d\n", SDp->id, SDp->lun, SDp->queue_depth, NCR_700_get_depth(SDp), SDp->current_tag);	}	if((len -= offset) <= 0)		return 0;	if(len > bytes_available)		len = bytes_available;	memcpy(proc_buf, buf + offset, len);	return len;}STATIC intNCR_700_queuecommand(Scsi_Cmnd *SCp, void (*done)(Scsi_Cmnd *)){	struct NCR_700_Host_Parameters *hostdata = 		(struct NCR_700_Host_Parameters *)SCp->host->hostdata[0];	__u32 move_ins;	int pci_direction;	struct NCR_700_command_slot *slot;	int hash;	if(hostdata->command_slot_count >= NCR_700_COMMAND_SLOTS_PER_HOST) {		/* We're over our allocation, this should never happen		 * since we report the max allocation to the mid layer */		printk(KERN_WARNING "scsi%d: Command depth has gone over queue depth\n", SCp->host->host_no);		return 1;	}	if(NCR_700_get_depth(SCp->device) != 0 && !(hostdata->tag_negotiated & (1<<SCp->target))) {		DEBUG((KERN_ERR "scsi%d (%d:%d) has non zero depth %d\n",		       SCp->host->host_no, SCp->target, SCp->lun,		       NCR_700_get_depth(SCp->device)));		return 1;	}	if(NCR_700_get_depth(SCp->device) >= NCR_700_MAX_TAGS) {		DEBUG((KERN_ERR "scsi%d (%d:%d) has max tag depth %d\n",		       SCp->host->host_no, SCp->target, SCp->lun,		       NCR_700_get_depth(SCp->device)));		return 1;	}	NCR_700_set_depth(SCp->device, NCR_700_get_depth(SCp->device) + 1);	/* begin the command here */	/* no need to check for NULL, test for command_slot_cound above	 * ensures a slot is free */	slot = find_empty_slot(hostdata);	slot->cmnd = SCp;	SCp->scsi_done = done;	SCp->host_scribble = (unsigned char *)slot;	SCp->SCp.ptr = NULL;	SCp->SCp.buffer = NULL;#ifdef NCR_700_DEBUG	printk("53c700: scsi%d, command ", SCp->host->host_no);	print_command(SCp->cmnd);#endif	if(SCp->device->tagged_supported && !SCp->device->tagged_queue	   && (hostdata->tag_negotiated &(1<<SCp->target)) == 0	   && NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING)) {		/* upper layer has indicated tags are supported.  We don't		 * necessarily believe it yet.		 *		 * NOTE: There is a danger here: the mid layer supports		 * tag queuing per LUN.  We only support it per PUN because		 * of potential reselection issues */		printk(KERN_INFO "scsi%d: (%d:%d) Enabling Tag Command Queuing\n", SCp->device->host->host_no, SCp->target, SCp->lun);		hostdata->tag_negotiated |= (1<<SCp->target);		NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_TAG_QUEUEING);		SCp->device->tagged_queue = 1;	}	if(hostdata->tag_negotiated &(1<<SCp->target)) {		struct NCR_700_command_slot *old =			find_ITL_Nexus(hostdata, SCp->target, SCp->lun);#ifdef NCR_700_TAG_DEBUG		struct NCR_700_command_slot *found;#endif				if(old != NULL && old->tag == SCp->device->current_tag) {			/* On some badly starving drives, this can be			 * a frequent occurance, so print the message			 * only once */			if(NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_TAG_STARVATION_WARNED)) {				printk(KERN_WARNING "scsi%d (%d:%d) Target is suffering from tag starvation.\n", SCp->host->host_no, SCp->target, SCp->lun);				NCR_700_set_flag(SCp->device, NCR_700_DEV_TAG_STARVATION_WARNED);			}			return 1;		}		slot->tag = SCp->device->current_tag++;#ifdef NCR_700_TAG_DEBUG		while((found = find_ITLQ_Nexus(hostdata, SCp->target, SCp->lun, slot->tag)) != NULL) {			printk("\n\n**ERROR** already using tag %d, but oldest is %d\n", slot->tag, (old == NULL) ? -1 : old->tag);			printk("  FOUND = %p, tag = %d, pun = %d, lun = %d\n",			       found, found->tag, found->cmnd->target, found->cmnd->lun);			slot->tag = SCp->device->current_tag++;			printk("   Tag list is: ");			while(old != NULL) {				if(old->cmnd->target == SCp->target &&				   old->cmnd->lun == SCp->lun)					printk("%d ", old->tag);				old = old->ITL_back;			}			printk("\n\n");		}#endif		hash = hash_ITLQ(SCp->target, SCp->lun, slot->tag);		/* link into the ITLQ hash queues */		slot->ITLQ_forw = hostdata->ITLQ_Hash_forw[hash];		hostdata->ITLQ_Hash_forw[hash] = slot;#ifdef NCR_700_TAG_DEBUG		if(slot->ITLQ_forw != NULL && slot->ITLQ_forw->ITLQ_back != NULL) {			printk(KERN_ERR "scsi%d (%d:%d) ITLQ_back is not NULL!!!!\n", SCp->host->host_no, SCp->target, SCp->lun);		}#endif		if(slot->ITLQ_forw != NULL)			slot->ITLQ_forw->ITLQ_back = slot;		else			hostdata->ITLQ_Hash_back[hash] = slot;		slot->ITLQ_back = NULL;	} else {		slot->tag = NCR_700_NO_TAG;	}	/* link into the ITL hash queues */	hash = hash_ITL(SCp->target, SCp->lun);	slot->ITL_forw = hostdata->ITL_Hash_forw[hash];	hostdata->ITL_Hash_forw[hash] = slot;#ifdef NCR_700_TAG_DEBUG	if(slot->ITL_forw != NULL && slot->ITL_forw->ITL_back != NULL) {		printk(KERN_ERR "scsi%d (%d:%d) ITL_back is not NULL!!!!\n",		       SCp->host->host_no, SCp->target, SCp->lun);	}#endif	if(slot->ITL_forw != NULL)		slot->ITL_forw->ITL_back = slot;	else		hostdata->ITL_Hash_back[hash] = slot;	slot->ITL_back = NULL;	/* sanity check: some of the commands generated by the mid-layer	 * have an eccentric idea of their sc_data_direction */	if(!SCp->use_sg && !SCp->request_bufflen 	   && SCp->sc_data_direction != SCSI_DATA_NONE) {#ifdef NCR_700_DEBUG		printk("53c700: Command");		print_command(SCp->cmnd);		printk("Has wrong data direction %d\n", SCp->sc_data_direction);#endif		SCp->sc_data_direction = SCSI_DATA_NONE;	}	switch (SCp->cmnd[0]) {	case REQUEST_SENSE:		/* clear the internal sense magic */		SCp->cmnd[6] = 0;		/* fall through */	default:		/* OK, get it from the command */		switch(SCp->sc_data_direction) {		case SCSI_DATA_UNKNOWN:		default:			printk(KERN_ERR "53c700: Unknown command for data direction ");			print_command(SCp->cmnd);						move_ins = 0;			break;		case SCSI_DATA_NONE:			move_ins = 0;			break;		case SCSI_DATA_READ:			move_ins = SCRIPT_MOVE_DATA_IN;			break;		case SCSI_DATA_WRITE:

⌨️ 快捷键说明

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