scsi_debug.c

来自「linux 内核源代码」· C语言 代码 · 共 2,078 行 · 第 1/5 页

C
2,078
字号
        case RESERVE_10:		errsts = check_readiness(SCpnt, 1, devip);                break;        case RELEASE:		errsts = check_readiness(SCpnt, 1, devip);                break;        case RELEASE_10:		errsts = check_readiness(SCpnt, 1, devip);                break;	case READ_CAPACITY:		errsts = resp_readcap(SCpnt, devip);		break;	case SERVICE_ACTION_IN:		if (SAI_READ_CAPACITY_16 != cmd[1]) {			mk_sense_buffer(devip, ILLEGAL_REQUEST,					INVALID_OPCODE, 0);			errsts = check_condition_result;			break;		}		errsts = resp_readcap16(SCpnt, devip);		break;	case MAINTENANCE_IN:		if (MI_REPORT_TARGET_PGS != cmd[1]) {			mk_sense_buffer(devip, ILLEGAL_REQUEST,					INVALID_OPCODE, 0);			errsts = check_condition_result;			break;		}		errsts = resp_report_tgtpgs(SCpnt, devip);		break;	case READ_16:	case READ_12:	case READ_10:	case READ_6:		if ((errsts = check_readiness(SCpnt, 0, devip)))			break;		if (scsi_debug_fake_rw)			break;		if ((*cmd) == READ_16) {			for (lba = 0, j = 0; j < 8; ++j) {				if (j > 0)					lba <<= 8;				lba += cmd[2 + j];			}			num = cmd[13] + (cmd[12] << 8) +				(cmd[11] << 16) + (cmd[10] << 24);		} else if ((*cmd) == READ_12) {			lba = cmd[5] + (cmd[4] << 8) +				(cmd[3] << 16) + (cmd[2] << 24);			num = cmd[9] + (cmd[8] << 8) +				(cmd[7] << 16) + (cmd[6] << 24);		} else if ((*cmd) == READ_10) {			lba = cmd[5] + (cmd[4] << 8) +				(cmd[3] << 16) + (cmd[2] << 24);			num = cmd[8] + (cmd[7] << 8);		} else {	/* READ (6) */			lba = cmd[3] + (cmd[2] << 8) +				((cmd[1] & 0x1f) << 16);			num = (0 == cmd[4]) ? 256 : cmd[4];		}		errsts = resp_read(SCpnt, lba, num, devip);		if (inj_recovered && (0 == errsts)) {			mk_sense_buffer(devip, RECOVERED_ERROR,					THRESHOLD_EXCEEDED, 0);			errsts = check_condition_result;		} else if (inj_transport && (0 == errsts)) {                        mk_sense_buffer(devip, ABORTED_COMMAND,                                        TRANSPORT_PROBLEM, ACK_NAK_TO);                        errsts = check_condition_result;                }		break;	case REPORT_LUNS:	/* mandatory, ignore unit attention */		delay_override = 1;		errsts = resp_report_luns(SCpnt, devip);		break;	case VERIFY:		/* 10 byte SBC-2 command */		errsts = check_readiness(SCpnt, 0, devip);		break;	case WRITE_16:	case WRITE_12:	case WRITE_10:	case WRITE_6:		if ((errsts = check_readiness(SCpnt, 0, devip)))			break;		if (scsi_debug_fake_rw)			break;		if ((*cmd) == WRITE_16) {			for (lba = 0, j = 0; j < 8; ++j) {				if (j > 0)					lba <<= 8;				lba += cmd[2 + j];			}			num = cmd[13] + (cmd[12] << 8) +				(cmd[11] << 16) + (cmd[10] << 24);		} else if ((*cmd) == WRITE_12) {			lba = cmd[5] + (cmd[4] << 8) +				(cmd[3] << 16) + (cmd[2] << 24);			num = cmd[9] + (cmd[8] << 8) +				(cmd[7] << 16) + (cmd[6] << 24);		} else if ((*cmd) == WRITE_10) {			lba = cmd[5] + (cmd[4] << 8) +				(cmd[3] << 16) + (cmd[2] << 24);			num = cmd[8] + (cmd[7] << 8);		} else {	/* WRITE (6) */			lba = cmd[3] + (cmd[2] << 8) +				((cmd[1] & 0x1f) << 16);			num = (0 == cmd[4]) ? 256 : cmd[4];		}		errsts = resp_write(SCpnt, lba, num, devip);		if (inj_recovered && (0 == errsts)) {			mk_sense_buffer(devip, RECOVERED_ERROR,					THRESHOLD_EXCEEDED, 0);			errsts = check_condition_result;		}		break;	case MODE_SENSE:	case MODE_SENSE_10:		errsts = resp_mode_sense(SCpnt, target, devip);		break;	case MODE_SELECT:		errsts = resp_mode_select(SCpnt, 1, devip);		break;	case MODE_SELECT_10:		errsts = resp_mode_select(SCpnt, 0, devip);		break;	case LOG_SENSE:		errsts = resp_log_sense(SCpnt, devip);		break;	case SYNCHRONIZE_CACHE:		delay_override = 1;		errsts = check_readiness(SCpnt, 0, devip);		break;	case WRITE_BUFFER:		errsts = check_readiness(SCpnt, 1, devip);		break;	default:		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)			printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "			       "supported\n", *cmd);		if ((errsts = check_readiness(SCpnt, 1, devip)))			break;	/* Unit attention takes precedence */		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_OPCODE, 0);		errsts = check_condition_result;		break;	}	return schedule_resp(SCpnt, devip, done, errsts,			     (delay_override ? 0 : scsi_debug_delay));}static int scsi_debug_ioctl(struct scsi_device *dev, int cmd, void __user *arg){	if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) {		printk(KERN_INFO "scsi_debug: ioctl: cmd=0x%x\n", cmd);	}	return -EINVAL;	/* return -ENOTTY; // correct return but upsets fdisk */}static int check_readiness(struct scsi_cmnd * SCpnt, int reset_only,			   struct sdebug_dev_info * devip){	if (devip->reset) {		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)			printk(KERN_INFO "scsi_debug: Reporting Unit "			       "attention: power on reset\n");		devip->reset = 0;		mk_sense_buffer(devip, UNIT_ATTENTION, POWERON_RESET, 0);		return check_condition_result;	}	if ((0 == reset_only) && devip->stopped) {		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)			printk(KERN_INFO "scsi_debug: Reporting Not "			       "ready: initializing command required\n");		mk_sense_buffer(devip, NOT_READY, LOGICAL_UNIT_NOT_READY,				0x2);		return check_condition_result;	}	return 0;}/* Returns 0 if ok else (DID_ERROR << 16). Sets scp->resid . */static int fill_from_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,				int arr_len){	int k, req_len, act_len, len, active;	void * kaddr;	void * kaddr_off;	struct scatterlist * sg;	if (0 == scp->request_bufflen)		return 0;	if (NULL == scp->request_buffer)		return (DID_ERROR << 16);	if (! ((scp->sc_data_direction == DMA_BIDIRECTIONAL) ||	      (scp->sc_data_direction == DMA_FROM_DEVICE)))		return (DID_ERROR << 16);	if (0 == scp->use_sg) {		req_len = scp->request_bufflen;		act_len = (req_len < arr_len) ? req_len : arr_len;		memcpy(scp->request_buffer, arr, act_len);		if (scp->resid)			scp->resid -= act_len;		else			scp->resid = req_len - act_len;		return 0;	}	active = 1;	req_len = act_len = 0;	scsi_for_each_sg(scp, sg, scp->use_sg, k) {		if (active) {			kaddr = (unsigned char *)				kmap_atomic(sg_page(sg), KM_USER0);			if (NULL == kaddr)				return (DID_ERROR << 16);			kaddr_off = (unsigned char *)kaddr + sg->offset;			len = sg->length;			if ((req_len + len) > arr_len) {				active = 0;				len = arr_len - req_len;			}			memcpy(kaddr_off, arr + req_len, len);			kunmap_atomic(kaddr, KM_USER0);			act_len += len;		}		req_len += sg->length;	}	if (scp->resid)		scp->resid -= act_len;	else		scp->resid = req_len - act_len;	return 0;}/* Returns number of bytes fetched into 'arr' or -1 if error. */static int fetch_to_dev_buffer(struct scsi_cmnd * scp, unsigned char * arr,			       int max_arr_len){	int k, req_len, len, fin;	void * kaddr;	void * kaddr_off;	struct scatterlist * sg;	if (0 == scp->request_bufflen)		return 0;	if (NULL == scp->request_buffer)		return -1;	if (! ((scp->sc_data_direction == DMA_BIDIRECTIONAL) ||	      (scp->sc_data_direction == DMA_TO_DEVICE)))		return -1;	if (0 == scp->use_sg) {		req_len = scp->request_bufflen;		len = (req_len < max_arr_len) ? req_len : max_arr_len;		memcpy(arr, scp->request_buffer, len);		return len;	}	sg = scsi_sglist(scp);	req_len = fin = 0;	for (k = 0; k < scp->use_sg; ++k, sg = sg_next(sg)) {		kaddr = (unsigned char *)kmap_atomic(sg_page(sg), KM_USER0);		if (NULL == kaddr)			return -1;		kaddr_off = (unsigned char *)kaddr + sg->offset;		len = sg->length;		if ((req_len + len) > max_arr_len) {			len = max_arr_len - req_len;			fin = 1;		}		memcpy(arr + req_len, kaddr_off, len);		kunmap_atomic(kaddr, KM_USER0);		if (fin)			return req_len + len;		req_len += sg->length;	}	return req_len;}static const char * inq_vendor_id = "Linux   ";static const char * inq_product_id = "scsi_debug      ";static const char * inq_product_rev = "0004";static int inquiry_evpd_83(unsigned char * arr, int port_group_id,			   int target_dev_id, int dev_id_num,			   const char * dev_id_str,			   int dev_id_str_len){	int num, port_a;	char b[32];	port_a = target_dev_id + 1;	/* T10 vendor identifier field format (faked) */	arr[0] = 0x2;	/* ASCII */	arr[1] = 0x1;	arr[2] = 0x0;	memcpy(&arr[4], inq_vendor_id, 8);	memcpy(&arr[12], inq_product_id, 16);	memcpy(&arr[28], dev_id_str, dev_id_str_len);	num = 8 + 16 + dev_id_str_len;	arr[3] = num;	num += 4;	if (dev_id_num >= 0) {		/* NAA-5, Logical unit identifier (binary) */		arr[num++] = 0x1;	/* binary (not necessarily sas) */		arr[num++] = 0x3;	/* PIV=0, lu, naa */		arr[num++] = 0x0;		arr[num++] = 0x8;		arr[num++] = 0x53;  /* naa-5 ieee company id=0x333333 (fake) */		arr[num++] = 0x33;		arr[num++] = 0x33;		arr[num++] = 0x30;		arr[num++] = (dev_id_num >> 24);		arr[num++] = (dev_id_num >> 16) & 0xff;		arr[num++] = (dev_id_num >> 8) & 0xff;		arr[num++] = dev_id_num & 0xff;		/* Target relative port number */		arr[num++] = 0x61;	/* proto=sas, binary */		arr[num++] = 0x94;	/* PIV=1, target port, rel port */		arr[num++] = 0x0;	/* reserved */		arr[num++] = 0x4;	/* length */		arr[num++] = 0x0;	/* reserved */		arr[num++] = 0x0;	/* reserved */		arr[num++] = 0x0;		arr[num++] = 0x1;	/* relative port A */	}	/* NAA-5, Target port identifier */	arr[num++] = 0x61;	/* proto=sas, binary */	arr[num++] = 0x93;	/* piv=1, target port, naa */	arr[num++] = 0x0;	arr[num++] = 0x8;	arr[num++] = 0x52;	/* naa-5, company id=0x222222 (fake) */	arr[num++] = 0x22;	arr[num++] = 0x22;	arr[num++] = 0x20;	arr[num++] = (port_a >> 24);	arr[num++] = (port_a >> 16) & 0xff;	arr[num++] = (port_a >> 8) & 0xff;	arr[num++] = port_a & 0xff;	/* NAA-5, Target port group identifier */	arr[num++] = 0x61;	/* proto=sas, binary */	arr[num++] = 0x95;	/* piv=1, target port group id */	arr[num++] = 0x0;	arr[num++] = 0x4;	arr[num++] = 0;	arr[num++] = 0;	arr[num++] = (port_group_id >> 8) & 0xff;	arr[num++] = port_group_id & 0xff;	/* NAA-5, Target device identifier */	arr[num++] = 0x61;	/* proto=sas, binary */	arr[num++] = 0xa3;	/* piv=1, target device, naa */	arr[num++] = 0x0;	arr[num++] = 0x8;	arr[num++] = 0x52;	/* naa-5, company id=0x222222 (fake) */	arr[num++] = 0x22;	arr[num++] = 0x22;	arr[num++] = 0x20;	arr[num++] = (target_dev_id >> 24);	arr[num++] = (target_dev_id >> 16) & 0xff;	arr[num++] = (target_dev_id >> 8) & 0xff;	arr[num++] = target_dev_id & 0xff;	/* SCSI name string: Target device identifier */	arr[num++] = 0x63;	/* proto=sas, UTF-8 */	arr[num++] = 0xa8;	/* piv=1, target device, SCSI name string */	arr[num++] = 0x0;	arr[num++] = 24;	memcpy(arr + num, "naa.52222220", 12);	num += 12;	snprintf(b, sizeof(b), "%08X", target_dev_id);	memcpy(arr + num, b, 8);	num += 8;	memset(arr + num, 0, 4);	num += 4;	return num;}static unsigned char vpd84_data[] = {/* from 4th byte */ 0x22,0x22,0x22,0x0,0xbb,0x0,    0x22,0x22,0x22,0x0,0xbb,0x1,    0x22,0x22,0x22,0x0,0xbb,0x2,};static int inquiry_evpd_84(unsigned char * arr){	memcpy(arr, vpd84_data, sizeof(vpd84_data));	return sizeof(vpd84_data);}static int inquiry_evpd_85(unsigned char * arr){	int num = 0;	const char * na1 = "https://www.kernel.org/config";	const char * na2 = "http://www.kernel.org/log";	int plen, olen;	arr[num++] = 0x1;	/* lu, storage config */	arr[num++] = 0x0;	/* reserved */	arr[num++] = 0x0;	olen = strlen(na1);	plen = olen + 1;	if (plen % 4)		plen = ((plen / 4) + 1) * 4;	arr[num++] = plen;	/* length, null termianted, padded */	memcpy(arr + num, na1, olen);	memset(arr + num + olen, 0, plen - olen);	num += plen;	arr[num++] = 0x4;	/* lu, logging */	arr[num++] = 0x0;	/* reserved */	arr[num++] = 0x0;	olen = strlen(na2);	plen = olen + 1;	if (plen % 4)		plen = ((plen / 4) + 1) * 4;	arr[num++] = plen;	/* length, null terminated, padded */	memcpy(arr + num, na2, olen);	memset(arr + num + olen, 0, plen - olen);

⌨️ 快捷键说明

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