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

📄 ncr5380.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 5 页
字号:
			 *			 * With successful commands, we fall through			 * and see if we can do an information transfer,			 * with failures we will restart.			 */			if (!NCR5380_select(instance, tmp,     			/*     			 * REQUEST SENSE commands are issued without tagged    			 * queueing, even on SCSI-II devices because the     			 * contingent allegiance condition exists for the     			 * entire unit.    			 */			    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : 			    TAG_NEXT)) {			    break;			} else {			    cli();			    LIST(tmp, hostdata->issue_queue);			    tmp->host_scribble = (unsigned char *) 				hostdata->issue_queue;			    hostdata->issue_queue = tmp;			    done = 0;			    sti();#if (NDEBUG & (NDEBUG_MAIN | NDEBUG_QUEUES))			printk("scsi%d : main(): select() failed, returned to issue_queue\n",			    instance->host_no);#endif			}		    } /* if target/lun is not busy */		} /* for */	    } /* if (!hostdata->connected) */			    if (hostdata->connected #ifdef REAL_DMA		&& !hostdata->dmalen#endif#ifdef USLEEP		&& (!hostdata->time_expires || hostdata->time_expires >= jiffies)#endif		) {		sti();#if (NDEBUG & NDEBUG_MAIN)		printk("scsi%d : main() : performing information transfer\n",			instance->host_no);#endif		NCR5380_information_transfer(instance);#if (NDEBUG & NDEBUG_MAIN)		printk("scsi%d : main() : done set false\n", instance->host_no);#endif		done = 0;	    } else 		break;	} /* for instance */    } while (!done);    main_running = 0;}#ifndef DONT_USE_INTR/* * 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) {    NCR5380_local_declare();     struct Scsi_Host *instance;    int done;    unsigned char basr;#if (NDEBUG & NDEBUG_INTR)    printk("scsi : NCR5380 irq %d triggered\n", irq);#endif    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) {#if (NDEBUG & NDEBUG_INTR)		    NCR5380_print(instance);#endif		    if ((NCR5380_read(STATUS_REG) & (SR_SEL | SR_IO)) == 			(SR_SEL | SR_IO)) {			done = 0;			sti();#if (NDEBUG & NDEBUG_INTR)			printk("scsi%d : SEL interrupt\n", instance->host_no);#endif			NCR5380_reselect(instance);			(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);		    } else if (basr & BASR_PARITY_ERROR) {#if (NDEBUG & NDEBUG_INTR)			printk("scsi%d : PARITY interrupt\n", instance->host_no);#endif			(void) NCR5380_read(RESET_PARITY_INTERRUPT_REG); 		    } else if ((NCR5380_read(STATUS_REG) & SR_RST) == SR_RST) {#if (NDEBUG & NDEBUG_INTR) 			printk("scsi%d : RESET interrupt\n", instance->host_no);#endif			(void)NCR5380_read(RESET_PARITY_INTERRUPT_REG);		    } else {/*   * XXX the rest of the interrupt conditions should *only* occur during a  * DMA transfer, which I haven't gotten around to fixing yet. */#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;			      while (NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK				     && jiffies < timeout)				;			      if (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#if (NDEBUG & NDEBUG_INTR)		    printk("scsi : unknown interrupt, BASR 0x%X, MR 0x%X, SR 0x%x\n", basr, NCR5380_read(MODE_REG), NCR5380_read(STATUS_REG));#endif		    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);#endif		    } 		} /* if BASR_IRQ */		if (!done) 		    run_main();	    } /* if (instance->irq == irq) */    } while (!done);}#endif#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) {    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;    NCR5380_setup(instance);    hostdata->restart_select = 0;#if defined (NDEBUG) && (NDEBUG & NDEBUG_ARBITRATION)     NCR5380_print(instance);    printk("scsi%d : starting arbitration, id = %d\n", instance->host_no,	instance->this_id);#endif    cli();     /*      * 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);    sti();    /* 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)	   && jiffies < timeout)	;      if (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#if (NDEBUG & NDEBUG_ARBITRATION)     printk("scsi%d : arbitration complete\n", instance->host_no);/* Avoid GCC 2.4.5 asm needs to many reloads error */    __asm__("nop");#endif    /*      * 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); #if (NDEBUG & NDEBUG_ARBITRATION)    printk("scsi%d : lost arbitration, deasserting MR_ARBITRATE\n", 	instance->host_no);#endif	return -1;    }    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_SEL);        if (NCR5380_read(INITIATOR_COMMAND_REG) & ICR_ARBITRATION_LOST) {	NCR5380_write(MODE_REG, MR_BASE);	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);#if (NDEBUG & NDEBUG_ARBITRATION)    printk("scsi%d : lost arbitration, deasserting ICR_ASSERT_SEL\n", 	instance->host_no);#endif	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);	#if (NDEBUG & NDEBUG_ARBITRATION)    printk("scsi%d : won arbitration\n", instance->host_no);#endif    /*      * 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);#if (NDEBUG & NDEBUG_SELECTION)    printk("scsi%d : selecting target %d\n", instance->host_no, cmd->target);#endif    /*      * 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.     */    while ((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 ("scsi%d : reselection after won arbitration?\n",		instance->host_no);	    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);	    return -1;    }    /* 

⌨️ 快捷键说明

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