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 + -
显示快捷键?