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