Enscript Output

extractedLnx/linux-2.6.38/drivers/scsi/scsi_debug.c_scsi_debug_queuecommand_lck.c

static
int scsi_debug_queuecommand_lck(struct scsi_cmnd *SCpnt, done_funct_t done)
{
	unsigned char *cmd = (unsigned char *) SCpnt->cmnd;
	int len, k;
	unsigned int num;
	unsigned long long lba;
	u32 ei_lba;
	int errsts = 0;
	int target = SCpnt->device->id;
	struct sdebug_dev_info *devip = NULL;
	int inj_recovered = 0;
	int inj_transport = 0;
	int inj_dif = 0;
	int inj_dix = 0;
	int delay_override = 0;
	int unmap = 0;

	scsi_set_resid(SCpnt, 0);
	if ((SCSI_DEBUG_OPT_NOISE & scsi_debug_opts) && cmd) {
		printk(KERN_INFO "scsi_debug: cmd ");
		for (k = 0, len = SCpnt->cmd_len; k < len; ++k)
			printk("%02x ", (int)cmd[k]);
		printk("\n");
	}

	if (target == SCpnt->device->host->hostt->this_id) {
		printk(KERN_INFO "scsi_debug: initiator's id used as "
		       "target!\n");
		return schedule_resp(SCpnt, NULL, done,
				     DID_NO_CONNECT << 16, 0);
	}

	if ((SCpnt->device->lun >= scsi_debug_max_luns) &&
	    (SCpnt->device->lun != SAM2_WLUN_REPORT_LUNS))
		return schedule_resp(SCpnt, NULL, done,
				     DID_NO_CONNECT << 16, 0);
	devip = devInfoReg(SCpnt->device);
	if (NULL == devip)
		return schedule_resp(SCpnt, NULL, done,
				     DID_NO_CONNECT << 16, 0);

	if ((scsi_debug_every_nth != 0) &&
	    (++scsi_debug_cmnd_count >= abs(scsi_debug_every_nth))) {
		scsi_debug_cmnd_count = 0;
		if (scsi_debug_every_nth < -1)
			scsi_debug_every_nth = -1;
		if (SCSI_DEBUG_OPT_TIMEOUT & scsi_debug_opts)
			return 0; /* ignore command causing timeout */
		else if (SCSI_DEBUG_OPT_RECOVERED_ERR & scsi_debug_opts)
			inj_recovered = 1; /* to reads and writes below */
		else if (SCSI_DEBUG_OPT_TRANSPORT_ERR & scsi_debug_opts)
			inj_transport = 1; /* to reads and writes below */
		else if (SCSI_DEBUG_OPT_DIF_ERR & scsi_debug_opts)
			inj_dif = 1; /* to reads and writes below */
		else if (SCSI_DEBUG_OPT_DIX_ERR & scsi_debug_opts)
			inj_dix = 1; /* to reads and writes below */
	}

	if (devip->wlun) {
		switch (*cmd) {
		case INQUIRY:
		case REQUEST_SENSE:
		case TEST_UNIT_READY:
		case REPORT_LUNS:
			break;  /* only allowable wlun commands */
		default:
			if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
				printk(KERN_INFO "scsi_debug: Opcode: 0x%x "
				       "not supported for wlun\n", *cmd);
			mk_sense_buffer(devip, ILLEGAL_REQUEST,
					INVALID_OPCODE, 0);
			errsts = check_condition_result;
			return schedule_resp(SCpnt, devip, done, errsts,
					     0);
		}
	}

	switch (*cmd) {
	case INQUIRY:     /* mandatory, ignore unit attention */
		delay_override = 1;
		errsts = resp_inquiry(SCpnt, target, devip);
		break;
	case REQUEST_SENSE:	/* mandatory, ignore unit attention */
		delay_override = 1;
		errsts = resp_requests(SCpnt, devip);
		break;
	case REZERO_UNIT:	/* actually this is REWIND for SSC */
	case START_STOP:
		errsts = resp_start_stop(SCpnt, devip);
		break;
	case ALLOW_MEDIUM_REMOVAL:
		errsts = check_readiness(SCpnt, 1, devip);
		if (errsts)
			break;
		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
			printk(KERN_INFO "scsi_debug: Medium removal %s\n",
			       cmd[4] ? "inhibited" : "enabled");
		break;
	case SEND_DIAGNOSTIC:     /* mandatory */
		errsts = check_readiness(SCpnt, 1, devip);
		break;
	case TEST_UNIT_READY:     /* mandatory */
		delay_override = 1;
		errsts = check_readiness(SCpnt, 0, devip);
		break;
	case RESERVE:
		errsts = check_readiness(SCpnt, 1, devip);
		break;
	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 (cmd[1] == SAI_READ_CAPACITY_16)
			errsts = resp_readcap16(SCpnt, devip);
		else if (cmd[1] == SAI_GET_LBA_STATUS) {

			if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0) {
				mk_sense_buffer(devip, ILLEGAL_REQUEST,
						INVALID_COMMAND_OPCODE, 0);
				errsts = check_condition_result;
			} else
				errsts = resp_get_lba_status(SCpnt, devip);
		} else {
			mk_sense_buffer(devip, ILLEGAL_REQUEST,
					INVALID_OPCODE, 0);
			errsts = check_condition_result;
		}
		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:
		/* READ{10,12,16} and DIF Type 2 are natural enemies */
		if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
		    cmd[1] & 0xe0) {
			mk_sense_buffer(devip, ILLEGAL_REQUEST,
					INVALID_COMMAND_OPCODE, 0);
			errsts = check_condition_result;
			break;
		}

		if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
		     scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
		    (cmd[1] & 0xe0) == 0)
			printk(KERN_ERR "Unprotected RD/WR to DIF device\n");

		/* fall through */
	case READ_6:
read:
		errsts = check_readiness(SCpnt, 0, devip);
		if (errsts)
			break;
		if (scsi_debug_fake_rw)
			break;
		get_data_transfer_info(cmd, &lba, &num, &ei_lba);
		errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
		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;
		} else if (inj_dif && (0 == errsts)) {
			mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
			errsts = illegal_condition_result;
		} else if (inj_dix && (0 == errsts)) {
			mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
			errsts = illegal_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:
		/* WRITE{10,12,16} and DIF Type 2 are natural enemies */
		if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION &&
		    cmd[1] & 0xe0) {
			mk_sense_buffer(devip, ILLEGAL_REQUEST,
					INVALID_COMMAND_OPCODE, 0);
			errsts = check_condition_result;
			break;
		}

		if ((scsi_debug_dif == SD_DIF_TYPE1_PROTECTION ||
		     scsi_debug_dif == SD_DIF_TYPE3_PROTECTION) &&
		    (cmd[1] & 0xe0) == 0)
			printk(KERN_ERR "Unprotected RD/WR to DIF device\n");

		/* fall through */
	case WRITE_6:
write:
		errsts = check_readiness(SCpnt, 0, devip);
		if (errsts)
			break;
		if (scsi_debug_fake_rw)
			break;
		get_data_transfer_info(cmd, &lba, &num, &ei_lba);
		errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
		if (inj_recovered && (0 == errsts)) {
			mk_sense_buffer(devip, RECOVERED_ERROR,
					THRESHOLD_EXCEEDED, 0);
			errsts = check_condition_result;
		} else if (inj_dif && (0 == errsts)) {
			mk_sense_buffer(devip, ABORTED_COMMAND, 0x10, 1);
			errsts = illegal_condition_result;
		} else if (inj_dix && (0 == errsts)) {
			mk_sense_buffer(devip, ILLEGAL_REQUEST, 0x10, 1);
			errsts = illegal_condition_result;
		}
		break;
	case WRITE_SAME_16:
		if (cmd[1] & 0x8) {
			if (scsi_debug_tpws == 0) {
				mk_sense_buffer(devip, ILLEGAL_REQUEST,
						INVALID_FIELD_IN_CDB, 0);
				errsts = check_condition_result;
			} else
				unmap = 1;
		}
		if (errsts)
			break;
		/* fall through */
	case WRITE_SAME:
		errsts = check_readiness(SCpnt, 0, devip);
		if (errsts)
			break;
		get_data_transfer_info(cmd, &lba, &num, &ei_lba);
		errsts = resp_write_same(SCpnt, lba, num, devip, ei_lba, unmap);
		break;
	case UNMAP:
		errsts = check_readiness(SCpnt, 0, devip);
		if (errsts)
			break;

		if (scsi_debug_unmap_max_desc == 0 || scsi_debug_tpu == 0) {
			mk_sense_buffer(devip, ILLEGAL_REQUEST,
					INVALID_COMMAND_OPCODE, 0);
			errsts = check_condition_result;
		} else
			errsts = resp_unmap(SCpnt, devip);
		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;
	case XDWRITEREAD_10:
		if (!scsi_bidi_cmnd(SCpnt)) {
			mk_sense_buffer(devip, ILLEGAL_REQUEST,
					INVALID_FIELD_IN_CDB, 0);
			errsts = check_condition_result;
			break;
		}

		errsts = check_readiness(SCpnt, 0, devip);
		if (errsts)
			break;
		if (scsi_debug_fake_rw)
			break;
		get_data_transfer_info(cmd, &lba, &num, &ei_lba);
		errsts = resp_read(SCpnt, lba, num, devip, ei_lba);
		if (errsts)
			break;
		errsts = resp_write(SCpnt, lba, num, devip, ei_lba);
		if (errsts)
			break;
		errsts = resp_xdwriteread(SCpnt, lba, num, devip);
		break;
	case VARIABLE_LENGTH_CMD:
		if (scsi_debug_dif == SD_DIF_TYPE2_PROTECTION) {

			if ((cmd[10] & 0xe0) == 0)
				printk(KERN_ERR
				       "Unprotected RD/WR to DIF device\n");

			if (cmd[9] == READ_32) {
				BUG_ON(SCpnt->cmd_len < 32);
				goto read;
			}

			if (cmd[9] == WRITE_32) {
				BUG_ON(SCpnt->cmd_len < 32);
				goto write;
			}
		}

		mk_sense_buffer(devip, ILLEGAL_REQUEST,
				INVALID_FIELD_IN_CDB, 0);
		errsts = check_condition_result;
		break;

	default:
		if (SCSI_DEBUG_OPT_NOISE & scsi_debug_opts)
			printk(KERN_INFO "scsi_debug: Opcode: 0x%x not "
			       "supported\n", *cmd);
		errsts = check_readiness(SCpnt, 1, devip);
		if (errsts)
			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));
}

Generated by GNU enscript 1.6.4.