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

📄 fas216.c

📁 内核linux2.4.20,可跟rtlinux3.2打补丁 组成实时linux系统,编译内核
💻 C
📖 第 1 页 / 共 5 页
字号:
 *	     result - driver byte of result */static voidfas216_std_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result){	info->stats.fins += 1;	SCpnt->result = result << 16 | info->scsi.SCp.Message << 8 |			info->scsi.SCp.Status;#ifdef DEBUG_CONNECT	printk("scsi%d.%c: command complete, result=%08X, command=",		info->host->host_no, '0' + SCpnt->target, SCpnt->result);	print_command(SCpnt->cmnd);#endif	/*	 * If the driver detected an error, or the command	 * was request sense, then we're all done.	 */	if (result != DID_OK || SCpnt->cmnd[0] == REQUEST_SENSE)		goto done;	/*	 * If the command returned CHECK_CONDITION status,	 * request the sense information.	 */	if (info->scsi.SCp.Status == CHECK_CONDITION)		goto request_sense;	/*	 * If the command did not complete with GOOD status,	 * we are all done here.	 */	if (info->scsi.SCp.Status != GOOD)		goto done;	/*	 * We have successfully completed a command.  Make sure that	 * we do not have any buffers left to transfer.  The world	 * is not perfect, and we seem to occasionally hit this.	 * It can be indicative of a buggy driver, target or the upper	 * levels of the SCSI code.	 */	if (info->scsi.SCp.ptr) {		switch (SCpnt->cmnd[0]) {		case INQUIRY:		case START_STOP://		case READ_CAPACITY:		case MODE_SENSE:			break;		default:			printk(KERN_ERR "scsi%d.%c: incomplete data transfer "				"detected: res=%08X ptr=%p len=%X command=",				info->host->host_no, '0' + SCpnt->target,				SCpnt->result, info->scsi.SCp.ptr,				info->scsi.SCp.this_residual);			print_command(SCpnt->cmnd);		}	}done:	SCpnt->scsi_done(SCpnt);	return;request_sense:	memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd));	SCpnt->cmnd[0] = REQUEST_SENSE;	SCpnt->cmnd[1] = SCpnt->lun << 5;	SCpnt->cmnd[4] = sizeof(SCpnt->sense_buffer);	SCpnt->cmd_len = COMMAND_SIZE(SCpnt->cmnd[0]);	SCpnt->SCp.buffer = NULL;	SCpnt->SCp.buffers_residual = 0;	SCpnt->SCp.ptr = (char *)SCpnt->sense_buffer;	SCpnt->SCp.this_residual = sizeof(SCpnt->sense_buffer);	SCpnt->SCp.Message = 0;	SCpnt->SCp.Status = 0;	SCpnt->sc_data_direction = SCSI_DATA_READ;	SCpnt->use_sg = 0;	SCpnt->tag = 0;	SCpnt->host_scribble = (void *)fas216_rq_sns_done;	/*	 * Place this command into the high priority "request	 * sense" slot.  This will be the very next command	 * executed, unless a target connects to us.	 */	if (info->reqSCpnt)		printk(KERN_WARNING "scsi%d.%c: loosing request command\n",			info->host->host_no, '0' + SCpnt->target);	info->reqSCpnt = SCpnt;}/* Function: void fas216_done(FAS216_Info *info, unsigned int result) * Purpose : complete processing for current command * Params  : info   - interface that completed *	     result - driver byte of result */static void fas216_done(FAS216_Info *info, unsigned int result){	void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int);	Scsi_Cmnd *SCpnt;	fas216_checkmagic(info);	if (!info->SCpnt)		goto no_command;	SCpnt = info->SCpnt;	info->SCpnt = NULL;    	info->scsi.phase = PHASE_IDLE;	if (!SCpnt->scsi_done)		goto no_done;	if (info->scsi.aborting) {		printk("scsi%d.%c: uncaught abort - returning DID_ABORT\n",			info->host->host_no, fas216_target(info));		result = DID_ABORT;		info->scsi.aborting = 0;	}	/*	 * Sanity check the completion - if we have zero bytes left	 * to transfer, we should not have a valid pointer.	 */	if (info->scsi.SCp.ptr && info->scsi.SCp.this_residual == 0) {		printk("scsi%d.%c: zero bytes left to transfer, but "		       "buffer pointer still valid: ptr=%p len=%08x command=",		       info->host->host_no, '0' + SCpnt->target,		       info->scsi.SCp.ptr, info->scsi.SCp.this_residual);		info->scsi.SCp.ptr = NULL;		print_command(SCpnt->cmnd);	}	/*	 * Clear down this command as completed.  If we need to request	 * the sense information, fas216_kick will re-assert the busy	 * status.	 */	clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);	fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble;	fn(info, SCpnt, result);	if (info->scsi.irq != NO_IRQ)		fas216_kick(info);	return;no_command:	panic("scsi%d.H: null command in fas216_done",		info->host->host_no);no_done:	panic("scsi%d.H: null scsi_done function in fas216_done",		info->host->host_no);}/* Function: int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)) * Purpose : queue a command for adapter to process. * Params  : SCpnt - Command to queue *	     done  - done function to call once command is complete * Returns : 0 - success, else error * Notes   : io_request_lock is held, interrupts are disabled. */int fas216_queue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;	int result;	fas216_checkmagic(info);#ifdef DEBUG_CONNECT	printk("scsi%d.%c: received queuable command (%p) %02X\n",		SCpnt->host->host_no, '0' + SCpnt->target,		SCpnt, SCpnt->cmnd[0]);#endif	SCpnt->scsi_done = done;	SCpnt->host_scribble = (void *)fas216_std_done;	SCpnt->result = 0;	SCpnt->SCp.Message = 0;	SCpnt->SCp.Status = 0;	if (SCpnt->use_sg) {		unsigned long len = 0;		int buf;		SCpnt->SCp.buffer = (struct scatterlist *) SCpnt->buffer;		SCpnt->SCp.buffers_residual = SCpnt->use_sg - 1;		SCpnt->SCp.ptr = (char *) SCpnt->SCp.buffer->address;		SCpnt->SCp.this_residual = SCpnt->SCp.buffer->length;		/*		 * Calculate correct buffer length.  Some commands		 * come in with the wrong request_bufflen.		 */		for (buf = 0; buf <= SCpnt->SCp.buffers_residual; buf++)			len += SCpnt->SCp.buffer[buf].length;		if (SCpnt->request_bufflen != len)			printk(KERN_WARNING "scsi%d.%c: bad request buffer "			       "length %d, should be %ld\n", info->host->host_no,			       '0' + SCpnt->target, SCpnt->request_bufflen, len);		SCpnt->request_bufflen = len;	} else {		SCpnt->SCp.buffer = NULL;		SCpnt->SCp.buffers_residual = 0;		SCpnt->SCp.ptr = (unsigned char *)SCpnt->request_buffer;		SCpnt->SCp.this_residual = SCpnt->request_bufflen;	}	/*	 * If the upper SCSI layers pass a buffer, but zero length,	 * we aren't interested in the buffer pointer.	 */	if (SCpnt->SCp.this_residual == 0 && SCpnt->SCp.ptr) {#if 0		printk(KERN_WARNING "scsi%d.%c: zero length buffer passed for "		       "command ", info->host->host_no, '0' + SCpnt->target);		print_command(SCpnt->cmnd);#endif		SCpnt->SCp.ptr = NULL;	}	info->stats.queues += 1;	SCpnt->tag = 0;	/*	 * Add command into execute queue and let it complete under	 * whatever scheme we're using.	 */	result = !queue_add_cmd_ordered(&info->queues.issue, SCpnt);	/*	 * If we successfully added the command,	 * kick the interface to get it moving.	 */	if (result == 0 && (!info->SCpnt || info->scsi.disconnectable))		fas216_kick(info);	return result;}/* Function: void fas216_internal_done(Scsi_Cmnd *SCpnt) * Purpose : trigger restart of a waiting thread in fas216_command * Params  : SCpnt - Command to wake */static void fas216_internal_done(Scsi_Cmnd *SCpnt){	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;	fas216_checkmagic(info);	info->internal_done = 1;}/* Function: int fas216_command(Scsi_Cmnd *SCpnt) * Purpose : queue a command for adapter to process. * Params  : SCpnt - Command to queue * Returns : scsi result code * Notes   : io_request_lock is held, interrupts are disabled. */int fas216_command(Scsi_Cmnd *SCpnt){	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;	fas216_checkmagic(info);	/*	 * We should only be using this if we don't have an interrupt.	 * Provide some "incentive" to use the queueing code.	 */	if (info->scsi.irq != NO_IRQ)		BUG();	info->internal_done = 0;	fas216_queue_command(SCpnt, fas216_internal_done);	/*	 * This wastes time, since we can't return until the command is	 * complete. We can't sleep either since we may get re-entered!	 * However, we must re-enable interrupts, or else we'll be	 * waiting forever.	 */	spin_unlock_irq(&io_request_lock);	while (!info->internal_done) {		/*		 * If we don't have an IRQ, then we must poll the card for		 * it's interrupt, and use that to call this driver's		 * interrupt routine.  That way, we keep the command		 * progressing.  Maybe we can add some inteligence here		 * and go to sleep if we know that the device is going		 * to be some time (eg, disconnected).		 */		if (inb(REG_STAT(info)) & STAT_INT) {			spin_lock_irq(&io_request_lock);			fas216_intr(info->host);			spin_unlock_irq(&io_request_lock);		}	}	spin_lock_irq(&io_request_lock);	return SCpnt->result;}enum res_abort {	res_failed,		/* unable to abort		*/	res_success,		/* command on issue queue	*/	res_success_clear,	/* command marked tgt/lun busy	*/	res_hw_abort		/* command on disconnected dev	*/};/* * Prototype: enum res_abort fas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt) * Purpose  : decide how to abort a command * Params   : SCpnt - command to abort * Returns  : abort status */static enum res_abortfas216_do_abort(FAS216_Info *info, Scsi_Cmnd *SCpnt){	enum res_abort res = res_failed;	if (queue_remove_cmd(&info->queues.issue, SCpnt)) {		/*		 * The command was on the issue queue, and has not been		 * issued yet.  We can remove the command from the queue,		 * and acknowledge the abort.  Neither the device nor the		 * interface know about the command.		 */		printk("on issue queue ");		res = res_success;	} else if (queue_remove_cmd(&info->queues.disconnected, SCpnt)) {		/*		 * The command was on the disconnected queue.  We must		 * reconnect with the device if possible, and send it		 * an abort message.		 */		printk("on disconnected queue ");		res = res_hw_abort;	} else if (info->SCpnt == SCpnt) {		printk("executing ");		switch (info->scsi.phase) {		/*		 * If the interface is idle, and the command is 'disconnectable',		 * then it is the same as on the disconnected queue.		 */		case PHASE_IDLE:			if (info->scsi.disconnectable) {				info->scsi.disconnectable = 0;				info->SCpnt = NULL;				res = res_hw_abort;			}			break;		default:			break;		}	} else if (info->origSCpnt == SCpnt) {		/*		 * The command will be executed next, but a command		 * is currently using the interface.  This is similar to		 * being on the issue queue, except the busylun bit has		 * been set.		 */		info->origSCpnt = NULL;		printk("waiting for execution ");		res = res_success_clear;	} else		printk("unknown ");	return res;}/* Function: int fas216_eh_abort(Scsi_Cmnd *SCpnt) * Purpose : abort this command * Params  : SCpnt - command to abort * Returns : FAILED if unable to abort * Notes   : io_request_lock is taken, and irqs are disabled */int fas216_eh_abort(Scsi_Cmnd *SCpnt){	FAS216_Info *info = (FAS216_Info *)SCpnt->host->hostdata;	int result = FAILED;	fas216_checkmagic(info);	info->stats.aborts += 1;	print_debug_list();	fas216_dumpstate(info);	fas216_dumpinfo(info);	printk(KERN_WARNING "scsi%d: abort ", info->host->host_no);	switch (fas216_do_abort(info, SCpnt)) {	/*	 * We managed to find the command and cleared it out.	 * We do not expect the command to be executing on the	 * target, but we have set the busylun bit.	 */	case res_success_clear:		printk("clear ");		clear_bit(SCpnt->target * 8 + SCpnt->lun, info->busyluns);	/*	 * We found the command, and cleared it out.  Either	 * the command is still known to be executing on the	 * target, or the busylun bit is not set.	 */	case res_success:		printk("success\n");		result = SUCCESS;		break;	/*	 * We need to reconnect to the target and send it an	 * ABORT or ABORT_TAG message.  We can only do this	 * if the bus is free.	 */	case res_hw_abort:			/*	 * We are unable to abort the command for some reason.	 */	default:	case res_failed:		printk("failed\n");		break;	}	return result;}/* Function: void fas216_reset_state(FAS216_Info *info) * Purpose : Initialise driver internal state * Params  : info - state to initialise */static void fas216_reset_state(FAS216_Info *info){	neg_t sync_state, wide_state;	int i;	fas216_checkmagic(info);	/*	 * Clear out all stale info in our state structure	 */	memset(info->busyluns, 0, sizeof(info->busyluns));	msgqueue_flush(&info->scsi.msgs);	info->scsi.reconnected.target = 0;	info->scsi.reconnected.lun = 0;	info->scsi.reconnected.tag = 0;	info->scsi.disconnectable = 0;	info->scsi.aborting = 0;	info->scsi.phase = PHASE_IDLE;	info->scsi.async_stp =			fas216_

⌨️ 快捷键说明

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