2 * Copyright (c) 2007 Vladimir Nadvornik <nadvornik@suse.cz>
3 * Copyright (c) 2007-2018 Dmitry V. Levin <ldv@altlinux.org>
4 * Copyright (c) 2015 Bart Van Assche <bart.vanassche@sandisk.com>
7 * SPDX-License-Identifier: LGPL-2.1-or-later
14 # include DEF_MPERS_TYPE(struct_sg_io_hdr)
18 typedef struct sg_io_hdr struct_sg_io_hdr;
20 #endif /* HAVE_SCSI_SG_H */
24 #include "xlat/sg_io_info.h"
27 # include "print_fields.h"
28 # include "xlat/sg_io_dxfer_direction.h"
29 # include "xlat/sg_io_flags.h"
32 print_sg_io_buffer(struct tcb *const tcp, const kernel_ulong_t addr,
33 const unsigned int data_size, const unsigned int iovec_count)
36 tprint_iov_upto(tcp, iovec_count, addr, IOV_DECODE_STR,
39 printstr_ex(tcp, addr, data_size, QUOTE_FORCE_HEX);
43 # define PRINT_FIELD_SG_IO_BUFFER(prefix_, where_, field_, size_, count_, tcp_) \
45 STRACE_PRINTF("%s%s=", (prefix_), #field_); \
46 print_sg_io_buffer((tcp_), (mpers_ptr_t)((where_).field_), \
51 decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
53 struct_sg_io_hdr sg_io;
54 static const size_t skip_iid =
55 offsetof(struct_sg_io_hdr, dxfer_direction);
57 tprints("{interface_id='S', ");
58 if (umoven_or_printaddr(tcp, arg + skip_iid, sizeof(sg_io) - skip_iid,
59 &sg_io.dxfer_direction)) {
61 return RVAL_IOCTL_DECODED;
64 PRINT_FIELD_XVAL("", sg_io, dxfer_direction, sg_io_dxfer_direction,
66 PRINT_FIELD_U(", ", sg_io, cmd_len);
67 PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, cmdp, sg_io.cmd_len, 0, tcp);
68 PRINT_FIELD_U(", ", sg_io, mx_sb_len);
69 PRINT_FIELD_U(", ", sg_io, iovec_count);
70 PRINT_FIELD_U(", ", sg_io, dxfer_len);
71 PRINT_FIELD_U(", ", sg_io, timeout);
72 PRINT_FIELD_FLAGS(", ", sg_io, flags, sg_io_flags, "SG_FLAG_???");
74 if (sg_io.dxfer_direction == SG_DXFER_TO_DEV ||
75 sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
76 PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, dxferp, sg_io.dxfer_len, sg_io.iovec_count, tcp);
79 struct_sg_io_hdr *entering_sg_io = malloc(sizeof(*entering_sg_io));
81 memcpy(entering_sg_io, &sg_io, sizeof(sg_io));
82 entering_sg_io->interface_id = (unsigned char) 'S';
83 set_tcb_priv_data(tcp, entering_sg_io, free);
90 decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
92 struct_sg_io_hdr *entering_sg_io = get_tcb_priv_data(tcp);
93 struct_sg_io_hdr sg_io;
95 if (umove(tcp, arg, &sg_io) < 0) {
96 /* print i/o fields fetched on entering syscall */
97 if (entering_sg_io->dxfer_direction == SG_DXFER_FROM_DEV)
98 PRINT_FIELD_PTR(", ", *entering_sg_io, dxferp);
99 PRINT_FIELD_PTR(", ", *entering_sg_io, sbp);
100 return RVAL_IOCTL_DECODED;
103 if (sg_io.interface_id != entering_sg_io->interface_id) {
104 PRINT_FIELD_U(" => ", sg_io, interface_id);
105 return RVAL_IOCTL_DECODED;
108 if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV ||
109 sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
110 uint32_t din_len = sg_io.dxfer_len;
111 const char *prefix = NULL;
113 if (sg_io.resid > 0 && (unsigned int) sg_io.resid <= din_len)
114 din_len -= sg_io.resid;
116 if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV)
123 PRINT_FIELD_SG_IO_BUFFER("", sg_io, dxferp, din_len,
124 sg_io.iovec_count, tcp);
127 PRINT_FIELD_X(", ", sg_io, status);
128 PRINT_FIELD_X(", ", sg_io, masked_status);
129 PRINT_FIELD_X(", ", sg_io, msg_status);
130 PRINT_FIELD_U(", ", sg_io, sb_len_wr);
131 PRINT_FIELD_SG_IO_BUFFER(", ", sg_io, sbp, sg_io.sb_len_wr, 0, tcp);
132 PRINT_FIELD_X(", ", sg_io, host_status);
133 PRINT_FIELD_X(", ", sg_io, driver_status);
134 PRINT_FIELD_D(", ", sg_io, resid);
135 PRINT_FIELD_U(", ", sg_io, duration);
136 PRINT_FIELD_FLAGS(", ", sg_io, info, sg_io_info, "SG_INFO_???");
138 return RVAL_IOCTL_DECODED;
141 #else /* !HAVE_SCSI_SG_H */
144 decode_request(struct tcb *const tcp, const kernel_ulong_t arg)
146 tprints("{interface_id='S', ...}");
147 return RVAL_IOCTL_DECODED;
151 decode_response(struct tcb *const tcp, const kernel_ulong_t arg)
158 MPERS_PRINTER_DECL(int, decode_sg_io_v3,
159 struct tcb *const tcp, const kernel_ulong_t arg)
161 return entering(tcp) ? decode_request(tcp, arg)
162 : decode_response(tcp, arg);