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

📄 aic79xx_osm.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 5 页
字号:
			if (dev->active == dev->tags_on_last_queuefull) {				dev->last_queuefull_same_count++;				/*				 * If we repeatedly see a queue full				 * at the same queue depth, this				 * device has a fixed number of tag				 * slots.  Lock in this tag depth				 * so we stop seeing queue fulls from				 * this device.				 */				if (dev->last_queuefull_same_count				 == AHD_LOCK_TAGS_COUNT) {					dev->maxtags = dev->active;					ahd_print_path(ahd, scb);					printf("Locking max tag count at %d\n",					       dev->active);				}			} else {				dev->tags_on_last_queuefull = dev->active;				dev->last_queuefull_same_count = 0;			}			ahd_set_transaction_status(scb, CAM_REQUEUE_REQ);			ahd_set_scsi_status(scb, SCSI_STATUS_OK);			ahd_platform_set_tags(ahd, &devinfo,				     (dev->flags & AHD_DEV_Q_BASIC)				   ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);			break;		}		/*		 * Drop down to a single opening, and treat this		 * as if the target returned BUSY SCSI status.		 */		dev->openings = 1;		ahd_platform_set_tags(ahd, &devinfo,			     (dev->flags & AHD_DEV_Q_BASIC)			   ? AHD_QUEUE_BASIC : AHD_QUEUE_TAGGED);		ahd_set_scsi_status(scb, SCSI_STATUS_BUSY);	}}static voidahd_linux_queue_cmd_complete(struct ahd_softc *ahd, struct scsi_cmnd *cmd){	/*	 * Map CAM error codes into Linux Error codes.  We	 * avoid the conversion so that the DV code has the	 * full error information available when making	 * state change decisions.	 */	{		uint32_t status;		u_int new_status;		status = ahd_cmd_get_transaction_status(cmd);		switch (status) {		case CAM_REQ_INPROG:		case CAM_REQ_CMP:		case CAM_SCSI_STATUS_ERROR:			new_status = DID_OK;			break;		case CAM_REQ_ABORTED:			new_status = DID_ABORT;			break;		case CAM_BUSY:			new_status = DID_BUS_BUSY;			break;		case CAM_REQ_INVALID:		case CAM_PATH_INVALID:			new_status = DID_BAD_TARGET;			break;		case CAM_SEL_TIMEOUT:			new_status = DID_NO_CONNECT;			break;		case CAM_SCSI_BUS_RESET:		case CAM_BDR_SENT:			new_status = DID_RESET;			break;		case CAM_UNCOR_PARITY:			new_status = DID_PARITY;			break;		case CAM_CMD_TIMEOUT:			new_status = DID_TIME_OUT;			break;		case CAM_UA_ABORT:		case CAM_REQ_CMP_ERR:		case CAM_AUTOSENSE_FAIL:		case CAM_NO_HBA:		case CAM_DATA_RUN_ERR:		case CAM_UNEXP_BUSFREE:		case CAM_SEQUENCE_FAIL:		case CAM_CCB_LEN_ERR:		case CAM_PROVIDE_FAIL:		case CAM_REQ_TERMIO:		case CAM_UNREC_HBA_ERROR:		case CAM_REQ_TOO_BIG:			new_status = DID_ERROR;			break;		case CAM_REQUEUE_REQ:			new_status = DID_REQUEUE;			break;		default:			/* We should never get here */			new_status = DID_ERROR;			break;		}		ahd_cmd_set_transaction_status(cmd, new_status);	}	cmd->scsi_done(cmd);}static voidahd_linux_sem_timeout(u_long arg){	struct	ahd_softc *ahd;	u_long	s;	ahd = (struct ahd_softc *)arg;	ahd_lock(ahd, &s);	if ((ahd->platform_data->flags & AHD_SCB_UP_EH_SEM) != 0) {		ahd->platform_data->flags &= ~AHD_SCB_UP_EH_SEM;		up(&ahd->platform_data->eh_sem);	}	ahd_unlock(ahd, &s);}voidahd_freeze_simq(struct ahd_softc *ahd){	ahd->platform_data->qfrozen++;	if (ahd->platform_data->qfrozen == 1) {		scsi_block_requests(ahd->platform_data->host);		ahd_platform_abort_scbs(ahd, CAM_TARGET_WILDCARD, ALL_CHANNELS,					CAM_LUN_WILDCARD, SCB_LIST_NULL,					ROLE_INITIATOR, CAM_REQUEUE_REQ);	}}voidahd_release_simq(struct ahd_softc *ahd){	u_long s;	int    unblock_reqs;	unblock_reqs = 0;	ahd_lock(ahd, &s);	if (ahd->platform_data->qfrozen > 0)		ahd->platform_data->qfrozen--;	if (ahd->platform_data->qfrozen == 0) {		unblock_reqs = 1;	}	ahd_unlock(ahd, &s);	/*	 * There is still a race here.  The mid-layer	 * should keep its own freeze count and use	 * a bottom half handler to run the queues	 * so we can unblock with our own lock held.	 */	if (unblock_reqs)		scsi_unblock_requests(ahd->platform_data->host);}static intahd_linux_queue_recovery_cmd(struct scsi_cmnd *cmd, scb_flag flag){	struct ahd_softc *ahd;	struct ahd_linux_device *dev;	struct scb *pending_scb;	u_int  saved_scbptr;	u_int  active_scbptr;	u_int  last_phase;	u_int  saved_scsiid;	u_int  cdb_byte;	int    retval;	int    was_paused;	int    paused;	int    wait;	int    disconnected;	ahd_mode_state saved_modes;	unsigned long flags;	pending_scb = NULL;	paused = FALSE;	wait = FALSE;	ahd = *(struct ahd_softc **)cmd->device->host->hostdata;	scmd_printk(KERN_INFO, cmd,	       "Attempting to queue a%s message:",	       flag == SCB_ABORT ? "n ABORT" : " TARGET RESET");	printf("CDB:");	for (cdb_byte = 0; cdb_byte < cmd->cmd_len; cdb_byte++)		printf(" 0x%x", cmd->cmnd[cdb_byte]);	printf("\n");	ahd_lock(ahd, &flags);	/*	 * First determine if we currently own this command.	 * Start by searching the device queue.  If not found	 * there, check the pending_scb list.  If not found	 * at all, and the system wanted us to just abort the	 * command, return success.	 */	dev = scsi_transport_device_data(cmd->device);	if (dev == NULL) {		/*		 * No target device for this command exists,		 * so we must not still own the command.		 */		scmd_printk(KERN_INFO, cmd, "Is not an active device\n");		retval = SUCCESS;		goto no_cmd;	}	/*	 * See if we can find a matching cmd in the pending list.	 */	LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {		if (pending_scb->io_ctx == cmd)			break;	}	if (pending_scb == NULL && flag == SCB_DEVICE_RESET) {		/* Any SCB for this device will do for a target reset */		LIST_FOREACH(pending_scb, &ahd->pending_scbs, pending_links) {		  	if (ahd_match_scb(ahd, pending_scb,					  scmd_id(cmd),					  scmd_channel(cmd) + 'A',					  CAM_LUN_WILDCARD,					  SCB_LIST_NULL, ROLE_INITIATOR))				break;		}	}	if (pending_scb == NULL) {		scmd_printk(KERN_INFO, cmd, "Command not found\n");		goto no_cmd;	}	if ((pending_scb->flags & SCB_RECOVERY_SCB) != 0) {		/*		 * We can't queue two recovery actions using the same SCB		 */		retval = FAILED;		goto  done;	}	/*	 * Ensure that the card doesn't do anything	 * behind our back.  Also make sure that we	 * didn't "just" miss an interrupt that would	 * affect this cmd.	 */	was_paused = ahd_is_paused(ahd);	ahd_pause_and_flushwork(ahd);	paused = TRUE;	if ((pending_scb->flags & SCB_ACTIVE) == 0) {		scmd_printk(KERN_INFO, cmd, "Command already completed\n");		goto no_cmd;	}	printf("%s: At time of recovery, card was %spaused\n",	       ahd_name(ahd), was_paused ? "" : "not ");	ahd_dump_card_state(ahd);	disconnected = TRUE;	if (flag == SCB_ABORT) {		if (ahd_search_qinfifo(ahd, cmd->device->id, 				       cmd->device->channel + 'A',				       cmd->device->lun, 				       pending_scb->hscb->tag,				       ROLE_INITIATOR, CAM_REQ_ABORTED,				       SEARCH_COMPLETE) > 0) {			printf("%s:%d:%d:%d: Cmd aborted from QINFIFO\n",			       ahd_name(ahd), cmd->device->channel, 			       cmd->device->id, cmd->device->lun);			retval = SUCCESS;			goto done;		}	} else if (ahd_search_qinfifo(ahd, cmd->device->id,				      cmd->device->channel + 'A',				      cmd->device->lun, pending_scb->hscb->tag,				      ROLE_INITIATOR, /*status*/0,				      SEARCH_COUNT) > 0) {		disconnected = FALSE;	}	saved_modes = ahd_save_modes(ahd);	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);	last_phase = ahd_inb(ahd, LASTPHASE);	saved_scbptr = ahd_get_scbptr(ahd);	active_scbptr = saved_scbptr;	if (disconnected && (ahd_inb(ahd, SEQ_FLAGS) & NOT_IDENTIFIED) == 0) {		struct scb *bus_scb;		bus_scb = ahd_lookup_scb(ahd, active_scbptr);		if (bus_scb == pending_scb)			disconnected = FALSE;		else if (flag != SCB_ABORT			 && ahd_inb(ahd, SAVED_SCSIID) == pending_scb->hscb->scsiid			 && ahd_inb(ahd, SAVED_LUN) == SCB_GET_LUN(pending_scb))			disconnected = FALSE;	}	/*	 * At this point, pending_scb is the scb associated with the	 * passed in command.  That command is currently active on the	 * bus or is in the disconnected state.	 */	saved_scsiid = ahd_inb(ahd, SAVED_SCSIID);	if (last_phase != P_BUSFREE	 && (SCB_GET_TAG(pending_scb) == active_scbptr	     || (flag == SCB_DEVICE_RESET		 && SCSIID_TARGET(ahd, saved_scsiid) == scmd_id(cmd)))) {		/*		 * We're active on the bus, so assert ATN		 * and hope that the target responds.		 */		pending_scb = ahd_lookup_scb(ahd, active_scbptr);		pending_scb->flags |= SCB_RECOVERY_SCB|flag;		ahd_outb(ahd, MSG_OUT, HOST_MSG);		ahd_outb(ahd, SCSISIGO, last_phase|ATNO);		scmd_printk(KERN_INFO, cmd, "Device is active, asserting ATN\n");		wait = TRUE;	} else if (disconnected) {		/*		 * Actually re-queue this SCB in an attempt		 * to select the device before it reconnects.		 */		pending_scb->flags |= SCB_RECOVERY_SCB|SCB_ABORT;		ahd_set_scbptr(ahd, SCB_GET_TAG(pending_scb));		pending_scb->hscb->cdb_len = 0;		pending_scb->hscb->task_attribute = 0;		pending_scb->hscb->task_management = SIU_TASKMGMT_ABORT_TASK;		if ((pending_scb->flags & SCB_PACKETIZED) != 0) {			/*			 * Mark the SCB has having an outstanding			 * task management function.  Should the command			 * complete normally before the task management			 * function can be sent, the host will be notified			 * to abort our requeued SCB.			 */			ahd_outb(ahd, SCB_TASK_MANAGEMENT,				 pending_scb->hscb->task_management);		} else {			/*			 * If non-packetized, set the MK_MESSAGE control			 * bit indicating that we desire to send a message.			 * We also set the disconnected flag since there is			 * no guarantee that our SCB control byte matches			 * the version on the card.  We don't want the			 * sequencer to abort the command thinking an			 * unsolicited reselection occurred.			 */			pending_scb->hscb->control |= MK_MESSAGE|DISCONNECTED;			/*			 * The sequencer will never re-reference the			 * in-core SCB.  To make sure we are notified			 * during reslection, set the MK_MESSAGE flag in			 * the card's copy of the SCB.			 */			ahd_outb(ahd, SCB_CONTROL,				 ahd_inb(ahd, SCB_CONTROL)|MK_MESSAGE);		}		/*		 * Clear out any entries in the QINFIFO first		 * so we are the next SCB for this target		 * to run.		 */		ahd_search_qinfifo(ahd, cmd->device->id,				   cmd->device->channel + 'A', cmd->device->lun,				   SCB_LIST_NULL, ROLE_INITIATOR,				   CAM_REQUEUE_REQ, SEARCH_COMPLETE);		ahd_qinfifo_requeue_tail(ahd, pending_scb);		ahd_set_scbptr(ahd, saved_scbptr);		ahd_print_path(ahd, pending_scb);		printf("Device is disconnected, re-queuing SCB\n");		wait = TRUE;	} else {		scmd_printk(KERN_INFO, cmd, "Unable to deliver message\n");		retval = FAILED;		goto done;	}no_cmd:	/*	 * Our assumption is that if we don't have the command, no	 * recovery action was required, so we return success.  Again,	 * the semantics of the mid-layer recovery engine are not	 * well defined, so this may change in time.	 */	retval = SUCCESS;done:	if (paused)		ahd_unpause(ahd);	if (wait) {		struct timer_list timer;		int ret;		ahd->platform_data->flags |= AHD_SCB_UP_EH_SEM;		ahd_unlock(ahd, &flags);		init_timer(&timer);		timer.data = (u_long)ahd;		timer.expires = jiffies + (5 * HZ);		timer.function = ahd_linux_sem_timeout;		add_timer(&timer);		printf("Recovery code sleeping\n");		down(&ahd->platform_data->eh_sem);		printf("Recovery code awake\n");        	ret = del_timer_sync(&timer);		if (ret == 0) {			printf("Timer Expired\n");			retval = FAILED;		}	}		ahd_unlock(ahd, &flags);	return (retval);}static void ahd_linux_set_width(struct scsi_target *starget, int width){	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);	struct ahd_devinfo devinfo;	unsigned long flags;	ahd_compile_devinfo(&devinfo, shost->this_id, starget->id, 0,			    starget->channel + 'A', ROLE_INITIATOR);	ahd_lock(ahd, &flags);	ahd_set_width(ahd, &devinfo, width, AHD_TRANS_GOAL, FALSE);	ahd_unlock(ahd, &flags);}static void ahd_linux_set_period(struct scsi_target *starget, int period){	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);	struct ahd_softc *ahd = *((struct ahd_softc **)shost->hostdata);	struct ahd_tmode_tstate *tstate;	struct ahd_initiator_tinfo *tinfo 		= ahd_fetch_transinfo(ahd,				      starget->channel + 'A',				      shost->this_id, starget->id, &tstate);	struct ahd_devinfo devinfo;	unsigned int ppr_options = tinfo->goal.ppr_options;	unsigned int dt;	unsigned long flags;	unsigned long offset = tinfo->goal.offset;#ifdef AHD_DEBUG	if ((ahd_debug & AHD_SHOW_DV) != 0)		printf("%s: set period to %d\n", 

⌨️ 快捷键说明

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