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

📄 mac_ncr5380.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	}    }}#endif /* REAL_DMA *//* * Function : void NCR5380_intr (int irq) *  * Purpose : handle interrupts, reestablishing I_T_L or I_T_L_Q nexuses *	from the disconnected queue, and restarting NCR5380_main()  *	as required. * * Inputs : int irq, irq that caused this interrupt. * */static void NCR5380_intr (int irq, void *dev_id, struct pt_regs *regs){    struct Scsi_Host *instance = first_instance;    int done = 1;    unsigned char basr;    INT_PRINTK("scsi%d: NCR5380 irq triggered\n", HOSTNO);    /* Look for pending interrupts */    basr = NCR5380_read(BUS_AND_STATUS_REG);    INT_PRINTK("scsi%d: BASR=%02x\n", HOSTNO, basr);    /* dispatch to appropriate routine if found and done=0 */    if (basr & BASR_IRQ) {	NCR_PRINT(NDEBUG_INTR);	if ((NCR5380_read(STATUS_REG) & (SR_SEL|SR_IO)) == (SR_SEL|SR_IO)) {	    done = 0;	    ENABLE_IRQ();	    INT_PRINTK("scsi%d: SEL interrupt\n", HOSTNO);	    NCR5380_reselect(instance);	    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);	}	else if (basr & BASR_PARITY_ERROR) {	    INT_PRINTK("scsi%d: PARITY interrupt\n", HOSTNO);	    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);	}	else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {	    INT_PRINTK("scsi%d: RESET interrupt\n", HOSTNO);	    (void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);	}	else {	    /*  	     * The rest of the interrupt conditions can occur only during a	     * DMA transfer	     */#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_MODE) &&		((basr & BASR_END_DMA_TRANSFER) || 		 !(basr & BASR_PHASE_MATCH))) {		    		INT_PRINTK("scsi%d: PHASE MISM or EOP interrupt\n", HOSTNO);		NCR5380_dma_complete( instance );		done = 0;		ENABLE_IRQ();	    } else#endif /* REAL_DMA */	    {/* MS: Ignore unknown phase mismatch interrupts (caused by EOP interrupt) */		if (basr & BASR_PHASE_MATCH)		    printk(KERN_NOTICE "scsi%d: unknown interrupt, "			   "BASR 0x%x, MR 0x%x, SR 0x%x\n",			   HOSTNO, basr, NCR5380_read(MODE_REG),			   NCR5380_read(STATUS_REG));		(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);	    }	} /* if !(SELECTION || PARITY) */    } /* BASR & IRQ */    else {	printk(KERN_NOTICE "scsi%d: interrupt without IRQ bit set in BASR, "	       "BASR 0x%X, MR 0x%X, SR 0x%x\n", HOSTNO, basr,	       NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));	(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);    }        if (!done) {	INT_PRINTK("scsi%d: in int routine, calling main\n", HOSTNO);	/* Put a call to NCR5380_main() on the queue... */	queue_main();    }}#ifdef NCR5380_STATSstatic void collect_stats(struct NCR5380_hostdata* hostdata, Scsi_Cmnd* cmd){# ifdef NCR5380_STAT_LIMIT    if (cmd->request_bufflen > NCR5380_STAT_LIMIT)# endif	switch (cmd->cmnd[0])	{	    case WRITE:	    case WRITE_6:	    case WRITE_10:		hostdata->time_write[cmd->target] += (jiffies - hostdata->timebase);		/*hostdata->bytes_write[cmd->target] += cmd->request_bufflen;*/		hostdata->pendingw--;		break;	    case READ:	    case READ_6:	    case READ_10:		hostdata->time_read[cmd->target] += (jiffies - hostdata->timebase);		/*hostdata->bytes_read[cmd->target] += cmd->request_bufflen;*/		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. */static int NCR5380_select (struct Scsi_Host *instance, Scsi_Cmnd *cmd, int tag){    SETUP_HOSTDATA(instance);    unsigned char tmp[3], phase;    unsigned char *data;    int len;    unsigned long timeout;    unsigned long flags;    hostdata->restart_select = 0;    NCR_PRINT(NDEBUG_ARBITRATION);    ARB_PRINTK("scsi%d: starting arbitration, id = %d\n", HOSTNO,	       instance->this_id);    /*      * Set the phase bits to 0, otherwise the NCR5380 won't drive the      * data bus during SELECTION.     */    save_flags(flags);    cli();    if (hostdata->connected) {	restore_flags(flags);	return -1;    }    NCR5380_write(TARGET_COMMAND_REG, 0);    /*      * Start arbitration.     */        NCR5380_write(OUTPUT_DATA_REG, hostdata->id_mask);    NCR5380_write(MODE_REG, MR_ARBITRATE);    restore_flags(flags);    /* Wait for arbitration logic to complete */#if NCR_TIMEOUT    {      unsigned long timeout = jiffies + 2*NCR_TIMEOUT;      while (!(NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_PROGRESS)	   && time_before(jiffies, timeout) && !hostdata->connected)	;      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)	 && !hostdata->connected);#endif    ARB_PRINTK("scsi%d: arbitration complete\n", HOSTNO);    if (hostdata->connected) {	NCR5380_write(MODE_REG, MR_BASE); 	return -1;    }    /*      * 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) ||	hostdata->connected) {	NCR5380_write(MODE_REG, MR_BASE); 	ARB_PRINTK("scsi%d: lost arbitration, deasserting MR_ARBITRATE\n",		   HOSTNO);	return -1;    }     /* after/during arbitration, BSY should be asserted.	IBM DPES-31080 Version S31Q works now */     /* Tnx to Thomas_Roesch@m2.maus.de for finding this! (Roman) */    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL |					 ICR_ASSERT_BSY ) ;        if ((NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) ||	hostdata->connected) {	NCR5380_write(MODE_REG, MR_BASE);	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);	ARB_PRINTK("scsi%d: lost arbitration, deasserting ICR_ASSERT_SEL\n",		   HOSTNO);	return -1;    }    /*      * Again, bus clear + bus settle time is 1.2us, however, this is      * a minimum so we'll udelay ceil(1.2)     */#ifdef CONFIG_ATARI_SCSI_TOSHIBA_DELAY    /* ++roman: But some targets (see above :-) seem to need a bit more... */    udelay(15);#else    udelay(2);#endif        if (hostdata->connected) {	NCR5380_write(MODE_REG, MR_BASE);	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);	return -1;    }    ARB_PRINTK("scsi%d: won arbitration\n", HOSTNO);    /*      * 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.     */    if (hostdata->connected) {	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);	return -1;    }    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);    SEL_PRINTK("scsi%d: selecting target %d\n", HOSTNO, cmd->target);    /*      * The SCSI specification calls for a 250 ms timeout for the actual      * selection.     */    timeout = jiffies + 25;     /*      * 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.     */#if 0    /* ++roman: If a target conformed to the SCSI standard, it wouldn't assert     * IO while SEL is true. But again, there are some disks out the in the     * world that do that nevertheless. (Somebody claimed that this announces     * reselection capability of the target.) So we better skip that test and     * only wait for BSY... (Famous german words: Der Kl黦ere gibt nach :-)     */    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & 	(SR_BSY | SR_IO)));    if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == 	    (SR_SEL | SR_IO)) {	    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);	    NCR5380_reselect(instance);	    printk (KERN_ERR "scsi%d: reselection after won arbitration?\n",		    HOSTNO);	    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);	    return -1;    }#else    while (time_before(jiffies, timeout) && !(NCR5380_read(STATUS_REG) & SR_BSY));#endif    /*      * 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(KERN_ERR "scsi%d: weirdness\n", HOSTNO);	    if (hostdata->restart_select)		printk(KERN_NOTICE "\trestart select\n");	    NCR_PRINT(NDEBUG_ANY);	    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);	    return -1;	}	cmd->result = DID_BAD_TARGET << 16;#ifdef NCR5380_STATS	collect_stats(hostdata, cmd);#endif#ifdef SUPPORT_TAGS	cmd_free_tag( cmd );#endif	cmd->scsi_done(cmd);	NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);	SEL_PRINTK("scsi%d: target did not respond within 250ms\n", HOSTNO);	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 */    while (!(NCR5380_read(STATUS_REG) & SR_REQ));    SEL_PRINTK("scsi%d: target %d selected, going into MESSAGE OUT phase.\n",

⌨️ 快捷键说明

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