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

📄 fas216.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
static voidfas216_devicereset_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result){	fas216_log(info, LOG_ERROR, "fas216 device reset complete");	info->rstSCpnt = NULL;	info->rst_dev_status = 1;	wake_up(&info->eh_wait);}/** * fas216_rq_sns_done - Finish processing automatic request sense command * @info: interface that completed * @SCpnt: command that completed * @result: driver byte of result * * Finish processing automatic request sense command */static voidfas216_rq_sns_done(FAS216_Info *info, Scsi_Cmnd *SCpnt, unsigned int result){	fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,		   "request sense complete, result=0x%04x%02x%02x",		   result, SCpnt->SCp.Message, SCpnt->SCp.Status);	if (result != DID_OK || SCpnt->SCp.Status != GOOD)		/*		 * Something went wrong.  Make sure that we don't		 * have valid data in the sense buffer that could		 * confuse the higher levels.		 */		memset(SCpnt->sense_buffer, 0, sizeof(SCpnt->sense_buffer));//printk("scsi%d.%c: sense buffer: ", info->host->host_no, '0' + SCpnt->device->id);//{ int i; for (i = 0; i < 32; i++) printk("%02x ", SCpnt->sense_buffer[i]); printk("\n"); }	/*	 * Note that we don't set SCpnt->result, since that should	 * reflect the status of the command that we were asked by	 * the upper layers to process.  This would have been set	 * correctly by fas216_std_done.	 */	SCpnt->scsi_done(SCpnt);}/** * fas216_std_done - finish processing of standard command * @info: interface that completed * @SCpnt: command that completed * @result: driver byte of result * * Finish processing of standard command */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;	fas216_log_command(info, LOG_CONNECT, SCpnt,		"command complete, result=0x%08x", SCpnt->result);	/*	 * If the driver detected an error, we're all done.	 */	if (host_byte(SCpnt->result) != DID_OK ||	    msg_byte(SCpnt->result) != COMMAND_COMPLETE)		goto done;	/*	 * If the command returned CHECK_CONDITION or COMMAND_TERMINATED	 * status, request the sense information.	 */	if (status_byte(SCpnt->result) == CHECK_CONDITION ||	    status_byte(SCpnt->result) == COMMAND_TERMINATED)		goto request_sense;	/*	 * If the command did not complete with GOOD status,	 * we are all done here.	 */	if (status_byte(SCpnt->result) != 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 MODE_SENSE:			break;		default:			printk(KERN_ERR "scsi%d.%c: incomplete data transfer "				"detected: res=%08X ptr=%p len=%X CDB: ",				info->host->host_no, '0' + SCpnt->device->id,				SCpnt->result, info->scsi.SCp.ptr,				info->scsi.SCp.this_residual);			__scsi_print_command(SCpnt->cmnd);			SCpnt->result &= ~(255 << 16);			SCpnt->result |= DID_BAD_TARGET << 16;			goto request_sense;		}	}done:	if (SCpnt->scsi_done) {		SCpnt->scsi_done(SCpnt);		return;	}	panic("scsi%d.H: null scsi_done function in fas216_done",		info->host->host_no);request_sense:	if (SCpnt->cmnd[0] == REQUEST_SENSE)		goto done;	fas216_log_target(info, LOG_CONNECT, SCpnt->device->id,			  "requesting sense");	memset(SCpnt->cmnd, 0, sizeof (SCpnt->cmnd));	SCpnt->cmnd[0] = REQUEST_SENSE;	SCpnt->cmnd[1] = SCpnt->device->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->request_bufflen = sizeof(SCpnt->sense_buffer);	SCpnt->sc_data_direction = DMA_FROM_DEVICE;	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->device->id);	info->reqSCpnt = SCpnt;}/** * fas216_done - complete processing for current command * @info: interface that completed * @result: driver byte of result * * Complete processing for current command */static void fas216_done(FAS216_Info *info, unsigned int result){	void (*fn)(FAS216_Info *, Scsi_Cmnd *, unsigned int);	Scsi_Cmnd *SCpnt;	unsigned long flags;	fas216_checkmagic(info);	if (!info->SCpnt)		goto no_command;	SCpnt = info->SCpnt;	info->SCpnt = NULL;    	info->scsi.phase = PHASE_IDLE;	if (info->scsi.aborting) {		fas216_log(info, 0, "uncaught abort - returning DID_ABORT");		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 CDB: ",		       info->host->host_no, '0' + SCpnt->device->id,		       info->scsi.SCp.ptr, info->scsi.SCp.this_residual);		info->scsi.SCp.ptr = NULL;		__scsi_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.	 */	info->device[SCpnt->device->id].parity_check = 0;	clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);	fn = (void (*)(FAS216_Info *, Scsi_Cmnd *, unsigned int))SCpnt->host_scribble;	fn(info, SCpnt, result);	if (info->scsi.irq != NO_IRQ) {		spin_lock_irqsave(&info->host_lock, flags);		if (info->scsi.phase == PHASE_IDLE)			fas216_kick(info);		spin_unlock_irqrestore(&info->host_lock, flags);	}	return;no_command:	panic("scsi%d.H: null command in fas216_done",		info->host->host_no);}/** * fas216_queue_command - queue a command for adapter to process. * @SCpnt: Command to queue * @done: done function to call once command is complete * * Queue a command for adapter to process. * Returns: 0 on 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->device->host->hostdata;	int result;	fas216_checkmagic(info);	fas216_log_command(info, LOG_CONNECT, SCpnt,			   "received command (%p)", SCpnt);	SCpnt->scsi_done = done;	SCpnt->host_scribble = (void *)fas216_std_done;	SCpnt->result = 0;	init_SCp(SCpnt);	info->stats.queues += 1;	SCpnt->tag = 0;	spin_lock(&info->host_lock);	/*	 * 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->scsi.phase == PHASE_IDLE)		fas216_kick(info);	spin_unlock(&info->host_lock);	fas216_log_target(info, LOG_CONNECT, -1, "queue %s",		result ? "failure" : "success");	return result;}/** * fas216_internal_done - trigger restart of a waiting thread in fas216_noqueue_command * @SCpnt: Command to wake * * Trigger restart of a waiting thread in fas216_command */static void fas216_internal_done(Scsi_Cmnd *SCpnt){	FAS216_Info *info = (FAS216_Info *)SCpnt->device->host->hostdata;	fas216_checkmagic(info);	info->internal_done = 1;}/** * fas216_noqueue_command - process a command for the adapter. * @SCpnt: Command to queue * * Queue a command for adapter to process. * Returns: scsi result code. * Notes: io_request_lock is held, interrupts are disabled. */int fas216_noqueue_command(Scsi_Cmnd *SCpnt, void (*done)(Scsi_Cmnd *)){	FAS216_Info *info = (FAS216_Info *)SCpnt->device->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.	 */	BUG_ON(info->scsi.irq != NO_IRQ);	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(info->host->host_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 (fas216_readb(info, REG_STAT) & STAT_INT) {			spin_lock_irq(info->host->host_lock);			fas216_intr(info);			spin_unlock_irq(info->host->host_lock);		}	}	spin_lock_irq(info->host->host_lock);	done(SCpnt);	return 0;}/* * Error handler timeout function.  Indicate that we timed out, * and wake up any error handler process so it can continue. */static void fas216_eh_timer(unsigned long data){	FAS216_Info *info = (FAS216_Info *)data;	fas216_log(info, LOG_ERROR, "error handling timed out\n");	del_timer(&info->eh_timer);	if (info->rst_bus_status == 0)		info->rst_bus_status = -1;	if (info->rst_dev_status == 0)		info->rst_dev_status = -1;	wake_up(&info->eh_wait);}enum res_find {	res_failed,		/* not found			*/	res_success,		/* command on issue queue	*/	res_hw_abort		/* command on disconnected dev	*/};/** * fas216_do_abort - decide how to abort a command * @SCpnt: command to abort * * Decide how to abort a command. * Returns: abort status */static enum res_find fas216_find_command(FAS216_Info *info, Scsi_Cmnd *SCpnt){	enum res_find 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;		clear_bit(SCpnt->device->id * 8 + SCpnt->device->lun, info->busyluns);		printk("waiting for execution ");		res = res_success;	} else		printk("unknown ");	return res;}/** * fas216_eh_abort - abort this command * @SCpnt: command to abort * * Abort this command. * 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->device->host->hostdata;	int result = FAILED;	fas216_checkmagic(info);	info->stats.aborts += 1;	printk(KERN_WARNING "scsi%d: abort command ", info->host->host_no);	__scsi_print_command(SCpnt->data_cmnd);	print_debug_list();	fas216_dumpstate(info);	printk(KERN_WARNING "scsi%d: abort %p ", info->host->host_no, SCpnt);	switch (fas216_find_command(info, SCpnt)) {	/*	 * 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;}/** * fas216_eh_device_reset - Reset the device associated with this command * @SCpnt: command specifing device to reset * * Reset the device associated with this command. * Returns: FAILED if unable to reset. * Notes: We won't be re-entered, so we'll only 

⌨️ 快捷键说明

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