1*44704f69SBart Van Assche /*
2*44704f69SBart Van Assche * Copyright (c) 2005-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 <fcntl.h>
11*44704f69SBart Van Assche #include <sys/stat.h>
12*44704f69SBart Van Assche #include <sys/types.h>
13*44704f69SBart Van Assche #include <unistd.h>
14*44704f69SBart Van Assche #include <sys/ioctl.h>
15*44704f69SBart Van Assche #include <io/common/devgetinfo.h>
16*44704f69SBart Van Assche #include <io/common/iotypes.h>
17*44704f69SBart Van Assche #include <io/cam/cam.h>
18*44704f69SBart Van Assche #include <io/cam/uagt.h>
19*44704f69SBart Van Assche #include <io/cam/rzdisk.h>
20*44704f69SBart Van Assche #include <io/cam/scsi_opcodes.h>
21*44704f69SBart Van Assche #include <io/cam/scsi_all.h>
22*44704f69SBart Van Assche #include <stdio.h>
23*44704f69SBart Van Assche #include <stdlib.h>
24*44704f69SBart Van Assche #include <stdarg.h>
25*44704f69SBart Van Assche #include <stdbool.h>
26*44704f69SBart Van Assche #include <string.h>
27*44704f69SBart Van Assche #include <errno.h>
28*44704f69SBart Van Assche
29*44704f69SBart Van Assche #include "sg_pt.h"
30*44704f69SBart Van Assche #include "sg_lib.h"
31*44704f69SBart Van Assche #include "sg_pr2serr.h"
32*44704f69SBart Van Assche
33*44704f69SBart Van Assche /* Version 2.04 20210617 */
34*44704f69SBart Van Assche
35*44704f69SBart Van Assche #define OSF1_MAXDEV 64
36*44704f69SBart Van Assche
37*44704f69SBart Van Assche #ifndef CAM_DIR_BOTH
38*44704f69SBart Van Assche #define CAM_DIR_BOTH 0x0 /* copy value from FreeBSD */
39*44704f69SBart Van Assche #endif
40*44704f69SBart Van Assche
41*44704f69SBart Van Assche struct osf1_dev_channel {
42*44704f69SBart Van Assche int bus;
43*44704f69SBart Van Assche int tgt;
44*44704f69SBart Van Assche int lun;
45*44704f69SBart Van Assche };
46*44704f69SBart Van Assche
47*44704f69SBart Van Assche // Private table of open devices: guaranteed zero on startup since
48*44704f69SBart Van Assche // part of static data.
49*44704f69SBart Van Assche static struct osf1_dev_channel *devicetable[OSF1_MAXDEV] SG_C_CPP_ZERO_INIT;
50*44704f69SBart Van Assche static char *cam_dev = "/dev/cam";
51*44704f69SBart Van Assche static int camfd;
52*44704f69SBart Van Assche static int camopened = 0;
53*44704f69SBart Van Assche
54*44704f69SBart Van Assche struct sg_pt_osf1_scsi {
55*44704f69SBart Van Assche uint8_t * cdb;
56*44704f69SBart Van Assche int cdb_len;
57*44704f69SBart Van Assche uint8_t * sense;
58*44704f69SBart Van Assche int sense_len;
59*44704f69SBart Van Assche uint8_t * dxferp;
60*44704f69SBart Van Assche int dxfer_len;
61*44704f69SBart Van Assche int dxfer_dir;
62*44704f69SBart Van Assche int scsi_status;
63*44704f69SBart Van Assche int resid;
64*44704f69SBart Van Assche int sense_resid;
65*44704f69SBart Van Assche int in_err;
66*44704f69SBart Van Assche int os_err;
67*44704f69SBart Van Assche int transport_err;
68*44704f69SBart Van Assche bool is_nvme;
69*44704f69SBart Van Assche int dev_fd;
70*44704f69SBart Van Assche };
71*44704f69SBart Van Assche
72*44704f69SBart Van Assche struct sg_pt_base {
73*44704f69SBart Van Assche struct sg_pt_osf1_scsi impl;
74*44704f69SBart Van Assche };
75*44704f69SBart Van Assche
76*44704f69SBart Van Assche
77*44704f69SBart Van Assche /* Returns >= 0 if successful. If error in Unix returns negated errno. */
78*44704f69SBart Van Assche int
scsi_pt_open_device(const char * device_name,bool read_only,int verbose)79*44704f69SBart Van Assche scsi_pt_open_device(const char * device_name, bool read_only, int verbose)
80*44704f69SBart Van Assche {
81*44704f69SBart Van Assche int oflags = 0 /* O_NONBLOCK*/ ;
82*44704f69SBart Van Assche
83*44704f69SBart Van Assche oflags |= (read_only ? O_RDONLY : O_RDWR);
84*44704f69SBart Van Assche return scsi_pt_open_flags(device_name, oflags, verbose);
85*44704f69SBart Van Assche }
86*44704f69SBart Van Assche
87*44704f69SBart Van Assche /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed
88*44704f69SBart Van Assche * together. The 'flags' argument is ignored in OSF-1.
89*44704f69SBart Van Assche * Returns >= 0 if successful, otherwise returns negated errno. */
90*44704f69SBart Van Assche int
scsi_pt_open_flags(const char * device_name,int flags,int verbose)91*44704f69SBart Van Assche scsi_pt_open_flags(const char * device_name, int flags, int verbose)
92*44704f69SBart Van Assche {
93*44704f69SBart Van Assche struct osf1_dev_channel *fdchan;
94*44704f69SBart Van Assche int fd, k;
95*44704f69SBart Van Assche
96*44704f69SBart Van Assche if (!camopened) {
97*44704f69SBart Van Assche camfd = open(cam_dev, O_RDWR, 0);
98*44704f69SBart Van Assche if (camfd < 0)
99*44704f69SBart Van Assche return -1;
100*44704f69SBart Van Assche camopened++;
101*44704f69SBart Van Assche }
102*44704f69SBart Van Assche
103*44704f69SBart Van Assche // Search table for a free entry
104*44704f69SBart Van Assche for (k = 0; k < OSF1_MAXDEV; k++)
105*44704f69SBart Van Assche if (! devicetable[k])
106*44704f69SBart Van Assche break;
107*44704f69SBart Van Assche
108*44704f69SBart Van Assche if (k == OSF1_MAXDEV) {
109*44704f69SBart Van Assche if (verbose)
110*44704f69SBart Van Assche pr2ws("too many open devices (%d)\n", OSF1_MAXDEV);
111*44704f69SBart Van Assche errno=EMFILE;
112*44704f69SBart Van Assche return -1;
113*44704f69SBart Van Assche }
114*44704f69SBart Van Assche
115*44704f69SBart Van Assche fdchan = (struct osf1_dev_channel *)calloc(1,
116*44704f69SBart Van Assche sizeof(struct osf1_dev_channel));
117*44704f69SBart Van Assche if (fdchan == NULL) {
118*44704f69SBart Van Assche // errno already set by call to malloc()
119*44704f69SBart Van Assche return -1;
120*44704f69SBart Van Assche }
121*44704f69SBart Van Assche
122*44704f69SBart Van Assche fd = open(device_name, O_RDONLY|O_NONBLOCK);
123*44704f69SBart Van Assche if (fd > 0) {
124*44704f69SBart Van Assche device_info_t devinfo;
125*44704f69SBart Van Assche bzero(&devinfo, sizeof(devinfo));
126*44704f69SBart Van Assche if (ioctl(fd, DEVGETINFO, &devinfo) == 0) {
127*44704f69SBart Van Assche fdchan->bus = devinfo.v1.businfo.bus.scsi.bus_num;
128*44704f69SBart Van Assche fdchan->tgt = devinfo.v1.businfo.bus.scsi.tgt_id;
129*44704f69SBart Van Assche fdchan->lun = devinfo.v1.businfo.bus.scsi.lun;
130*44704f69SBart Van Assche }
131*44704f69SBart Van Assche close (fd);
132*44704f69SBart Van Assche } else {
133*44704f69SBart Van Assche free(fdchan);
134*44704f69SBart Van Assche return -1;
135*44704f69SBart Van Assche }
136*44704f69SBart Van Assche
137*44704f69SBart Van Assche devicetable[k] = fdchan;
138*44704f69SBart Van Assche return k;
139*44704f69SBart Van Assche }
140*44704f69SBart Van Assche
141*44704f69SBart Van Assche /* Returns 0 if successful. If error in Unix returns negated errno. */
142*44704f69SBart Van Assche int
scsi_pt_close_device(int device_fd)143*44704f69SBart Van Assche scsi_pt_close_device(int device_fd)
144*44704f69SBart Van Assche {
145*44704f69SBart Van Assche struct osf1_dev_channel *fdchan;
146*44704f69SBart Van Assche int i;
147*44704f69SBart Van Assche
148*44704f69SBart Van Assche if ((device_fd < 0) || (device_fd >= OSF1_MAXDEV)) {
149*44704f69SBart Van Assche errno = ENODEV;
150*44704f69SBart Van Assche return -1;
151*44704f69SBart Van Assche }
152*44704f69SBart Van Assche
153*44704f69SBart Van Assche fdchan = devicetable[device_fd];
154*44704f69SBart Van Assche if (NULL == fdchan) {
155*44704f69SBart Van Assche errno = ENODEV;
156*44704f69SBart Van Assche return -1;
157*44704f69SBart Van Assche }
158*44704f69SBart Van Assche
159*44704f69SBart Van Assche free(fdchan);
160*44704f69SBart Van Assche devicetable[device_fd] = NULL;
161*44704f69SBart Van Assche
162*44704f69SBart Van Assche for (i = 0; i < OSF1_MAXDEV; i++) {
163*44704f69SBart Van Assche if (devicetable[i])
164*44704f69SBart Van Assche break;
165*44704f69SBart Van Assche }
166*44704f69SBart Van Assche if (i == OSF1_MAXDEV) {
167*44704f69SBart Van Assche close(camfd);
168*44704f69SBart Van Assche camopened = 0;
169*44704f69SBart Van Assche }
170*44704f69SBart Van Assche return 0;
171*44704f69SBart Van Assche }
172*44704f69SBart Van Assche
173*44704f69SBart Van Assche struct sg_pt_base *
construct_scsi_pt_obj_with_fd(int device_fd,int verbose)174*44704f69SBart Van Assche construct_scsi_pt_obj_with_fd(int device_fd, int verbose)
175*44704f69SBart Van Assche {
176*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp;
177*44704f69SBart Van Assche
178*44704f69SBart Van Assche ptp = (struct sg_pt_osf1_scsi *)malloc(sizeof(struct sg_pt_osf1_scsi));
179*44704f69SBart Van Assche if (ptp) {
180*44704f69SBart Van Assche bzero(ptp, sizeof(struct sg_pt_osf1_scsi));
181*44704f69SBart Van Assche ptp->dev_fd = (device_fd < 0) ? -1 : device_fd;
182*44704f69SBart Van Assche ptp->is_nvme = false;
183*44704f69SBart Van Assche ptp->dxfer_dir = CAM_DIR_NONE;
184*44704f69SBart Van Assche } else if (verbose)
185*44704f69SBart Van Assche pr2ws("%s: malloc() out of memory\n", __func__);
186*44704f69SBart Van Assche return (struct sg_pt_base *)ptp;
187*44704f69SBart Van Assche }
188*44704f69SBart Van Assche
189*44704f69SBart Van Assche struct sg_pt_base *
construct_scsi_pt_obj(void)190*44704f69SBart Van Assche construct_scsi_pt_obj(void)
191*44704f69SBart Van Assche {
192*44704f69SBart Van Assche return construct_scsi_pt_obj_with_fd(-1, 0);
193*44704f69SBart Van Assche }
194*44704f69SBart Van Assche
195*44704f69SBart Van Assche void
destruct_scsi_pt_obj(struct sg_pt_base * vp)196*44704f69SBart Van Assche destruct_scsi_pt_obj(struct sg_pt_base * vp)
197*44704f69SBart Van Assche {
198*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
199*44704f69SBart Van Assche
200*44704f69SBart Van Assche if (ptp)
201*44704f69SBart Van Assche free(ptp);
202*44704f69SBart Van Assche }
203*44704f69SBart Van Assche
204*44704f69SBart Van Assche void
clear_scsi_pt_obj(struct sg_pt_base * vp)205*44704f69SBart Van Assche clear_scsi_pt_obj(struct sg_pt_base * vp)
206*44704f69SBart Van Assche {
207*44704f69SBart Van Assche bool is_nvme;
208*44704f69SBart Van Assche int dev_fd;
209*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
210*44704f69SBart Van Assche
211*44704f69SBart Van Assche if (ptp) {
212*44704f69SBart Van Assche is_nvme = ptp->is_nvme;
213*44704f69SBart Van Assche dev_fd = ptp->dev_fd;
214*44704f69SBart Van Assche bzero(ptp, sizeof(struct sg_pt_osf1_scsi));
215*44704f69SBart Van Assche ptp->dev_fd = dev_fd;
216*44704f69SBart Van Assche ptp->is_nvme = is_nvme;
217*44704f69SBart Van Assche ptp->dxfer_dir = CAM_DIR_NONE;
218*44704f69SBart Van Assche }
219*44704f69SBart Van Assche }
220*44704f69SBart Van Assche
221*44704f69SBart Van Assche void
partial_clear_scsi_pt_obj(struct sg_pt_base * vp)222*44704f69SBart Van Assche partial_clear_scsi_pt_obj(struct sg_pt_base * vp)
223*44704f69SBart Van Assche {
224*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
225*44704f69SBart Van Assche
226*44704f69SBart Van Assche if (NULL == ptp)
227*44704f69SBart Van Assche return;
228*44704f69SBart Van Assche ptp->in_err = 0;
229*44704f69SBart Van Assche ptp->os_err = 0;
230*44704f69SBart Van Assche ptp->transport_err = 0;
231*44704f69SBart Van Assche ptp->scsi_status = 0;
232*44704f69SBart Van Assche ptp->dxfer_dir = CAM_DIR_NONE;
233*44704f69SBart Van Assche ptp->dxferp = NULL;
234*44704f69SBart Van Assche ptp->dxfer_len = 0;
235*44704f69SBart Van Assche }
236*44704f69SBart Van Assche
237*44704f69SBart Van Assche void
set_scsi_pt_cdb(struct sg_pt_base * vp,const uint8_t * cdb,int cdb_len)238*44704f69SBart Van Assche set_scsi_pt_cdb(struct sg_pt_base * vp, const uint8_t * cdb,
239*44704f69SBart Van Assche int cdb_len)
240*44704f69SBart Van Assche {
241*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
242*44704f69SBart Van Assche
243*44704f69SBart Van Assche ptp->cdb = (uint8_t *)cdb;
244*44704f69SBart Van Assche ptp->cdb_len = cdb_len;
245*44704f69SBart Van Assche }
246*44704f69SBart Van Assche
247*44704f69SBart Van Assche int
get_scsi_pt_cdb_len(const struct sg_pt_base * vp)248*44704f69SBart Van Assche get_scsi_pt_cdb_len(const struct sg_pt_base * vp)
249*44704f69SBart Van Assche {
250*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
251*44704f69SBart Van Assche
252*44704f69SBart Van Assche return ptp->cdb_len;
253*44704f69SBart Van Assche }
254*44704f69SBart Van Assche
255*44704f69SBart Van Assche uint8_t *
get_scsi_pt_cdb_buf(const struct sg_pt_base * vp)256*44704f69SBart Van Assche get_scsi_pt_cdb_buf(const struct sg_pt_base * vp)
257*44704f69SBart Van Assche {
258*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
259*44704f69SBart Van Assche
260*44704f69SBart Van Assche return ptp->cdb;
261*44704f69SBart Van Assche }
262*44704f69SBart Van Assche
263*44704f69SBart Van Assche void
set_scsi_pt_sense(struct sg_pt_base * vp,uint8_t * sense,int max_sense_len)264*44704f69SBart Van Assche set_scsi_pt_sense(struct sg_pt_base * vp, uint8_t * sense,
265*44704f69SBart Van Assche int max_sense_len)
266*44704f69SBart Van Assche {
267*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
268*44704f69SBart Van Assche
269*44704f69SBart Van Assche if (sense) {
270*44704f69SBart Van Assche if (max_sense_len > 0)
271*44704f69SBart Van Assche bzero(sense, max_sense_len);
272*44704f69SBart Van Assche }
273*44704f69SBart Van Assche ptp->sense = sense;
274*44704f69SBart Van Assche ptp->sense_len = max_sense_len;
275*44704f69SBart Van Assche }
276*44704f69SBart Van Assche
277*44704f69SBart Van Assche /* from device */
278*44704f69SBart Van Assche void
set_scsi_pt_data_in(struct sg_pt_base * vp,uint8_t * dxferp,int dxfer_len)279*44704f69SBart Van Assche set_scsi_pt_data_in(struct sg_pt_base * vp, uint8_t * dxferp,
280*44704f69SBart Van Assche int dxfer_len)
281*44704f69SBart Van Assche {
282*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
283*44704f69SBart Van Assche
284*44704f69SBart Van Assche if (ptp->dxferp)
285*44704f69SBart Van Assche ++ptp->in_err;
286*44704f69SBart Van Assche if (dxfer_len > 0) {
287*44704f69SBart Van Assche ptp->dxferp = dxferp;
288*44704f69SBart Van Assche ptp->dxfer_len = dxfer_len;
289*44704f69SBart Van Assche ptp->dxfer_dir = CAM_DIR_IN;
290*44704f69SBart Van Assche }
291*44704f69SBart Van Assche }
292*44704f69SBart Van Assche
293*44704f69SBart Van Assche /* to device */
294*44704f69SBart Van Assche void
set_scsi_pt_data_out(struct sg_pt_base * vp,const uint8_t * dxferp,int dxfer_len)295*44704f69SBart Van Assche set_scsi_pt_data_out(struct sg_pt_base * vp, const uint8_t * dxferp,
296*44704f69SBart Van Assche int dxfer_len)
297*44704f69SBart Van Assche {
298*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
299*44704f69SBart Van Assche
300*44704f69SBart Van Assche if (ptp->dxferp)
301*44704f69SBart Van Assche ++ptp->in_err;
302*44704f69SBart Van Assche if (dxfer_len > 0) {
303*44704f69SBart Van Assche ptp->dxferp = (uint8_t *)dxferp;
304*44704f69SBart Van Assche ptp->dxfer_len = dxfer_len;
305*44704f69SBart Van Assche ptp->dxfer_dir = CAM_DIR_OUT;
306*44704f69SBart Van Assche }
307*44704f69SBart Van Assche }
308*44704f69SBart Van Assche
309*44704f69SBart Van Assche void
set_scsi_pt_packet_id(struct sg_pt_base * vp,int pack_id)310*44704f69SBart Van Assche set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id)
311*44704f69SBart Van Assche {
312*44704f69SBart Van Assche }
313*44704f69SBart Van Assche
314*44704f69SBart Van Assche void
set_scsi_pt_tag(struct sg_pt_base * vp,uint64_t tag)315*44704f69SBart Van Assche set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag)
316*44704f69SBart Van Assche {
317*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
318*44704f69SBart Van Assche
319*44704f69SBart Van Assche ++ptp->in_err;
320*44704f69SBart Van Assche }
321*44704f69SBart Van Assche
322*44704f69SBart Van Assche void
set_scsi_pt_task_management(struct sg_pt_base * vp,int tmf_code)323*44704f69SBart Van Assche set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code)
324*44704f69SBart Van Assche {
325*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
326*44704f69SBart Van Assche
327*44704f69SBart Van Assche ++ptp->in_err;
328*44704f69SBart Van Assche }
329*44704f69SBart Van Assche
330*44704f69SBart Van Assche void
set_scsi_pt_task_attr(struct sg_pt_base * vp,int attrib,int priority)331*44704f69SBart Van Assche set_scsi_pt_task_attr(struct sg_pt_base * vp, int attrib, int priority)
332*44704f69SBart Van Assche {
333*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
334*44704f69SBart Van Assche
335*44704f69SBart Van Assche ++ptp->in_err;
336*44704f69SBart Van Assche }
337*44704f69SBart Van Assche
338*44704f69SBart Van Assche void
set_scsi_pt_flags(struct sg_pt_base * objp,int flags)339*44704f69SBart Van Assche set_scsi_pt_flags(struct sg_pt_base * objp, int flags)
340*44704f69SBart Van Assche {
341*44704f69SBart Van Assche /* do nothing, suppress warnings */
342*44704f69SBart Van Assche objp = objp;
343*44704f69SBart Van Assche flags = flags;
344*44704f69SBart Van Assche }
345*44704f69SBart Van Assche
346*44704f69SBart Van Assche static int
release_sim(struct sg_pt_base * vp,int device_fd,int verbose)347*44704f69SBart Van Assche release_sim(struct sg_pt_base *vp, int device_fd, int verbose) {
348*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
349*44704f69SBart Van Assche struct osf1_dev_channel *fdchan = devicetable[device_fd];
350*44704f69SBart Van Assche UAGT_CAM_CCB uagt;
351*44704f69SBart Van Assche CCB_RELSIM relsim;
352*44704f69SBart Van Assche int retval;
353*44704f69SBart Van Assche
354*44704f69SBart Van Assche bzero(&uagt, sizeof(uagt));
355*44704f69SBart Van Assche bzero(&relsim, sizeof(relsim));
356*44704f69SBart Van Assche
357*44704f69SBart Van Assche uagt.uagt_ccb = (CCB_HEADER *) &relsim;
358*44704f69SBart Van Assche uagt.uagt_ccblen = sizeof(relsim);
359*44704f69SBart Van Assche
360*44704f69SBart Van Assche relsim.cam_ch.cam_ccb_len = sizeof(relsim);
361*44704f69SBart Van Assche relsim.cam_ch.cam_func_code = XPT_REL_SIMQ;
362*44704f69SBart Van Assche relsim.cam_ch.cam_flags = CAM_DIR_IN | CAM_DIS_CALLBACK;
363*44704f69SBart Van Assche relsim.cam_ch.cam_path_id = fdchan->bus;
364*44704f69SBart Van Assche relsim.cam_ch.cam_target_id = fdchan->tgt;
365*44704f69SBart Van Assche relsim.cam_ch.cam_target_lun = fdchan->lun;
366*44704f69SBart Van Assche
367*44704f69SBart Van Assche retval = ioctl(camfd, UAGT_CAM_IO, &uagt);
368*44704f69SBart Van Assche if (retval < 0) {
369*44704f69SBart Van Assche if (verbose)
370*44704f69SBart Van Assche pr2ws("CAM ioctl error (Release SIM Queue)\n");
371*44704f69SBart Van Assche }
372*44704f69SBart Van Assche return retval;
373*44704f69SBart Van Assche }
374*44704f69SBart Van Assche
375*44704f69SBart Van Assche int
do_scsi_pt(struct sg_pt_base * vp,int device_fd,int time_secs,int verbose)376*44704f69SBart Van Assche do_scsi_pt(struct sg_pt_base * vp, int device_fd, int time_secs, int verbose)
377*44704f69SBart Van Assche {
378*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
379*44704f69SBart Van Assche struct osf1_dev_channel *fdchan;
380*44704f69SBart Van Assche int len, retval;
381*44704f69SBart Van Assche CCB_SCSIIO ccb;
382*44704f69SBart Van Assche UAGT_CAM_CCB uagt;
383*44704f69SBart Van Assche uint8_t sensep[ADDL_SENSE_LENGTH];
384*44704f69SBart Van Assche
385*44704f69SBart Van Assche
386*44704f69SBart Van Assche ptp->os_err = 0;
387*44704f69SBart Van Assche if (ptp->in_err) {
388*44704f69SBart Van Assche if (verbose)
389*44704f69SBart Van Assche pr2ws("Replicated or unused set_scsi_pt...\n");
390*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
391*44704f69SBart Van Assche }
392*44704f69SBart Van Assche if (device_fd < 0) {
393*44704f69SBart Van Assche if (ptp->dev_fd < 0) {
394*44704f69SBart Van Assche if (verbose)
395*44704f69SBart Van Assche pr2ws("%s: No device file descriptor given\n", __func__);
396*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
397*44704f69SBart Van Assche }
398*44704f69SBart Van Assche } else {
399*44704f69SBart Van Assche if (ptp->dev_fd >= 0) {
400*44704f69SBart Van Assche if (device_fd != ptp->dev_fd) {
401*44704f69SBart Van Assche if (verbose)
402*44704f69SBart Van Assche pr2ws("%s: file descriptor given to create and this "
403*44704f69SBart Van Assche "differ\n", __func__);
404*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
405*44704f69SBart Van Assche }
406*44704f69SBart Van Assche } else
407*44704f69SBart Van Assche ptp->dev_fd = device_fd;
408*44704f69SBart Van Assche }
409*44704f69SBart Van Assche if (NULL == ptp->cdb) {
410*44704f69SBart Van Assche if (verbose)
411*44704f69SBart Van Assche pr2ws("No command (cdb) given\n");
412*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
413*44704f69SBart Van Assche }
414*44704f69SBart Van Assche
415*44704f69SBart Van Assche if ((ptp->dev_fd < 0) || (ptp->dev_fd >= OSF1_MAXDEV)) {
416*44704f69SBart Van Assche if (verbose)
417*44704f69SBart Van Assche pr2ws("Bad file descriptor\n");
418*44704f69SBart Van Assche ptp->os_err = ENODEV;
419*44704f69SBart Van Assche return -ptp->os_err;
420*44704f69SBart Van Assche }
421*44704f69SBart Van Assche fdchan = devicetable[ptp->dev_fd];
422*44704f69SBart Van Assche if (NULL == fdchan) {
423*44704f69SBart Van Assche if (verbose)
424*44704f69SBart Van Assche pr2ws("File descriptor closed??\n");
425*44704f69SBart Van Assche ptp->os_err = ENODEV;
426*44704f69SBart Van Assche return -ptp->os_err;
427*44704f69SBart Van Assche }
428*44704f69SBart Van Assche if (0 == camopened) {
429*44704f69SBart Van Assche if (verbose)
430*44704f69SBart Van Assche pr2ws("No open CAM device\n");
431*44704f69SBart Van Assche return SCSI_PT_DO_BAD_PARAMS;
432*44704f69SBart Van Assche }
433*44704f69SBart Van Assche
434*44704f69SBart Van Assche bzero(&uagt, sizeof(uagt));
435*44704f69SBart Van Assche bzero(&ccb, sizeof(ccb));
436*44704f69SBart Van Assche
437*44704f69SBart Van Assche uagt.uagt_ccb = (CCB_HEADER *) &ccb;
438*44704f69SBart Van Assche uagt.uagt_ccblen = sizeof(ccb);
439*44704f69SBart Van Assche uagt.uagt_snsbuf = ccb.cam_sense_ptr = ptp->sense ? ptp->sense : sensep;
440*44704f69SBart Van Assche uagt.uagt_snslen = ccb.cam_sense_len = ptp->sense ? ptp->sense_len :
441*44704f69SBart Van Assche sizeof sensep;
442*44704f69SBart Van Assche uagt.uagt_buffer = ccb.cam_data_ptr = ptp->dxferp;
443*44704f69SBart Van Assche uagt.uagt_buflen = ccb.cam_dxfer_len = ptp->dxfer_len;
444*44704f69SBart Van Assche
445*44704f69SBart Van Assche ccb.cam_timeout = time_secs;
446*44704f69SBart Van Assche ccb.cam_ch.my_addr = (CCB_HEADER *) &ccb;
447*44704f69SBart Van Assche ccb.cam_ch.cam_ccb_len = sizeof(ccb);
448*44704f69SBart Van Assche ccb.cam_ch.cam_func_code = XPT_SCSI_IO;
449*44704f69SBart Van Assche ccb.cam_ch.cam_flags = ptp->dxfer_dir;
450*44704f69SBart Van Assche ccb.cam_cdb_len = ptp->cdb_len;
451*44704f69SBart Van Assche memcpy(ccb.cam_cdb_io.cam_cdb_bytes, ptp->cdb, ptp->cdb_len);
452*44704f69SBart Van Assche ccb.cam_ch.cam_path_id = fdchan->bus;
453*44704f69SBart Van Assche ccb.cam_ch.cam_target_id = fdchan->tgt;
454*44704f69SBart Van Assche ccb.cam_ch.cam_target_lun = fdchan->lun;
455*44704f69SBart Van Assche
456*44704f69SBart Van Assche if (ioctl(camfd, UAGT_CAM_IO, &uagt) < 0) {
457*44704f69SBart Van Assche if (verbose)
458*44704f69SBart Van Assche pr2ws("CAN I/O Error\n");
459*44704f69SBart Van Assche ptp->os_err = EIO;
460*44704f69SBart Van Assche return -ptp->os_err;
461*44704f69SBart Van Assche }
462*44704f69SBart Van Assche
463*44704f69SBart Van Assche if (((ccb.cam_ch.cam_status & CAM_STATUS_MASK) == CAM_REQ_CMP) ||
464*44704f69SBart Van Assche ((ccb.cam_ch.cam_status & CAM_STATUS_MASK) == CAM_REQ_CMP_ERR)) {
465*44704f69SBart Van Assche ptp->scsi_status = ccb.cam_scsi_status;
466*44704f69SBart Van Assche ptp->resid = ccb.cam_resid;
467*44704f69SBart Van Assche if (ptp->sense)
468*44704f69SBart Van Assche ptp->sense_resid = ccb.cam_sense_resid;
469*44704f69SBart Van Assche } else {
470*44704f69SBart Van Assche ptp->transport_err = 1;
471*44704f69SBart Van Assche }
472*44704f69SBart Van Assche
473*44704f69SBart Van Assche /* If the SIM queue is frozen, release SIM queue. */
474*44704f69SBart Van Assche if (ccb.cam_ch.cam_status & CAM_SIM_QFRZN)
475*44704f69SBart Van Assche release_sim(vp, ptp->dev_fd, verbose);
476*44704f69SBart Van Assche
477*44704f69SBart Van Assche return 0;
478*44704f69SBart Van Assche }
479*44704f69SBart Van Assche
480*44704f69SBart Van Assche int
get_scsi_pt_result_category(const struct sg_pt_base * vp)481*44704f69SBart Van Assche get_scsi_pt_result_category(const struct sg_pt_base * vp)
482*44704f69SBart Van Assche {
483*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
484*44704f69SBart Van Assche
485*44704f69SBart Van Assche if (ptp->os_err)
486*44704f69SBart Van Assche return SCSI_PT_RESULT_OS_ERR;
487*44704f69SBart Van Assche else if (ptp->transport_err)
488*44704f69SBart Van Assche return SCSI_PT_RESULT_TRANSPORT_ERR;
489*44704f69SBart Van Assche else if ((SAM_STAT_CHECK_CONDITION == ptp->scsi_status) ||
490*44704f69SBart Van Assche (SAM_STAT_COMMAND_TERMINATED == ptp->scsi_status))
491*44704f69SBart Van Assche return SCSI_PT_RESULT_SENSE;
492*44704f69SBart Van Assche else if (ptp->scsi_status)
493*44704f69SBart Van Assche return SCSI_PT_RESULT_STATUS;
494*44704f69SBart Van Assche else
495*44704f69SBart Van Assche return SCSI_PT_RESULT_GOOD;
496*44704f69SBart Van Assche }
497*44704f69SBart Van Assche
498*44704f69SBart Van Assche int
get_scsi_pt_resid(const struct sg_pt_base * vp)499*44704f69SBart Van Assche get_scsi_pt_resid(const struct sg_pt_base * vp)
500*44704f69SBart Van Assche {
501*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
502*44704f69SBart Van Assche
503*44704f69SBart Van Assche return ptp->resid;
504*44704f69SBart Van Assche }
505*44704f69SBart Van Assche
506*44704f69SBart Van Assche void
get_pt_req_lengths(const struct sg_pt_base * vp,int * req_dinp,int * req_doutp)507*44704f69SBart Van Assche get_pt_req_lengths(const struct sg_pt_base * vp, int * req_dinp,
508*44704f69SBart Van Assche int * req_doutp)
509*44704f69SBart Van Assche {
510*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
511*44704f69SBart Van Assche bool bidi = (ptp->dxfer_dir == CAM_DIR_BOTH);
512*44704f69SBart Van Assche
513*44704f69SBart Van Assche if (req_dinp) {
514*44704f69SBart Van Assche if (ptp->dxfer_len > 0)
515*44704f69SBart Van Assche *req_dinp = ptp->dxfer_len;
516*44704f69SBart Van Assche else
517*44704f69SBart Van Assche *req_dinp = 0;
518*44704f69SBart Van Assche }
519*44704f69SBart Van Assche if (req_doutp) {
520*44704f69SBart Van Assche if ((!bidi) && (ptp->dxfer_len > 0))
521*44704f69SBart Van Assche *req_doutp = ptp->dxfer_len;
522*44704f69SBart Van Assche else
523*44704f69SBart Van Assche *req_doutp = 0;
524*44704f69SBart Van Assche }
525*44704f69SBart Van Assche }
526*44704f69SBart Van Assche
527*44704f69SBart Van Assche void
get_pt_actual_lengths(const struct sg_pt_base * vp,int * act_dinp,int * act_doutp)528*44704f69SBart Van Assche get_pt_actual_lengths(const struct sg_pt_base * vp, int * act_dinp,
529*44704f69SBart Van Assche int * act_doutp)
530*44704f69SBart Van Assche {
531*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
532*44704f69SBart Van Assche bool bidi = (ptp->dxfer_dir == CAM_DIR_BOTH);
533*44704f69SBart Van Assche
534*44704f69SBart Van Assche if (act_dinp) {
535*44704f69SBart Van Assche if (ptp->dxfer_len > 0)
536*44704f69SBart Van Assche *act_dinp = ptp->dxfer_len - ptp->resid;
537*44704f69SBart Van Assche else
538*44704f69SBart Van Assche *act_dinp = 0;
539*44704f69SBart Van Assche }
540*44704f69SBart Van Assche if (act_doutp) {
541*44704f69SBart Van Assche if ((!bidi) && (ptp->dxfer_len > 0))
542*44704f69SBart Van Assche *act_doutp = ptp->dxfer_len - ptp->resid;
543*44704f69SBart Van Assche else
544*44704f69SBart Van Assche *act_doutp = 0;
545*44704f69SBart Van Assche }
546*44704f69SBart Van Assche }
547*44704f69SBart Van Assche
548*44704f69SBart Van Assche
549*44704f69SBart Van Assche int
get_scsi_pt_status_response(const struct sg_pt_base * vp)550*44704f69SBart Van Assche get_scsi_pt_status_response(const struct sg_pt_base * vp)
551*44704f69SBart Van Assche {
552*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
553*44704f69SBart Van Assche
554*44704f69SBart Van Assche return ptp->scsi_status;
555*44704f69SBart Van Assche }
556*44704f69SBart Van Assche
557*44704f69SBart Van Assche int
get_scsi_pt_sense_len(const struct sg_pt_base * vp)558*44704f69SBart Van Assche get_scsi_pt_sense_len(const struct sg_pt_base * vp)
559*44704f69SBart Van Assche {
560*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
561*44704f69SBart Van Assche int len;
562*44704f69SBart Van Assche
563*44704f69SBart Van Assche len = ptp->sense_len - ptp->sense_resid;
564*44704f69SBart Van Assche return (len > 0) ? len : 0;
565*44704f69SBart Van Assche }
566*44704f69SBart Van Assche
567*44704f69SBart Van Assche uint8_t *
get_scsi_pt_sense_buf(const struct sg_pt_base * vp)568*44704f69SBart Van Assche get_scsi_pt_sense_buf(const struct sg_pt_base * vp)
569*44704f69SBart Van Assche {
570*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
571*44704f69SBart Van Assche
572*44704f69SBart Van Assche return ptp->sense;
573*44704f69SBart Van Assche }
574*44704f69SBart Van Assche
575*44704f69SBart Van Assche int
get_scsi_pt_duration_ms(const struct sg_pt_base * vp)576*44704f69SBart Van Assche get_scsi_pt_duration_ms(const struct sg_pt_base * vp)
577*44704f69SBart Van Assche {
578*44704f69SBart Van Assche // const struct sg_pt_osf1_scsi * ptp = &vp->impl;
579*44704f69SBart Van Assche
580*44704f69SBart Van Assche return -1;
581*44704f69SBart Van Assche }
582*44704f69SBart Van Assche
583*44704f69SBart Van Assche /* If not available return 0 otherwise return number of nanoseconds that the
584*44704f69SBart Van Assche * lower layers (and hardware) took to execute the command just completed. */
585*44704f69SBart Van Assche uint64_t
get_pt_duration_ns(const struct sg_pt_base * vp)586*44704f69SBart Van Assche get_pt_duration_ns(const struct sg_pt_base * vp __attribute__ ((unused)))
587*44704f69SBart Van Assche {
588*44704f69SBart Van Assche return 0;
589*44704f69SBart Van Assche }
590*44704f69SBart Van Assche
591*44704f69SBart Van Assche int
get_scsi_pt_transport_err(const struct sg_pt_base * vp)592*44704f69SBart Van Assche get_scsi_pt_transport_err(const struct sg_pt_base * vp)
593*44704f69SBart Van Assche {
594*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
595*44704f69SBart Van Assche
596*44704f69SBart Van Assche return ptp->transport_err;
597*44704f69SBart Van Assche }
598*44704f69SBart Van Assche
599*44704f69SBart Van Assche int
get_scsi_pt_os_err(const struct sg_pt_base * vp)600*44704f69SBart Van Assche get_scsi_pt_os_err(const struct sg_pt_base * vp)
601*44704f69SBart Van Assche {
602*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
603*44704f69SBart Van Assche
604*44704f69SBart Van Assche return ptp->os_err;
605*44704f69SBart Van Assche }
606*44704f69SBart Van Assche
607*44704f69SBart Van Assche bool
pt_device_is_nvme(const struct sg_pt_base * vp)608*44704f69SBart Van Assche pt_device_is_nvme(const struct sg_pt_base * vp)
609*44704f69SBart Van Assche {
610*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
611*44704f69SBart Van Assche
612*44704f69SBart Van Assche return ptp ? ptp->is_nvme : false;
613*44704f69SBart Van Assche }
614*44704f69SBart Van Assche
615*44704f69SBart Van Assche char *
get_scsi_pt_transport_err_str(const struct sg_pt_base * vp,int max_b_len,char * b)616*44704f69SBart Van Assche get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len,
617*44704f69SBart Van Assche char * b)
618*44704f69SBart Van Assche {
619*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
620*44704f69SBart Van Assche
621*44704f69SBart Van Assche if (0 == ptp->transport_err) {
622*44704f69SBart Van Assche strncpy(b, "no transport error available", max_b_len);
623*44704f69SBart Van Assche b[max_b_len - 1] = '\0';
624*44704f69SBart Van Assche return b;
625*44704f69SBart Van Assche }
626*44704f69SBart Van Assche strncpy(b, "no transport error available", max_b_len);
627*44704f69SBart Van Assche b[max_b_len - 1] = '\0';
628*44704f69SBart Van Assche return b;
629*44704f69SBart Van Assche }
630*44704f69SBart Van Assche
631*44704f69SBart Van Assche char *
get_scsi_pt_os_err_str(const struct sg_pt_base * vp,int max_b_len,char * b)632*44704f69SBart Van Assche get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b)
633*44704f69SBart Van Assche {
634*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
635*44704f69SBart Van Assche const char * cp;
636*44704f69SBart Van Assche
637*44704f69SBart Van Assche cp = safe_strerror(ptp->os_err);
638*44704f69SBart Van Assche strncpy(b, cp, max_b_len);
639*44704f69SBart Van Assche if ((int)strlen(cp) >= max_b_len)
640*44704f69SBart Van Assche b[max_b_len - 1] = '\0';
641*44704f69SBart Van Assche return b;
642*44704f69SBart Van Assche }
643*44704f69SBart Van Assche
644*44704f69SBart Van Assche int
do_nvm_pt(struct sg_pt_base * vp,int submq,int timeout_secs,int verbose)645*44704f69SBart Van Assche do_nvm_pt(struct sg_pt_base * vp, int submq, int timeout_secs, int verbose)
646*44704f69SBart Van Assche {
647*44704f69SBart Van Assche if (vp) { }
648*44704f69SBart Van Assche if (submq) { }
649*44704f69SBart Van Assche if (timeout_secs) { }
650*44704f69SBart Van Assche if (verbose) { }
651*44704f69SBart Van Assche return SCSI_PT_DO_NOT_SUPPORTED;
652*44704f69SBart Van Assche }
653*44704f69SBart Van Assche
654*44704f69SBart Van Assche int
check_pt_file_handle(int device_fd,const char * device_name,int vb)655*44704f69SBart Van Assche check_pt_file_handle(int device_fd, const char * device_name, int vb)
656*44704f69SBart Van Assche {
657*44704f69SBart Van Assche if (device_fd) {}
658*44704f69SBart Van Assche if (device_name) {}
659*44704f69SBart Van Assche if (vb) {}
660*44704f69SBart Van Assche return 0;
661*44704f69SBart Van Assche }
662*44704f69SBart Van Assche
663*44704f69SBart Van Assche /* Valid file handles (which is the return value) are >= 0 . Returns -1
664*44704f69SBart Van Assche * if there is no valid file handle. */
665*44704f69SBart Van Assche int
get_pt_file_handle(const struct sg_pt_base * vp)666*44704f69SBart Van Assche get_pt_file_handle(const struct sg_pt_base * vp)
667*44704f69SBart Van Assche {
668*44704f69SBart Van Assche const struct sg_pt_osf1_scsi * ptp = &vp->impl;
669*44704f69SBart Van Assche
670*44704f69SBart Van Assche return ptp->dev_fd;
671*44704f69SBart Van Assche }
672*44704f69SBart Van Assche
673*44704f69SBart Van Assche /* If a NVMe block device (which includes the NSID) handle is associated
674*44704f69SBart Van Assche * with 'vp', then its NSID is returned (values range from 0x1 to
675*44704f69SBart Van Assche * 0xffffffe). Otherwise 0 is returned. */
676*44704f69SBart Van Assche uint32_t
get_pt_nvme_nsid(const struct sg_pt_base * vp)677*44704f69SBart Van Assche get_pt_nvme_nsid(const struct sg_pt_base * vp)
678*44704f69SBart Van Assche {
679*44704f69SBart Van Assche if (vp) { }
680*44704f69SBart Van Assche return 0;
681*44704f69SBart Van Assche }
682*44704f69SBart Van Assche
683*44704f69SBart Van Assche uint32_t
get_pt_result(const struct sg_pt_base * vp)684*44704f69SBart Van Assche get_pt_result(const struct sg_pt_base * vp)
685*44704f69SBart Van Assche {
686*44704f69SBart Van Assche if (vp) { }
687*44704f69SBart Van Assche return 0;
688*44704f69SBart Van Assche }
689*44704f69SBart Van Assche
690*44704f69SBart Van Assche /* Forget any previous dev_han and install the one given. May attempt to
691*44704f69SBart Van Assche * find file type (e.g. if pass-though) from OS so there could be an error.
692*44704f69SBart Van Assche * Returns 0 for success or the same value as get_scsi_pt_os_err()
693*44704f69SBart Van Assche * will return. dev_han should be >= 0 for a valid file handle or -1 . */
694*44704f69SBart Van Assche int
set_pt_file_handle(struct sg_pt_base * vp,int dev_han,int vb)695*44704f69SBart Van Assche set_pt_file_handle(struct sg_pt_base * vp, int dev_han, int vb)
696*44704f69SBart Van Assche {
697*44704f69SBart Van Assche struct sg_pt_osf1_scsi * ptp = &vp->impl;
698*44704f69SBart Van Assche
699*44704f69SBart Van Assche if (vb) {}
700*44704f69SBart Van Assche ptp->dev_fd = (dev_han < 0) ? -1 : dev_han;
701*44704f69SBart Van Assche ptp->in_err = 0;
702*44704f69SBart Van Assche ptp->os_err = 0;
703*44704f69SBart Van Assche ptp->is_nvme = false;
704*44704f69SBart Van Assche return 0;
705*44704f69SBart Van Assche }
706*44704f69SBart Van Assche
707*44704f69SBart Van Assche void
set_scsi_pt_transport_err(struct sg_pt_base * vp,int err)708*44704f69SBart Van Assche set_scsi_pt_transport_err(struct sg_pt_base * vp, int err)
709*44704f69SBart Van Assche {
710*44704f69SBart Van Assche if (vp) { }
711*44704f69SBart Van Assche if (err) { }
712*44704f69SBart Van Assche }
713*44704f69SBart Van Assche
714*44704f69SBart Van Assche void
set_pt_metadata_xfer(struct sg_pt_base * vp,uint8_t * mdxferp,uint32_t mdxfer_len,bool out_true)715*44704f69SBart Van Assche set_pt_metadata_xfer(struct sg_pt_base * vp, uint8_t * mdxferp,
716*44704f69SBart Van Assche uint32_t mdxfer_len, bool out_true)
717*44704f69SBart Van Assche {
718*44704f69SBart Van Assche if (vp) { }
719*44704f69SBart Van Assche if (mdxferp) { }
720*44704f69SBart Van Assche if (mdxfer_len) { }
721*44704f69SBart Van Assche if (out_true) { }
722*44704f69SBart Van Assche }
723