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

📄 mac_ncr5380.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
{    int i, s;    unsigned char *command;    SPRINTF("scsi%d: destination target %d, lun %d\n",	    H_NO(cmd), cmd->target, cmd->lun);    SPRINTF("        command = ");    command = cmd->cmnd;    SPRINTF("%2d (0x%02x)", command[0], command[0]);    for (i = 1, s = COMMAND_SIZE(command[0]); i < s; ++i)	SPRINTF(" %02x", command[i]);    SPRINTF("\n");    return pos;}/*  * Function : void NCR5380_init (struct Scsi_Host *instance) * * Purpose : initializes *instance and corresponding 5380 chip. * * Inputs : instance - instantiation of the 5380 driver.   * * Notes : I assume that the host, hostno, and id bits have been * 	set correctly.  I don't care about the irq and other fields.  *  */static void NCR5380_init (struct Scsi_Host *instance, int flags){    int i;    SETUP_HOSTDATA(instance);    NCR5380_all_init();    hostdata->aborted = 0;    hostdata->id_mask = 1 << instance->this_id;    hostdata->id_higher_mask = 0;    for (i = hostdata->id_mask; i <= 0x80; i <<= 1)	if (i > hostdata->id_mask)	    hostdata->id_higher_mask |= i;    for (i = 0; i < 8; ++i)	hostdata->busy[i] = 0;#ifdef SUPPORT_TAGS    init_tags();#endif#if defined (REAL_DMA)    hostdata->dma_len = 0;#endif    hostdata->targets_present = 0;    hostdata->connected = NULL;    hostdata->issue_queue = NULL;    hostdata->disconnected_queue = NULL;    hostdata->flags = FLAG_CHECK_LAST_BYTE_SENT;    if (!the_template) {	the_template = instance->hostt;	first_instance = instance;    }	#ifndef AUTOSENSE    if ((instance->cmd_per_lun > 1) || (instance->can_queue > 1))	 printk("scsi%d: WARNING : support for multiple outstanding commands enabled\n"	        "        without AUTOSENSE option, contingent allegiance conditions may\n"	        "        be incorrectly cleared.\n", HOSTNO);#endif /* def AUTOSENSE */    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);    NCR5380_write(MODE_REG, MR_BASE);    NCR5380_write(TARGET_COMMAND_REG, 0);    NCR5380_write(SELECT_ENABLE_REG, 0);}/*  * Function : int NCR5380_queue_command (Scsi_Cmnd *cmd,  *	void (*done)(Scsi_Cmnd *))  * * Purpose :  enqueues a SCSI command * * Inputs : cmd - SCSI command, done - function called on completion, with *	a pointer to the command descriptor. *  * Returns : 0 * * Side effects :  *      cmd is added to the per instance issue_queue, with minor  *	twiddling done to the host specific fields of cmd.  If the  *	main coroutine is not running, it is restarted. * *//* Only make static if a wrapper function is used */#ifndef NCR5380_queue_commandstatic#endifint NCR5380_queue_command (Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)){    SETUP_HOSTDATA(cmd->host);    Scsi_Cmnd *tmp;    int oldto;    unsigned long flags;    extern int update_timeout(Scsi_Cmnd * SCset, int timeout);#if (NDEBUG & NDEBUG_NO_WRITE)    switch (cmd->cmnd[0]) {    case WRITE_6:    case WRITE_10:	printk(KERN_NOTICE "scsi%d: WRITE attempted with NO_WRITE debugging flag set\n",	       H_NO(cmd));	cmd->result = (DID_ERROR << 16);	done(cmd);	return 0;    }#endif /* (NDEBUG & NDEBUG_NO_WRITE) */#ifdef NCR5380_STATS# if 0    if (!hostdata->connected && !hostdata->issue_queue &&	!hostdata->disconnected_queue) {	hostdata->timebase = jiffies;    }# endif# 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    /*      * We use the host_scribble field as a pointer to the next command       * in a queue      */    NEXT(cmd) = NULL;    cmd->scsi_done = done;    cmd->result = 0;    /*      * Insert the cmd into the issue queue. Note that REQUEST SENSE      * commands are added to the head of the queue since any command will     * clear the contingent allegiance condition that exists and the      * sense data is only guaranteed to be valid while the condition exists.     */    save_flags(flags);    cli();    if (!(hostdata->issue_queue) || (cmd->cmnd[0] == REQUEST_SENSE)) {	LIST(cmd, hostdata->issue_queue);	NEXT(cmd) = hostdata->issue_queue;	hostdata->issue_queue = cmd;    } else {	for (tmp = (Scsi_Cmnd *)hostdata->issue_queue;	     NEXT(tmp); tmp = NEXT(tmp))	    ;	LIST(cmd, tmp);	NEXT(tmp) = cmd;    }    restore_flags(flags);    QU_PRINTK("scsi%d: command added to %s of queue\n", H_NO(cmd),	      (cmd->cmnd[0] == REQUEST_SENSE) ? "head" : "tail");    /* If queue_command() is called from an interrupt (real one or bottom     * half), we let queue_main() do the job of taking care about main. If it     * is already running, this is a no-op, else main will be queued.     *     * If we're not in an interrupt, we can call NCR5380_main()     * unconditionally, because it cannot be already running.     */    if (in_interrupt() > 0 || ((flags >> 8) & 7) >= 6)	queue_main();    else	NCR5380_main();    return 0;}/* * Function : NCR5380_main (void)  * * Purpose : NCR5380_main is a coroutine that runs as long as more work can  *	be done on the NCR5380 host adapters in a system.  Both  *	NCR5380_queue_command() and NCR5380_intr() will try to start it  *	in case it is not running. *  * NOTE : NCR5380_main exits with interrupts *disabled*, the caller should  *  reenable them.  This prevents reentrancy and kernel stack overflow. */ 	    static void NCR5380_main (void){    Scsi_Cmnd *tmp, *prev;    struct Scsi_Host *instance = first_instance;    struct NCR5380_hostdata *hostdata = HOSTDATA(instance);    int done;    unsigned long flags;        /*     * We run (with interrupts disabled) until we're sure that none of      * the host adapters have anything that can be done, at which point      * we set main_running to 0 and exit.     *     * Interrupts are enabled before doing various other internal      * instructions, after we've decided that we need to run through     * the loop again.     *     * this should prevent any race conditions.     *      * ++roman: Just disabling the NCR interrupt isn't sufficient here,     * because also a timer int can trigger an abort or reset, which can     * alter queues and touch the Falcon lock.     */    /* Tell int handlers main() is now already executing.  Note that       no races are possible here. If an int comes in before       'main_running' is set here, and queues/executes main via the       task queue, it doesn't do any harm, just this instance of main       won't find any work left to do. */    if (main_running)    	return;    main_running = 1;    save_flags(flags);    do {	cli(); /* Freeze request queues */	done = 1;		if (!hostdata->connected) {	    MAIN_PRINTK( "scsi%d: not connected\n", HOSTNO );	    /*	     * Search through the issue_queue for a command destined	     * for a target that's not busy.	     */#if (NDEBUG & NDEBUG_LISTS)	    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, prev = NULL;		 tmp && (tmp != prev); prev = tmp, tmp = NEXT(tmp))		;		/*printk("%p  ", tmp);*/	    if ((tmp == prev) && tmp) printk(" LOOP\n");/* else printk("\n");*/#endif	    for (tmp = (Scsi_Cmnd *) hostdata->issue_queue, 		 prev = NULL; tmp; prev = tmp, tmp = NEXT(tmp) ) {#if (NDEBUG & NDEBUG_LISTS)		if (prev != tmp)		    printk("MAIN tmp=%p   target=%d   busy=%d lun=%d\n",			   tmp, tmp->target, hostdata->busy[tmp->target],			   tmp->lun);#endif		/*  When we find one, remove it from the issue queue. */		if (#ifdef SUPPORT_TAGS		    !is_lun_busy( tmp, tmp->cmnd[0] != REQUEST_SENSE)#else		    !(hostdata->busy[tmp->target] & (1 << tmp->lun))#endif		    ) {		    cli(); /* ++guenther: just to be sure, this must be atomic */		    if (prev) {		        REMOVE(prev, NEXT(prev), tmp, NEXT(tmp));			NEXT(prev) = NEXT(tmp);		    } else {		        REMOVE(-1, hostdata->issue_queue, tmp, NEXT(tmp));			hostdata->issue_queue = NEXT(tmp);		    }		    NEXT(tmp) = NULL;		    		    /* reenable interrupts after finding one */		    restore_flags(flags);		    		    /* 		     * Attempt to establish an I_T_L nexus here. 		     * On success, instance->hostdata->connected is set.		     * On failure, we must add the command back to the		     *   issue queue so we can keep trying.			     */		    MAIN_PRINTK("scsi%d: main(): command for target %d "				"lun %d removed from issue_queue\n",				HOSTNO, tmp->target, tmp->lun);		    /* 		     * REQUEST SENSE commands are issued without tagged		     * queueing, even on SCSI-II devices because the 		     * contingent allegiance condition exists for the 		     * entire unit.		     */		    /* ++roman: ...and the standard also requires that		     * REQUEST SENSE command are untagged.		     */		    #ifdef SUPPORT_TAGS		    cmd_get_tag( tmp, tmp->cmnd[0] != REQUEST_SENSE );#endif		    if (!NCR5380_select(instance, tmp, 			    (tmp->cmnd[0] == REQUEST_SENSE) ? TAG_NONE : 			    TAG_NEXT)) {			break;		    } else {			cli();			LIST(tmp, hostdata->issue_queue);			NEXT(tmp) = hostdata->issue_queue;			hostdata->issue_queue = tmp;#ifdef SUPPORT_TAGS			cmd_free_tag( tmp );#endif			restore_flags(flags);			MAIN_PRINTK("scsi%d: main(): select() failed, "				    "returned to issue_queue\n", HOSTNO);			if (hostdata->connected)			    break;		    }		} /* if target/lun/target queue is not busy */	    } /* for issue_queue */	} /* if (!hostdata->connected) */			if (hostdata->connected #ifdef REAL_DMA	    && !hostdata->dma_len#endif	    ) {	    restore_flags(flags);	    MAIN_PRINTK("scsi%d: main: performing information transfer\n",			HOSTNO);	    NCR5380_information_transfer(instance);	    MAIN_PRINTK("scsi%d: main: done set false\n", HOSTNO);	    done = 0;	}    } while (!done);    /* Better allow ints _after_ 'main_running' has been cleared, else       an interrupt could believe we'll pick up the work it left for       us, but we won't see it anymore here... */    main_running = 0;    restore_flags(flags);}#ifdef REAL_DMA/* * Function : void NCR5380_dma_complete (struct Scsi_Host *instance) * * Purpose : Called by interrupt handler when DMA finishes or a phase *	mismatch occurs (which would finish the DMA transfer).   * * Inputs : instance - this instance of the NCR5380. * */static void NCR5380_dma_complete( struct Scsi_Host *instance ){    SETUP_HOSTDATA(instance);    int           transfered, saved_data = 0, overrun = 0, cnt, toPIO;    unsigned char **data, p;    volatile int  *count;    if (!hostdata->connected) {	printk(KERN_WARNING "scsi%d: received end of DMA interrupt with "	       "no connected cmd\n", HOSTNO);	return;    }        if (mac_read_overruns) {	p = hostdata->connected->SCp.phase;	if (p & SR_IO) {	    udelay(10);	    if ((((NCR5380_read(BUS_AND_STATUS_REG)) &		  (BASR_PHASE_MATCH|BASR_ACK)) ==		 (BASR_PHASE_MATCH|BASR_ACK))) {		saved_data = NCR5380_read(INPUT_DATA_REG);		overrun = 1;		DMA_PRINTK("scsi%d: read overrun handled\n", HOSTNO);	    }	}    }    DMA_PRINTK("scsi%d: real DMA transfer complete, basr 0x%X, sr 0x%X\n",	       HOSTNO, NCR5380_read(BUS_AND_STATUS_REG),	       NCR5380_read(STATUS_REG));    (void) NCR5380_read(RESET_PARITY_INTERRUPT_REG);    NCR5380_write(MODE_REG, MR_BASE);    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);    transfered = hostdata->dma_len - NCR5380_dma_residual(instance);    hostdata->dma_len = 0;    data = (unsigned char **) &(hostdata->connected->SCp.ptr);    count = &(hostdata->connected->SCp.this_residual);    *data += transfered;    *count -= transfered;    if (mac_read_overruns) {	if ((NCR5380_read(STATUS_REG) & PHASE_MASK) == p && (p & SR_IO)) {	    cnt = toPIO = mac_read_overruns;	    if (overrun) {		DMA_PRINTK("Got an input overrun, using saved byte\n");		*(*data)++ = saved_data;		(*count)--;		cnt--;		toPIO--;	    }	    DMA_PRINTK("Doing %d-byte PIO to 0x%08lx\n", cnt, (long)*data);	    NCR5380_transfer_pio(instance, &p, &cnt, data);	    *count -= toPIO - cnt;

⌨️ 快捷键说明

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