1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche * Copyright (c) 2008-2021 Douglas Gilbert.
3*44704f69SBart Van Assche * All rights reserved.
4*44704f69SBart Van Assche * Use of this source code is governed by a BSD-style
5*44704f69SBart Van Assche * license that can be found in the BSD_LICENSE file.
6*44704f69SBart Van Assche *
7*44704f69SBart Van Assche * SPDX-License-Identifier: BSD-2-Clause
8*44704f69SBart Van Assche */
9*44704f69SBart Van Assche
10*44704f69SBart Van Assche #include <stdio.h>
11*44704f69SBart Van Assche #include <stdlib.h>
12*44704f69SBart Van Assche #include <stdarg.h>
13*44704f69SBart Van Assche #include <string.h>
14*44704f69SBart Van Assche #include <unistd.h>
15*44704f69SBart Van Assche #define __STDC_FORMAT_MACROS 1
16*44704f69SBart Van Assche #include <inttypes.h>
17*44704f69SBart Van Assche
18*44704f69SBart Van Assche #ifdef HAVE_CONFIG_H
19*44704f69SBart Van Assche #include "config.h"
20*44704f69SBart Van Assche #endif
21*44704f69SBart Van Assche
22*44704f69SBart Van Assche #include "sg_lib.h"
23*44704f69SBart Van Assche #include "sg_cmds_basic.h"
24*44704f69SBart Van Assche #include "sg_cmds_mmc.h"
25*44704f69SBart Van Assche #include "sg_pt.h"
26*44704f69SBart Van Assche #include "sg_unaligned.h"
27*44704f69SBart Van Assche #include "sg_pr2serr.h"
28*44704f69SBart Van Assche
29*44704f69SBart Van Assche
30*44704f69SBart Van Assche #define SENSE_BUFF_LEN 64 /* Arbitrary, could be larger */
31*44704f69SBart Van Assche
32*44704f69SBart Van Assche #define DEF_PT_TIMEOUT 60 /* 60 seconds */
33*44704f69SBart Van Assche
34*44704f69SBart Van Assche #define GET_CONFIG_CMD 0x46
35*44704f69SBart Van Assche #define GET_CONFIG_CMD_LEN 10
36*44704f69SBart Van Assche #define GET_PERFORMANCE_CMD 0xac
37*44704f69SBart Van Assche #define GET_PERFORMANCE_CMD_LEN 12
38*44704f69SBart Van Assche #define SET_CD_SPEED_CMD 0xbb
39*44704f69SBart Van Assche #define SET_CD_SPEED_CMDLEN 12
40*44704f69SBart Van Assche #define SET_STREAMING_CMD 0xb6
41*44704f69SBart Van Assche #define SET_STREAMING_CMDLEN 12
42*44704f69SBart Van Assche
43*44704f69SBart Van Assche
44*44704f69SBart Van Assche static struct sg_pt_base *
create_pt_obj(const char * cname)45*44704f69SBart Van Assche create_pt_obj(const char * cname)
46*44704f69SBart Van Assche {
47*44704f69SBart Van Assche struct sg_pt_base * ptvp = construct_scsi_pt_obj();
48*44704f69SBart Van Assche if (NULL == ptvp)
49*44704f69SBart Van Assche pr2ws("%s: out of memory\n", cname);
50*44704f69SBart Van Assche return ptvp;
51*44704f69SBart Van Assche }
52*44704f69SBart Van Assche
53*44704f69SBart Van Assche /* Invokes a SCSI SET CD SPEED command (MMC).
54*44704f69SBart Van Assche * Return of 0 -> success, SG_LIB_CAT_INVALID_OP -> command not supported,
55*44704f69SBart Van Assche * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_UNIT_ATTENTION,
56*44704f69SBart Van Assche * SG_LIB_CAT_NOT_READY -> device not ready, SG_LIB_CAT_ABORTED_COMMAND,
57*44704f69SBart Van Assche * -1 -> other failure */
58*44704f69SBart Van Assche int
sg_ll_set_cd_speed(int sg_fd,int rot_control,int drv_read_speed,int drv_write_speed,bool noisy,int verbose)59*44704f69SBart Van Assche sg_ll_set_cd_speed(int sg_fd, int rot_control, int drv_read_speed,
60*44704f69SBart Van Assche int drv_write_speed, bool noisy, int verbose)
61*44704f69SBart Van Assche {
62*44704f69SBart Van Assche static const char * const cdb_s = "set cd speed";
63*44704f69SBart Van Assche int res, ret, sense_cat;
64*44704f69SBart Van Assche uint8_t scsCmdBlk[SET_CD_SPEED_CMDLEN] = {SET_CD_SPEED_CMD, 0,
65*44704f69SBart Van Assche 0, 0, 0, 0, 0, 0, 0, 0, 0 ,0};
66*44704f69SBart Van Assche uint8_t sense_b[SENSE_BUFF_LEN];
67*44704f69SBart Van Assche struct sg_pt_base * ptvp;
68*44704f69SBart Van Assche
69*44704f69SBart Van Assche scsCmdBlk[1] |= (rot_control & 0x3);
70*44704f69SBart Van Assche sg_put_unaligned_be16((uint16_t)drv_read_speed, scsCmdBlk + 2);
71*44704f69SBart Van Assche sg_put_unaligned_be16((uint16_t)drv_write_speed, scsCmdBlk + 4);
72*44704f69SBart Van Assche
73*44704f69SBart Van Assche if (verbose) {
74*44704f69SBart Van Assche int k;
75*44704f69SBart Van Assche
76*44704f69SBart Van Assche pr2ws(" %s cdb: ", cdb_s);
77*44704f69SBart Van Assche for (k = 0; k < SET_CD_SPEED_CMDLEN; ++k)
78*44704f69SBart Van Assche pr2ws("%02x ", scsCmdBlk[k]);
79*44704f69SBart Van Assche pr2ws("\n");
80*44704f69SBart Van Assche }
81*44704f69SBart Van Assche if (NULL == ((ptvp = create_pt_obj(cdb_s))))
82*44704f69SBart Van Assche return -1;
83*44704f69SBart Van Assche set_scsi_pt_cdb(ptvp, scsCmdBlk, sizeof(scsCmdBlk));
84*44704f69SBart Van Assche set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
85*44704f69SBart Van Assche res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
86*44704f69SBart Van Assche ret = sg_cmds_process_resp(ptvp, cdb_s, res, noisy, verbose, &sense_cat);
87*44704f69SBart Van Assche if (-1 == ret) {
88*44704f69SBart Van Assche if (get_scsi_pt_transport_err(ptvp))
89*44704f69SBart Van Assche ret = SG_LIB_TRANSPORT_ERROR;
90*44704f69SBart Van Assche else
91*44704f69SBart Van Assche ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
92*44704f69SBart Van Assche } else if (-2 == ret) {
93*44704f69SBart Van Assche switch (sense_cat) {
94*44704f69SBart Van Assche case SG_LIB_CAT_NOT_READY:
95*44704f69SBart Van Assche case SG_LIB_CAT_UNIT_ATTENTION:
96*44704f69SBart Van Assche case SG_LIB_CAT_INVALID_OP:
97*44704f69SBart Van Assche case SG_LIB_CAT_ILLEGAL_REQ:
98*44704f69SBart Van Assche case SG_LIB_CAT_ABORTED_COMMAND:
99*44704f69SBart Van Assche ret = sense_cat;
100*44704f69SBart Van Assche break;
101*44704f69SBart Van Assche case SG_LIB_CAT_RECOVERED:
102*44704f69SBart Van Assche case SG_LIB_CAT_NO_SENSE:
103*44704f69SBart Van Assche ret = 0;
104*44704f69SBart Van Assche break;
105*44704f69SBart Van Assche default:
106*44704f69SBart Van Assche ret = -1;
107*44704f69SBart Van Assche break;
108*44704f69SBart Van Assche }
109*44704f69SBart Van Assche } else
110*44704f69SBart Van Assche ret = 0;
111*44704f69SBart Van Assche
112*44704f69SBart Van Assche destruct_scsi_pt_obj(ptvp);
113*44704f69SBart Van Assche return ret;
114*44704f69SBart Van Assche }
115*44704f69SBart Van Assche
116*44704f69SBart Van Assche /* Invokes a SCSI GET CONFIGURATION command (MMC-3,4,5).
117*44704f69SBart Van Assche * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not
118*44704f69SBart Van Assche * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported,
119*44704f69SBart Van Assche * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */
120*44704f69SBart Van Assche int
sg_ll_get_config(int sg_fd,int rt,int starting,void * resp,int mx_resp_len,bool noisy,int verbose)121*44704f69SBart Van Assche sg_ll_get_config(int sg_fd, int rt, int starting, void * resp,
122*44704f69SBart Van Assche int mx_resp_len, bool noisy, int verbose)
123*44704f69SBart Van Assche {
124*44704f69SBart Van Assche static const char * const cdb_s = "get configuration";
125*44704f69SBart Van Assche int res, ret, sense_cat;
126*44704f69SBart Van Assche uint8_t gcCmdBlk[GET_CONFIG_CMD_LEN] = {GET_CONFIG_CMD, 0, 0, 0,
127*44704f69SBart Van Assche 0, 0, 0, 0, 0, 0};
128*44704f69SBart Van Assche uint8_t sense_b[SENSE_BUFF_LEN];
129*44704f69SBart Van Assche struct sg_pt_base * ptvp;
130*44704f69SBart Van Assche
131*44704f69SBart Van Assche if ((rt < 0) || (rt > 3)) {
132*44704f69SBart Van Assche pr2ws("Bad rt value: %d\n", rt);
133*44704f69SBart Van Assche return -1;
134*44704f69SBart Van Assche }
135*44704f69SBart Van Assche gcCmdBlk[1] = (rt & 0x3);
136*44704f69SBart Van Assche if ((starting < 0) || (starting > 0xffff)) {
137*44704f69SBart Van Assche pr2ws("Bad starting field number: 0x%x\n", starting);
138*44704f69SBart Van Assche return -1;
139*44704f69SBart Van Assche }
140*44704f69SBart Van Assche sg_put_unaligned_be16((uint16_t)starting, gcCmdBlk + 2);
141*44704f69SBart Van Assche if ((mx_resp_len < 0) || (mx_resp_len > 0xffff)) {
142*44704f69SBart Van Assche pr2ws("Bad mx_resp_len: 0x%x\n", starting);
143*44704f69SBart Van Assche return -1;
144*44704f69SBart Van Assche }
145*44704f69SBart Van Assche sg_put_unaligned_be16((uint16_t)mx_resp_len, gcCmdBlk + 7);
146*44704f69SBart Van Assche
147*44704f69SBart Van Assche if (verbose) {
148*44704f69SBart Van Assche int k;
149*44704f69SBart Van Assche
150*44704f69SBart Van Assche pr2ws(" %s cdb: ", cdb_s);
151*44704f69SBart Van Assche for (k = 0; k < GET_CONFIG_CMD_LEN; ++k)
152*44704f69SBart Van Assche pr2ws("%02x ", gcCmdBlk[k]);
153*44704f69SBart Van Assche pr2ws("\n");
154*44704f69SBart Van Assche }
155*44704f69SBart Van Assche
156*44704f69SBart Van Assche if (NULL == ((ptvp = create_pt_obj(cdb_s))))
157*44704f69SBart Van Assche return -1;
158*44704f69SBart Van Assche set_scsi_pt_cdb(ptvp, gcCmdBlk, sizeof(gcCmdBlk));
159*44704f69SBart Van Assche set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
160*44704f69SBart Van Assche set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
161*44704f69SBart Van Assche res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
162*44704f69SBart Van Assche ret = sg_cmds_process_resp(ptvp, cdb_s, res, noisy, verbose, &sense_cat);
163*44704f69SBart Van Assche if (-1 == ret) {
164*44704f69SBart Van Assche if (get_scsi_pt_transport_err(ptvp))
165*44704f69SBart Van Assche ret = SG_LIB_TRANSPORT_ERROR;
166*44704f69SBart Van Assche else
167*44704f69SBart Van Assche ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
168*44704f69SBart Van Assche } else if (-2 == ret) {
169*44704f69SBart Van Assche switch (sense_cat) {
170*44704f69SBart Van Assche case SG_LIB_CAT_INVALID_OP:
171*44704f69SBart Van Assche case SG_LIB_CAT_ILLEGAL_REQ:
172*44704f69SBart Van Assche case SG_LIB_CAT_UNIT_ATTENTION:
173*44704f69SBart Van Assche case SG_LIB_CAT_ABORTED_COMMAND:
174*44704f69SBart Van Assche ret = sense_cat;
175*44704f69SBart Van Assche break;
176*44704f69SBart Van Assche case SG_LIB_CAT_RECOVERED:
177*44704f69SBart Van Assche case SG_LIB_CAT_NO_SENSE:
178*44704f69SBart Van Assche ret = 0;
179*44704f69SBart Van Assche break;
180*44704f69SBart Van Assche default:
181*44704f69SBart Van Assche ret = -1;
182*44704f69SBart Van Assche break;
183*44704f69SBart Van Assche }
184*44704f69SBart Van Assche } else {
185*44704f69SBart Van Assche if ((verbose > 2) && (ret > 3)) {
186*44704f69SBart Van Assche uint8_t * bp;
187*44704f69SBart Van Assche int len;
188*44704f69SBart Van Assche
189*44704f69SBart Van Assche bp = (uint8_t *)resp;
190*44704f69SBart Van Assche len = sg_get_unaligned_be32(bp + 0);
191*44704f69SBart Van Assche if (len < 0)
192*44704f69SBart Van Assche len = 0;
193*44704f69SBart Van Assche len = (ret < len) ? ret : len;
194*44704f69SBart Van Assche pr2ws(" %s: response:\n", cdb_s);
195*44704f69SBart Van Assche if (3 == verbose) {
196*44704f69SBart Van Assche pr2ws("%s:\n", (len > 256 ? ", first 256 bytes" : ""));
197*44704f69SBart Van Assche hex2stderr((const uint8_t *)resp, (len > 256 ? 256 : len),
198*44704f69SBart Van Assche -1);
199*44704f69SBart Van Assche } else {
200*44704f69SBart Van Assche pr2ws(":\n");
201*44704f69SBart Van Assche hex2stderr((const uint8_t *)resp, len, 0);
202*44704f69SBart Van Assche }
203*44704f69SBart Van Assche }
204*44704f69SBart Van Assche ret = 0;
205*44704f69SBart Van Assche }
206*44704f69SBart Van Assche destruct_scsi_pt_obj(ptvp);
207*44704f69SBart Van Assche return ret;
208*44704f69SBart Van Assche }
209*44704f69SBart Van Assche
210*44704f69SBart Van Assche /* Invokes a SCSI GET PERFORMANCE command (MMC-3...6).
211*44704f69SBart Van Assche * Returns 0 when successful, SG_LIB_CAT_INVALID_OP if command not
212*44704f69SBart Van Assche * supported, SG_LIB_CAT_ILLEGAL_REQ if field in cdb not supported,
213*44704f69SBart Van Assche * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_ABORTED_COMMAND, else -1 */
214*44704f69SBart Van Assche int
sg_ll_get_performance(int sg_fd,int data_type,unsigned int starting_lba,int max_num_desc,int ttype,void * resp,int mx_resp_len,bool noisy,int verbose)215*44704f69SBart Van Assche sg_ll_get_performance(int sg_fd, int data_type, unsigned int starting_lba,
216*44704f69SBart Van Assche int max_num_desc, int ttype, void * resp,
217*44704f69SBart Van Assche int mx_resp_len, bool noisy, int verbose)
218*44704f69SBart Van Assche {
219*44704f69SBart Van Assche static const char * const cdb_s = "get performance";
220*44704f69SBart Van Assche int res, ret, sense_cat;
221*44704f69SBart Van Assche uint8_t gpCmdBlk[GET_PERFORMANCE_CMD_LEN] = {GET_PERFORMANCE_CMD, 0,
222*44704f69SBart Van Assche 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
223*44704f69SBart Van Assche uint8_t sense_b[SENSE_BUFF_LEN];
224*44704f69SBart Van Assche struct sg_pt_base * ptvp;
225*44704f69SBart Van Assche
226*44704f69SBart Van Assche if ((data_type < 0) || (data_type > 0x1f)) {
227*44704f69SBart Van Assche pr2ws("Bad data_type value: %d\n", data_type);
228*44704f69SBart Van Assche return -1;
229*44704f69SBart Van Assche }
230*44704f69SBart Van Assche gpCmdBlk[1] = (data_type & 0x1f);
231*44704f69SBart Van Assche sg_put_unaligned_be32((uint32_t)starting_lba, gpCmdBlk + 2);
232*44704f69SBart Van Assche if ((max_num_desc < 0) || (max_num_desc > 0xffff)) {
233*44704f69SBart Van Assche pr2ws("Bad max_num_desc: 0x%x\n", max_num_desc);
234*44704f69SBart Van Assche return -1;
235*44704f69SBart Van Assche }
236*44704f69SBart Van Assche sg_put_unaligned_be16((uint16_t)max_num_desc, gpCmdBlk + 8);
237*44704f69SBart Van Assche if ((ttype < 0) || (ttype > 0xff)) {
238*44704f69SBart Van Assche pr2ws("Bad type: 0x%x\n", ttype);
239*44704f69SBart Van Assche return -1;
240*44704f69SBart Van Assche }
241*44704f69SBart Van Assche gpCmdBlk[10] = (uint8_t)ttype;
242*44704f69SBart Van Assche
243*44704f69SBart Van Assche if (verbose) {
244*44704f69SBart Van Assche int k;
245*44704f69SBart Van Assche
246*44704f69SBart Van Assche pr2ws(" %s cdb: ", cdb_s);
247*44704f69SBart Van Assche for (k = 0; k < GET_PERFORMANCE_CMD_LEN; ++k)
248*44704f69SBart Van Assche pr2ws("%02x ", gpCmdBlk[k]);
249*44704f69SBart Van Assche pr2ws("\n");
250*44704f69SBart Van Assche }
251*44704f69SBart Van Assche
252*44704f69SBart Van Assche if (NULL == ((ptvp = create_pt_obj(cdb_s))))
253*44704f69SBart Van Assche return -1;
254*44704f69SBart Van Assche set_scsi_pt_cdb(ptvp, gpCmdBlk, sizeof(gpCmdBlk));
255*44704f69SBart Van Assche set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
256*44704f69SBart Van Assche set_scsi_pt_data_in(ptvp, (uint8_t *)resp, mx_resp_len);
257*44704f69SBart Van Assche res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
258*44704f69SBart Van Assche ret = sg_cmds_process_resp(ptvp, cdb_s, res, noisy, verbose, &sense_cat);
259*44704f69SBart Van Assche if (-1 == ret) {
260*44704f69SBart Van Assche if (get_scsi_pt_transport_err(ptvp))
261*44704f69SBart Van Assche ret = SG_LIB_TRANSPORT_ERROR;
262*44704f69SBart Van Assche else
263*44704f69SBart Van Assche ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
264*44704f69SBart Van Assche } else if (-2 == ret) {
265*44704f69SBart Van Assche switch (sense_cat) {
266*44704f69SBart Van Assche case SG_LIB_CAT_INVALID_OP:
267*44704f69SBart Van Assche case SG_LIB_CAT_ILLEGAL_REQ:
268*44704f69SBart Van Assche case SG_LIB_CAT_UNIT_ATTENTION:
269*44704f69SBart Van Assche case SG_LIB_CAT_ABORTED_COMMAND:
270*44704f69SBart Van Assche ret = sense_cat;
271*44704f69SBart Van Assche break;
272*44704f69SBart Van Assche case SG_LIB_CAT_RECOVERED:
273*44704f69SBart Van Assche case SG_LIB_CAT_NO_SENSE:
274*44704f69SBart Van Assche ret = 0;
275*44704f69SBart Van Assche break;
276*44704f69SBart Van Assche default:
277*44704f69SBart Van Assche ret = -1;
278*44704f69SBart Van Assche break;
279*44704f69SBart Van Assche }
280*44704f69SBart Van Assche } else {
281*44704f69SBart Van Assche if ((verbose > 2) && (ret > 3)) {
282*44704f69SBart Van Assche uint8_t * bp;
283*44704f69SBart Van Assche int len;
284*44704f69SBart Van Assche
285*44704f69SBart Van Assche bp = (uint8_t *)resp;
286*44704f69SBart Van Assche len = sg_get_unaligned_be32(bp + 0);
287*44704f69SBart Van Assche if (len < 0)
288*44704f69SBart Van Assche len = 0;
289*44704f69SBart Van Assche len = (ret < len) ? ret : len;
290*44704f69SBart Van Assche pr2ws(" %s: response", cdb_s);
291*44704f69SBart Van Assche if (3 == verbose) {
292*44704f69SBart Van Assche pr2ws("%s:\n", (len > 256 ? ", first 256 bytes" : ""));
293*44704f69SBart Van Assche hex2stderr((const uint8_t *)resp, (len > 256 ? 256 : len),
294*44704f69SBart Van Assche -1);
295*44704f69SBart Van Assche } else {
296*44704f69SBart Van Assche pr2ws(":\n");
297*44704f69SBart Van Assche hex2stderr((const uint8_t *)resp, len, 0);
298*44704f69SBart Van Assche }
299*44704f69SBart Van Assche }
300*44704f69SBart Van Assche ret = 0;
301*44704f69SBart Van Assche }
302*44704f69SBart Van Assche destruct_scsi_pt_obj(ptvp);
303*44704f69SBart Van Assche return ret;
304*44704f69SBart Van Assche }
305*44704f69SBart Van Assche
306*44704f69SBart Van Assche /* Invokes a SCSI SET STREAMING command (MMC). Return of 0 -> success,
307*44704f69SBart Van Assche * SG_LIB_CAT_INVALID_OP -> Set Streaming not supported,
308*44704f69SBart Van Assche * SG_LIB_CAT_ILLEGAL_REQ -> bad field in cdb, SG_LIB_CAT_ABORTED_COMMAND,
309*44704f69SBart Van Assche * SG_LIB_CAT_UNIT_ATTENTION, SG_LIB_CAT_NOT_READY -> device not ready,
310*44704f69SBart Van Assche * -1 -> other failure */
311*44704f69SBart Van Assche int
sg_ll_set_streaming(int sg_fd,int type,void * paramp,int param_len,bool noisy,int verbose)312*44704f69SBart Van Assche sg_ll_set_streaming(int sg_fd, int type, void * paramp, int param_len,
313*44704f69SBart Van Assche bool noisy, int verbose)
314*44704f69SBart Van Assche {
315*44704f69SBart Van Assche static const char * const cdb_s = "set streaming";
316*44704f69SBart Van Assche int res, ret, sense_cat;
317*44704f69SBart Van Assche uint8_t ssCmdBlk[SET_STREAMING_CMDLEN] =
318*44704f69SBart Van Assche {SET_STREAMING_CMD, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
319*44704f69SBart Van Assche uint8_t sense_b[SENSE_BUFF_LEN];
320*44704f69SBart Van Assche struct sg_pt_base * ptvp;
321*44704f69SBart Van Assche
322*44704f69SBart Van Assche ssCmdBlk[8] = type;
323*44704f69SBart Van Assche sg_put_unaligned_be16((uint16_t)param_len, ssCmdBlk + 9);
324*44704f69SBart Van Assche if (verbose) {
325*44704f69SBart Van Assche int k;
326*44704f69SBart Van Assche
327*44704f69SBart Van Assche pr2ws(" %s cdb: ", cdb_s);
328*44704f69SBart Van Assche for (k = 0; k < SET_STREAMING_CMDLEN; ++k)
329*44704f69SBart Van Assche pr2ws("%02x ", ssCmdBlk[k]);
330*44704f69SBart Van Assche pr2ws("\n");
331*44704f69SBart Van Assche if ((verbose > 1) && paramp && param_len) {
332*44704f69SBart Van Assche pr2ws(" %s parameter list:\n", cdb_s);
333*44704f69SBart Van Assche hex2stderr((const uint8_t *)paramp, param_len, -1);
334*44704f69SBart Van Assche }
335*44704f69SBart Van Assche }
336*44704f69SBart Van Assche
337*44704f69SBart Van Assche if (NULL == ((ptvp = create_pt_obj(cdb_s))))
338*44704f69SBart Van Assche return -1;
339*44704f69SBart Van Assche set_scsi_pt_cdb(ptvp, ssCmdBlk, sizeof(ssCmdBlk));
340*44704f69SBart Van Assche set_scsi_pt_sense(ptvp, sense_b, sizeof(sense_b));
341*44704f69SBart Van Assche set_scsi_pt_data_out(ptvp, (uint8_t *)paramp, param_len);
342*44704f69SBart Van Assche res = do_scsi_pt(ptvp, sg_fd, DEF_PT_TIMEOUT, verbose);
343*44704f69SBart Van Assche ret = sg_cmds_process_resp(ptvp, cdb_s, res, noisy, verbose, &sense_cat);
344*44704f69SBart Van Assche if (-1 == ret) {
345*44704f69SBart Van Assche if (get_scsi_pt_transport_err(ptvp))
346*44704f69SBart Van Assche ret = SG_LIB_TRANSPORT_ERROR;
347*44704f69SBart Van Assche else
348*44704f69SBart Van Assche ret = sg_convert_errno(get_scsi_pt_os_err(ptvp));
349*44704f69SBart Van Assche } else if (-2 == ret) {
350*44704f69SBart Van Assche switch (sense_cat) {
351*44704f69SBart Van Assche case SG_LIB_CAT_NOT_READY:
352*44704f69SBart Van Assche case SG_LIB_CAT_INVALID_OP:
353*44704f69SBart Van Assche case SG_LIB_CAT_ILLEGAL_REQ:
354*44704f69SBart Van Assche case SG_LIB_CAT_UNIT_ATTENTION:
355*44704f69SBart Van Assche case SG_LIB_CAT_ABORTED_COMMAND:
356*44704f69SBart Van Assche ret = sense_cat;
357*44704f69SBart Van Assche break;
358*44704f69SBart Van Assche case SG_LIB_CAT_RECOVERED:
359*44704f69SBart Van Assche case SG_LIB_CAT_NO_SENSE:
360*44704f69SBart Van Assche ret = 0;
361*44704f69SBart Van Assche break;
362*44704f69SBart Van Assche default:
363*44704f69SBart Van Assche ret = -1;
364*44704f69SBart Van Assche break;
365*44704f69SBart Van Assche }
366*44704f69SBart Van Assche } else
367*44704f69SBart Van Assche ret = 0;
368*44704f69SBart Van Assche destruct_scsi_pt_obj(ptvp);
369*44704f69SBart Van Assche return ret;
370*44704f69SBart Van Assche }
371