blob: dc51dd571cd6af16da0953cd9229255110a4c212 [file] [log] [blame]
Dmitry V. Levin27aeaa22012-03-16 10:43:32 +00001/*
2 * Copyright (c) 2007 Vladimir Nadvornik <nadvornik@suse.cz>
3 * Copyright (c) 2007 Dmitry V. Levin <ldv@altlinux.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
Dmitry V. Levinb011af52007-06-30 11:37:09 +000029#include "defs.h"
Dmitry V. Levinfdb896e2014-02-25 23:04:55 +000030
31#ifdef HAVE_SCSI_SG_H
32
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +030033# include <linux/ioctl.h>
Dmitry V. Levinfdb896e2014-02-25 23:04:55 +000034# include <scsi/sg.h>
Dmitry V. Levinb011af52007-06-30 11:37:09 +000035
Bart Van Assche67d0a8e2015-02-06 13:37:03 +010036# include "xlat/sg_io_dxfer_direction.h"
37
38# ifdef HAVE_LINUX_BSG_H
39# include <linux/bsg.h>
40# include <sys/uio.h>
41# include "xlat/bsg_protocol.h"
42# include "xlat/bsg_subprotocol.h"
43# endif
Dmitry V. Levinb011af52007-06-30 11:37:09 +000044
Dmitry V. Levin48b06a62016-05-07 23:10:50 +000045static bool
46print_uchar(struct tcb *tcp, void *elem_buf, size_t elem_size, void *data)
Dmitry V. Levinb011af52007-06-30 11:37:09 +000047{
Dmitry V. Levin48b06a62016-05-07 23:10:50 +000048 tprintf("%02x", (unsigned int) (* (unsigned char *) elem_buf));
Dmitry V. Levinb011af52007-06-30 11:37:09 +000049
Dmitry V. Levin48b06a62016-05-07 23:10:50 +000050 return true;
51}
52
53static void
54print_sg_io_buffer(struct tcb *tcp, const unsigned long addr, const unsigned int len)
55{
56 unsigned char buf;
57
58 print_array(tcp, addr, len, &buf, sizeof(buf),
59 umoven_or_printaddr, print_uchar, 0);
Dmitry V. Levinb011af52007-06-30 11:37:09 +000060}
61
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +030062static int
63print_sg_io_v3_req(struct tcb *tcp, const long arg)
Dmitry V. Levinb011af52007-06-30 11:37:09 +000064{
Bart Van Assche67d0a8e2015-02-06 13:37:03 +010065 struct sg_io_hdr sg_io;
Dmitry V. Levinb011af52007-06-30 11:37:09 +000066
Bart Van Assche67d0a8e2015-02-06 13:37:03 +010067 if (umove(tcp, arg, &sg_io) < 0) {
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +030068 tprints("???}");
69 return RVAL_DECODED | 1;
Bart Van Assche67d0a8e2015-02-06 13:37:03 +010070 }
71
Bart Van Assche67d0a8e2015-02-06 13:37:03 +010072 printxval(sg_io_dxfer_direction, sg_io.dxfer_direction,
73 "SG_DXFER_???");
74 tprintf(", cmd[%u]=", sg_io.cmd_len);
75 print_sg_io_buffer(tcp, (unsigned long) sg_io.cmdp, sg_io.cmd_len);
76 tprintf(", mx_sb_len=%d", sg_io.mx_sb_len);
77 tprintf(", iovec_count=%d", sg_io.iovec_count);
78 tprintf(", dxfer_len=%u", sg_io.dxfer_len);
79 tprintf(", timeout=%u", sg_io.timeout);
80 tprintf(", flags=%#x", sg_io.flags);
81
82 if (sg_io.dxfer_direction == SG_DXFER_TO_DEV ||
83 sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
84 tprintf(", data[%u]=", sg_io.dxfer_len);
85 if (sg_io.iovec_count)
86 tprint_iov_upto(tcp, sg_io.iovec_count,
Fabien Siron2a54d8b2016-06-22 13:27:03 +000087 (unsigned long) sg_io.dxferp,
88 IOV_DECODE_STR,
Bart Van Assche67d0a8e2015-02-06 13:37:03 +010089 sg_io.dxfer_len);
Bart Van Assche791145e2015-02-06 13:36:26 +010090 else
Bart Van Assche67d0a8e2015-02-06 13:37:03 +010091 print_sg_io_buffer(tcp, (unsigned long) sg_io.dxferp,
92 sg_io.dxfer_len);
Dmitry V. Levinb011af52007-06-30 11:37:09 +000093 }
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +030094 return 1;
Dmitry V. Levinb011af52007-06-30 11:37:09 +000095}
96
97static void
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +030098print_sg_io_v3_res(struct tcb *tcp, const long arg)
Dmitry V. Levinb011af52007-06-30 11:37:09 +000099{
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100100 struct sg_io_hdr sg_io;
Bart Van Assche0014bb12015-02-06 13:36:26 +0100101
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100102 if (umove(tcp, arg, &sg_io) < 0) {
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300103 tprints(", ???");
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100104 return;
105 }
106
107 if (sg_io.dxfer_direction == SG_DXFER_FROM_DEV ||
108 sg_io.dxfer_direction == SG_DXFER_TO_FROM_DEV) {
109 uint32_t din_len = sg_io.dxfer_len;
110
111 if (sg_io.resid > 0)
112 din_len -= sg_io.resid;
Bart Van Assche791145e2015-02-06 13:36:26 +0100113 tprintf(", data[%u]=", din_len);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100114 if (sg_io.iovec_count)
115 tprint_iov_upto(tcp, sg_io.iovec_count,
Fabien Siron2a54d8b2016-06-22 13:27:03 +0000116 (unsigned long) sg_io.dxferp,
117 IOV_DECODE_STR,
Bart Van Assche791145e2015-02-06 13:36:26 +0100118 din_len);
119 else
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100120 print_sg_io_buffer(tcp, (unsigned long) sg_io.dxferp,
Bart Van Assche791145e2015-02-06 13:36:26 +0100121 din_len);
Dmitry V. Levinb011af52007-06-30 11:37:09 +0000122 }
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100123 tprintf(", status=%02x", sg_io.status);
124 tprintf(", masked_status=%02x", sg_io.masked_status);
125 tprintf(", sb[%u]=", sg_io.sb_len_wr);
126 print_sg_io_buffer(tcp, (unsigned long) sg_io.sbp, sg_io.sb_len_wr);
127 tprintf(", host_status=%#x", sg_io.host_status);
128 tprintf(", driver_status=%#x", sg_io.driver_status);
129 tprintf(", resid=%d", sg_io.resid);
130 tprintf(", duration=%d", sg_io.duration);
131 tprintf(", info=%#x", sg_io.info);
132}
133
134#ifdef HAVE_LINUX_BSG_H
135
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300136static int
137print_sg_io_v4_req(struct tcb *tcp, const long arg)
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100138{
139 struct sg_io_v4 sg_io;
140
141 if (umove(tcp, arg, &sg_io) < 0) {
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300142 tprints("???}");
143 return RVAL_DECODED | 1;
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100144 }
145
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100146 printxval(bsg_protocol, sg_io.protocol, "BSG_PROTOCOL_???");
147 tprints(", ");
148 printxval(bsg_subprotocol, sg_io.subprotocol, "BSG_SUB_PROTOCOL_???");
149 tprintf(", request[%u]=", sg_io.request_len);
150 print_sg_io_buffer(tcp, sg_io.request, sg_io.request_len);
Dmitry V. Levin51507202016-05-26 10:07:36 +0000151 tprintf(", request_tag=%" PRI__u64, sg_io.request_tag);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100152 tprintf(", request_attr=%u", sg_io.request_attr);
153 tprintf(", request_priority=%u", sg_io.request_priority);
154 tprintf(", request_extra=%u", sg_io.request_extra);
155 tprintf(", max_response_len=%u", sg_io.max_response_len);
156
157 tprintf(", dout_iovec_count=%u", sg_io.dout_iovec_count);
158 tprintf(", dout_xfer_len=%u", sg_io.dout_xfer_len);
159 tprintf(", din_iovec_count=%u", sg_io.din_iovec_count);
160 tprintf(", din_xfer_len=%u", sg_io.din_xfer_len);
161 tprintf(", timeout=%u", sg_io.timeout);
162 tprintf(", flags=%u", sg_io.flags);
Dmitry V. Levin51507202016-05-26 10:07:36 +0000163 tprintf(", usr_ptr=%" PRI__u64, sg_io.usr_ptr);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100164 tprintf(", spare_in=%u", sg_io.spare_in);
165 tprintf(", dout[%u]=", sg_io.dout_xfer_len);
166 if (sg_io.dout_iovec_count)
167 tprint_iov_upto(tcp, sg_io.dout_iovec_count, sg_io.dout_xferp,
Fabien Siron2a54d8b2016-06-22 13:27:03 +0000168 IOV_DECODE_STR, sg_io.dout_xfer_len);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100169 else
170 print_sg_io_buffer(tcp, sg_io.dout_xferp, sg_io.dout_xfer_len);
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300171 return 1;
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100172}
173
174static void
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300175print_sg_io_v4_res(struct tcb *tcp, const long arg)
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100176{
177 struct sg_io_v4 sg_io;
178 uint32_t din_len;
179
180 if (umove(tcp, arg, &sg_io) < 0) {
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300181 tprints(", ???");
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100182 return;
183 }
184
185 tprintf(", response[%u]=", sg_io.response_len);
186 print_sg_io_buffer(tcp, sg_io.response, sg_io.response_len);
187 din_len = sg_io.din_xfer_len;
188 if (sg_io.din_resid > 0)
189 din_len -= sg_io.din_resid;
190 tprintf(", din[%u]=", din_len);
191 if (sg_io.din_iovec_count)
192 tprint_iov_upto(tcp, sg_io.din_iovec_count, sg_io.din_xferp,
Fabien Siron2a54d8b2016-06-22 13:27:03 +0000193 IOV_DECODE_STR, din_len);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100194 else
195 print_sg_io_buffer(tcp, sg_io.din_xferp, din_len);
196 tprintf(", driver_status=%u", sg_io.driver_status);
197 tprintf(", transport_status=%u", sg_io.transport_status);
198 tprintf(", device_status=%u", sg_io.device_status);
199 tprintf(", retry_delay=%u", sg_io.retry_delay);
200 tprintf(", info=%u", sg_io.info);
201 tprintf(", duration=%u", sg_io.duration);
202 tprintf(", response_len=%u", sg_io.response_len);
203 tprintf(", din_resid=%u", sg_io.din_resid);
204 tprintf(", dout_resid=%u", sg_io.dout_resid);
Dmitry V. Levin51507202016-05-26 10:07:36 +0000205 tprintf(", generated_tag=%" PRI__u64, sg_io.generated_tag);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100206 tprintf(", spare_out=%u", sg_io.spare_out);
207}
208
209#else /* !HAVE_LINUX_BSG_H */
210
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300211static int
212print_sg_io_v4_req(struct tcb *tcp, const long arg)
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100213{
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300214 tprints("...}");
215 return RVAL_DECODED | 1;
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100216}
217
218static void
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300219print_sg_io_v4_res(struct tcb *tcp, const long arg)
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100220{
221}
222
223#endif
224
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300225static int
226print_sg_io_req(struct tcb *tcp, uint32_t iid, const long arg)
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100227{
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300228 tprintf("{'%c', ", iid);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100229
230 switch (iid) {
231 case 'S':
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300232 return print_sg_io_v3_req(tcp, arg);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100233 case 'Q':
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300234 return print_sg_io_v4_req(tcp, arg);
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100235 default:
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300236 tprints("...}");
237 return RVAL_DECODED | 1;
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100238 }
239
240}
241
242static void
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300243print_sg_io_res(struct tcb *tcp, uint32_t iid, const long arg)
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100244{
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300245 switch (iid) {
246 case 'S':
247 print_sg_io_v3_res(tcp, arg);
248 break;
249 case 'Q':
250 print_sg_io_v4_res(tcp, arg);
251 break;
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100252 }
Dmitry V. Levinb011af52007-06-30 11:37:09 +0000253}
254
255int
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300256scsi_ioctl(struct tcb *tcp, const unsigned int code, const long arg)
Dmitry V. Levinb011af52007-06-30 11:37:09 +0000257{
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100258 uint32_t iid;
259
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300260 if (SG_IO != code)
261 return RVAL_DECODED;
262
263 if (entering(tcp)) {
264 tprints(", ");
265 if (!arg || umove(tcp, arg, &iid) < 0) {
266 printaddr(arg);
267 return RVAL_DECODED | 1;
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100268 } else {
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300269 return print_sg_io_req(tcp, iid, arg);
270 }
271 } else {
272 if (!syserror(tcp)) {
273 if (umove(tcp, arg, &iid) < 0)
274 tprints(", ???");
275 else
Bart Van Assche67d0a8e2015-02-06 13:37:03 +0100276 print_sg_io_res(tcp, iid, arg);
Dmitry V. Levinb011af52007-06-30 11:37:09 +0000277 }
Dmitry V. Levin3d0e1f32015-07-07 21:38:07 +0300278 tprintf("}");
279 return RVAL_DECODED | 1;
Dmitry V. Levinb011af52007-06-30 11:37:09 +0000280 }
Dmitry V. Levinb011af52007-06-30 11:37:09 +0000281}
Dmitry V. Levinfdb896e2014-02-25 23:04:55 +0000282
283#endif /* HAVE_SCSI_SG_H */