1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche * Copyright (c) 2017 Leorize.
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
8*44704f69SBart Van Assche #include <errno.h>
9*44704f69SBart Van Assche #include <fcntl.h>
10*44704f69SBart Van Assche #include <stdarg.h>
11*44704f69SBart Van Assche #include <stdio.h>
12*44704f69SBart Van Assche #include <stdlib.h>
13*44704f69SBart Van Assche #include <string.h>
14*44704f69SBart Van Assche
15*44704f69SBart Van Assche #include <device/CAM.h>
16*44704f69SBart Van Assche #include <scsi.h>
17*44704f69SBart Van Assche
18*44704f69SBart Van Assche #include "sg_lib.h"
19*44704f69SBart Van Assche #include "sg_pt.h"
20*44704f69SBart Van Assche
21*44704f69SBart Van Assche #if defined(__GNUC__) || defined(__clang__)
22*44704f69SBart Van Assche static int pr2ws(const char * fmt, ...)
23*44704f69SBart Van Assche __attribute__ ((format (printf, 1, 2)));
24*44704f69SBart Van Assche #else
25*44704f69SBart Van Assche static int pr2ws(const char * fmt, ...);
26*44704f69SBart Van Assche #endif
27*44704f69SBart Van Assche
28*44704f69SBart Van Assche static int
pr2ws(const char * fmt,...)29*44704f69SBart Van Assche pr2ws(const char * fmt, ...)
30*44704f69SBart Van Assche {
31*44704f69SBart Van Assche va_list args;
32*44704f69SBart Van Assche int n;
33*44704f69SBart Van Assche
34*44704f69SBart Van Assche va_start(args, fmt);
35*44704f69SBart Van Assche n = vfprintf(sg_warnings_strm ? sg_warnings_strm : stderr, fmt, args);
36*44704f69SBart Van Assche va_end(args);
37*44704f69SBart Van Assche return n;
38*44704f69SBart Van Assche }
39*44704f69SBart Van Assche
40*44704f69SBart Van Assche struct sg_pt_haiku_scsi {
41*44704f69SBart Van Assche raw_device_command raw_command;
42*44704f69SBart Van Assche size_t data_len;
43*44704f69SBart Van Assche int in_err;
44*44704f69SBart Van Assche int os_err;
45*44704f69SBart Van Assche int dev_fd;
46*44704f69SBart Van Assche };
47*44704f69SBart Van Assche
48*44704f69SBart Van Assche struct sg_pt_base {
49*44704f69SBart Van Assche struct sg_pt_haiku_scsi impl;
50*44704f69SBart Van Assche };
51*44704f69SBart Van Assche
52*44704f69SBart Van Assche /* Returns >= 0 if successful. If error in Unix returns negated errno. */
53*44704f69SBart Van Assche int
scsi_pt_open_device(const char * device_name,bool read_only,int verbose)54*44704f69SBart Van Assche scsi_pt_open_device(const char * device_name, bool read_only, int verbose)
55*44704f69SBart Van Assche {
56*44704f69SBart Van Assche int oflags = O_NONBLOCK;
57*44704f69SBart Van Assche
58*44704f69SBart Van Assche oflags |= (read_only ? O_RDONLY : O_RDWR);
59*44704f69SBart Van Assche return scsi_pt_open_flags(device_name, oflags, verbose);
60*44704f69SBart Van Assche }
61*44704f69SBart Van Assche
62*44704f69SBart Van Assche /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed */
63*44704f69SBart Van Assche /* together. The 'flags' argument is advisory and may be ignored. */
64*44704f69SBart Van Assche /* Returns >= 0 if successful, otherwise returns negated errno. */
65*44704f69SBart Van Assche int
scsi_pt_open_flags(const char * device_name,int flags,int verbose)66*44704f69SBart Van Assche scsi_pt_open_flags(const char * device_name, int flags, int verbose)
67*44704f69SBart Van Assche {
68*44704f69SBart Van Assche int fd;
69*44704f69SBart Van Assche
70*44704f69SBart Van Assche if (verbose > 1) {
71*44704f69SBart Van Assche pr2ws("open %s with flags=0x%x\n", device_name, flags);
72*44704f69SBart Van Assche }
73*44704f69SBart Van Assche fd = open(device_name, flags);
74*44704f69SBart Van Assche if (fd < 0)
75*44704f69SBart Van Assche fd = -errno;
76*44704f69SBart Van Assche return fd;
77*44704f69SBart Van Assche }
78*44704f69SBart Van Assche
79*44704f69SBart Van Assche /* Returns 0 if successful. If error in Unix returns negated errno. */
80*44704f69SBart Van Assche int
scsi_pt_close_device(int device_fd)81*44704f69SBart Van Assche scsi_pt_close_device(int device_fd)
82*44704f69SBart Van Assche {
83*44704f69SBart Van Assche int res;
84*44704f69SBart Van Assche
85*44704f69SBart Van Assche res = close(device_fd);
86*44704f69SBart Van Assche if (res < 0)
87*44704f69SBart Van Assche res = -errno;
88*44704f69SBart Van Assche return res;
89*44704f69SBart Van Assche }
90*44704f69SBart Van Assche
91*44704f69SBart Van Assche struct sg_pt_base *
construct_scsi_pt_obj_with_fd(int device_fd,int verbose)92*44704f69SBart Van Assche construct_scsi_pt_obj_with_fd(int device_fd, int verbose)
93*44704f69SBart Van Assche {
94*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp;
95*44704f69SBart Van Assche
96*44704f69SBart Van Assche /* The following 2 lines are temporary. It is to avoid a NULL pointer
97*44704f69SBart Van Assche * crash when an old utility is used with a newer library built after
98*44704f69SBart Van Assche * the sg_warnings_strm cleanup */
99*44704f69SBart Van Assche if (NULL == sg_warnings_strm)
100*44704f69SBart Van Assche sg_warnings_strm = stderr;
101*44704f69SBart Van Assche
102*44704f69SBart Van Assche ptp = (struct sg_pt_haiku_scsi *)
103*44704f69SBart Van Assche calloc(1, sizeof(struct sg_pt_haiku_scsi));
104*44704f69SBart Van Assche if (ptp) {
105*44704f69SBart Van Assche ptp->raw_command.flags = B_RAW_DEVICE_REPORT_RESIDUAL;
106*44704f69SBart Van Assche ptp->dev_fd = device_fd;
107*44704f69SBart Van Assche } else if (verbose)
108*44704f69SBart Van Assche pr2ws("%s: malloc() out of memory\n", __func__);
109*44704f69SBart Van Assche return (struct sg_pt_base *)ptp;
110*44704f69SBart Van Assche }
111*44704f69SBart Van Assche
112*44704f69SBart Van Assche struct sg_pt_base *
construct_scsi_pt_obj()113*44704f69SBart Van Assche construct_scsi_pt_obj()
114*44704f69SBart Van Assche {
115*44704f69SBart Van Assche return construct_scsi_pt_obj_with_fd(-1, 0);
116*44704f69SBart Van Assche }
117*44704f69SBart Van Assche
118*44704f69SBart Van Assche void
destruct_scsi_pt_obj(struct sg_pt_base * vp)119*44704f69SBart Van Assche destruct_scsi_pt_obj(struct sg_pt_base * vp)
120*44704f69SBart Van Assche {
121*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
122*44704f69SBart Van Assche
123*44704f69SBart Van Assche if (ptp)
124*44704f69SBart Van Assche free(ptp);
125*44704f69SBart Van Assche }
126*44704f69SBart Van Assche
127*44704f69SBart Van Assche void
clear_scsi_pt_obj(struct sg_pt_base * vp)128*44704f69SBart Van Assche clear_scsi_pt_obj(struct sg_pt_base * vp)
129*44704f69SBart Van Assche {
130*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
131*44704f69SBart Van Assche
132*44704f69SBart Van Assche if (ptp) {
133*44704f69SBart Van Assche
134*44704f69SBart Van Assche int fd = ptp->dev_fd;
135*44704f69SBart Van Assche memset(ptp, 0, sizeof(struct sg_pt_haiku_scsi));
136*44704f69SBart Van Assche ptp->dev_fd = fd;
137*44704f69SBart Van Assche ptp->raw_command.flags = B_RAW_DEVICE_REPORT_RESIDUAL;
138*44704f69SBart Van Assche }
139*44704f69SBart Van Assche }
140*44704f69SBart Van Assche
141*44704f69SBart Van Assche void
set_scsi_pt_cdb(struct sg_pt_base * vp,const unsigned char * cdb,int cdb_len)142*44704f69SBart Van Assche set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb,
143*44704f69SBart Van Assche int cdb_len)
144*44704f69SBart Van Assche {
145*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
146*44704f69SBart Van Assche
147*44704f69SBart Van Assche for (int i = 0; i < 16; ++i)
148*44704f69SBart Van Assche if (ptp->raw_command.command[i])
149*44704f69SBart Van Assche ++ptp->in_err;
150*44704f69SBart Van Assche memcpy(ptp->raw_command.command, cdb, cdb_len);
151*44704f69SBart Van Assche ptp->raw_command.command_length = (uint8_t)cdb_len;
152*44704f69SBart Van Assche }
153*44704f69SBart Van Assche
154*44704f69SBart Van Assche void
set_scsi_pt_sense(struct sg_pt_base * vp,unsigned char * sense,int max_sense_len)155*44704f69SBart Van Assche set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense,
156*44704f69SBart Van Assche int max_sense_len)
157*44704f69SBart Van Assche {
158*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
159*44704f69SBart Van Assche
160*44704f69SBart Van Assche if (ptp->raw_command.sense_data)
161*44704f69SBart Van Assche ++ptp->in_err;
162*44704f69SBart Van Assche memset(sense, 0, max_sense_len);
163*44704f69SBart Van Assche ptp->raw_command.sense_data = sense;
164*44704f69SBart Van Assche ptp->raw_command.sense_data_length = max_sense_len;
165*44704f69SBart Van Assche }
166*44704f69SBart Van Assche
167*44704f69SBart Van Assche /* Setup for data transfer from device */
168*44704f69SBart Van Assche void
set_scsi_pt_data_in(struct sg_pt_base * vp,unsigned char * dxferp,int dxfer_len)169*44704f69SBart Van Assche set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp,
170*44704f69SBart Van Assche int dxfer_len)
171*44704f69SBart Van Assche {
172*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
173*44704f69SBart Van Assche
174*44704f69SBart Van Assche if (ptp->raw_command.data)
175*44704f69SBart Van Assche ++ptp->in_err;
176*44704f69SBart Van Assche if (dxfer_len > 0) {
177*44704f69SBart Van Assche ptp->raw_command.data = dxferp;
178*44704f69SBart Van Assche ptp->raw_command.data_length = dxfer_len;
179*44704f69SBart Van Assche ptp->data_len = dxfer_len;
180*44704f69SBart Van Assche ptp->raw_command.flags |= B_RAW_DEVICE_DATA_IN;
181*44704f69SBart Van Assche }
182*44704f69SBart Van Assche }
183*44704f69SBart Van Assche
184*44704f69SBart Van Assche /* Setup for data transfer toward device */
185*44704f69SBart Van Assche void
set_scsi_pt_data_out(struct sg_pt_base * vp,const unsigned char * dxferp,int dxfer_len)186*44704f69SBart Van Assche set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp,
187*44704f69SBart Van Assche int dxfer_len)
188*44704f69SBart Van Assche {
189*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
190*44704f69SBart Van Assche
191*44704f69SBart Van Assche if (ptp->raw_command.data)
192*44704f69SBart Van Assche ++ptp->in_err;
193*44704f69SBart Van Assche if (dxfer_len > 0) {
194*44704f69SBart Van Assche ptp->raw_command.data = (unsigned char *)dxferp;
195*44704f69SBart Van Assche ptp->raw_command.data_length = dxfer_len;
196*44704f69SBart Van Assche ptp->data_len = dxfer_len;
197*44704f69SBart Van Assche ptp->raw_command.flags &= ~B_RAW_DEVICE_DATA_IN;
198*44704f69SBart Van Assche }
199*44704f69SBart Van Assche }
200*44704f69SBart Van Assche
201*44704f69SBart Van Assche void
set_scsi_pt_packet_id(struct sg_pt_base * vp,int pack_id)202*44704f69SBart Van Assche set_scsi_pt_packet_id(struct sg_pt_base * vp __attribute__ ((unused)),
203*44704f69SBart Van Assche int pack_id __attribute__ ((unused)))
204*44704f69SBart Van Assche {
205*44704f69SBart Van Assche }
206*44704f69SBart Van Assche
207*44704f69SBart Van Assche void
set_scsi_pt_tag(struct sg_pt_base * vp,uint64_t tag)208*44704f69SBart Van Assche set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag __attribute__ ((unused)))
209*44704f69SBart Van Assche {
210*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
211*44704f69SBart Van Assche
212*44704f69SBart Van Assche ++ptp->in_err;
213*44704f69SBart Van Assche }
214*44704f69SBart Van Assche
215*44704f69SBart Van Assche void
set_scsi_pt_task_management(struct sg_pt_base * vp,int tmf_code)216*44704f69SBart Van Assche set_scsi_pt_task_management(struct sg_pt_base * vp,
217*44704f69SBart Van Assche int tmf_code __attribute__ ((unused)))
218*44704f69SBart Van Assche {
219*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
220*44704f69SBart Van Assche
221*44704f69SBart Van Assche ++ptp->in_err;
222*44704f69SBart Van Assche }
223*44704f69SBart Van Assche
224*44704f69SBart Van Assche void
set_scsi_pt_task_attr(struct sg_pt_base * vp,int attrib,int priority)225*44704f69SBart Van Assche set_scsi_pt_task_attr(struct sg_pt_base * vp,
226*44704f69SBart Van Assche int attrib __attribute__ ((unused)),
227*44704f69SBart Van Assche int priority __attribute__ ((unused)))
228*44704f69SBart Van Assche {
229*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
230*44704f69SBart Van Assche
231*44704f69SBart Van Assche ++ptp->in_err;
232*44704f69SBart Van Assche }
233*44704f69SBart Van Assche
234*44704f69SBart Van Assche void
set_scsi_pt_flags(struct sg_pt_base * vp,int flags)235*44704f69SBart Van Assche set_scsi_pt_flags(struct sg_pt_base * vp __attribute__ ((unused)),
236*44704f69SBart Van Assche int flags __attribute__ ((unused)))
237*44704f69SBart Van Assche {
238*44704f69SBart Van Assche }
239*44704f69SBart Van Assche
240*44704f69SBart Van Assche /* Executes SCSI command (or at least forwards it to lower layers).
241*44704f69SBart Van Assche * Clears os_err field prior to active call (whose result may set it
242*44704f69SBart Van Assche * again). */
243*44704f69SBart Van Assche int
do_scsi_pt(struct sg_pt_base * vp,int fd,int timeout_secs,int verbose)244*44704f69SBart Van Assche do_scsi_pt(struct sg_pt_base * vp, int fd, int timeout_secs, int verbose)
245*44704f69SBart Van Assche {
246*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
247*44704f69SBart Van Assche
248*44704f69SBart Van Assche ptp->os_err = 0;
249*44704f69SBart Van Assche if (ptp->in_err) {
250*44704f69SBart Van Assche if (verbose)
251*44704f69SBart Van Assche pr2ws("Replicated or unused set_scsi_pt...\n");
252*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
253*44704f69SBart Van Assche }
254*44704f69SBart Van Assche if (fd >= 0) {
255*44704f69SBart Van Assche if ((ptp->dev_fd >= 0) && (fd != ptp->dev_fd)) {
256*44704f69SBart Van Assche if (verbose)
257*44704f69SBart Van Assche pr2ws("%s: file descriptor given to create() and here "
258*44704f69SBart Van Assche "differ\n", __func__);
259*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
260*44704f69SBart Van Assche }
261*44704f69SBart Van Assche ptp->dev_fd = fd;
262*44704f69SBart Van Assche } else if (ptp->dev_fd < 0) {
263*44704f69SBart Van Assche if (verbose)
264*44704f69SBart Van Assche pr2ws("%s: invalid file descriptors\n", __func__);
265*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
266*44704f69SBart Van Assche } else
267*44704f69SBart Van Assche fd = ptp->dev_fd;
268*44704f69SBart Van Assche
269*44704f69SBart Van Assche if (NULL == ptp->raw_command.command) {
270*44704f69SBart Van Assche if (verbose)
271*44704f69SBart Van Assche pr2ws("No SCSI command (cdb) given\n");
272*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
273*44704f69SBart Van Assche }
274*44704f69SBart Van Assche /* raw_command.timeout is in microseconds */
275*44704f69SBart Van Assche ptp->raw_command.timeout = ((timeout_secs > 0) ? (timeout_secs * 1000000) :
276*44704f69SBart Van Assche CAM_TIME_DEFAULT);
277*44704f69SBart Van Assche
278*44704f69SBart Van Assche if (ioctl(fd, B_RAW_DEVICE_COMMAND, &ptp->raw_command) < 0) {
279*44704f69SBart Van Assche ptp->os_err = errno;
280*44704f69SBart Van Assche if (verbose > 1)
281*44704f69SBart Van Assche pr2ws("ioctl(B_RAW_DEVICE_COMMAND) failed: %s (errno=%d)\n",
282*44704f69SBart Van Assche safe_strerror(ptp->os_err), ptp->os_err);
283*44704f69SBart Van Assche return -ptp->os_err;
284*44704f69SBart Van Assche }
285*44704f69SBart Van Assche
286*44704f69SBart Van Assche return SCSI_PT_DO_START_OK;
287*44704f69SBart Van Assche }
288*44704f69SBart Van Assche
289*44704f69SBart Van Assche int
get_scsi_pt_result_category(const struct sg_pt_base * vp)290*44704f69SBart Van Assche get_scsi_pt_result_category(const struct sg_pt_base * vp)
291*44704f69SBart Van Assche {
292*44704f69SBart Van Assche int cam_status_masked;
293*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
294*44704f69SBart Van Assche
295*44704f69SBart Van Assche if (ptp->os_err)
296*44704f69SBart Van Assche return SCSI_PT_RESULT_OS_ERR;
297*44704f69SBart Van Assche cam_status_masked = ptp->raw_command.cam_status & CAM_STATUS_MASK;
298*44704f69SBart Van Assche if (cam_status_masked != CAM_REQ_CMP &&
299*44704f69SBart Van Assche cam_status_masked != CAM_REQ_CMP_ERR)
300*44704f69SBart Van Assche return SCSI_PT_RESULT_TRANSPORT_ERR;
301*44704f69SBart Van Assche else if ((SAM_STAT_CHECK_CONDITION == ptp->raw_command.scsi_status) ||
302*44704f69SBart Van Assche (SAM_STAT_COMMAND_TERMINATED == ptp->raw_command.scsi_status))
303*44704f69SBart Van Assche return SCSI_PT_RESULT_SENSE;
304*44704f69SBart Van Assche else if (ptp->raw_command.scsi_status)
305*44704f69SBart Van Assche return SCSI_PT_RESULT_STATUS;
306*44704f69SBart Van Assche else
307*44704f69SBart Van Assche return SCSI_PT_RESULT_GOOD;
308*44704f69SBart Van Assche }
309*44704f69SBart Van Assche
310*44704f69SBart Van Assche int
get_scsi_pt_resid(const struct sg_pt_base * vp)311*44704f69SBart Van Assche get_scsi_pt_resid(const struct sg_pt_base * vp)
312*44704f69SBart Van Assche {
313*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
314*44704f69SBart Van Assche
315*44704f69SBart Van Assche /* For various reasons Haiku return data_len - data_resid */
316*44704f69SBart Van Assche return ptp->data_len - ptp->raw_command.data_length;
317*44704f69SBart Van Assche }
318*44704f69SBart Van Assche
319*44704f69SBart Van Assche int
get_scsi_pt_status_response(const struct sg_pt_base * vp)320*44704f69SBart Van Assche get_scsi_pt_status_response(const struct sg_pt_base * vp)
321*44704f69SBart Van Assche {
322*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
323*44704f69SBart Van Assche
324*44704f69SBart Van Assche return ptp->raw_command.scsi_status;
325*44704f69SBart Van Assche }
326*44704f69SBart Van Assche
327*44704f69SBart Van Assche uint8_t *
get_scsi_pt_sense_buf(const struct sg_pt_base * vp)328*44704f69SBart Van Assche get_scsi_pt_sense_buf(const struct sg_pt_base * vp)
329*44704f69SBart Van Assche {
330*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
331*44704f69SBart Van Assche
332*44704f69SBart Van Assche return (uint8_t *)ptp->raw_command.sense_data;
333*44704f69SBart Van Assche }
334*44704f69SBart Van Assche
335*44704f69SBart Van Assche int
get_scsi_pt_sense_len(const struct sg_pt_base * vp)336*44704f69SBart Van Assche get_scsi_pt_sense_len(const struct sg_pt_base * vp)
337*44704f69SBart Van Assche {
338*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
339*44704f69SBart Van Assche
340*44704f69SBart Van Assche return ptp->raw_command.sense_data_length;
341*44704f69SBart Van Assche }
342*44704f69SBart Van Assche
343*44704f69SBart Van Assche int
get_scsi_pt_os_err(const struct sg_pt_base * vp)344*44704f69SBart Van Assche get_scsi_pt_os_err(const struct sg_pt_base * vp)
345*44704f69SBart Van Assche {
346*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
347*44704f69SBart Van Assche
348*44704f69SBart Van Assche return ptp->os_err;
349*44704f69SBart Van Assche }
350*44704f69SBart Van Assche
351*44704f69SBart Van Assche char *
get_scsi_pt_os_err_str(const struct sg_pt_base * vp,int max_b_len,char * b)352*44704f69SBart Van Assche get_scsi_pt_os_err_str(const struct sg_pt_base * vp __attribute__ ((unused)),
353*44704f69SBart Van Assche int max_b_len, char * b)
354*44704f69SBart Van Assche {
355*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
356*44704f69SBart Van Assche
357*44704f69SBart Van Assche const char *cp;
358*44704f69SBart Van Assche
359*44704f69SBart Van Assche cp = safe_strerror(ptp->os_err);
360*44704f69SBart Van Assche strncpy(b, cp, max_b_len);
361*44704f69SBart Van Assche if ((int)strlen(cp) >= max_b_len)
362*44704f69SBart Van Assche b[max_b_len - 1] = '\0';
363*44704f69SBart Van Assche return b;
364*44704f69SBart Van Assche }
365*44704f69SBart Van Assche
366*44704f69SBart Van Assche int
get_scsi_pt_transport_err(const struct sg_pt_base * vp)367*44704f69SBart Van Assche get_scsi_pt_transport_err(const struct sg_pt_base * vp)
368*44704f69SBart Van Assche {
369*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
370*44704f69SBart Van Assche
371*44704f69SBart Van Assche if ((ptp->raw_command.cam_status & CAM_STATUS_MASK) != CAM_REQ_CMP ||
372*44704f69SBart Van Assche (ptp->raw_command.cam_status & CAM_STATUS_MASK) != CAM_REQ_CMP_ERR)
373*44704f69SBart Van Assche return ptp->raw_command.cam_status & CAM_STATUS_MASK;
374*44704f69SBart Van Assche
375*44704f69SBart Van Assche return 0;
376*44704f69SBart Van Assche }
377*44704f69SBart Van Assche
378*44704f69SBart Van Assche char *
get_scsi_pt_transport_err_str(const struct sg_pt_base * vp,int max_b_len,char * b)379*44704f69SBart Van Assche get_scsi_pt_transport_err_str(
380*44704f69SBart Van Assche const struct sg_pt_base * vp __attribute__ ((unused)),
381*44704f69SBart Van Assche int max_b_len, char * b)
382*44704f69SBart Van Assche {
383*44704f69SBart Van Assche strncpy(b, "no transport error available", max_b_len);
384*44704f69SBart Van Assche b[max_b_len - 1] = '\0';
385*44704f69SBart Van Assche return b;
386*44704f69SBart Van Assche }
387*44704f69SBart Van Assche
388*44704f69SBart Van Assche int
get_scsi_pt_duration_ms(const struct sg_pt_base * vp)389*44704f69SBart Van Assche get_scsi_pt_duration_ms(const struct sg_pt_base * vp __attribute__ ((unused)))
390*44704f69SBart Van Assche {
391*44704f69SBart Van Assche return -1;
392*44704f69SBart Van Assche }
393*44704f69SBart Van Assche
394*44704f69SBart Van Assche void
partial_clear_scsi_pt_obj(struct sg_pt_base * vp)395*44704f69SBart Van Assche partial_clear_scsi_pt_obj(struct sg_pt_base * vp)
396*44704f69SBart Van Assche {
397*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
398*44704f69SBart Van Assche
399*44704f69SBart Van Assche if (NULL == ptp)
400*44704f69SBart Van Assche return;
401*44704f69SBart Van Assche ptp->in_err = 0;
402*44704f69SBart Van Assche ptp->os_err = 0;
403*44704f69SBart Van Assche ptp->data_len = 0;
404*44704f69SBart Van Assche ptp->raw_command.cam_status = 0;
405*44704f69SBart Van Assche ptp->raw_command.data_length = 0;
406*44704f69SBart Van Assche }
407*44704f69SBart Van Assche
pt_device_is_nvme(const struct sg_pt_base * vp)408*44704f69SBart Van Assche bool pt_device_is_nvme(const struct sg_pt_base * vp __attribute__ ((unused)))
409*44704f69SBart Van Assche {
410*44704f69SBart Van Assche return 0;
411*44704f69SBart Van Assche }
412*44704f69SBart Van Assche
413*44704f69SBart Van Assche int
check_pt_file_handle(int device_fd,const char * device_name,int vb)414*44704f69SBart Van Assche check_pt_file_handle(int device_fd, const char * device_name, int vb)
415*44704f69SBart Van Assche {
416*44704f69SBart Van Assche if (device_fd) {}
417*44704f69SBart Van Assche if (device_name) {}
418*44704f69SBart Van Assche if (vb) {}
419*44704f69SBart Van Assche return 1; /* guess it is a SCSI generic pass-though device */
420*44704f69SBart Van Assche }
421*44704f69SBart Van Assche
422*44704f69SBart Van Assche int
do_nvm_pt(struct sg_pt_base * vp,int submq,int timeout_secs,int verbose)423*44704f69SBart Van Assche do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose)
424*44704f69SBart Van Assche {
425*44704f69SBart Van Assche if (vp) { }
426*44704f69SBart Van Assche if (submq) { }
427*44704f69SBart Van Assche if (timeout_secs) { }
428*44704f69SBart Van Assche if (verbose) { }
429*44704f69SBart Van Assche return SCSI_PT_DO_NOT_SUPPORTED;
430*44704f69SBart Van Assche }
431*44704f69SBart Van Assche
432*44704f69SBart Van Assche void
get_pt_actual_lengths(const struct sg_pt_base * vp,int * act_dinp,int * act_doutp)433*44704f69SBart Van Assche get_pt_actual_lengths(const struct sg_pt_base * vp, int * act_dinp,
434*44704f69SBart Van Assche int * act_doutp)
435*44704f69SBart Van Assche {
436*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
437*44704f69SBart Van Assche
438*44704f69SBart Van Assche if (ptp->data_len == 0) {
439*44704f69SBart Van Assche if (act_dinp)
440*44704f69SBart Van Assche *act_dinp = 0;
441*44704f69SBart Van Assche if (act_doutp)
442*44704f69SBart Van Assche *act_doutp = 0;
443*44704f69SBart Van Assche } else if (act_dinp && (ptp->raw_command.flags & B_RAW_DEVICE_DATA_IN)) {
444*44704f69SBart Van Assche /* "For various reasons Haiku return data_len - data_resid" */
445*44704f69SBart Van Assche *act_dinp = ptp->raw_command.data_length;
446*44704f69SBart Van Assche if (act_doutp)
447*44704f69SBart Van Assche *act_doutp = 0;
448*44704f69SBart Van Assche } else if (act_doutp &&
449*44704f69SBart Van Assche !(ptp->raw_command.flags & B_RAW_DEVICE_DATA_IN)) {
450*44704f69SBart Van Assche *act_doutp = ptp->raw_command.data_length;
451*44704f69SBart Van Assche if (act_dinp)
452*44704f69SBart Van Assche *act_dinp = 0;
453*44704f69SBart Van Assche } else {
454*44704f69SBart Van Assche if (act_dinp)
455*44704f69SBart Van Assche *act_dinp = 0;
456*44704f69SBart Van Assche if (act_doutp)
457*44704f69SBart Van Assche *act_doutp = 0;
458*44704f69SBart Van Assche }
459*44704f69SBart Van Assche }
460*44704f69SBart Van Assche
461*44704f69SBart Van Assche /* If not available return 0 otherwise return number of nanoseconds that the
462*44704f69SBart Van Assche * lower layers (and hardware) took to execute the command just completed. */
463*44704f69SBart Van Assche uint64_t
get_pt_duration_ns(const struct sg_pt_base * vp)464*44704f69SBart Van Assche get_pt_duration_ns(const struct sg_pt_base * vp __attribute__ ((unused)))
465*44704f69SBart Van Assche {
466*44704f69SBart Van Assche return 0;
467*44704f69SBart Van Assche }
468*44704f69SBart Van Assche
469*44704f69SBart Van Assche /* Valid file handles (which is the return value) are >= 0 . Returns -1
470*44704f69SBart Van Assche * if there is no valid file handle. */
471*44704f69SBart Van Assche int
get_pt_file_handle(const struct sg_pt_base * vp)472*44704f69SBart Van Assche get_pt_file_handle(const struct sg_pt_base * vp)
473*44704f69SBart Van Assche {
474*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
475*44704f69SBart Van Assche
476*44704f69SBart Van Assche return ptp->dev_fd;
477*44704f69SBart Van Assche }
478*44704f69SBart Van Assche
479*44704f69SBart Van Assche
480*44704f69SBart Van Assche /* If a NVMe block device (which includes the NSID) handle is associated
481*44704f69SBart Van Assche * with 'vp', then its NSID is returned (values range from 0x1 to
482*44704f69SBart Van Assche * 0xffffffe). Otherwise 0 is returned. */
483*44704f69SBart Van Assche uint32_t
get_pt_nvme_nsid(const struct sg_pt_base * vp)484*44704f69SBart Van Assche get_pt_nvme_nsid(const struct sg_pt_base * vp)
485*44704f69SBart Van Assche {
486*44704f69SBart Van Assche if (vp) { }
487*44704f69SBart Van Assche return 0;
488*44704f69SBart Van Assche }
489*44704f69SBart Van Assche
490*44704f69SBart Van Assche void
get_pt_req_lengths(const struct sg_pt_base * vp,int * req_dinp,int * req_doutp)491*44704f69SBart Van Assche get_pt_req_lengths(const struct sg_pt_base * vp, int * req_dinp,
492*44704f69SBart Van Assche int * req_doutp)
493*44704f69SBart Van Assche {
494*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
495*44704f69SBart Van Assche
496*44704f69SBart Van Assche if (ptp->data_len == 0) {
497*44704f69SBart Van Assche if (req_dinp)
498*44704f69SBart Van Assche *req_dinp = 0;
499*44704f69SBart Van Assche if (req_doutp)
500*44704f69SBart Van Assche *req_doutp = 0;
501*44704f69SBart Van Assche } else if (req_dinp && (ptp->raw_command.flags & B_RAW_DEVICE_DATA_IN)) {
502*44704f69SBart Van Assche /* "For various reasons Haiku return data_len - data_resid" */
503*44704f69SBart Van Assche *req_dinp = ptp->data_len;
504*44704f69SBart Van Assche if (req_doutp)
505*44704f69SBart Van Assche *req_doutp = 0;
506*44704f69SBart Van Assche } else if (req_doutp &&
507*44704f69SBart Van Assche !(ptp->raw_command.flags & B_RAW_DEVICE_DATA_IN)) {
508*44704f69SBart Van Assche *req_doutp = ptp->data_len;
509*44704f69SBart Van Assche if (req_dinp)
510*44704f69SBart Van Assche *req_dinp = 0;
511*44704f69SBart Van Assche } else {
512*44704f69SBart Van Assche if (req_dinp)
513*44704f69SBart Van Assche *req_dinp = 0;
514*44704f69SBart Van Assche if (req_doutp)
515*44704f69SBart Van Assche *req_doutp = 0;
516*44704f69SBart Van Assche }
517*44704f69SBart Van Assche }
518*44704f69SBart Van Assche
519*44704f69SBart Van Assche uint32_t
get_pt_result(const struct sg_pt_base * vp)520*44704f69SBart Van Assche get_pt_result(const struct sg_pt_base * vp)
521*44704f69SBart Van Assche {
522*44704f69SBart Van Assche return (uint32_t)get_scsi_pt_status_response(vp);
523*44704f69SBart Van Assche }
524*44704f69SBart Van Assche
525*44704f69SBart Van Assche uint8_t *
get_scsi_pt_cdb_buf(const struct sg_pt_base * vp)526*44704f69SBart Van Assche get_scsi_pt_cdb_buf(const struct sg_pt_base * vp)
527*44704f69SBart Van Assche {
528*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
529*44704f69SBart Van Assche
530*44704f69SBart Van Assche return (uint8_t *)ptp->raw_command.command;
531*44704f69SBart Van Assche }
532*44704f69SBart Van Assche
533*44704f69SBart Van Assche int
get_scsi_pt_cdb_len(const struct sg_pt_base * vp)534*44704f69SBart Van Assche get_scsi_pt_cdb_len(const struct sg_pt_base * vp)
535*44704f69SBart Van Assche {
536*44704f69SBart Van Assche const struct sg_pt_haiku_scsi * ptp = &vp->impl;
537*44704f69SBart Van Assche
538*44704f69SBart Van Assche return (int)ptp->raw_command.command_length;
539*44704f69SBart Van Assche }
540*44704f69SBart Van Assche
541*44704f69SBart Van Assche /* Forget any previous dev_han and install the one given. May attempt to
542*44704f69SBart Van Assche * find file type (e.g. if pass-though) from OS so there could be an error.
543*44704f69SBart Van Assche * Returns 0 for success or the same value as get_scsi_pt_os_err()
544*44704f69SBart Van Assche * will return. dev_han should be >= 0 for a valid file handle or -1 . */
545*44704f69SBart Van Assche int
set_pt_file_handle(struct sg_pt_base * vp,int dev_han,int vb)546*44704f69SBart Van Assche set_pt_file_handle(struct sg_pt_base * vp, int dev_han, int vb)
547*44704f69SBart Van Assche {
548*44704f69SBart Van Assche struct sg_pt_haiku_scsi * ptp = &vp->impl;
549*44704f69SBart Van Assche
550*44704f69SBart Van Assche if (vb) {}
551*44704f69SBart Van Assche ptp->dev_fd = (dev_han < 0) ? -1 : dev_han;
552*44704f69SBart Van Assche ptp->in_err = 0;
553*44704f69SBart Van Assche ptp->os_err = 0;
554*44704f69SBart Van Assche return 0;
555*44704f69SBart Van Assche }
556*44704f69SBart Van Assche
557*44704f69SBart Van Assche void
set_scsi_pt_transport_err(struct sg_pt_base * vp,int err)558*44704f69SBart Van Assche set_scsi_pt_transport_err(struct sg_pt_base * vp, int err)
559*44704f69SBart Van Assche {
560*44704f69SBart Van Assche if (vp) { }
561*44704f69SBart Van Assche if (err) { }
562*44704f69SBart Van Assche }
563*44704f69SBart Van Assche
564*44704f69SBart Van Assche void
set_pt_metadata_xfer(struct sg_pt_base * vp,uint8_t * mdxferp,uint32_t mdxfer_len,bool out_true)565*44704f69SBart Van Assche set_pt_metadata_xfer(struct sg_pt_base * vp, uint8_t * mdxferp,
566*44704f69SBart Van Assche uint32_t mdxfer_len, bool out_true)
567*44704f69SBart Van Assche {
568*44704f69SBart Van Assche if (vp) { }
569*44704f69SBart Van Assche if (mdxferp) { }
570*44704f69SBart Van Assche if (mdxfer_len) { }
571*44704f69SBart Van Assche if (out_true) { }
572*44704f69SBart Van Assche }
573