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