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

📄 aiclib.c

📁 h内核
💻 C
📖 第 1 页 / 共 4 页
字号:
			  &sense_entry,			  &asc_entry);	*sense_key_desc = sense_entry->desc;	if (asc_entry != NULL)		*asc_desc = asc_entry->desc;	else if (asc >= 0x80 && asc <= 0xff)		*asc_desc = "Vendor Specific ASC";	else if (ascq >= 0x80 && ascq <= 0xff)		*asc_desc = "Vendor Specific ASCQ";	else		*asc_desc = "Reserved ASC/ASCQ pair";}/* * Given sense and device type information, return the appropriate action. * If we do not understand the specific error as identified by the ASC/ASCQ * pair, fall back on the more generic actions derived from the sense key. */aic_sense_actionaic_sense_error_action(struct scsi_sense_data *sense_data,		       struct scsi_inquiry_data *inq_data, uint32_t sense_flags){	const struct asc_table_entry *asc_entry;	const struct sense_key_table_entry *sense_entry;	int error_code, sense_key, asc, ascq;	aic_sense_action action;	scsi_extract_sense(sense_data, &error_code, &sense_key, &asc, &ascq);	if (error_code == SSD_DEFERRED_ERROR) {		/*		 * XXX dufault@FreeBSD.org		 * This error doesn't relate to the command associated		 * with this request sense.  A deferred error is an error		 * for a command that has already returned GOOD status		 * (see SCSI2 8.2.14.2).		 *		 * By my reading of that section, it looks like the current		 * command has been cancelled, we should now clean things up		 * (hopefully recovering any lost data) and then retry the		 * current command.  There are two easy choices, both wrong:		 *		 * 1. Drop through (like we had been doing), thus treating		 *    this as if the error were for the current command and		 *    return and stop the current command.		 * 		 * 2. Issue a retry (like I made it do) thus hopefully		 *    recovering the current transfer, and ignoring the		 *    fact that we've dropped a command.		 *		 * These should probably be handled in a device specific		 * sense handler or punted back up to a user mode daemon		 */		action = SS_RETRY|SSQ_DECREMENT_COUNT|SSQ_PRINT_SENSE;	} else {		fetchtableentries(sense_key, asc, ascq,				  inq_data,				  &sense_entry,				  &asc_entry);		/*		 * Override the 'No additional Sense' entry (0,0)		 * with the error action of the sense key.		 */		if (asc_entry != NULL		 && (asc != 0 || ascq != 0))			action = asc_entry->action;		else			action = sense_entry->action;		if (sense_key == SSD_KEY_RECOVERED_ERROR) {			/*			 * The action succeeded but the device wants			 * the user to know that some recovery action			 * was required.			 */			action &= ~(SS_MASK|SSQ_MASK|SS_ERRMASK);			action |= SS_NOP|SSQ_PRINT_SENSE;		} else if (sense_key == SSD_KEY_ILLEGAL_REQUEST) {			if ((sense_flags & SF_QUIET_IR) != 0)				action &= ~SSQ_PRINT_SENSE;		} else if (sense_key == SSD_KEY_UNIT_ATTENTION) {			if ((sense_flags & SF_RETRY_UA) != 0			 && (action & SS_MASK) == SS_FAIL) {				action &= ~(SS_MASK|SSQ_MASK);				action |= SS_RETRY|SSQ_DECREMENT_COUNT|					  SSQ_PRINT_SENSE;			}		}	}	if ((sense_flags & SF_PRINT_ALWAYS) != 0)		action |= SSQ_PRINT_SENSE;	else if ((sense_flags & SF_NO_PRINT) != 0)		action &= ~SSQ_PRINT_SENSE;	return (action);}/*       * Try make as good a match as possible with * available sub drivers */intaic_inquiry_match(caddr_t inqbuffer, caddr_t table_entry){	struct scsi_inquiry_pattern *entry;	struct scsi_inquiry_data *inq; 	entry = (struct scsi_inquiry_pattern *)table_entry;	inq = (struct scsi_inquiry_data *)inqbuffer;	if (((SID_TYPE(inq) == entry->type)	  || (entry->type == T_ANY))	 && (SID_IS_REMOVABLE(inq) ? entry->media_type & SIP_MEDIA_REMOVABLE				   : entry->media_type & SIP_MEDIA_FIXED)	 && (cam_strmatch(inq->vendor, entry->vendor, sizeof(inq->vendor)) == 0)	 && (cam_strmatch(inq->product, entry->product,			  sizeof(inq->product)) == 0)	 && (cam_strmatch(inq->revision, entry->revision,			  sizeof(inq->revision)) == 0)) {		return (0);	}        return (-1);}/* * Table of syncrates that don't follow the "divisible by 4" * rule. This table will be expanded in future SCSI specs. */static struct {	u_int period_factor;	u_int period;	/* in 100ths of ns */} scsi_syncrates[] = {	{ 0x08, 625 },	/* FAST-160 */	{ 0x09, 1250 },	/* FAST-80 */	{ 0x0a, 2500 },	/* FAST-40 40MHz */	{ 0x0b, 3030 },	/* FAST-40 33MHz */	{ 0x0c, 5000 }	/* FAST-20 */};/* * Return the frequency in kHz corresponding to the given * sync period factor. */u_intaic_calc_syncsrate(u_int period_factor){	int i;	int num_syncrates;	num_syncrates = sizeof(scsi_syncrates) / sizeof(scsi_syncrates[0]);	/* See if the period is in the "exception" table */	for (i = 0; i < num_syncrates; i++) {		if (period_factor == scsi_syncrates[i].period_factor) {			/* Period in kHz */			return (100000000 / scsi_syncrates[i].period);		}	}	/*	 * Wasn't in the table, so use the standard	 * 4 times conversion.	 */	return (10000000 / (period_factor * 4 * 10));}/* * Return speed in KB/s. */u_intaic_calc_speed(u_int width, u_int period, u_int offset, u_int min_rate){	u_int freq;	if (offset != 0 && period < min_rate)		freq  = aic_calc_syncsrate(period);	else		/* Roughly 3.3MB/s for async */		freq  = 3300;	freq <<= width;	return (freq);}uint32_taic_error_action(struct scsi_cmnd *cmd, struct scsi_inquiry_data *inq_data,		 cam_status status, u_int scsi_status){	aic_sense_action  err_action;	int		  sense;	sense  = (cmd->result >> 24) == DRIVER_SENSE;	switch (status) {	case CAM_REQ_CMP:		err_action = SS_NOP;		break;	case CAM_AUTOSENSE_FAIL:	case CAM_SCSI_STATUS_ERROR:		switch (scsi_status) {		case SCSI_STATUS_OK:		case SCSI_STATUS_COND_MET:		case SCSI_STATUS_INTERMED:		case SCSI_STATUS_INTERMED_COND_MET:			err_action = SS_NOP;			break;		case SCSI_STATUS_CMD_TERMINATED:		case SCSI_STATUS_CHECK_COND:			if (sense != 0) {				struct scsi_sense_data *sense;				sense = (struct scsi_sense_data *)				    &cmd->sense_buffer;				err_action =				    aic_sense_error_action(sense, inq_data, 0);			} else {				err_action = SS_RETRY|SSQ_FALLBACK					   | SSQ_DECREMENT_COUNT|EIO;			}			break;		case SCSI_STATUS_QUEUE_FULL:		case SCSI_STATUS_BUSY:			err_action = SS_RETRY|SSQ_DELAY|SSQ_MANY				   | SSQ_DECREMENT_COUNT|EBUSY;			break;		case SCSI_STATUS_RESERV_CONFLICT:		default:			err_action = SS_FAIL|EBUSY;			break;		}		break;	case CAM_CMD_TIMEOUT:	case CAM_REQ_CMP_ERR:	case CAM_UNEXP_BUSFREE:	case CAM_UNCOR_PARITY:	case CAM_DATA_RUN_ERR:		err_action = SS_RETRY|SSQ_FALLBACK|EIO;		break;	case CAM_UA_ABORT:	case CAM_UA_TERMIO:	case CAM_MSG_REJECT_REC:	case CAM_SEL_TIMEOUT:		err_action = SS_FAIL|EIO;		break;	case CAM_REQ_INVALID:	case CAM_PATH_INVALID:	case CAM_DEV_NOT_THERE:	case CAM_NO_HBA:	case CAM_PROVIDE_FAIL:	case CAM_REQ_TOO_BIG:			case CAM_RESRC_UNAVAIL:	case CAM_BUSY:	default:		/* panic??  These should never occur in our application. */		err_action = SS_FAIL|EIO;		break;	case CAM_SCSI_BUS_RESET:	case CAM_BDR_SENT:			case CAM_REQUEUE_REQ:		/* Unconditional requeue */		err_action = SS_RETRY;		break;	}	return (err_action);}char *aic_parse_brace_option(char *opt_name, char *opt_arg, char *end, int depth,		       aic_option_callback_t *callback, u_long callback_arg){	char	*tok_end;	char	*tok_end2;	int      i;	int      instance;	int	 targ;	int	 done;	char	 tok_list[] = {'.', ',', '{', '}', '\0'};	/* All options use a ':' name/arg separator */	if (*opt_arg != ':')		return (opt_arg);	opt_arg++;	instance = -1;	targ = -1;	done = FALSE;	/*	 * Restore separator that may be in	 * the middle of our option argument.	 */	tok_end = strchr(opt_arg, '\0');	if (tok_end < end)		*tok_end = ',';	while (!done) {		switch (*opt_arg) {		case '{':			if (instance == -1) {				instance = 0;			} else {				if (depth > 1) {					if (targ == -1)						targ = 0;				} else {					printf("Malformed Option %s\n",					       opt_name);					done = TRUE;				}			}			opt_arg++;			break;		case '}':			if (targ != -1)				targ = -1;			else if (instance != -1)				instance = -1;			opt_arg++;			break;		case ',':		case '.':			if (instance == -1)				done = TRUE;			else if (targ >= 0)				targ++;			else if (instance >= 0)				instance++;			opt_arg++;			break;		case '\0':			done = TRUE;			break;		default:			tok_end = end;			for (i = 0; tok_list[i]; i++) {				tok_end2 = strchr(opt_arg, tok_list[i]);				if ((tok_end2) && (tok_end2 < tok_end))					tok_end = tok_end2;			}			callback(callback_arg, instance, targ,				 simple_strtol(opt_arg, NULL, 0));			opt_arg = tok_end;			break;		}	}	return (opt_arg);}

⌨️ 快捷键说明

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