]> granicus.if.org Git - strace/blob - scsi.c
tests: add support of multi-line diagnostics to check_h
[strace] / scsi.c
1 /*
2  * Copyright (c) 2007 Vladimir Nadvornik <nadvornik@suse.cz>
3  * Copyright (c) 2007-2018 Dmitry V. Levin <ldv@altlinux.org>
4  * Copyright (c) 2007-2019 The strace developers.
5  * All rights reserved.
6  *
7  * SPDX-License-Identifier: LGPL-2.1-or-later
8  */
9
10 #include "defs.h"
11
12 #ifdef HAVE_SCSI_SG_H
13 # include <scsi/sg.h>
14 #endif
15
16 #define XLAT_MACROS_ONLY
17 # include "xlat/scsi_sg_commands.h"
18 #undef XLAT_MACROS_ONLY
19 #include "xlat/sg_scsi_reset.h"
20
21 static int
22 decode_sg_io(struct tcb *const tcp, const uint32_t iid,
23              const kernel_ulong_t arg)
24 {
25         switch (iid) {
26                 case 'S':
27                         return decode_sg_io_v3(tcp, arg);
28                 case 'Q':
29                         return decode_sg_io_v4(tcp, arg);
30                 default:
31                         tprintf("[%u]", iid);
32                         return RVAL_IOCTL_DECODED;
33         }
34
35 }
36
37 #ifdef HAVE_SCSI_SG_H
38
39 static int
40 decode_sg_scsi_id(struct tcb *const tcp, const kernel_ulong_t arg)
41 {
42         struct sg_scsi_id id;
43
44         if (entering(tcp))
45                 return 0;
46
47         tprints(", ");
48         if (!umove_or_printaddr(tcp, arg, &id)) {
49                 tprintf("{host_no=%d"
50                         ", channel=%d"
51                         ", scsi_id=%#x"
52                         ", lun=%d"
53                         ", scsi_type=%#x"
54                         ", h_cmd_per_lun=%hd"
55                         ", d_queue_depth=%hd}",
56                         id.host_no,
57                         id.channel,
58                         id.scsi_id,
59                         id.lun,
60                         id.scsi_type,
61                         id.h_cmd_per_lun,
62                         id.d_queue_depth);
63         }
64         return RVAL_IOCTL_DECODED;
65 }
66
67 #endif /* HAVE_SCSI_SG_H */
68
69 int
70 scsi_ioctl(struct tcb *const tcp, const unsigned int code,
71            const kernel_ulong_t arg)
72 {
73         switch (code) {
74         case SG_IO:
75                 if (entering(tcp)) {
76                         uint32_t iid;
77
78                         tprints(", ");
79                         if (umove_or_printaddr(tcp, arg, &iid)) {
80                                 break;
81                         } else {
82                                 return decode_sg_io(tcp, iid, arg);
83                         }
84                 } else {
85                         uint32_t *piid = get_tcb_priv_data(tcp);
86                         if (piid)
87                                 decode_sg_io(tcp, *piid, arg);
88                         tprints("}");
89                         break;
90                 }
91
92 #ifdef HAVE_SCSI_SG_H
93         /* returns struct sg_scsi_id */
94         case SG_GET_SCSI_ID:
95                 return decode_sg_scsi_id(tcp, arg);
96         /* returns struct sg_req_info */
97         case SG_GET_REQUEST_TABLE:
98                 return decode_sg_req_info(tcp, arg);
99 #endif /* HAVE_SCSI_SG_H */
100
101         /* takes a value by pointer */
102         case SG_SCSI_RESET: {
103                 unsigned int val;
104                 tprints(", ");
105                 if (!umove_or_printaddr(tcp, arg, &val)) {
106                         tprints("[");
107                         if (val & SG_SCSI_RESET_NO_ESCALATE) {
108                                 printxval(sg_scsi_reset,
109                                           SG_SCSI_RESET_NO_ESCALATE, 0);
110                                 tprints("|");
111                         }
112                         printxval(sg_scsi_reset,
113                                   val & ~SG_SCSI_RESET_NO_ESCALATE,
114                                   "SG_SCSI_RESET_???");
115                         tprints("]");
116
117                 }
118                 break;
119         }
120
121         /* takes a signed int by pointer */
122         case SG_NEXT_CMD_LEN:
123         case SG_SET_COMMAND_Q:
124         case SG_SET_DEBUG:
125         case SG_SET_FORCE_LOW_DMA:
126         case SG_SET_FORCE_PACK_ID:
127         case SG_SET_KEEP_ORPHAN:
128         case SG_SET_RESERVED_SIZE:
129         case SG_SET_TIMEOUT:
130                 tprints(", ");
131                 printnum_int(tcp, arg, "%d");
132                 break;
133
134         /* returns a signed int by pointer */
135         case SG_EMULATED_HOST:
136         case SG_GET_ACCESS_COUNT:
137         case SG_GET_COMMAND_Q:
138         case SG_GET_KEEP_ORPHAN:
139         case SG_GET_LOW_DMA:
140         case SG_GET_NUM_WAITING:
141         case SG_GET_PACK_ID:
142         case SG_GET_RESERVED_SIZE:
143         case SG_GET_SG_TABLESIZE:
144         case SG_GET_TRANSFORM:
145         case SG_GET_VERSION_NUM:
146                 if (entering(tcp))
147                         return 0;
148                 tprints(", ");
149                 printnum_int(tcp, arg, "%d");
150                 break;
151
152         /* takes an integer by value */
153         case SG_SET_TRANSFORM:
154                 tprintf(", %#x", (unsigned int) arg);
155                 break;
156
157         /* no arguments */
158         case SG_GET_TIMEOUT:
159                 break;
160
161         default:
162                 return RVAL_DECODED;
163         }
164
165         return RVAL_IOCTL_DECODED;
166 }