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

📄 ncr5380.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
							tmp->host_scribble = (unsigned char *) hostdata->issue_queue;							hostdata->issue_queue = tmp;							done = 0;							dprintk(NDEBUG_MAIN|NDEBUG_QUEUES, ("scsi%d : main(): select() failed, returned to issue_queue\n", instance->host_no));						}						/* lock held here still */					}	/* if target/lun is not busy */				}	/* for */				/* exited locked */			}	/* if (!hostdata->connected) */			if (hostdata->selecting) {				tmp = (Scsi_Cmnd *) hostdata->selecting;				/* Selection will drop and retake the lock */				if (!NCR5380_select(instance, tmp, (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : TAG_NEXT)) {					/* Ok ?? */				} else {					/* RvC: device failed, so we wait a long time					   this is needed for Mustek scanners, that					   do not respond to commands immediately					   after a scan */					printk(KERN_DEBUG "scsi%d: device %d did not respond in time\n", instance->host_no, tmp->target);					//spin_lock_irq(&io_request_lock);					LIST(tmp, hostdata->issue_queue);					tmp->host_scribble = (unsigned char *) hostdata->issue_queue;					hostdata->issue_queue = tmp;					//spin_unlock_irq(&io_request_lock);					hostdata->time_expires = jiffies + USLEEP_WAITLONG;					NCR5380_set_timer(instance);				}			}	/* if hostdata->selecting */			if (hostdata->connected#ifdef REAL_DMA			    && !hostdata->dmalen#endif			    && (!hostdata->time_expires || time_before_eq(hostdata->time_expires, jiffies))			    ) {				dprintk(NDEBUG_MAIN, ("scsi%d : main() : performing information transfer\n", instance->host_no));				NCR5380_information_transfer(instance);				dprintk(NDEBUG_MAIN, ("scsi%d : main() : done set false\n", instance->host_no));				done = 0;			} else				break;		}		/* for instance */	} while (!done);	/* Exit lock held */	clear_bit(0, &main_running);}#ifndef DONT_USE_INTR#include <linux/blk.h>#include <linux/spinlock.h>/** * 	NCR5380_intr	-	generic NCR5380 irq handler * *	Handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses *      from the disconnected queue, and restarting NCR5380_main()  *      as required. * *	Locks: caller must hold the io_request lock. */static void NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {	NCR5380_local_declare();	struct Scsi_Host *instance;	int done;	unsigned char basr;	dprintk(NDEBUG_INTR, ("scsi : NCR5380 irq %d triggered\n", irq));	do {		done = 1;		for (instance = first_instance; instance && (instance->hostt == the_template); instance = instance->next)			if (instance->irq == irq) {				/* Look for pending interrupts */				NCR5380_setup(instance);				basr = NCR5380_read(BUS_AND_STATUS_REG);				/* XXX dispatch to appropriate routine if found and done=0 */				if (basr & BASR_IRQ) {					NCR5380_dprint(NDEBUG_INTR, instance);					if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == (SR_SEL | SR_IO)) {						done = 0;						dprintk(NDEBUG_INTR, ("scsi%d : SEL interrupt\n", instance->host_no));						NCR5380_reselect(instance);						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);					} else if (basr & BASR_PARITY_ERROR) {						dprintk(NDEBUG_INTR, ("scsi%d : PARITY interrupt\n", instance->host_no));						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);					} else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {						dprintk(NDEBUG_INTR, ("scsi%d : RESET interrupt\n", instance->host_no));						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);					} else {#if defined(REAL_DMA)						/*						 * We should only get PHASE MISMATCH and EOP interrupts						 * if we have DMA enabled, so do a sanity check based on						 * the current setting of the MODE register.						 */						if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) {							int transfered;							if (!hostdata->connected)								panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno);							transfered = (hostdata->dmalen - NCR5380_dma_residual(instance));							hostdata->connected->SCp.this_residual -= transferred;							hostdata->connected->SCp.ptr += transferred;							hostdata->dmalen = 0;							(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);#if NCR_TIMEOUT							{								unsigned long timeout = jiffies + NCR_TIMEOUT;								spin_unlock_irq(&io_request_lock);								while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK && 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", host->host_no, __LINE__);							}#else /* NCR_TIMEOUT */							while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK);#endif							NCR5380_write(MODE_REG, MR_BASE);							NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);						}#else						dprintk(NDEBUG_INTR, ("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG)));						(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);#endif					}				}	/* if BASR_IRQ */				if (!done)					run_main();			}	/* if (instance->irq == irq) */	} while (!done);}/** *	do_NCR5380_intr *	@irq: interrupt number *	@dev_id: device info *	@regs: registers (unused) * *	Takes the io_request_lock and invokes the generic NCR5380 interrupt *	handler code * *	Locks: takes and releases the io_request lock */static void do_NCR5380_intr(int irq, void *dev_id, struct pt_regs *regs) {	unsigned long flags;	 spin_lock_irqsave(&io_request_lock, flags);	 NCR5380_intr(irq, dev_id, regs);	 spin_unlock_irqrestore(&io_request_lock, flags);}#endif/** *	collect_stats		-	collect stats on a scsi command *	@hostdata: adapter  *	@cmd: command being issued * *	Update the statistical data by parsing the command in question */ static void collect_stats(struct NCR5380_hostdata *hostdata, Scsi_Cmnd * cmd) {#ifdef NCR5380_STATS	switch (cmd->cmnd[0]) {	case WRITE:	case WRITE_6:	case WRITE_10:		hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);		hostdata->pendingw--;		break;	case READ:	case READ_6:	case READ_10:		hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);		hostdata->pendingr--;		break;	}#endif}/*  * Function : int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd,  *      int tag); * * Purpose : establishes I_T_L or I_T_L_Q nexus for new or existing command, *      including ARBITRATION, SELECTION, and initial message out for  *      IDENTIFY and queue messages.  * * Inputs : instance - instantiation of the 5380 driver on which this  *      target lives, cmd - SCSI command to execute, tag - set to TAG_NEXT for  *      new tag, TAG_NONE for untagged queueing, otherwise set to the tag for  *      the command that is presently connected. *  * Returns : -1 if selection could not execute for some reason, *      0 if selection succeeded or failed because the target  *      did not respond. * * Side effects :  *      If bus busy, arbitration failed, etc, NCR5380_select() will exit  *              with registers as they should have been on entry - ie *              SELECT_ENABLE will be set appropriately, the NCR5380 *              will cease to drive any SCSI bus signals. * *      If successful : I_T_L or I_T_L_Q nexus will be established,  *              instance->connected will be set to cmd.   *              SELECT interrupt will be disabled. * *      If failed (no target) : cmd->scsi_done() will be called, and the  *              cmd->result host byte set to DID_BAD_TARGET. * *	Locks: caller holds io_request_lock */ static int NCR5380_select(struct Scsi_Host *instance, Scsi_Cmnd * cmd, int tag) {	NCR5380_local_declare();	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;	unsigned char tmp[3], phase;	unsigned char *data;	int len;	unsigned long timeout;	unsigned char value;	NCR5380_setup(instance);	if (hostdata->selecting) {		goto part2;	/* RvC: sorry prof. Dijkstra, but it keeps the				   rest of the code nearly the same */	}	hostdata->restart_select = 0;	NCR5380_dprint(NDEBUG_ARBITRATION, instance);	dprintk(NDEBUG_ARBITRATION, ("scsi%d : starting arbitration, id = %d\n", instance->host_no, instance->this_id));	/* 	 * Set the phase bits to 0, otherwise the NCR5380 won't drive the 	 * data bus during SELECTION.	 */	NCR5380_write(TARGET_COMMAND_REG, 0);	/* 	 * Start arbitration.	 */	NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);	NCR5380_write(MODE_REG, MR_ARBITRATE);	/* Wait for arbitration logic to complete */#if NCR_TIMEOUT	{		unsigned long timeout = jiffies + 2 * NCR_TIMEOUT;		spin_unlock_irq(&io_request_lock);		while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)		       && time_before(jiffies, timeout));		spin_lock_irq(&io_request_lock);		if (time_after_eq(jiffies, timeout)) {			printk("scsi: arbitration timeout at %d\n", __LINE__);			NCR5380_write(MODE_REG, MR_BASE);			NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);			return -1;		}	}#else				/* NCR_TIMEOUT */	while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS));#endif	dprintk(NDEBUG_ARBITRATION, ("scsi%d : arbitration complete\n", instance->host_no));	/* 	 * The arbitration delay is 2.2us, but this is a minimum and there is 	 * no maximum so we can safely sleep for ceil(2.2) usecs to accommodate	 * the integral nature of udelay().	 *	 */	udelay(3);	/* Check for lost arbitration */	if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) || (NCR5380_read(CURRENT_SCSI_DATA_REG) & hostdata->id_higher_mask) || (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {		NCR5380_write(MODE_REG, MR_BASE);		dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", instance->host_no));		return -1;	}	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL);	if (!(hostdata->flags & FLAG_DTC3181E) &&	    /* RvC: DTC3181E has some trouble with this	     *      so we simply removed it. Seems to work with	     *      only Mustek scanner attached	     */	    (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST)) {		NCR5380_write(MODE_REG, MR_BASE);		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);		dprintk(NDEBUG_ARBITRATION, ("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", instance->host_no));		return -1;	}	/* 	 * Again, bus clear + bus settle time is 1.2us, however, this is 	 * a minimum so we'll udelay ceil(1.2)	 */	udelay(2);	dprintk(NDEBUG_ARBITRATION, ("scsi%d : won arbitration\n", instance->host_no));	/* 	 * Now that we have won arbitration, start Selection process, asserting 	 * the host and target ID's on the SCSI bus.	 */	NCR5380_write(OUTPUT_DATA_REG, (hostdata->id_mask | (1 << cmd->target)));	/* 	 * Raise ATN while SEL is true before BSY goes false from arbitration,	 * since this is the only way to guarantee that we'll get a MESSAGE OUT	 * phase immediately after selection.	 */	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_BSY | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));	NCR5380_write(MODE_REG, MR_BASE);	/* 	 * Reselect interrupts must be turned off prior to the dropping of BSY,	 * otherwise we will trigger an interrupt.	 */	NCR5380_write(SELECT_ENABLE_REG, 0);	/*	 * The initiator shall then wait at least two deskew delays and release 	 * the BSY signal.	 */	udelay(1);		/* wingel -- wait two bus deskew delay >2*45ns */	/* Reset BSY */	NCR5380_write(INITIATOR_COMMAND_REG, (ICR_BASE | ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_SEL));	/* 	 * Something weird happens when we cease to drive BSY - looks	 * like the board/chip is letting us do another read before the 	 * appropriate propagation delay has expired, and we're confusing	 * a BSY signal from ourselves as the target's response to SELECTION.	 *	 * A small delay (the 'C++' frontend breaks the pipeline with an	 * unnecessary jump, making it work on my 386-33/Trantor T128, the	 * tighter 'C' code breaks and requires this) solves the problem - 	 * the 1 us delay is arbitrary, and only used because this delay will 	 * be the same on other platforms and since it works here, it should 	 * work there.	 *	 * wingel suggests that this could be due to failing to wait	 * one deskew delay.	 */	udelay(1);	dprintk(NDEBUG_SELECTION, ("scsi%d : selecting target %d\n", instance->host_no, cmd->target));	/* 	 * The SCSI specification calls for a 250 ms timeout for the actual 	 * selection.	 */	timeout = jiffies + (250 * HZ / 1000);	/* 	 * XXX very interesting - we're seeing a bounce where the BSY we 	 * asserted is being reflected / still asserted (propagation delay?)	 * and it's detecting as true.  Sigh.	 */	hostdata->select_time = 0;	/* we count the clock ticks at which we polled */	hostdata->selecting = cmd;part2:	/* RvC: here we enter after a sleeping period, or immediately after	   execution of part 1	   we poll only once ech clock tick */	value = NCR5380_read(STATUS_REG) & (SR_BSY | SR_IO);	if (!value && (hostdata->select_time < 25)) {		/* RvC: we still must wait for a device response */		hostdata->select_time++;	/* after 25 ticks the device has failed */		hostdata->time_expires = jiffies + 1;		NCR5380_set_timer(instance);		return 0;	/* RvC: we return here with hostdata->selecting set,				   to go to sleep */	}	hostdata->selecting = 0;	/* clear this pointer, because we passed the					   waiting period */

⌨️ 快捷键说明

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