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

📄 53c700.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
			NCR_700_dma_cache_wback((unsigned long)hostdata->msgout,					MSG_ARRAY_SIZE);			/* I'm just being paranoid here, the command should			 * already have been flushed from the cache */			NCR_700_dma_cache_wback((unsigned long)slot->cmnd->cmnd,					slot->cmnd->cmd_len);					}	} else if(dsps == A_RESELECTED_DURING_SELECTION) {		/* This section is full of debugging code because I've		 * never managed to reach it.  I think what happens is		 * that, because the 700 runs with selection		 * interrupts enabled the whole time that we take a		 * selection interrupt before we manage to get to the		 * reselected script interrupt */		__u8 reselection_id = NCR_700_readb(host, SFBR_REG);		struct NCR_700_command_slot *slot;				/* Take out our own ID */		reselection_id &= ~(1<<host->this_id);				/* I've never seen this happen, so keep this as a printk rather		 * than a debug */		printk(KERN_INFO "scsi%d: (%d:%d) RESELECTION DURING SELECTION, dsp=%08x[%04x] state=%d, count=%d\n",		       host->host_no, reselection_id, lun, dsp, dsp - hostdata->pScript, hostdata->state, hostdata->command_slot_count);		{			/* FIXME: DEBUGGING CODE */			__u32 SG = (__u32)bS_to_cpu(hostdata->script[A_SGScriptStartAddress_used[0]]);			int i;			for(i=0; i< NCR_700_COMMAND_SLOTS_PER_HOST; i++) {				if(SG >= to32bit(&hostdata->slots[i].pSG[0])				   && SG <= to32bit(&hostdata->slots[i].pSG[NCR_700_SG_SEGMENTS]))					break;			}			printk(KERN_INFO "IDENTIFIED SG segment as being %08x in slot %p, cmd %p, slot->resume_offset=%08x\n", SG, &hostdata->slots[i], hostdata->slots[i].cmnd, hostdata->slots[i].resume_offset);			SCp =  hostdata->slots[i].cmnd;		}		if(SCp != NULL) {			slot = (struct NCR_700_command_slot *)SCp->host_scribble;			/* change slot from busy to queued to redo command */			slot->state = NCR_700_SLOT_QUEUED;		}		hostdata->cmd = NULL;				if(reselection_id == 0) {			if(hostdata->reselection_id == 0xff) {				printk(KERN_ERR "scsi%d: Invalid reselection during selection!!\n", host->host_no);				return 0;			} else {				printk(KERN_ERR "scsi%d: script reselected and we took a selection interrupt\n",				       host->host_no);				reselection_id = hostdata->reselection_id;			}		} else {						/* convert to real ID */			reselection_id = bitmap_to_number(reselection_id);		}		hostdata->reselection_id = reselection_id;		/* just in case we have a stale simple tag message, clear it */		hostdata->msgin[1] = 0;		NCR_700_dma_cache_wback_inv((unsigned long)hostdata->msgin,					    MSG_ARRAY_SIZE);		if(hostdata->tag_negotiated & (1<<reselection_id)) {			resume_offset = hostdata->pScript + Ent_GetReselectionWithTag;		} else {			resume_offset = hostdata->pScript + Ent_GetReselectionData;		}	} else if(dsps == A_COMPLETED_SELECTION_AS_TARGET) {		/* we've just disconnected from the bus, do nothing since		 * a return here will re-run the queued command slot		 * that may have been interrupted by the initial selection */		DEBUG((" SELECTION COMPLETED\n"));	} else if((dsps & 0xfffff0f0) == A_MSG_IN) { 		resume_offset = process_message(host, hostdata, SCp,						dsp, dsps);	} else if((dsps &  0xfffff000) == 0) {		__u8 i = (dsps & 0xf0) >> 4, j = (dsps & 0xf00) >> 8;		printk(KERN_ERR "scsi%d: (%d:%d), unhandled script condition %s %s at %04x\n",		       host->host_no, pun, lun, NCR_700_condition[i],		       NCR_700_phase[j], dsp - hostdata->pScript);		if(SCp != NULL) {			print_command(SCp->cmnd);			if(SCp->use_sg) {				for(i = 0; i < SCp->use_sg + 1; i++) {					printk(KERN_INFO " SG[%d].length = %d, move_insn=%08x, addr %08x\n", i, ((struct scatterlist *)SCp->buffer)[i].length, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].ins, ((struct NCR_700_command_slot *)SCp->host_scribble)->SG[i].pAddr);				}			}		}	       		NCR_700_internal_bus_reset(host);	} else if((dsps & 0xfffff000) == A_DEBUG_INTERRUPT) {		printk(KERN_NOTICE "scsi%d (%d:%d) DEBUG INTERRUPT %d AT %08x[%04x], continuing\n",		       host->host_no, pun, lun, dsps & 0xfff, dsp, dsp - hostdata->pScript);		resume_offset = dsp;	} else {		printk(KERN_ERR "scsi%d: (%d:%d), unidentified script interrupt 0x%x at %04x\n",		       host->host_no, pun, lun, dsps, dsp - hostdata->pScript);		NCR_700_internal_bus_reset(host);	}	return resume_offset;}/* We run the 53c700 with selection interrupts always enabled.  This * means that the chip may be selected as soon as the bus frees.  On a * busy bus, this can be before the scripts engine finishes its * processing.  Therefore, part of the selection processing has to be * to find out what the scripts engine is doing and complete the * function if necessary (i.e. process the pending disconnect or save * the interrupted initial selection */STATIC inline __u32process_selection(struct Scsi_Host *host, __u32 dsp){	__u8 id = 0;	/* Squash compiler warning */	int count = 0;	__u32 resume_offset = 0;	struct NCR_700_Host_Parameters *hostdata =		(struct NCR_700_Host_Parameters *)host->hostdata[0];	Scsi_Cmnd *SCp = hostdata->cmd;	__u8 sbcl;	for(count = 0; count < 5; count++) {		id = NCR_700_readb(host, hostdata->chip710 ?				   CTEST9_REG : SFBR_REG);		/* Take out our own ID */		id &= ~(1<<host->this_id);		if(id != 0) 			break;		udelay(5);	}	sbcl = NCR_700_readb(host, SBCL_REG);	if((sbcl & SBCL_IO) == 0) {		/* mark as having been selected rather than reselected */		id = 0xff;	} else {		/* convert to real ID */		hostdata->reselection_id = id = bitmap_to_number(id);		DEBUG(("scsi%d:  Reselected by %d\n",		       host->host_no, id));	}	if(hostdata->state == NCR_700_HOST_BUSY && SCp != NULL) {		struct NCR_700_command_slot *slot =			(struct NCR_700_command_slot *)SCp->host_scribble;		DEBUG(("  ID %d WARNING: RESELECTION OF BUSY HOST, saving cmd %p, slot %p, addr %x [%04x], resume %x!\n", id, hostdata->cmd, slot, dsp, dsp - hostdata->pScript, resume_offset));				switch(dsp - hostdata->pScript) {		case Ent_Disconnect1:		case Ent_Disconnect2:			save_for_reselection(hostdata, SCp, Ent_Disconnect2 + hostdata->pScript);			break;		case Ent_Disconnect3:		case Ent_Disconnect4:			save_for_reselection(hostdata, SCp, Ent_Disconnect4 + hostdata->pScript);			break;		case Ent_Disconnect5:		case Ent_Disconnect6:			save_for_reselection(hostdata, SCp, Ent_Disconnect6 + hostdata->pScript);			break;		case Ent_Disconnect7:		case Ent_Disconnect8:			save_for_reselection(hostdata, SCp, Ent_Disconnect8 + hostdata->pScript);			break;		case Ent_Finish1:		case Ent_Finish2:			process_script_interrupt(A_GOOD_STATUS_AFTER_STATUS, dsp, SCp, host, hostdata);			break;					default:			slot->state = NCR_700_SLOT_QUEUED;			break;			}	}	hostdata->state = NCR_700_HOST_BUSY;	hostdata->cmd = NULL;	/* clear any stale simple tag message */	hostdata->msgin[1] = 0;	NCR_700_dma_cache_wback_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);	if(id == 0xff) {		/* Selected as target, Ignore */		resume_offset = hostdata->pScript + Ent_SelectedAsTarget;	} else if(hostdata->tag_negotiated & (1<<id)) {		resume_offset = hostdata->pScript + Ent_GetReselectionWithTag;	} else {		resume_offset = hostdata->pScript + Ent_GetReselectionData;	}	return resume_offset;}static inline voidNCR_700_clear_fifo(struct Scsi_Host *host) {	const struct NCR_700_Host_Parameters *hostdata		= (struct NCR_700_Host_Parameters *)host->hostdata[0];	if(hostdata->chip710) {		NCR_700_writeb(CLR_FIFO_710, host, CTEST8_REG);	} else {		NCR_700_writeb(CLR_FIFO, host, DFIFO_REG);	}}static inline voidNCR_700_flush_fifo(struct Scsi_Host *host) {	const struct NCR_700_Host_Parameters *hostdata		= (struct NCR_700_Host_Parameters *)host->hostdata[0];	if(hostdata->chip710) {		NCR_700_writeb(FLUSH_DMA_FIFO_710, host, CTEST8_REG);		udelay(10);		NCR_700_writeb(0, host, CTEST8_REG);	} else {		NCR_700_writeb(FLUSH_DMA_FIFO, host, DFIFO_REG);		udelay(10);		NCR_700_writeb(0, host, DFIFO_REG);	}}STATIC intNCR_700_start_command(Scsi_Cmnd *SCp){	struct NCR_700_command_slot *slot =		(struct NCR_700_command_slot *)SCp->host_scribble;	struct NCR_700_Host_Parameters *hostdata =		(struct NCR_700_Host_Parameters *)SCp->host->hostdata[0];	unsigned long flags;	__u16 count = 1;	/* for IDENTIFY message */		save_flags(flags);	cli();	if(hostdata->state != NCR_700_HOST_FREE) {		/* keep this inside the lock to close the race window where		 * the running command finishes on another CPU while we don't		 * change the state to queued on this one */		slot->state = NCR_700_SLOT_QUEUED;		restore_flags(flags);		DEBUG(("scsi%d: host busy, queueing command %p, slot %p\n",		       SCp->host->host_no, slot->cmnd, slot));		return 0;	}	hostdata->state = NCR_700_HOST_BUSY;	hostdata->cmd = SCp;	slot->state = NCR_700_SLOT_BUSY;	/* keep interrupts disabled until we have the command correctly	 * set up so we cannot take a selection interrupt */	hostdata->msgout[0] = NCR_700_identify(SCp->cmnd[0] != REQUEST_SENSE,					       SCp->lun);	/* for INQUIRY or REQUEST_SENSE commands, we cannot be sure	 * if the negotiated transfer parameters still hold, so	 * always renegotiate them */	if(SCp->cmnd[0] == INQUIRY || SCp->cmnd[0] == REQUEST_SENSE) {		NCR_700_clear_flag(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC);	}	/* REQUEST_SENSE is asking for contingent I_T_L(_Q) status.	 * If a contingent allegiance condition exists, the device	 * will refuse all tags, so send the request sense as untagged	 * */	if((hostdata->tag_negotiated & (1<<SCp->target))	   && (slot->tag != NCR_700_NO_TAG && SCp->cmnd[0] != REQUEST_SENSE)) {		hostdata->msgout[count++] = A_SIMPLE_TAG_MSG;		hostdata->msgout[count++] = slot->tag;	}	if(hostdata->fast &&	   NCR_700_is_flag_clear(SCp->device, NCR_700_DEV_NEGOTIATED_SYNC)) {		memcpy(&hostdata->msgout[count], NCR_700_SDTR_msg,		       sizeof(NCR_700_SDTR_msg));		count += sizeof(NCR_700_SDTR_msg);		NCR_700_set_flag(SCp->device, NCR_700_DEV_BEGIN_SYNC_NEGOTIATION);	}	script_patch_16(hostdata->script, MessageCount, count);	script_patch_ID(hostdata->script,			Device_ID, 1<<SCp->target);	script_patch_32_abs(hostdata->script, CommandAddress, 			    slot->pCmd);	script_patch_16(hostdata->script, CommandCount, SCp->cmd_len);	/* finally plumb the beginning of the SG list into the script	 * */	script_patch_32_abs(hostdata->script, SGScriptStartAddress,			    to32bit(&slot->pSG[0].ins));	NCR_700_clear_fifo(SCp->host);	if(slot->resume_offset == 0)		slot->resume_offset = hostdata->pScript;	/* now perform all the writebacks and invalidates */	NCR_700_dma_cache_wback((unsigned long)hostdata->msgout, count);	NCR_700_dma_cache_inv((unsigned long)hostdata->msgin, MSG_ARRAY_SIZE);	NCR_700_dma_cache_wback((unsigned long)SCp->cmnd, SCp->cmd_len);	NCR_700_dma_cache_inv((unsigned long)hostdata->status, 1);	/* set the synchronous period/offset */	NCR_700_writeb(NCR_700_get_SXFER(SCp->device),		       SCp->host, SXFER_REG);	NCR_700_writel(slot->temp, SCp->host, TEMP_REG);	NCR_700_writel(slot->resume_offset, SCp->host, DSP_REG);	/* allow interrupts here so that if we're selected we can take	 * a selection interrupt.  The script start may not be	 * effective in this case, but the selection interrupt will	 * save our command in that case */	restore_flags(flags);	return 1;}voidNCR_700_intr(int irq, void *dev_id, struct pt_regs *regs){	struct Scsi_Host *host = (struct Scsi_Host *)dev_id;	struct NCR_700_Host_Parameters *hostdata =		(struct NCR_700_Host_Parameters *)host->hostdata[0];	__u8 istat;	__u32 resume_offset = 0;	__u8 pun = 0xff, lun = 0xff;	unsigned long flags;	/* Unfortunately, we have to take the io_request_lock here	 * rather than the host lock hostdata->lock because we're	 * looking to exclude queuecommand from messing with the	 * registers while we're processing the interrupt.  Since	 * queuecommand is called holding io_request_lock, and we have	 * to take io_request_lock before we call the command	 * scsi_done, we would get a deadlock if we took	 * hostdata->lock here and in queuecommand (because the order	 * of locking in queuecommand: 1) io_request_lock then 2)	 * hostdata->lock would be the reverse of taking it in this	 * routine */	spin_lock_irqsave(&io_request_lock, flags);	if((istat = NCR_700_readb(host, ISTAT_REG))	      & (SCSI_INT_PENDING | DMA_INT_PENDING)) {		__u32 dsps;		__u8 sstat0 = 0, dstat = 0;		__u32 dsp;		Scsi_Cmnd *SCp = hostdata->cmd;		enum NCR_700_Host_State state;		state = hostdata->state;		SCp = hostdata->cmd;		if(istat & SCSI_INT_PENDING) {			udelay(10);			sstat0 = NCR_700_readb(host, SSTAT0_REG);		}		if(istat & DMA_INT_PENDING) {			udelay(10);			dstat = NCR_700_readb(host, DSTAT_REG);		}		dsps = NCR_700_readl(host, DSPS_REG);		dsp = NCR_700_readl(host, DSP_REG);		DEBUG(("scsi%d: istat %02x sstat0 %02x dstat %02x dsp %04x[%08x] dsps 0x%x\n",		       host->host_no, istat, sstat0, dstat,		       (dsp - (__u32)(hostdata->pScript))/4,		       dsp, dsps));		if(SCp != NULL) {			pun = SCp->target;			lun = SCp->lun;		}		if(sstat0 & SCSI_RESET_DETECTED) {			Scsi_Device *SDp;			int i;			hostdata->state = NCR_700_HOST_BUSY;			printk(KERN_ERR "scsi%d: Bus Reset detected, executing command %p, slot %p, dsp %08x[%04x]\n",			       host->host_no, SCp, SCp == NULL ? NULL : SCp->host_scribble, dsp, dsp - hostdata->pScript);			/* clear all the negotiated parameters */			for(SDp = host->host_queue; SDp != NULL; SDp = SDp->next)				SDp->hostdata = 0;						/* clear all the slots and their pending commands */			for(i = 0; i < NCR_700_COMMAND_SLOTS_PER_HOST; i++) {				Scsi_Cmnd *SCp;				struct NCR_700_command_slot *slot =					&hostdata->slots[i];				if(slot->state == NCR_700_SLOT_FREE)

⌨️ 快捷键说明

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