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

📄 ncr5380.c

📁 <Linux1.0核心游记>电子书+书后源码+Linux1.0源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#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 		while (!(NCR5380_read(TARGET_COMMAND_REG) & TCR_LAST_BYTE_SENT));#else	    udelay (5);#endif	}    }    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE);    NCR5380_write(MODE_REG, MR_BASE);    *data = d + c;    *count = 0;    *phase = (NCR5380_read(STATUS_REG & PHASE_MASK));#if defined(PSEUDO_DMA) && !defined(UNSAFE)    sti();#endif /* defined(REAL_DMA_POLL) */    return foo;#endif /* def REAL_DMA */}#endif /* defined(REAL_DMA) | defined(PSEUDO_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) {    NCR5380_local_declare();    struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) 	instance->hostdata;    unsigned char msgout = NOP;    int len, transfersize;    unsigned char *data;    unsigned char phase, tmp, old_phase=0xff;    Scsi_Cmnd *cmd = (Scsi_Cmnd *) hostdata->connected;    NCR5380_setup(instance);    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;#if (NDEBUG & NDEBUG_INFORMATION)		NCR5380_print_phase(instance);#endif	    }	    switch (phase) {	    case PHASE_DATAIN:	    case PHASE_DATAOUT:#if (NDEBUG & NDEBUG_NO_DATAOUT)		printk("scsi%d : NDEBUG_NO_DATAOUT set, attempted DATAOUT aborted\n",		    instance->host_no);		msgout = ABORT;		NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | ICR_ASSERT_ATN);		break;#endif		/* 		 * 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;#if (NDEBUG & NDEBUG_INFORMATION)		    printk("scsi%d : %d bytes and %d buffers left\n",			instance->host_no, cmd->SCp.this_residual,			cmd->SCp.buffers_residual);#endif		}		/*		 * The preffered 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.		 */#if defined(PSEUDO_DMA) || defined(REAL_DMA_POLL)#ifdef NCR5380_dma_xfer_len		if (!scsi_devices[cmd->index].borken &&		    (transfersize = NCR5380_dma_xfer_len(instance, cmd)) != 0) {#else		if (!scsi_devices[cmd->index].borken && 		    (transfersize = cmd->transfersize) && 		    cmd->SCp.this_residual && !(cmd->SCp.this_residual % 		    transfersize)) {#endif		    len = transfersize;		    if (NCR5380_transfer_dma(instance, &phase,			&len, (unsigned char **) &cmd->SCp.ptr)) {			/*			 * If the watchdog timer fires, all future accesses to this			 * device will use the polled-IO.			 */ 			printk("scsi%d : switching target %d lun %d to slow handshake\n",			    instance->host_no, cmd->target, cmd->lun);			scsi_devices[cmd->index].borken = 1;			NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 			    ICR_ASSERT_ATN);			msgout = ABORT;		    } else			cmd->SCp.this_residual -= transfersize - len;		} else#endif /* defined(REAL_DMA) || defined(REAL_DMA_POLL) */		  NCR5380_transfer_pio(instance, &phase, 		    (int *) &cmd->SCp.this_residual, (unsigned char **)		    &cmd->SCp.ptr);		break;	    case PHASE_MSGIN:		/* 		 * XXX - we don't handle multi-byte messages here, since we 		 * shouldn't get them after the I_T_L_Q nexus is established		 * for tagged queuing, and the host should initiate any 		 * negotiations for sync. SCSI, etc.		 */		len = 1;		data = &tmp;		NCR5380_transfer_pio(instance, &phase, &len, &data);		cmd->SCp.Message = tmp;		switch (tmp) {		/*		 * Linking lets us reduce the time required to get the 		 * next command out to the device, hopefully this will		 * mean we don't waste another revolution due to the delays		 * required by ARBITRATION and another SELECTION.		 *		 * In the current implementation proposal, low level drivers		 * merely have to start the next command, pointed to by 		 * next_link, done() is called as with unlinked commands.		 */#ifdef LINKED		case LINKED_CMD_COMPLETE:		case LINKED_FLG_CMD_COMPLETE:#if (NDEBUG & NDEBUG_LINKED) 		    printk("scsi%d : target %d lun %d linked command complete.\n",			instance->host_no, cmd->target, cmd->lun);#endif		    /* 		     * Sanity check : A linked command should only terminate with		     * one of these messages if there are more linked commands		     * available.		     */		    if (!cmd->next_link) {			 printk("scsi%d : target %d lun %d linked command complete, no next_link\n"			    instance->host_no, cmd->target, cmd->lun);			    msgout = ABORT;			    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE |				ICR_ASSERT_ATN);			    break;		    }		    initialize_SCp(cmd->next_link);		    /* The next command is still part of this process */		    cmd->next_link->tag = cmd->tag;		    cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); #if (NDEBUG & NDEBUG_LINKED) 		    printk("scsi%d : target %d lun %d linked request done, calling scsi_done().\n",			instance->host_no, cmd->target, cmd->lun);#endif		    cmd->scsi_done(cmd);		    cmd = hostdata->connected;		    break;#endif /* def LINKED */		case ABORT:		case COMMAND_COMPLETE: 		    hostdata->connected = NULL;#if (NDEBUG & NDEBUG_QUEUES)		    printk("scsi%d : command for target %d, lun %d completed\n",			instance->host_no, cmd->target, cmd->lun);#endif		    hostdata->busy[cmd->target] &= ~(1 << cmd->lun);		    /* 		     * I'm not sure what the correct thing to do here is : 		     * 		     * If the command that just executed is NOT a request 		     * sense, the obvious thing to do is to set the result		     * code to the values of the stored parameters.		     * 		     * If it was a REQUEST SENSE command, we need some way 		     * to differentiate between the failure code of the original		     * and the failure code of the REQUEST sense - the obvious		     * case is success, where we fall through and leave the result		     * code unchanged.		     * 		     * The non-obvious place is where the REQUEST SENSE failed 		     */		    if (cmd->cmnd[0] != REQUEST_SENSE) 			cmd->result = cmd->SCp.Status | (cmd->SCp.Message << 8); 		    else if (cmd->SCp.Status != GOOD)			cmd->result = (cmd->result & 0x00ffff) | (DID_ERROR << 16);		    #ifdef AUTOSENSE		    if ((cmd->cmnd[0] != REQUEST_SENSE) && 			(cmd->SCp.Status == CHECK_CONDITION)) {#if (NDEBUG & NDEBUG_AUTOSENSE) 			printk("scsi%d : performing request sense\n", 			    instance->host_no);#endif			cmd->cmnd[0] = REQUEST_SENSE;			cmd->cmnd[1] &= 0xe0;			cmd->cmnd[2] = 0;			cmd->cmnd[3] = 0;			cmd->cmnd[4] = sizeof(cmd->sense_buffer);			cmd->cmnd[5] = 0;			cmd->SCp.buffer = NULL;			cmd->SCp.buffers_residual = 0;			cmd->SCp.ptr = (char *) cmd->sense_buffer;			cmd->SCp.this_residual = sizeof(cmd->sense_buffer);			cli();			cmd->host_scribble = (unsigned char *) 			    hostdata->issue_queue;		        hostdata->issue_queue = (Scsi_Cmnd *) cmd;		        sti();#if (NDEBUG & NDEBUG_QUEUES)			printk("scsi%d : REQUEST SENSE added to head of issue queue\n");#endif		   } else#endif /* def AUTOSENSE */			cmd->scsi_done(cmd);		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);		    		    while ((NCR5380_read(STATUS_REG) & SR_BSY) && 			!hostdata->connected);		    return;		case MESSAGE_REJECT:		    switch (hostdata->last_message) {		    case HEAD_OF_QUEUE_TAG:		    case ORDERED_QUEUE_TAG:		    case SIMPLE_QUEUE_TAG:			scsi_devices[cmd->index].tagged_queue = 0;			hostdata->busy[cmd->target] |= (1 << cmd->lun);			break;		    default:			break;		    }		case DISCONNECT:		    scsi_devices[cmd->index].disconnect = 1;		    cli();		    cmd->host_scribble = (unsigned char *) 			hostdata->disconnected_queue;		    hostdata->connected = NULL;		    hostdata->disconnected_queue = cmd;		    sti();#if (NDEBUG & NDEBUG_QUEUES)		    printk("scsi%d : command for target %d lun %d was moved from connected to"		           "  the disconnected_queue\n", instance->host_no, 			    cmd->target, cmd->lun);#endif		    /* Enable reselect interupts */		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);		    /* Wait for bus free to avoid nasty timeouts */		    while ((NCR5380_read(STATUS_REG) & SR_BSY) && 			!hostdata->connected);		    return;		/* 		 * The SCSI data pointer is *IMPLICITLY* saved on a disconnect		 * operation, in violation of the SCSI spec so we can safely 		 * ignore SAVE/RESTORE pointers calls.		 *		 * Unfortunately, some disks violate the SCSI spec and 		 * don't issue the required SAVE_POINTERS message before		 * disconnecting, and we have to break spec to remain 		 * compatable.		 */		case SAVE_POINTERS:		case RESTORE_POINTERS:		    break;		default:/*  * XXX rejected messages should be handled in the pio data transfer phase, * since ATN should be raised before ACK goes false when we reject a message */		    printk("Unknown message!\n");#ifdef notyet		/*   		 * If we get something wierd that we aren't expecting,  		 * reject it.		 */		    msgout = MESSAGE_REJECT;		    NCR5380_write(INITIATOR_COMMAND_REG, ICR_BASE | 			ICR_ASSERT_ATN);#endif 		    break;		} /* switch (tmp) */		break;	    case PHASE_MSGOUT:		len = 1;		data = &msgout;		hostdata->last_message = msgout;		NCR5380_transfer_pio(instance, &phase, &len, &data);		if (msgout == ABORT) {		    hostdata->busy[cmd->target] &= ~(1 << cmd->lun);		    hostdata->connected = NULL;		    cmd->result = DID_ERROR << 16;		    cmd->scsi_done(cmd);		    NCR5380_write(SELECT_ENABLE_REG, hostdata->id_mask);		    return;		}		msgout = NOP;		break;	    case PHASE_CMDOUT:		len = COMMAND_SIZE(cmd->cmnd[0]);		data = cmd->cmnd;		/* 		 * XXX for performance reasons, on machines with a 		 * PSEUDO-DMA architecture we should probably 		 * use the dma transfer function.  		 */		NCR5380_transfer_pio(instance, &phase, &len, 		    &data);#ifdef USLEEP		if (!disconnect && should_disconnect(cmd->cmnd[0])) {		    hostdata->time_expires = jiffies + USLEEP_SLEEP;#if (NDEBUG & NDEBUG_USLEEP)		printk("scsi%d : issued command, sleeping until %ul\n", instance->host_no,		    hostdata->time_expires);#endif		    NCR5380_set_timer (instance);		    return;		}#endif /* def USLEEP */		break;	    case PHASE_STATIN:		len = 1;		data = &tmp;		NCR5380_transfer_pio(instance, &phase, &len, &data);		cmd->SCp.Status = tmp;		break;	    default:		printk("scsi%d : unknown phase\n", instance->host_no);#ifdef NDEBUG		NCR5380_print(instance);#endif	    } /* switch(phase) */	} /* if (tmp * SR_REQ) */ #ifdef USLEEP	else {	    if (!disconnect && hostdata->time_expires && jiffies > 		hostdata->time_expires) {		hostdata->time_expires = jiffies + USLEEP_SLEEP;#if (NDEBUG & NDEBUG_USLEEP)		printk("scsi%d : poll timed out, sleeping until %ul\n", instance->host_no,		    hostdata->time_expires);#endif		NCR5380_set_timer (instance);		return;	    }	}#endif    }

⌨️ 快捷键说明

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