Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1// SPDX-License-Identifier: GPL-2.0
  2#include <stdio.h>
  3#include <string.h>
  4#include <inttypes.h>
  5#include "event-parse.h"
  6
  7typedef unsigned long sector_t;
  8typedef uint64_t u64;
  9typedef unsigned int u32;
 10
 11/*
 12 *      SCSI opcodes
 13 */
 14#define TEST_UNIT_READY			0x00
 15#define REZERO_UNIT			0x01
 16#define REQUEST_SENSE			0x03
 17#define FORMAT_UNIT			0x04
 18#define READ_BLOCK_LIMITS		0x05
 19#define REASSIGN_BLOCKS			0x07
 20#define INITIALIZE_ELEMENT_STATUS	0x07
 21#define READ_6				0x08
 22#define WRITE_6				0x0a
 23#define SEEK_6				0x0b
 24#define READ_REVERSE			0x0f
 25#define WRITE_FILEMARKS			0x10
 26#define SPACE				0x11
 27#define INQUIRY				0x12
 28#define RECOVER_BUFFERED_DATA		0x14
 29#define MODE_SELECT			0x15
 30#define RESERVE				0x16
 31#define RELEASE				0x17
 32#define COPY				0x18
 33#define ERASE				0x19
 34#define MODE_SENSE			0x1a
 35#define START_STOP			0x1b
 36#define RECEIVE_DIAGNOSTIC		0x1c
 37#define SEND_DIAGNOSTIC			0x1d
 38#define ALLOW_MEDIUM_REMOVAL		0x1e
 39
 40#define READ_FORMAT_CAPACITIES		0x23
 41#define SET_WINDOW			0x24
 42#define READ_CAPACITY			0x25
 43#define READ_10				0x28
 44#define WRITE_10			0x2a
 45#define SEEK_10				0x2b
 46#define POSITION_TO_ELEMENT		0x2b
 47#define WRITE_VERIFY			0x2e
 48#define VERIFY				0x2f
 49#define SEARCH_HIGH			0x30
 50#define SEARCH_EQUAL			0x31
 51#define SEARCH_LOW			0x32
 52#define SET_LIMITS			0x33
 53#define PRE_FETCH			0x34
 54#define READ_POSITION			0x34
 55#define SYNCHRONIZE_CACHE		0x35
 56#define LOCK_UNLOCK_CACHE		0x36
 57#define READ_DEFECT_DATA		0x37
 58#define MEDIUM_SCAN			0x38
 59#define COMPARE				0x39
 60#define COPY_VERIFY			0x3a
 61#define WRITE_BUFFER			0x3b
 62#define READ_BUFFER			0x3c
 63#define UPDATE_BLOCK			0x3d
 64#define READ_LONG			0x3e
 65#define WRITE_LONG			0x3f
 66#define CHANGE_DEFINITION		0x40
 67#define WRITE_SAME			0x41
 68#define UNMAP				0x42
 69#define READ_TOC			0x43
 70#define READ_HEADER			0x44
 71#define GET_EVENT_STATUS_NOTIFICATION	0x4a
 72#define LOG_SELECT			0x4c
 73#define LOG_SENSE			0x4d
 74#define XDWRITEREAD_10			0x53
 75#define MODE_SELECT_10			0x55
 76#define RESERVE_10			0x56
 77#define RELEASE_10			0x57
 78#define MODE_SENSE_10			0x5a
 79#define PERSISTENT_RESERVE_IN		0x5e
 80#define PERSISTENT_RESERVE_OUT		0x5f
 81#define VARIABLE_LENGTH_CMD		0x7f
 82#define REPORT_LUNS			0xa0
 83#define SECURITY_PROTOCOL_IN		0xa2
 84#define MAINTENANCE_IN			0xa3
 85#define MAINTENANCE_OUT			0xa4
 86#define MOVE_MEDIUM			0xa5
 87#define EXCHANGE_MEDIUM			0xa6
 88#define READ_12				0xa8
 89#define SERVICE_ACTION_OUT_12		0xa9
 90#define WRITE_12			0xaa
 91#define SERVICE_ACTION_IN_12		0xab
 92#define WRITE_VERIFY_12			0xae
 93#define VERIFY_12			0xaf
 94#define SEARCH_HIGH_12			0xb0
 95#define SEARCH_EQUAL_12			0xb1
 96#define SEARCH_LOW_12			0xb2
 97#define SECURITY_PROTOCOL_OUT		0xb5
 98#define READ_ELEMENT_STATUS		0xb8
 99#define SEND_VOLUME_TAG			0xb6
100#define WRITE_LONG_2			0xea
101#define EXTENDED_COPY			0x83
102#define RECEIVE_COPY_RESULTS		0x84
103#define ACCESS_CONTROL_IN		0x86
104#define ACCESS_CONTROL_OUT		0x87
105#define READ_16				0x88
106#define WRITE_16			0x8a
107#define READ_ATTRIBUTE			0x8c
108#define WRITE_ATTRIBUTE			0x8d
109#define VERIFY_16			0x8f
110#define SYNCHRONIZE_CACHE_16		0x91
111#define WRITE_SAME_16			0x93
112#define SERVICE_ACTION_BIDIRECTIONAL	0x9d
113#define SERVICE_ACTION_IN_16		0x9e
114#define SERVICE_ACTION_OUT_16		0x9f
115/* values for service action in */
116#define	SAI_READ_CAPACITY_16		0x10
117#define SAI_GET_LBA_STATUS		0x12
118/* values for VARIABLE_LENGTH_CMD service action codes
119 * see spc4r17 Section D.3.5, table D.7 and D.8 */
120#define VLC_SA_RECEIVE_CREDENTIAL	0x1800
121/* values for maintenance in */
122#define MI_REPORT_IDENTIFYING_INFORMATION		0x05
123#define MI_REPORT_TARGET_PGS				0x0a
124#define MI_REPORT_ALIASES				0x0b
125#define MI_REPORT_SUPPORTED_OPERATION_CODES		0x0c
126#define MI_REPORT_SUPPORTED_TASK_MANAGEMENT_FUNCTIONS	0x0d
127#define MI_REPORT_PRIORITY				0x0e
128#define MI_REPORT_TIMESTAMP				0x0f
129#define MI_MANAGEMENT_PROTOCOL_IN			0x10
130/* value for MI_REPORT_TARGET_PGS ext header */
131#define MI_EXT_HDR_PARAM_FMT		0x20
132/* values for maintenance out */
133#define MO_SET_IDENTIFYING_INFORMATION	0x06
134#define MO_SET_TARGET_PGS		0x0a
135#define MO_CHANGE_ALIASES		0x0b
136#define MO_SET_PRIORITY			0x0e
137#define MO_SET_TIMESTAMP		0x0f
138#define MO_MANAGEMENT_PROTOCOL_OUT	0x10
139/* values for variable length command */
140#define XDREAD_32			0x03
141#define XDWRITE_32			0x04
142#define XPWRITE_32			0x06
143#define XDWRITEREAD_32			0x07
144#define READ_32				0x09
145#define VERIFY_32			0x0a
146#define WRITE_32			0x0b
147#define WRITE_SAME_32			0x0d
148
149#define SERVICE_ACTION16(cdb) (cdb[1] & 0x1f)
150#define SERVICE_ACTION32(cdb) ((cdb[8] << 8) | cdb[9])
151
152static const char *
153scsi_trace_misc(struct trace_seq *, unsigned char *, int);
154
155static const char *
156scsi_trace_rw6(struct trace_seq *p, unsigned char *cdb, int len)
157{
158	const char *ret = p->buffer + p->len;
159	sector_t lba = 0, txlen = 0;
160
161	lba |= ((cdb[1] & 0x1F) << 16);
162	lba |=  (cdb[2] << 8);
163	lba |=   cdb[3];
164	txlen = cdb[4];
165
166	trace_seq_printf(p, "lba=%llu txlen=%llu",
167			 (unsigned long long)lba, (unsigned long long)txlen);
168	trace_seq_putc(p, 0);
169	return ret;
170}
171
172static const char *
173scsi_trace_rw10(struct trace_seq *p, unsigned char *cdb, int len)
174{
175	const char *ret = p->buffer + p->len;
176	sector_t lba = 0, txlen = 0;
177
178	lba |= (cdb[2] << 24);
179	lba |= (cdb[3] << 16);
180	lba |= (cdb[4] << 8);
181	lba |=  cdb[5];
182	txlen |= (cdb[7] << 8);
183	txlen |=  cdb[8];
184
185	trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
186			 (unsigned long long)lba, (unsigned long long)txlen,
187			 cdb[1] >> 5);
188
189	if (cdb[0] == WRITE_SAME)
190		trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
191
192	trace_seq_putc(p, 0);
193	return ret;
194}
195
196static const char *
197scsi_trace_rw12(struct trace_seq *p, unsigned char *cdb, int len)
198{
199	const char *ret = p->buffer + p->len;
200	sector_t lba = 0, txlen = 0;
201
202	lba |= (cdb[2] << 24);
203	lba |= (cdb[3] << 16);
204	lba |= (cdb[4] << 8);
205	lba |=  cdb[5];
206	txlen |= (cdb[6] << 24);
207	txlen |= (cdb[7] << 16);
208	txlen |= (cdb[8] << 8);
209	txlen |=  cdb[9];
210
211	trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
212			 (unsigned long long)lba, (unsigned long long)txlen,
213			 cdb[1] >> 5);
214	trace_seq_putc(p, 0);
215	return ret;
216}
217
218static const char *
219scsi_trace_rw16(struct trace_seq *p, unsigned char *cdb, int len)
220{
221	const char *ret = p->buffer + p->len;
222	sector_t lba = 0, txlen = 0;
223
224	lba |= ((u64)cdb[2] << 56);
225	lba |= ((u64)cdb[3] << 48);
226	lba |= ((u64)cdb[4] << 40);
227	lba |= ((u64)cdb[5] << 32);
228	lba |= (cdb[6] << 24);
229	lba |= (cdb[7] << 16);
230	lba |= (cdb[8] << 8);
231	lba |=  cdb[9];
232	txlen |= (cdb[10] << 24);
233	txlen |= (cdb[11] << 16);
234	txlen |= (cdb[12] << 8);
235	txlen |=  cdb[13];
236
237	trace_seq_printf(p, "lba=%llu txlen=%llu protect=%u",
238			 (unsigned long long)lba, (unsigned long long)txlen,
239			 cdb[1] >> 5);
240
241	if (cdb[0] == WRITE_SAME_16)
242		trace_seq_printf(p, " unmap=%u", cdb[1] >> 3 & 1);
243
244	trace_seq_putc(p, 0);
245	return ret;
246}
247
248static const char *
249scsi_trace_rw32(struct trace_seq *p, unsigned char *cdb, int len)
250{
251	const char *ret = p->buffer + p->len, *cmd;
252	sector_t lba = 0, txlen = 0;
253	u32 ei_lbrt = 0;
254
255	switch (SERVICE_ACTION32(cdb)) {
256	case READ_32:
257		cmd = "READ";
258		break;
259	case VERIFY_32:
260		cmd = "VERIFY";
261		break;
262	case WRITE_32:
263		cmd = "WRITE";
264		break;
265	case WRITE_SAME_32:
266		cmd = "WRITE_SAME";
267		break;
268	default:
269		trace_seq_printf(p, "UNKNOWN");
270		goto out;
271	}
272
273	lba |= ((u64)cdb[12] << 56);
274	lba |= ((u64)cdb[13] << 48);
275	lba |= ((u64)cdb[14] << 40);
276	lba |= ((u64)cdb[15] << 32);
277	lba |= (cdb[16] << 24);
278	lba |= (cdb[17] << 16);
279	lba |= (cdb[18] << 8);
280	lba |=  cdb[19];
281	ei_lbrt |= (cdb[20] << 24);
282	ei_lbrt |= (cdb[21] << 16);
283	ei_lbrt |= (cdb[22] << 8);
284	ei_lbrt |=  cdb[23];
285	txlen |= (cdb[28] << 24);
286	txlen |= (cdb[29] << 16);
287	txlen |= (cdb[30] << 8);
288	txlen |=  cdb[31];
289
290	trace_seq_printf(p, "%s_32 lba=%llu txlen=%llu protect=%u ei_lbrt=%u",
291			 cmd, (unsigned long long)lba,
292			 (unsigned long long)txlen, cdb[10] >> 5, ei_lbrt);
293
294	if (SERVICE_ACTION32(cdb) == WRITE_SAME_32)
295		trace_seq_printf(p, " unmap=%u", cdb[10] >> 3 & 1);
296
297out:
298	trace_seq_putc(p, 0);
299	return ret;
300}
301
302static const char *
303scsi_trace_unmap(struct trace_seq *p, unsigned char *cdb, int len)
304{
305	const char *ret = p->buffer + p->len;
306	unsigned int regions = cdb[7] << 8 | cdb[8];
307
308	trace_seq_printf(p, "regions=%u", (regions - 8) / 16);
309	trace_seq_putc(p, 0);
310	return ret;
311}
312
313static const char *
314scsi_trace_service_action_in(struct trace_seq *p, unsigned char *cdb, int len)
315{
316	const char *ret = p->buffer + p->len, *cmd;
317	sector_t lba = 0;
318	u32 alloc_len = 0;
319
320	switch (SERVICE_ACTION16(cdb)) {
321	case SAI_READ_CAPACITY_16:
322		cmd = "READ_CAPACITY_16";
323		break;
324	case SAI_GET_LBA_STATUS:
325		cmd = "GET_LBA_STATUS";
326		break;
327	default:
328		trace_seq_printf(p, "UNKNOWN");
329		goto out;
330	}
331
332	lba |= ((u64)cdb[2] << 56);
333	lba |= ((u64)cdb[3] << 48);
334	lba |= ((u64)cdb[4] << 40);
335	lba |= ((u64)cdb[5] << 32);
336	lba |= (cdb[6] << 24);
337	lba |= (cdb[7] << 16);
338	lba |= (cdb[8] << 8);
339	lba |=  cdb[9];
340	alloc_len |= (cdb[10] << 24);
341	alloc_len |= (cdb[11] << 16);
342	alloc_len |= (cdb[12] << 8);
343	alloc_len |=  cdb[13];
344
345	trace_seq_printf(p, "%s lba=%llu alloc_len=%u", cmd,
346			 (unsigned long long)lba, alloc_len);
347
348out:
349	trace_seq_putc(p, 0);
350	return ret;
351}
352
353static const char *
354scsi_trace_varlen(struct trace_seq *p, unsigned char *cdb, int len)
355{
356	switch (SERVICE_ACTION32(cdb)) {
357	case READ_32:
358	case VERIFY_32:
359	case WRITE_32:
360	case WRITE_SAME_32:
361		return scsi_trace_rw32(p, cdb, len);
362	default:
363		return scsi_trace_misc(p, cdb, len);
364	}
365}
366
367static const char *
368scsi_trace_misc(struct trace_seq *p, unsigned char *cdb, int len)
369{
370	const char *ret = p->buffer + p->len;
371
372	trace_seq_printf(p, "-");
373	trace_seq_putc(p, 0);
374	return ret;
375}
376
377const char *
378scsi_trace_parse_cdb(struct trace_seq *p, unsigned char *cdb, int len)
379{
380	switch (cdb[0]) {
381	case READ_6:
382	case WRITE_6:
383		return scsi_trace_rw6(p, cdb, len);
384	case READ_10:
385	case VERIFY:
386	case WRITE_10:
387	case WRITE_SAME:
388		return scsi_trace_rw10(p, cdb, len);
389	case READ_12:
390	case VERIFY_12:
391	case WRITE_12:
392		return scsi_trace_rw12(p, cdb, len);
393	case READ_16:
394	case VERIFY_16:
395	case WRITE_16:
396	case WRITE_SAME_16:
397		return scsi_trace_rw16(p, cdb, len);
398	case UNMAP:
399		return scsi_trace_unmap(p, cdb, len);
400	case SERVICE_ACTION_IN_16:
401		return scsi_trace_service_action_in(p, cdb, len);
402	case VARIABLE_LENGTH_CMD:
403		return scsi_trace_varlen(p, cdb, len);
404	default:
405		return scsi_trace_misc(p, cdb, len);
406	}
407}
408
409unsigned long long process_scsi_trace_parse_cdb(struct trace_seq *s,
410						unsigned long long *args)
411{
412	scsi_trace_parse_cdb(s, (unsigned char *) (unsigned long) args[1], args[2]);
413	return 0;
414}
415
416int PEVENT_PLUGIN_LOADER(struct pevent *pevent)
417{
418	pevent_register_print_function(pevent,
419				       process_scsi_trace_parse_cdb,
420				       PEVENT_FUNC_ARG_STRING,
421				       "scsi_trace_parse_cdb",
422				       PEVENT_FUNC_ARG_PTR,
423				       PEVENT_FUNC_ARG_PTR,
424				       PEVENT_FUNC_ARG_INT,
425				       PEVENT_FUNC_ARG_VOID);
426	return 0;
427}
428
429void PEVENT_PLUGIN_UNLOADER(struct pevent *pevent)
430{
431	pevent_unregister_print_function(pevent, process_scsi_trace_parse_cdb,
432					 "scsi_trace_parse_cdb");
433}