-static
-int scsi_debug_queuecommand(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;
- int errsts = 0;
- int target = SCpnt->device->id;
- struct sdebug_dev_info * devip = NULL;
- int inj_recovered = 0;
- int inj_transport = 0;
- int delay_override = 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 */
- }
-
- 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:
- if ((errsts = check_readiness(SCpnt, 1, devip)))
- 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 (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;
- get_data_transfer_info(cmd, &lba, &num);
- 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;
- get_data_transfer_info(cmd, &lba, &num);
- 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;
- 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);
- errsts = resp_read(SCpnt, lba, num, devip);
- if (errsts)
- break;
- errsts = resp_write(SCpnt, lba, num, devip);
- if (errsts)
- break;
- errsts = resp_xdwriteread(SCpnt, lba, num, 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));
-}
-