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

📄 ncr5380.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);		NCR5380_reselect(instance);		printk("scsi%d : reselection after won arbitration?\n", instance->host_no);		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);		return -1;	}	/* 	 * No less than two deskew delays after the initiator detects the 	 * BSY signal is true, it shall release the SEL signal and may 	 * change the DATA BUS.                                     -wingel	 */	udelay(1);	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);	if (!(NCR5380_read(STATUS_REG) & SR_BSY)) {		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);		if (hostdata->targets_present & (1 << cmd->target)) {			printk("scsi%d : weirdness\n", instance->host_no);			if (hostdata->restart_select)				printk("\trestart select\n");			NCR5380_dprint(NDEBUG_SELECTION, instance);			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);			return -1;		}		cmd->result = DID_BAD_TARGET << 16;		collect_stats(hostdata, cmd);		cmd->scsi_done(cmd);		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);		dprintk(NDEBUG_SELECTION, ("scsi%d : target did not respond within 250ms\n", instance->host_no));		NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);		return 0;	}	hostdata->targets_present |= (1 << cmd->target);	/*	 * Since we followed the SCSI spec, and raised ATN while SEL 	 * was true but before BSY was false during selection, the information	 * transfer phase should be a MESSAGE OUT phase so that we can send the	 * IDENTIFY message.	 * 	 * If SCSI-II tagged queuing is enabled, we also send a SIMPLE_QUEUE_TAG	 * message (2 bytes) with a tag ID that we increment with every command	 * until it wraps back to 0.	 *	 * XXX - it turns out that there are some broken SCSI-II devices,	 *       which claim to support tagged queuing but fail when more than	 *       some number of commands are issued at once.	 */	/* Wait for start of REQ/ACK handshake */#ifdef NCR_TIMEOUT	{		unsigned long timeout = jiffies + NCR_TIMEOUT;		spin_unlock_irq(&io_request_lock);		while (!(NCR5380_read(STATUS_REG) & SR_REQ) && time_before(jiffies, timeout));		spin_lock_irq(&io_request_lock);		if (time_after_eq(jiffies, timeout)) {			printk("scsi%d: timeout at NCR5380.c:%d\n", instance->host_no, __LINE__);			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);			return -1;		}	}#else				/* NCR_TIMEOUT */	while (!(NCR5380_read(STATUS_REG) & SR_REQ));#endif				/* def NCR_TIMEOUT */	dprintk(NDEBUG_SELECTION, ("scsi%d : target %d selected, going into MESSAGE OUT phase.\n", instance->host_no, cmd->target));	tmp[0] = IDENTIFY(((instance->irq == IRQ_NONE) ? 0 : 1), cmd->lun);	len = 1;	cmd->tag = 0;	/* Send message(s) */	data = tmp;	phase = PHASE_MSGOUT;	NCR5380_transfer_pio(instance, &phase, &len, &data);	dprintk(NDEBUG_SELECTION, ("scsi%d : nexus established.\n", instance->host_no));	/* XXX need to handle errors here */	hostdata->connected = cmd;	hostdata->busy[cmd->target] |= (1 << cmd->lun);	initialize_SCp(cmd);	return 0;}/*  * Function : int NCR5380_transfer_pio (struct Scsi_Host *instance,  *      unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using polled I/O * * Inputs : instance - instance of driver, *phase - pointer to  *      what phase is expected, *count - pointer to number of  *      bytes to transfer, **data - pointer to data pointer. *  * Returns : -1 when different phase is entered without transferring *      maximum number of bytes, 0 if all bytes or transfered or exit *      is in same phase. * *      Also, *phase, *count, *data are modified in place. * * XXX Note : handling for bus free may be useful. *//* * Note : this code is not as quick as it could be, however it  * IS 100% reliable, and for the actual data transfer where speed * counts, we will always do a pseudo DMA or DMA transfer. */static int NCR5380_transfer_pio(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {	NCR5380_local_declare();	unsigned char p = *phase, tmp;	int c = *count;	unsigned char *d = *data;	/*	 *      RvC: some administrative data to process polling time	 */	int break_allowed = 0;	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;	NCR5380_setup(instance);	if (!(p & SR_IO))		dprintk(NDEBUG_PIO, ("scsi%d : pio write %d bytes\n", instance->host_no, c));	else		dprintk(NDEBUG_PIO, ("scsi%d : pio read %d bytes\n", instance->host_no, c));	/* 	 * The NCR5380 chip will only drive the SCSI bus when the 	 * phase specified in the appropriate bits of the TARGET COMMAND	 * REGISTER match the STATUS REGISTER	 */	 NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));	/* RvC: don't know if this is necessary, but other SCSI I/O is short	 *      so breaks are not necessary there	 */	if ((p == PHASE_DATAIN) || (p == PHASE_DATAOUT)) {		break_allowed = 1;	}	do {		/* 		 * Wait for assertion of REQ, after which the phase bits will be 		 * valid 		 */		/* RvC: we simply poll once, after that we stop temporarily		 *      and let the device buffer fill up		 *      if breaking is not allowed, we keep polling as long as needed		 */		while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ) && !break_allowed);		if (!(tmp & SR_REQ)) {			/* timeout condition */			hostdata->time_expires = jiffies + USLEEP_SLEEP;			NCR5380_set_timer(instance);			break;		}		dprintk(NDEBUG_HANDSHAKE, ("scsi%d : REQ detected\n", instance->host_no));		/* Check for phase mismatch */		if ((tmp & PHASE_MASK) != p) {			dprintk(NDEBUG_HANDSHAKE, ("scsi%d : phase mismatch\n", instance->host_no));			NCR5380_dprint_phase(NDEBUG_HANDSHAKE, instance);			break;		}		/* Do actual transfer from SCSI bus to / from memory */		if (!(p & SR_IO))			NCR5380_write(OUTPUT_DATA_REG, *d);		else			*d = NCR5380_read(CURRENT_SCSI_DATA_REG);		++d;		/* 		 * The SCSI standard suggests that in MSGOUT phase, the initiator		 * should drop ATN on the last byte of the message phase		 * after REQ has been asserted for the handshake but before		 * the initiator raises ACK.		 */		if (!(p & SR_IO)) {			if (!((p & SR_MSG) && c > 1)) {				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);				NCR5380_dprint(NDEBUG_PIO, instance);				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ACK);			} else {				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN);				NCR5380_dprint(NDEBUG_PIO, instance);				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);			}		} else {			NCR5380_dprint(NDEBUG_PIO, instance);			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);		}		while (NCR5380_read(STATUS_REG) & SR_REQ);		dprintk(NDEBUG_HANDSHAKE, ("scsi%d : req false, handshake complete\n", instance->host_no));/* * We have several special cases to consider during REQ/ACK handshaking :  * 1.  We were in MSGOUT phase, and we are on the last byte of the  *      message.  ATN must be dropped as ACK is dropped. * * 2.  We are in a MSGIN phase, and we are on the last byte of the   *      message.  We must exit with ACK asserted, so that the calling *      code may raise ATN before dropping ACK to reject the message. * * 3.  ACK and ATN are clear and the target may proceed as normal. */		if (!(p == PHASE_MSGIN && c == 1)) {			if (p == PHASE_MSGOUT && c > 1)				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);			else				NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);		}	} while (--c);	dprintk(NDEBUG_PIO, ("scsi%d : residual %d\n", instance->host_no, c));	*count = c;	*data = d;	tmp = NCR5380_read(STATUS_REG);	if (tmp & SR_REQ)		*phase = tmp & PHASE_MASK;	else		*phase = PHASE_UNKNOWN;	if (!c || (*phase == p))		return 0;	else		return -1;}/** *	do_reset	-	issue a reset command *	@host: adapter to reset * *	Issue a reset sequence to the NCR5380 and try and get the bus *	back into sane shape. * *	Locks: caller holds io_request lock */ static void do_reset(struct Scsi_Host *host) {	NCR5380_local_declare();	NCR5380_setup(host);	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(NCR5380_read(STATUS_REG) & PHASE_MASK));	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_RST);	udelay(25);	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);}/* * Function : do_abort (Scsi_Host *host) *  * Purpose : abort the currently established nexus.  Should only be  *      called from a routine which can drop into a  *  * Returns : 0 on success, -1 on failure. * * Locks: io_request lock held by caller */static int do_abort(struct Scsi_Host *host) {	NCR5380_local_declare();	unsigned char tmp, *msgptr, phase;	int len;	NCR5380_setup(host);	/* Request message out phase */	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);	/* 	 * Wait for the target to indicate a valid phase by asserting 	 * REQ.  Once this happens, we'll have either a MSGOUT phase 	 * and can immediately send the ABORT message, or we'll have some 	 * other phase and will have to source/sink data.	 * 	 * We really don't care what value was on the bus or what value	 * the target sees, so we just handshake.	 */	while (!(tmp = NCR5380_read(STATUS_REG)) & SR_REQ);	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));	if ((tmp & PHASE_MASK) != PHASE_MSGOUT) {		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN | ICR_ASSERT_ACK);		while (NCR5380_read(STATUS_REG) & SR_REQ);		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);	}	tmp = ABORT;	msgptr = &tmp;	len = 1;	phase = PHASE_MSGOUT;	NCR5380_transfer_pio(host, &phase, &len, &msgptr);	/*	 * If we got here, and the command completed successfully,	 * we're about to go into bus free state.	 */	return len ? -1 : 0;}#if defined(REAL_DMA) || defined(PSEUDO_DMA) || defined (REAL_DMA_POLL)/*  * Function : int NCR5380_transfer_dma (struct Scsi_Host *instance,  *      unsigned char *phase, int *count, unsigned char **data) * * Purpose : transfers data in given phase using either real *      or pseudo DMA. * * Inputs : instance - instance of driver, *phase - pointer to  *      what phase is expected, *count - pointer to number of  *      bytes to transfer, **data - pointer to data pointer. *  * Returns : -1 when different phase is entered without transferring *      maximum number of bytes, 0 if all bytes or transfered or exit *      is in same phase. * *      Also, *phase, *count, *data are modified in place. * *	Locks: io_request lock held by caller */static int NCR5380_transfer_dma(struct Scsi_Host *instance, unsigned char *phase, int *count, unsigned char **data) {	NCR5380_local_declare();	register int c = *count;	register unsigned char p = *phase;	register unsigned char *d = *data;	unsigned char tmp;	int foo;#if defined(REAL_DMA_POLL)	int cnt, toPIO;	unsigned char saved_data = 0, overrun = 0, residue;#endif	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;	NCR5380_setup(instance);	if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {		*phase = tmp;		return -1;	}#if defined(REAL_DMA) || defined(REAL_DMA_POLL)#ifdef READ_OVERRUNS	if (p & SR_IO) {		c -= 2;	}#endif	dprintk(NDEBUG_DMA, ("scsi%d : initializing DMA channel %d for %s, %d bytes %s %0x\n", instance->host_no, instance->dma_channel, (p & SR_IO) ? "reading" : "writing", c, (p & SR_IO) ? "to" : "from", (unsigned) d));	hostdata->dma_len = (p & SR_IO) ? NCR5380_dma_read_setup(instance, d, c) : NCR5380_dma_write_setup(instance, d, c);#endif	NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(p));#ifdef REAL_DMA	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_EOP_INTR | MR_MONITOR_BSY);#elif defined(REAL_DMA_POLL)	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);#else	/*	 * Note : on my sample board, watch-dog timeouts occurred when interrupts	 * were not disabled for the duration of a single DMA transfer, from 	 * before the setting of DMA mode to after transfer of the last byte.	 */#if defined(PSEUDO_DMA) && defined(UNSAFE)	spin_unlock_irq(&io_request_lock);#endif	/* KLL May need eop and parity in 53c400 */	if (hostdata->flags & FLAG_NCR53C400)		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE | MR_ENABLE_PAR_CHECK | MR_ENABLE_PAR_INTR | MR_ENABLE_EOP_INTR | MR_DMA_MODE | MR_MONITOR_BSY);	else		NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);#endif				/* def REAL_DMA */	dprintk(NDEBUG_DMA, ("scsi%d : mode reg = 0x%X\n", instance->host_no, NCR5380_read(MODE_REG)));	/* 	 *	On the PAS16 at least I/O recovery delays are not needed here.	 *	Everyone else seems to want them.	 */	if (p & SR_IO) {		io_recovery_delay(1);		NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);	} else {		io_recovery_delay(1);		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);		io_recovery_delay(1);		NCR5380_w

⌨️ 快捷键说明

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