0001
0002 #include <stdio.h>
0003 #include <string.h>
0004 #include <inttypes.h>
0005 #include "event-parse.h"
0006 #include "trace-seq.h"
0007
0008 typedef unsigned long sector_t;
0009 typedef uint64_t u64;
0010 typedef unsigned int u32;
0011
0012
0013
0014
0015 #define TEST_UNIT_READY 0x00
0016 #define REZERO_UNIT 0x01
0017 #define REQUEST_SENSE 0x03
0018 #define FORMAT_UNIT 0x04
0019 #define READ_BLOCK_LIMITS 0x05
0020 #define REASSIGN_BLOCKS 0x07
0021 #define INITIALIZE_ELEMENT_STATUS 0x07
0022 #define READ_6 0x08
0023 #define WRITE_6 0x0a
0024 #define SEEK_6 0x0b
0025 #define READ_REVERSE 0x0f
0026 #define WRITE_FILEMARKS 0x10
0027 #define SPACE 0x11
0028 #define INQUIRY 0x12
0029 #define RECOVER_BUFFERED_DATA 0x14
0030 #define MODE_SELECT 0x15
0031 #define RESERVE 0x16
0032 #define RELEASE 0x17
0033 #define COPY 0x18
0034 #define ERASE 0x19
0035 #define MODE_SENSE 0x1a
0036 #define START_STOP 0x1b
0037 #define RECEIVE_DIAGNOSTIC 0x1c
0038 #define SEND_DIAGNOSTIC 0x1d
0039 #define ALLOW_MEDIUM_REMOVAL 0x1e
0040
0041 #define READ_FORMAT_CAPACITIES 0x23
0042 #define SET_WINDOW 0x24
0043 #define READ_CAPACITY 0x25
0044 #define READ_10 0x28
0045 #define WRITE_10 0x2a
0046 #define SEEK_10 0x2b
0047 #define POSITION_TO_ELEMENT 0x2b
0048 #define WRITE_VERIFY 0x2e
0049 #define VERIFY 0x2f
0050 #define SEARCH_HIGH 0x30
0051 #define SEARCH_EQUAL 0x31
0052 #define SEARCH_LOW 0x32
0053 #define SET_LIMITS 0x33
0054 #define PRE_FETCH 0x34
0055 #define READ_POSITION 0x34
0056 #define SYNCHRONIZE_CACHE 0x35
0057 #define LOCK_UNLOCK_CACHE 0x36
0058 #define READ_DEFECT_DATA 0x37
0059 #define MEDIUM_SCAN 0x38
0060 #define COMPARE 0x39
0061 #define COPY_VERIFY 0x3a
0062 #define WRITE_BUFFER 0x3b
0063 #define READ_BUFFER 0x3c
0064 #define UPDATE_BLOCK 0x3d
0065 #define READ_LONG 0x3e
0066 #define WRITE_LONG 0x3f
0067 #define CHANGE_DEFINITION 0x40
0068 #define WRITE_SAME 0x41
0069 #define UNMAP 0x42
0070 #define READ_TOC 0x43
0071 #define READ_HEADER 0x44
0072 #define GET_EVENT_STATUS_NOTIFICATION 0x4a
0073 #define LOG_SELECT 0x4c
0074 #define LOG_SENSE 0x4d
0075 #define XDWRITEREAD_10 0x53
0076 #define MODE_SELECT_10 0x55
0077 #define RESERVE_10 0x56
0078 #define RELEASE_10 0x57
0079 #define MODE_SENSE_10 0x5a
0080 #define PERSISTENT_RESERVE_IN 0x5e
0081 #define PERSISTENT_RESERVE_OUT 0x5f
0082 #define VARIABLE_LENGTH_CMD 0x7f
0083 #define REPORT_LUNS 0xa0
0084 #define SECURITY_PROTOCOL_IN 0xa2
0085 #define MAINTENANCE_IN 0xa3
0086 #define MAINTENANCE_OUT 0xa4
0087 #define MOVE_MEDIUM 0xa5
0088 #define EXCHANGE_MEDIUM 0xa6
0089 #define READ_12 0xa8
0090 #define SERVICE_ACTION_OUT_12 0xa9
0091 #define WRITE_12 0xaa
0092 #define SERVICE_ACTION_IN_12 0xab
0093 #define WRITE_VERIFY_12 0xae
0094 #define VERIFY_12 0xaf
0095 #define SEARCH_HIGH_12 0xb0
0096 #define SEARCH_EQUAL_12 0xb1
0097 #define SEARCH_LOW_12 0xb2
0098 #define SECURITY_PROTOCOL_OUT 0xb5
0099 #define READ_ELEMENT_STATUS 0xb8
0100 #define SEND_VOLUME_TAG 0xb6
0101 #define WRITE_LONG_2 0xea
0102 #define EXTENDED_COPY 0x83
0103 #define RECEIVE_COPY_RESULTS 0x84
0104 #define ACCESS_CONTROL_IN 0x86
0105 #define ACCESS_CONTROL_OUT 0x87
0106 #define READ_16 0x88
0107 #define WRITE_16 0x8a
0108 #define READ_ATTRIBUTE 0x8c
0109 #define WRITE_ATTRIBUTE 0x8d
0110 #define VERIFY_16 0x8f
0111 #define SYNCHRONIZE_CACHE_16 0x91
0112 #define WRITE_SAME_16 0x93
0113 #define SERVICE_ACTION_BIDIRECTIONAL 0x9d
0114 #define SERVICE_ACTION_IN_16 0x9e
0115 #define SERVICE_ACTION_OUT_16 0x9f
0116
0117 #define SAI_READ_CAPACITY_16 0x10
0118 #define SAI_GET_LBA_STATUS 0x12
0119
0120
0121 #define VLC_SA_RECEIVE_CREDENTIAL 0x1800
0122
0123 #define MI_REPORT_IDENTIFYING_INFORMATION 0x05
0124 #define MI_REPORT_TARGET_PGS 0x0a
0125 #define MI_REPORT_ALIASES 0x0b
0126 #define MI_REPORT_SUPPORTED_OPERATION_CODES 0x0c
0127 #define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS 0x0d
0128 #define MI_REPORT_PRIORITY 0x0e
0129 #define MI_REPORT_TIMESTAMP 0x0f
0130 #define MI_MANAGEMENT_PROTOCOL_IN 0x10
0131
0132 #define MI_EXT_HDR_PARAM_FMT 0x20
0133
0134 #define MO_SET_IDENTIFYING_INFORMATION 0x06
0135 #define MO_SET_TARGET_PGS 0x0a
0136 #define MO_CHANGE_ALIASES 0x0b
0137 #define MO_SET_PRIORITY 0x0e
0138 #define MO_SET_TIMESTAMP 0x0f
0139 #define MO_MANAGEMENT_PROTOCOL_OUT 0x10
0140
0141 #define XDREAD_32 0x03
0142 #define XDWRITE_32 0x04
0143 #define XPWRITE_32 0x06
0144 #define XDWRITEREAD_32 0x07
0145 #define READ_32 0x09
0146 #define VERIFY_32 0x0a
0147 #define WRITE_32 0x0b
0148 #define WRITE_SAME_32 0x0d
0149
0150 #define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f)
0151 #define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9])
0152
0153 static const char *
0154 scsi_trace_misc(struct trace_seq *, unsigned char *, int);
0155
0156 static const char *
0157 scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
0158 {
0159 const char *ret = p->buffer + p->len;
0160 sector_t lba = 0, txlen = 0;
0161
0162 lba |= ((cdb[1] & 0x1F) << 16);
0163 lba |= (cdb[2] << 8);
0164 lba |= cdb[3];
0165 txlen = cdb[4];
0166
0167 trace_seq_printf(p, "lba=%llu txlen=%llu",
0168 (unsigned long long)lba, (unsigned long long)txlen);
0169 trace_seq_putc(p, 0);
0170 return ret;
0171 }
0172
0173 static const char *
0174 scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
0175 {
0176 const char *ret = p->buffer + p->len;
0177 sector_t lba = 0, txlen = 0;
0178
0179 lba |= (cdb[2] << 24);
0180 lba |= (cdb[3] << 16);
0181 lba |= (cdb[4] << 8);
0182 lba |= cdb[5];
0183 txlen |= (cdb[7] << 8);
0184 txlen |= cdb[8];
0185
0186 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
0187 (unsigned long long)lba, (unsigned long long)txlen,
0188 cdb[1] >> 5);
0189
0190 if (cdb[0] == WRITE_SAME)
0191 trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
0192
0193 trace_seq_putc(p, 0);
0194 return ret;
0195 }
0196
0197 static const char *
0198 scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
0199 {
0200 const char *ret = p->buffer + p->len;
0201 sector_t lba = 0, txlen = 0;
0202
0203 lba |= (cdb[2] << 24);
0204 lba |= (cdb[3] << 16);
0205 lba |= (cdb[4] << 8);
0206 lba |= cdb[5];
0207 txlen |= (cdb[6] << 24);
0208 txlen |= (cdb[7] << 16);
0209 txlen |= (cdb[8] << 8);
0210 txlen |= cdb[9];
0211
0212 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
0213 (unsigned long long)lba, (unsigned long long)txlen,
0214 cdb[1] >> 5);
0215 trace_seq_putc(p, 0);
0216 return ret;
0217 }
0218
0219 static const char *
0220 scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
0221 {
0222 const char *ret = p->buffer + p->len;
0223 sector_t lba = 0, txlen = 0;
0224
0225 lba |= ((u64)cdb[2] << 56);
0226 lba |= ((u64)cdb[3] << 48);
0227 lba |= ((u64)cdb[4] << 40);
0228 lba |= ((u64)cdb[5] << 32);
0229 lba |= (cdb[6] << 24);
0230 lba |= (cdb[7] << 16);
0231 lba |= (cdb[8] << 8);
0232 lba |= cdb[9];
0233 txlen |= (cdb[10] << 24);
0234 txlen |= (cdb[11] << 16);
0235 txlen |= (cdb[12] << 8);
0236 txlen |= cdb[13];
0237
0238 trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
0239 (unsigned long long)lba, (unsigned long long)txlen,
0240 cdb[1] >> 5);
0241
0242 if (cdb[0] == WRITE_SAME_16)
0243 trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
0244
0245 trace_seq_putc(p, 0);
0246 return ret;
0247 }
0248
0249 static const char *
0250 scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
0251 {
0252 const char *ret = p->buffer + p->len, *cmd;
0253 sector_t lba = 0, txlen = 0;
0254 u32 ei_lbrt = 0;
0255
0256 switch (SERVICE_ACTION32(cdb)) {
0257 case READ_32:
0258 cmd = "READ";
0259 break;
0260 case VERIFY_32:
0261 cmd = "VERIFY";
0262 break;
0263 case WRITE_32:
0264 cmd = "WRITE";
0265 break;
0266 case WRITE_SAME_32:
0267 cmd = "WRITE_SAME";
0268 break;
0269 default:
0270 trace_seq_printf(p, "UNKNOWN");
0271 goto out;
0272 }
0273
0274 lba |= ((u64)cdb[12] << 56);
0275 lba |= ((u64)cdb[13] << 48);
0276 lba |= ((u64)cdb[14] << 40);
0277 lba |= ((u64)cdb[15] << 32);
0278 lba |= (cdb[16] << 24);
0279 lba |= (cdb[17] << 16);
0280 lba |= (cdb[18] << 8);
0281 lba |= cdb[19];
0282 ei_lbrt |= (cdb[20] << 24);
0283 ei_lbrt |= (cdb[21] << 16);
0284 ei_lbrt |= (cdb[22] << 8);
0285 ei_lbrt |= cdb[23];
0286 txlen |= (cdb[28] << 24);
0287 txlen |= (cdb[29] << 16);
0288 txlen |= (cdb[30] << 8);
0289 txlen |= cdb[31];
0290
0291 trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u",
0292 cmd, (unsigned long long)lba,
0293 (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt);
0294
0295 if (SERVICE_ACTION32(cdb) == WRITE_SAME_32)
0296 trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1);
0297
0298 out:
0299 trace_seq_putc(p, 0);
0300 return ret;
0301 }
0302
0303 static const char *
0304 scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
0305 {
0306 const char *ret = p->buffer + p->len;
0307 unsigned int regions = cdb[7] << 8 | cdb[8];
0308
0309 trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
0310 trace_seq_putc(p, 0);
0311 return ret;
0312 }
0313
0314 static const char *
0315 scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
0316 {
0317 const char *ret = p->buffer + p->len, *cmd;
0318 sector_t lba = 0;
0319 u32 alloc_len = 0;
0320
0321 switch (SERVICE_ACTION16(cdb)) {
0322 case SAI_READ_CAPACITY_16:
0323 cmd = "READ_CAPACITY_16";
0324 break;
0325 case SAI_GET_LBA_STATUS:
0326 cmd = "GET_LBA_STATUS";
0327 break;
0328 default:
0329 trace_seq_printf(p, "UNKNOWN");
0330 goto out;
0331 }
0332
0333 lba |= ((u64)cdb[2] << 56);
0334 lba |= ((u64)cdb[3] << 48);
0335 lba |= ((u64)cdb[4] << 40);
0336 lba |= ((u64)cdb[5] << 32);
0337 lba |= (cdb[6] << 24);
0338 lba |= (cdb[7] << 16);
0339 lba |= (cdb[8] << 8);
0340 lba |= cdb[9];
0341 alloc_len |= (cdb[10] << 24);
0342 alloc_len |= (cdb[11] << 16);
0343 alloc_len |= (cdb[12] << 8);
0344 alloc_len |= cdb[13];
0345
0346 trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd,
0347 (unsigned long long)lba, alloc_len);
0348
0349 out:
0350 trace_seq_putc(p, 0);
0351 return ret;
0352 }
0353
0354 static const char *
0355 scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
0356 {
0357 switch (SERVICE_ACTION32(cdb)) {
0358 case READ_32:
0359 case VERIFY_32:
0360 case WRITE_32:
0361 case WRITE_SAME_32:
0362 return scsi_trace_rw32(p, cdb, len);
0363 default:
0364 return scsi_trace_misc(p, cdb, len);
0365 }
0366 }
0367
0368 static const char *
0369 scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
0370 {
0371 const char *ret = p->buffer + p->len;
0372
0373 trace_seq_printf(p, "-");
0374 trace_seq_putc(p, 0);
0375 return ret;
0376 }
0377
0378 const char *
0379 scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
0380 {
0381 switch (cdb[0]) {
0382 case READ_6:
0383 case WRITE_6:
0384 return scsi_trace_rw6(p, cdb, len);
0385 case READ_10:
0386 case VERIFY:
0387 case WRITE_10:
0388 case WRITE_SAME:
0389 return scsi_trace_rw10(p, cdb, len);
0390 case READ_12:
0391 case VERIFY_12:
0392 case WRITE_12:
0393 return scsi_trace_rw12(p, cdb, len);
0394 case READ_16:
0395 case VERIFY_16:
0396 case WRITE_16:
0397 case WRITE_SAME_16:
0398 return scsi_trace_rw16(p, cdb, len);
0399 case UNMAP:
0400 return scsi_trace_unmap(p, cdb, len);
0401 case SERVICE_ACTION_IN_16:
0402 return scsi_trace_service_action_in(p, cdb, len);
0403 case VARIABLE_LENGTH_CMD:
0404 return scsi_trace_varlen(p, cdb, len);
0405 default:
0406 return scsi_trace_misc(p, cdb, len);
0407 }
0408 }
0409
0410 unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s,
0411 unsigned long long *args)
0412 {
0413 scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]);
0414 return 0;
0415 }
0416
0417 int TEP_PLUGIN_LOADER(struct tep_handle *tep)
0418 {
0419 tep_register_print_function(tep,
0420 process_scsi_trace_parse_cdb,
0421 TEP_FUNC_ARG_STRING,
0422 "scsi_trace_parse_cdb",
0423 TEP_FUNC_ARG_PTR,
0424 TEP_FUNC_ARG_PTR,
0425 TEP_FUNC_ARG_INT,
0426 TEP_FUNC_ARG_VOID);
0427 return 0;
0428 }
0429
0430 void TEP_PLUGIN_UNLOADER(struct tep_handle *tep)
0431 {
0432 tep_unregister_print_function(tep, process_scsi_trace_parse_cdb,
0433 "scsi_trace_parse_cdb");
0434 }