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

📄 atari_ncr5380.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
     * 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",	       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)/*  * 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;    unsigned char tmp;    unsigned long flags;    if ((tmp = (NCR5380_read(STATUS_REG) & PHASE_MASK)) != p) {        *phase = tmp;        return -1;    }    if (atari_read_overruns && (p & SR_IO)) {	c -= atari_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);#endif /* def REAL_DMA  */    if (IS_A_TT()) {	/* 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);    }        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);    }    if (!IS_A_TT()) {	/* On the Falcon, the DMA setup must be done after the last */	/* NCR access, else the DMA setup gets trashed!	 */	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);    }    return 0;}#endif /* defined(REAL_DMA) *//* * Function : NCR5380_information_transfer (struct Scsi_Host *instance) * * Purpose : run through the various SCSI phases and do as the target  * 	directs us to.  Operates on the currently connected command,  *	instance->connected. * * Inputs : instance, instance for which we are doing commands * * Side effects : SCSI things happen, the disconnected queue will be  *	modified if a command disconnects, *instance->connected will *	change. * * XXX Note : we need to watch for bus free or a reset condition here  * 	to recover from an unexpected bus free condition. */ static void NCR5380_information_transfer (struct Scsi_Host *instance){    SETUP_HOSTDATA(instance);    unsigned long flags;    unsigned char msgout = NOP;    int sink = 0;    int len;#if defined(REAL_DMA)    int transfersize;#endif    unsigned char *data;    unsigned char phase, tmp, extended_msg[10], old_phase=0xff;    Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;    while (1) {	tmp = NCR5380_read(STATUS_REG);	/* We only have a valid SCSI phase when REQ is asserted */	if (tmp & SR_REQ) {	    phase = (tmp & PHASE_MASK); 	    if (phase != old_phase) {		old_phase = phase;		NCR_PRINT_PHASE(NDEBUG_INFORMATION);	    }	    	    if (sink && (phase != PHASE_MSGOUT)) {		NCR5380_write(TARGET_COMMAND_REG, PHASE_SR_TO_TCR(tmp));		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);		sink = 0;		continue;	    }	    switch (phase) {	    case PHASE_DATAOUT:#if (NDEBUG & NDEBUG_NO_DATAOUT)		printk("scsi%d: NDEBUG_NO_DATAOUT set, attempted DATAOUT "		       "aborted\n", HOSTNO);		sink = 1;		do_abort(instance);		cmd->result = DID_ERROR  << 16;		cmd->done(cmd);		return;#endif	    case PHASE_DATAIN:		/* 		 * If there is no room left in the current buffer in the		 * scatter-gather list, move onto the next one.		 */		if (!cmd->SCp.this_residual && cmd->SCp.buffers_residual) {		    ++cmd->SCp.buffer;		    --cmd->SCp.buffers_residual;		    cmd->SCp.this_residual = cmd->SCp.buffer->length;		    cmd->SCp.ptr = cmd->SCp.buffer->address;		    /* ++roman: Try to merge some scatter-buffers if		     * they are at contiguous physical addresses.		     */		    merge_contiguous_buffers( cmd );		    INF_PRINTK("scsi%d: %d bytes and %d buffers left\n",			       HOSTNO, cmd->SCp.this_residual,			       cmd->SCp.buffers_residual);		}		/*		 * The preferred transfer method is going to be 		 * PSEUDO-DMA for systems that are strictly PIO,		 * since we can let the hardware do the handshaking.		 *		 * For this to work, we need to know the transfersize		 * ahead of time, since the pseudo-DMA code will sit		 * in an unconditional loop.		 *//* ++roman: I suggest, this should be *   #if def(REAL_DMA) * instead of leaving REAL_DMA out. */#if defined(REAL_DMA)		if (!cmd->device->borken &&		    (transfersize = NCR5

⌨️ 快捷键说明

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