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

📄 mac_ncr5380.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
	       HOSTNO, cmd->target);    tmp[0] = IDENTIFY(1, cmd->lun);#ifdef SUPPORT_TAGS    if (cmd->tag != TAG_NONE) {	tmp[1] = hostdata->last_message = SIMPLE_QUEUE_TAG;	tmp[2] = cmd->tag;	len = 3;    } else 	len = 1;#else    len = 1;    cmd->tag=0;#endif /* SUPPORT_TAGS */    /* Send message(s) */    data = tmp;    phase = PHASE_MSGOUT;    NCR5380_transfer_pio(instance, &phase, &len, &data);    SEL_PRINTK("scsi%d: nexus established.\n", HOSTNO);    /* XXX need to handle errors here */    hostdata->connected = cmd;#ifndef SUPPORT_TAGS    hostdata->busy[cmd->target] |= (1 << cmd->lun);#endif        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 are 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){    register unsigned char p = *phase, tmp;    register int c = *count;    register unsigned char *d = *data;    /*      * 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));    do {	/* 	 * Wait for assertion of REQ, after which the phase bits will be 	 * valid 	 */	while (!((tmp = NCR5380_read(STATUS_REG)) & SR_REQ));	HSH_PRINTK("scsi%d: REQ detected\n", HOSTNO);	/* Check for phase mismatch */		if ((tmp & PHASE_MASK) != p) {	    PIO_PRINTK("scsi%d: phase mismatch\n", HOSTNO);	    NCR_PRINT_PHASE(NDEBUG_PIO);	    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);		NCR_PRINT(NDEBUG_PIO);		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);		NCR_PRINT(NDEBUG_PIO);		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 		    ICR_ASSERT_DATA | ICR_ASSERT_ATN | ICR_ASSERT_ACK);	    }	} else {	    NCR_PRINT(NDEBUG_PIO);	    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ACK);	}	while (NCR5380_read(STATUS_REG) & SR_REQ);	HSH_PRINTK("scsi%d: req false, handshake complete\n", HOSTNO);/* * 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);    PIO_PRINTK("scsi%d: residual %d\n", HOSTNO, c);    *count = c;    *data = d;    tmp = NCR5380_read(STATUS_REG);    /* The phase read from the bus is valid if either REQ is (already)     * asserted or if ACK hasn't been released yet. The latter is the case if     * we're in MSGIN and all wanted bytes have been received. */    if ((tmp & SR_REQ) || (p == PHASE_MSGIN && c == 0))	*phase = tmp & PHASE_MASK;    else 	*phase = PHASE_UNKNOWN;    if (!c || (*phase == p))	return 0;    else 	return -1;}/* * 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. */static int do_abort (struct Scsi_Host *host) {    unsigned char tmp, *msgptr, phase;    int len;    /* 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)/*  * 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. * */static int NCR5380_transfer_dma( struct Scsi_Host *instance, 				 unsigned char *phase, int *count,				 unsigned char **data){    SETUP_HOSTDATA(instance);    register int c = *count;    register unsigned char p = *phase;    register unsigned char *d = *data;    register int foo;    unsigned char tmp;    unsigned long flags;    if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {        *phase = tmp;        return -1;    }    if (mac_read_overruns && (p & SR_IO)) {	c -= mac_read_overruns;    }    DMA_PRINTK("scsi%d: initializing DMA for %s, %d bytes %s %p\n",	       HOSTNO, (p & SR_IO) ? "reading" : "writing",	       c, (p & SR_IO) ? "to" : "from", d);    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);#else /* PSEUDO_DMA! */#if defined(PSEUDO_DMA) && !defined(UNSAFE)    save_flags(flags);    cli();#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#ifndef EMULATE_PSEUDO_DMA	NCR5380_write(MODE_REG, MR_BASE | MR_DMA_MODE);#else        NCR5380_write(MODE_REG, MR_BASE);#endif#endif /* def REAL_DMA  */#ifdef REAL_DMA    /* On the Medusa, it is a must to initialize the DMA before     * starting the NCR. This is also the cleaner way for the TT.     */    save_flags(flags);    cli();    hostdata->dma_len = (p & SR_IO) ?        NCR5380_dma_read_setup(instance, d, c) :         NCR5380_dma_write_setup(instance, d, c);    restore_flags(flags);#endif /* def REAL_DMA */#ifndef EMULATE_PSEUDO_DMA    if (p & SR_IO)	NCR5380_write(START_DMA_INITIATOR_RECEIVE_REG, 0);    else {	NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_DATA);	NCR5380_write(START_DMA_SEND_REG, 0);    }#else    hostdata->dma_len = c;#endif#if defined(REAL_DMA)    return 0;#else /* defined(PSEUDO_DMA) */    if (p & SR_IO) {#ifdef DMA_WORKS_RIGHT        foo = NCR5380_pread(instance, d, c);#else	int diff = 1;	if (hostdata->flags & FLAG_NCR53C400) {	    diff=0;	}	if (!(foo = NCR5380_pread(instance, d, c - diff))) {	    /*	     * We can't disable DMA mode after successfully transferring 	     * what we plan to be the last byte, since that would open up	     * a race condition where if the target asserted REQ before 	     * we got the DMA mode reset, the NCR5380 would have latched	     * an additional byte into the INPUT DATA register and we'd	     * have dropped it.	     * 	     * The workaround was to transfer one fewer bytes than we 	     * intended to with the pseudo-DMA read function, wait for 	     * the chip to latch the last byte, read it, and then disable	     * pseudo-DMA mode.	     * 	     * After REQ is asserted, the NCR5380 asserts DRQ and ACK.	     * REQ is deasserted when ACK is asserted, and not reasserted	     * until ACK goes false.  Since the NCR5380 won't lower ACK	     * until DACK is asserted, which won't happen unless we twiddle	     * the DMA port or we take the NCR5380 out of DMA mode, we 	     * can guarantee that we won't handshake another extra 	     * byte.    	     */	    if (!(hostdata->flags & FLAG_NCR53C400)) {		while (!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_DRQ));		/* Wait for clean handshake */		while (NCR5380_read(STATUS_REG) & SR_REQ);		d[c - 1] = NCR5380_read(INPUT_DATA_REG);	    }	}#endif    } else {#ifdef DMA_WORKS_RIGHT        foo = NCR5380_pwrite(instance, d, c);#else        int timeout;#if (NDEBUG & NDEBUG_C400_PWRITE)	printk("About to pwrite %d bytes\n", c);#endif	if (!(foo = NCR5380_pwrite(instance, d, c))) {	    /*	     * Wait for the last byte to be sent.  If REQ is being asserted for 	     * the byte we're interested, we'll ACK it and it will go false.  	     */	    if (!(hostdata->flags & FLAG_HAS_LAST_BYTE_SENT)) {		timeout = 20000;#if 1#if 1		while (!(NCR5380_read(BUS_AND_STATUS_REG) & 			BASR_DRQ) && (NCR5380_read(BUS_AND_STATUS_REG) &			BASR_PHASE_MATCH));#else		if (NCR5380_read(STATUS_REG) & SR_REQ) {		    for (; timeout && 			!(NCR5380_read(BUS_AND_STATUS_REG) & BASR_ACK); 			--timeout);		    for (; timeout && (NCR5380_read(STATUS_REG) & SR_REQ);			--timeout);		} #endif	#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)		if (!timeout) 		    printk("scsi%d : timed out on last byte\n",			    instance->host_no);#endif		if (hostdata->flags & FLAG_CHECK_LAST_BYTE_SENT) {		    hostdata->flags &= ~FLAG_CHECK_LAST_BYTE_SENT;		    if (NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT) {			hostdata->flags |= FLAG_HAS_LAST_BYTE_SENT;#if (NDEBUG & NDEBUG_LAST_BYTE_SENT)			printk("scsi%d : last bit sent works\n", 			    instance->host_no);#endif		    }		}	    } else  {#if (NDEBUG & NDEBUG_C400_PWRITE)		printk("Waiting for LASTBYTE\n");#endif		while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT));#if (NDEBUG & NDEBUG_C400_PWRITE)		printk("Got LASTBYTE\n");#endif	    }#else	    udelay (5);#endif	}#endif    }    NCR5380_write(MODE_REG, MR_BASE);    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE)

⌨️ 快捷键说明

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