1 /* 2 * Copyright (c) 2005-2018 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 8 /* sg_pt_linux version 1.37 20180126 */ 9 10 11 #include <stdio.h> 12 #include <stdlib.h> 13 #include <stdarg.h> 14 #include <stdbool.h> 15 #include <string.h> 16 #include <ctype.h> 17 #include <unistd.h> 18 #include <errno.h> 19 #include <fcntl.h> 20 #include <sys/ioctl.h> 21 #include <sys/stat.h> 22 #include <sys/sysmacros.h> /* to define 'major' */ 23 #ifndef major 24 #include <sys/types.h> 25 #endif 26 27 28 #ifdef HAVE_CONFIG_H 29 #include "config.h" 30 #endif 31 32 #include <linux/major.h> 33 34 #include "sg_pt.h" 35 #include "sg_lib.h" 36 #include "sg_linux_inc.h" 37 #include "sg_pt_linux.h" 38 39 40 #ifdef major 41 #define SG_DEV_MAJOR major 42 #else 43 #ifdef HAVE_LINUX_KDEV_T_H 44 #include <linux/kdev_t.h> 45 #endif 46 #define SG_DEV_MAJOR MAJOR /* MAJOR() macro faulty if > 255 minors */ 47 #endif 48 49 #ifndef BLOCK_EXT_MAJOR 50 #define BLOCK_EXT_MAJOR 259 51 #endif 52 53 #define DEF_TIMEOUT 60000 /* 60,000 millisecs (60 seconds) */ 54 55 static const char * linux_host_bytes[] = { 56 "DID_OK", "DID_NO_CONNECT", "DID_BUS_BUSY", "DID_TIME_OUT", 57 "DID_BAD_TARGET", "DID_ABORT", "DID_PARITY", "DID_ERROR", 58 "DID_RESET", "DID_BAD_INTR", "DID_PASSTHROUGH", "DID_SOFT_ERROR", 59 "DID_IMM_RETRY", "DID_REQUEUE" /* 0xd */, 60 "DID_TRANSPORT_DISRUPTED", "DID_TRANSPORT_FAILFAST", 61 "DID_TARGET_FAILURE" /* 0x10 */, 62 "DID_NEXUS_FAILURE (reservation conflict)", 63 "DID_ALLOC_FAILURE", 64 "DID_MEDIUM_ERROR", 65 }; 66 67 #define LINUX_HOST_BYTES_SZ \ 68 (int)(sizeof(linux_host_bytes) / sizeof(linux_host_bytes[0])) 69 70 static const char * linux_driver_bytes[] = { 71 "DRIVER_OK", "DRIVER_BUSY", "DRIVER_SOFT", "DRIVER_MEDIA", 72 "DRIVER_ERROR", "DRIVER_INVALID", "DRIVER_TIMEOUT", "DRIVER_HARD", 73 "DRIVER_SENSE" 74 }; 75 76 #define LINUX_DRIVER_BYTES_SZ \ 77 (int)(sizeof(linux_driver_bytes) / sizeof(linux_driver_bytes[0])) 78 79 #if 0 80 static const char * linux_driver_suggests[] = { 81 "SUGGEST_OK", "SUGGEST_RETRY", "SUGGEST_ABORT", "SUGGEST_REMAP", 82 "SUGGEST_DIE", "UNKNOWN","UNKNOWN","UNKNOWN", 83 "SUGGEST_SENSE" 84 }; 85 86 #define LINUX_DRIVER_SUGGESTS_SZ \ 87 (int)(sizeof(linux_driver_suggests) / sizeof(linux_driver_suggests[0])) 88 #endif 89 90 /* 91 * These defines are for constants that should be visible in the 92 * /usr/include/scsi directory (brought in by sg_linux_inc.h). 93 * Redefined and aliased here to decouple this code from 94 * sg_io_linux.h N.B. the SUGGEST_* constants are no longer used. 95 */ 96 #ifndef DRIVER_MASK 97 #define DRIVER_MASK 0x0f 98 #endif 99 #ifndef SUGGEST_MASK 100 #define SUGGEST_MASK 0xf0 101 #endif 102 #ifndef DRIVER_SENSE 103 #define DRIVER_SENSE 0x08 104 #endif 105 #define SG_LIB_DRIVER_MASK DRIVER_MASK 106 #define SG_LIB_SUGGEST_MASK SUGGEST_MASK 107 #define SG_LIB_DRIVER_SENSE DRIVER_SENSE 108 109 bool sg_bsg_nvme_char_major_checked = false; 110 int sg_bsg_major = 0; 111 volatile int sg_nvme_char_major = 0; 112 113 long sg_lin_page_size = 4096; /* default, overridden with correct value */ 114 115 116 #if defined(__GNUC__) || defined(__clang__) 117 static int pr2ws(const char * fmt, ...) 118 __attribute__ ((format (printf, 1, 2))); 119 #else 120 static int pr2ws(const char * fmt, ...); 121 #endif 122 123 124 static int 125 pr2ws(const char * fmt, ...) 126 { 127 va_list args; 128 int n; 129 130 va_start(args, fmt); 131 n = vfprintf(sg_warnings_strm ? sg_warnings_strm : stderr, fmt, args); 132 va_end(args); 133 return n; 134 } 135 136 /* This function only needs to be called once (unless a NVMe controller 137 * can be hot-plugged into system in which case it should be called 138 * (again) after that event). */ 139 void 140 sg_find_bsg_nvme_char_major(int verbose) 141 { 142 bool got_one = false; 143 int n; 144 const char * proc_devices = "/proc/devices"; 145 char * cp; 146 FILE *fp; 147 char a[128]; 148 char b[128]; 149 150 sg_lin_page_size = sysconf(_SC_PAGESIZE); 151 if (NULL == (fp = fopen(proc_devices, "r"))) { 152 if (verbose) 153 pr2ws("fopen %s failed: %s\n", proc_devices, strerror(errno)); 154 return; 155 } 156 while ((cp = fgets(b, sizeof(b), fp))) { 157 if ((1 == sscanf(b, "%126s", a)) && 158 (0 == memcmp(a, "Character", 9))) 159 break; 160 } 161 while (cp && (cp = fgets(b, sizeof(b), fp))) { 162 if (2 == sscanf(b, "%d %126s", &n, a)) { 163 if (0 == strcmp("bsg", a)) { 164 sg_bsg_major = n; 165 if (got_one) 166 break; 167 got_one = true; 168 } else if (0 == strcmp("nvme", a)) { 169 sg_nvme_char_major = n; 170 if (got_one) 171 break; 172 got_one = true; 173 } 174 } else 175 break; 176 } 177 if (verbose > 3) { 178 if (cp) { 179 if (sg_bsg_major > 0) 180 pr2ws("found sg_bsg_major=%d\n", sg_bsg_major); 181 if (sg_nvme_char_major > 0) 182 pr2ws("found sg_nvme_char_major=%d\n", sg_nvme_char_major); 183 } else 184 pr2ws("found no bsg not nvme char device in %s\n", proc_devices); 185 } 186 fclose(fp); 187 } 188 189 /* Assumes that sg_find_bsg_nvme_char_major() has already been called. Returns 190 * true if dev_fd is a scsi generic pass-through device. If yields 191 * *is_nvme_p = true with *nsid_p = 0 then dev_fd is a NVMe char device. 192 * If yields *nsid_p > 0 then dev_fd is a NVMe block device. */ 193 static bool 194 check_file_type(int dev_fd, struct stat * dev_statp, bool * is_bsg_p, 195 bool * is_nvme_p, uint32_t * nsid_p, int * os_err_p, 196 int verbose) 197 { 198 bool is_nvme = false; 199 bool is_sg = false; 200 bool is_bsg = false; 201 bool is_block = false; 202 int os_err = 0; 203 int major_num; 204 uint32_t nsid = 0; /* invalid NSID */ 205 206 if (dev_fd >= 0) { 207 if (fstat(dev_fd, dev_statp) < 0) { 208 os_err = errno; 209 if (verbose) 210 pr2ws("%s: fstat() failed: %s (errno=%d)\n", __func__, 211 safe_strerror(os_err), os_err); 212 goto skip_out; 213 } 214 major_num = (int)SG_DEV_MAJOR(dev_statp->st_rdev); 215 if (S_ISCHR(dev_statp->st_mode)) { 216 if (SCSI_GENERIC_MAJOR == major_num) 217 is_sg = true; 218 else if (sg_bsg_major == major_num) 219 is_bsg = true; 220 else if (sg_nvme_char_major == major_num) 221 is_nvme = true; 222 } else if (S_ISBLK(dev_statp->st_mode)) { 223 is_block = true; 224 if (BLOCK_EXT_MAJOR == major_num) { 225 is_nvme = true; 226 nsid = ioctl(dev_fd, NVME_IOCTL_ID, NULL); 227 if (SG_NVME_BROADCAST_NSID == nsid) { /* means ioctl error */ 228 os_err = errno; 229 if (verbose) 230 pr2ws("%s: ioctl(NVME_IOCTL_ID) failed: %s " 231 "(errno=%d)\n", __func__, safe_strerror(os_err), 232 os_err); 233 } else 234 os_err = 0; 235 } 236 } 237 } else { 238 os_err = EBADF; 239 if (verbose) 240 pr2ws("%s: invalid file descriptor (%d)\n", __func__, dev_fd); 241 } 242 skip_out: 243 if (verbose > 3) { 244 pr2ws("%s: file descriptor is ", __func__); 245 if (is_sg) 246 pr2ws("sg device\n"); 247 else if (is_bsg) 248 pr2ws("bsg device\n"); 249 else if (is_nvme && (0 == nsid)) 250 pr2ws("NVMe char device\n"); 251 else if (is_nvme) 252 pr2ws("NVMe block device, nsid=%lld\n", 253 ((uint32_t)-1 == nsid) ? -1LL : (long long)nsid); 254 else if (is_block) 255 pr2ws("block device\n"); 256 else 257 pr2ws("undetermined device, could be regular file\n"); 258 } 259 if (is_bsg_p) 260 *is_bsg_p = is_bsg; 261 if (is_nvme_p) 262 *is_nvme_p = is_nvme; 263 if (nsid_p) 264 *nsid_p = nsid; 265 if (os_err_p) 266 *os_err_p = os_err; 267 return is_sg; 268 } 269 270 /* Assumes dev_fd is an "open" file handle associated with device_name. If 271 * the implementation (possibly for one OS) cannot determine from dev_fd if 272 * a SCSI or NVMe pass-through is referenced, then it might guess based on 273 * device_name. Returns 1 if SCSI generic pass-though device, returns 2 if 274 * secondary SCSI pass-through device (in Linux a bsg device); returns 3 is 275 * char NVMe device (i.e. no NSID); returns 4 if block NVMe device (includes 276 * NSID), or 0 if something else (e.g. ATA block device) or dev_fd < 0. 277 * If error, returns negated errno (operating system) value. */ 278 int 279 check_pt_file_handle(int dev_fd, const char * device_name, int verbose) 280 { 281 if (verbose > 4) 282 pr2ws("%s: dev_fd=%d, device_name: %s\n", __func__, dev_fd, 283 device_name); 284 /* Linux doesn't need device_name to determine which pass-through */ 285 if (! sg_bsg_nvme_char_major_checked) { 286 sg_bsg_nvme_char_major_checked = true; 287 sg_find_bsg_nvme_char_major(verbose); 288 } 289 if (dev_fd >= 0) { 290 bool is_sg, is_bsg, is_nvme; 291 int err; 292 uint32_t nsid; 293 struct stat a_stat; 294 295 is_sg = check_file_type(dev_fd, &a_stat, &is_bsg, &is_nvme, &nsid, 296 &err, verbose); 297 if (err) 298 return -err; 299 else if (is_sg) 300 return 1; 301 else if (is_bsg) 302 return 2; 303 else if (is_nvme && (0 == nsid)) 304 return 3; 305 else if (is_nvme) 306 return 4; 307 else 308 return 0; 309 } else 310 return 0; 311 } 312 313 /* 314 * We make a runtime decision whether to use the sg v3 interface or the sg 315 * v4 interface (currently exclusively used by the bsg driver). If all the 316 * following are true we use sg v4 which is only currently supported on bsg 317 * device nodes: 318 * a) there is a bsg entry in the /proc/devices file 319 * b) the device node given to scsi_pt_open() is a char device 320 * c) the char major number of the device node given to scsi_pt_open() 321 * matches the char major number of the bsg entry in /proc/devices 322 * Otherwise the sg v3 interface is used. 323 * 324 * Note that in either case we prepare the data in a sg v4 structure. If 325 * the runtime tests indicate that the v3 interface is needed then 326 * do_scsi_pt_v3() transfers the input data into a v3 structure and 327 * then the output data is transferred back into a sg v4 structure. 328 * That implementation detail could change in the future. 329 * 330 * [20120806] Only use MAJOR() macro in kdev_t.h if that header file is 331 * available and major() macro [N.B. lower case] is not available. 332 */ 333 334 335 #ifdef major 336 #define SG_DEV_MAJOR major 337 #else 338 #ifdef HAVE_LINUX_KDEV_T_H 339 #include <linux/kdev_t.h> 340 #endif 341 #define SG_DEV_MAJOR MAJOR /* MAJOR() macro faulty if > 255 minors */ 342 #endif 343 344 345 /* Returns >= 0 if successful. If error in Unix returns negated errno. */ 346 int 347 scsi_pt_open_device(const char * device_name, bool read_only, int verbose) 348 { 349 int oflags = O_NONBLOCK; 350 351 oflags |= (read_only ? O_RDONLY : O_RDWR); 352 return scsi_pt_open_flags(device_name, oflags, verbose); 353 } 354 355 /* Similar to scsi_pt_open_device() but takes Unix style open flags OR-ed */ 356 /* together. The 'flags' argument is advisory and may be ignored. */ 357 /* Returns >= 0 if successful, otherwise returns negated errno. */ 358 int 359 scsi_pt_open_flags(const char * device_name, int flags, int verbose) 360 { 361 int fd; 362 363 if (! sg_bsg_nvme_char_major_checked) { 364 sg_bsg_nvme_char_major_checked = true; 365 sg_find_bsg_nvme_char_major(verbose); 366 } 367 if (verbose > 1) { 368 pr2ws("open %s with flags=0x%x\n", device_name, flags); 369 } 370 fd = open(device_name, flags); 371 if (fd < 0) { 372 fd = -errno; 373 if (verbose > 1) 374 pr2ws("%s: open(%s, 0x%x) failed: %s\n", __func__, device_name, 375 flags, safe_strerror(-fd)); 376 } 377 return fd; 378 } 379 380 /* Returns 0 if successful. If error in Unix returns negated errno. */ 381 int 382 scsi_pt_close_device(int device_fd) 383 { 384 int res; 385 386 res = close(device_fd); 387 if (res < 0) 388 res = -errno; 389 return res; 390 } 391 392 393 /* Caller should additionally call get_scsi_pt_os_err() after this call */ 394 struct sg_pt_base * 395 construct_scsi_pt_obj_with_fd(int dev_fd, int verbose) 396 { 397 int err; 398 struct sg_pt_linux_scsi * ptp; 399 400 /* The following 2 lines are temporary. It is to avoid a NULL pointer 401 * crash when an old utility is used with a newer library built after 402 * the sg_warnings_strm cleanup */ 403 if (NULL == sg_warnings_strm) 404 sg_warnings_strm = stderr; 405 406 ptp = (struct sg_pt_linux_scsi *) 407 calloc(1, sizeof(struct sg_pt_linux_scsi)); 408 if (ptp) { 409 err = set_pt_file_handle((struct sg_pt_base *)ptp, dev_fd, verbose); 410 if ((0 == err) && (! ptp->is_nvme)) { 411 ptp->io_hdr.guard = 'Q'; 412 #ifdef BSG_PROTOCOL_SCSI 413 ptp->io_hdr.protocol = BSG_PROTOCOL_SCSI; 414 #endif 415 #ifdef BSG_SUB_PROTOCOL_SCSI_CMD 416 ptp->io_hdr.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; 417 #endif 418 } 419 } else if (verbose) 420 pr2ws("%s: calloc() failed, out of memory?\n", __func__); 421 422 return (struct sg_pt_base *)ptp; 423 } 424 425 struct sg_pt_base * 426 construct_scsi_pt_obj() 427 { 428 return construct_scsi_pt_obj_with_fd(-1 /* dev_fd */, 0 /* verbose */); 429 } 430 431 void 432 destruct_scsi_pt_obj(struct sg_pt_base * vp) 433 { 434 struct sg_pt_linux_scsi * ptp = &vp->impl; 435 436 if (ptp->free_nvme_id_ctlp) { 437 free(ptp->free_nvme_id_ctlp); 438 ptp->free_nvme_id_ctlp = NULL; 439 ptp->nvme_id_ctlp = NULL; 440 } 441 if (ptp) 442 free(ptp); 443 } 444 445 /* Remembers previous device file descriptor */ 446 void 447 clear_scsi_pt_obj(struct sg_pt_base * vp) 448 { 449 bool is_sg, is_bsg, is_nvme; 450 int fd; 451 uint32_t nvme_nsid; 452 struct sg_pt_linux_scsi * ptp = &vp->impl; 453 454 if (ptp) { 455 fd = ptp->dev_fd; 456 is_sg = ptp->is_sg; 457 is_bsg = ptp->is_bsg; 458 is_nvme = ptp->is_nvme; 459 nvme_nsid = ptp->nvme_nsid; 460 memset(ptp, 0, sizeof(struct sg_pt_linux_scsi)); 461 ptp->io_hdr.guard = 'Q'; 462 #ifdef BSG_PROTOCOL_SCSI 463 ptp->io_hdr.protocol = BSG_PROTOCOL_SCSI; 464 #endif 465 #ifdef BSG_SUB_PROTOCOL_SCSI_CMD 466 ptp->io_hdr.subprotocol = BSG_SUB_PROTOCOL_SCSI_CMD; 467 #endif 468 ptp->dev_fd = fd; 469 ptp->is_sg = is_sg; 470 ptp->is_bsg = is_bsg; 471 ptp->is_nvme = is_nvme; 472 ptp->nvme_direct = false; 473 ptp->nvme_nsid = nvme_nsid; 474 } 475 } 476 477 /* Forget any previous dev_fd and install the one given. May attempt to 478 * find file type (e.g. if pass-though) from OS so there could be an error. 479 * Returns 0 for success or the same value as get_scsi_pt_os_err() 480 * will return. dev_fd should be >= 0 for a valid file handle or -1 . */ 481 int 482 set_pt_file_handle(struct sg_pt_base * vp, int dev_fd, int verbose) 483 { 484 struct sg_pt_linux_scsi * ptp = &vp->impl; 485 struct stat a_stat; 486 487 if (! sg_bsg_nvme_char_major_checked) { 488 sg_bsg_nvme_char_major_checked = true; 489 sg_find_bsg_nvme_char_major(verbose); 490 } 491 ptp->dev_fd = dev_fd; 492 if (dev_fd >= 0) 493 ptp->is_sg = check_file_type(dev_fd, &a_stat, &ptp->is_bsg, 494 &ptp->is_nvme, &ptp->nvme_nsid, 495 &ptp->os_err, verbose); 496 else { 497 ptp->is_sg = false; 498 ptp->is_bsg = false; 499 ptp->is_nvme = false; 500 ptp->nvme_direct = false; 501 ptp->nvme_nsid = 0; 502 ptp->os_err = 0; 503 } 504 return ptp->os_err; 505 } 506 507 /* Valid file handles (which is the return value) are >= 0 . Returns -1 508 * if there is no valid file handle. */ 509 int 510 get_pt_file_handle(const struct sg_pt_base * vp) 511 { 512 const struct sg_pt_linux_scsi * ptp = &vp->impl; 513 514 return ptp->dev_fd; 515 } 516 517 void 518 set_scsi_pt_cdb(struct sg_pt_base * vp, const unsigned char * cdb, 519 int cdb_len) 520 { 521 struct sg_pt_linux_scsi * ptp = &vp->impl; 522 523 if (ptp->io_hdr.request) 524 ++ptp->in_err; 525 ptp->io_hdr.request = (__u64)(sg_uintptr_t)cdb; 526 ptp->io_hdr.request_len = cdb_len; 527 } 528 529 void 530 set_scsi_pt_sense(struct sg_pt_base * vp, unsigned char * sense, 531 int max_sense_len) 532 { 533 struct sg_pt_linux_scsi * ptp = &vp->impl; 534 535 if (ptp->io_hdr.response) 536 ++ptp->in_err; 537 memset(sense, 0, max_sense_len); 538 ptp->io_hdr.response = (__u64)(sg_uintptr_t)sense; 539 ptp->io_hdr.max_response_len = max_sense_len; 540 } 541 542 /* Setup for data transfer from device */ 543 void 544 set_scsi_pt_data_in(struct sg_pt_base * vp, unsigned char * dxferp, 545 int dxfer_ilen) 546 { 547 struct sg_pt_linux_scsi * ptp = &vp->impl; 548 549 if (ptp->io_hdr.din_xferp) 550 ++ptp->in_err; 551 if (dxfer_ilen > 0) { 552 ptp->io_hdr.din_xferp = (__u64)(sg_uintptr_t)dxferp; 553 ptp->io_hdr.din_xfer_len = dxfer_ilen; 554 } 555 } 556 557 /* Setup for data transfer toward device */ 558 void 559 set_scsi_pt_data_out(struct sg_pt_base * vp, const unsigned char * dxferp, 560 int dxfer_olen) 561 { 562 struct sg_pt_linux_scsi * ptp = &vp->impl; 563 564 if (ptp->io_hdr.dout_xferp) 565 ++ptp->in_err; 566 if (dxfer_olen > 0) { 567 ptp->io_hdr.dout_xferp = (__u64)(sg_uintptr_t)dxferp; 568 ptp->io_hdr.dout_xfer_len = dxfer_olen; 569 } 570 } 571 572 void 573 set_pt_metadata_xfer(struct sg_pt_base * vp, unsigned char * dxferp, 574 uint32_t dxfer_len, bool out_true) 575 { 576 struct sg_pt_linux_scsi * ptp = &vp->impl; 577 578 if (dxfer_len > 0) { 579 ptp->mdxferp = dxferp; 580 ptp->mdxfer_len = dxfer_len; 581 ptp->mdxfer_out = out_true; 582 } 583 } 584 585 void 586 set_scsi_pt_packet_id(struct sg_pt_base * vp, int pack_id) 587 { 588 struct sg_pt_linux_scsi * ptp = &vp->impl; 589 590 ptp->io_hdr.spare_in = pack_id; 591 } 592 593 void 594 set_scsi_pt_tag(struct sg_pt_base * vp, uint64_t tag) 595 { 596 struct sg_pt_linux_scsi * ptp = &vp->impl; 597 598 ptp->io_hdr.request_tag = tag; 599 } 600 601 /* Note that task management function codes are transport specific */ 602 void 603 set_scsi_pt_task_management(struct sg_pt_base * vp, int tmf_code) 604 { 605 struct sg_pt_linux_scsi * ptp = &vp->impl; 606 607 ptp->io_hdr.subprotocol = 1; /* SCSI task management function */ 608 ptp->tmf_request[0] = (unsigned char)tmf_code; /* assume it fits */ 609 ptp->io_hdr.request = (__u64)(sg_uintptr_t)(&(ptp->tmf_request[0])); 610 ptp->io_hdr.request_len = 1; 611 } 612 613 void 614 set_scsi_pt_task_attr(struct sg_pt_base * vp, int attribute, int priority) 615 { 616 struct sg_pt_linux_scsi * ptp = &vp->impl; 617 618 ptp->io_hdr.request_attr = attribute; 619 ptp->io_hdr.request_priority = priority; 620 } 621 622 #ifndef BSG_FLAG_Q_AT_TAIL 623 #define BSG_FLAG_Q_AT_TAIL 0x10 624 #endif 625 #ifndef BSG_FLAG_Q_AT_HEAD 626 #define BSG_FLAG_Q_AT_HEAD 0x20 627 #endif 628 629 /* Need this later if translated to v3 interface */ 630 #ifndef SG_FLAG_Q_AT_TAIL 631 #define SG_FLAG_Q_AT_TAIL 0x10 632 #endif 633 #ifndef SG_FLAG_Q_AT_HEAD 634 #define SG_FLAG_Q_AT_HEAD 0x20 635 #endif 636 637 void 638 set_scsi_pt_flags(struct sg_pt_base * vp, int flags) 639 { 640 struct sg_pt_linux_scsi * ptp = &vp->impl; 641 642 /* default action of bsg driver (sg v4) is QUEUE_AT_HEAD */ 643 /* default action of block layer SG_IO ioctl is QUEUE_AT_TAIL */ 644 if (SCSI_PT_FLAGS_QUEUE_AT_HEAD & flags) { /* favour AT_HEAD */ 645 ptp->io_hdr.flags |= BSG_FLAG_Q_AT_HEAD; 646 ptp->io_hdr.flags &= ~BSG_FLAG_Q_AT_TAIL; 647 } else if (SCSI_PT_FLAGS_QUEUE_AT_TAIL & flags) { 648 ptp->io_hdr.flags |= BSG_FLAG_Q_AT_TAIL; 649 ptp->io_hdr.flags &= ~BSG_FLAG_Q_AT_HEAD; 650 } 651 } 652 653 /* N.B. Returns din_resid and ignores dout_resid */ 654 int 655 get_scsi_pt_resid(const struct sg_pt_base * vp) 656 { 657 const struct sg_pt_linux_scsi * ptp = &vp->impl; 658 659 if (NULL == ptp) 660 return 0; 661 return ptp->nvme_direct ? 0 : ptp->io_hdr.din_resid; 662 } 663 664 int 665 get_scsi_pt_status_response(const struct sg_pt_base * vp) 666 { 667 const struct sg_pt_linux_scsi * ptp = &vp->impl; 668 669 if (NULL == ptp) 670 return 0; 671 return (int)(ptp->nvme_direct ? ptp->nvme_status : 672 ptp->io_hdr.device_status); 673 } 674 675 uint32_t 676 get_pt_result(const struct sg_pt_base * vp) 677 { 678 const struct sg_pt_linux_scsi * ptp = &vp->impl; 679 680 if (NULL == ptp) 681 return 0; 682 return ptp->nvme_direct ? ptp->nvme_result : 683 ptp->io_hdr.device_status; 684 } 685 686 int 687 get_scsi_pt_sense_len(const struct sg_pt_base * vp) 688 { 689 const struct sg_pt_linux_scsi * ptp = &vp->impl; 690 691 return ptp->io_hdr.response_len; 692 } 693 694 int 695 get_scsi_pt_duration_ms(const struct sg_pt_base * vp) 696 { 697 const struct sg_pt_linux_scsi * ptp = &vp->impl; 698 699 return ptp->io_hdr.duration; 700 } 701 702 int 703 get_scsi_pt_transport_err(const struct sg_pt_base * vp) 704 { 705 const struct sg_pt_linux_scsi * ptp = &vp->impl; 706 707 return ptp->io_hdr.transport_status; 708 } 709 710 void 711 set_scsi_pt_transport_err(struct sg_pt_base * vp, int err) 712 { 713 struct sg_pt_linux_scsi * ptp = &vp->impl; 714 715 ptp->io_hdr.transport_status = err; 716 } 717 718 /* Returns b which will contain a null char terminated string (if 719 * max_b_len > 0). Combined driver and transport (called "host" in Linux 720 * kernel) statuses */ 721 char * 722 get_scsi_pt_transport_err_str(const struct sg_pt_base * vp, int max_b_len, 723 char * b) 724 { 725 const struct sg_pt_linux_scsi * ptp = &vp->impl; 726 int ds = ptp->io_hdr.driver_status; 727 int hs = ptp->io_hdr.transport_status; 728 int n, m; 729 char * cp = b; 730 int driv; 731 const char * driv_cp = "invalid"; 732 733 if (max_b_len < 1) 734 return b; 735 m = max_b_len; 736 n = 0; 737 if (hs) { 738 if ((hs < 0) || (hs >= LINUX_HOST_BYTES_SZ)) 739 n = snprintf(cp, m, "Host_status=0x%02x is invalid\n", hs); 740 else 741 n = snprintf(cp, m, "Host_status=0x%02x [%s]\n", hs, 742 linux_host_bytes[hs]); 743 } 744 m -= n; 745 if (m < 1) { 746 b[max_b_len - 1] = '\0'; 747 return b; 748 } 749 cp += n; 750 driv = ds & SG_LIB_DRIVER_MASK; 751 if (driv < LINUX_DRIVER_BYTES_SZ) 752 driv_cp = linux_driver_bytes[driv]; 753 #if 0 754 sugg = (ds & SG_LIB_SUGGEST_MASK) >> 4; 755 if (sugg < LINUX_DRIVER_SUGGESTS_SZ) 756 sugg_cp = linux_driver_suggests[sugg]; 757 #endif 758 n = snprintf(cp, m, "Driver_status=0x%02x [%s]\n", ds, driv_cp); 759 m -= n; 760 if (m < 1) 761 b[max_b_len - 1] = '\0'; 762 return b; 763 } 764 765 int 766 get_scsi_pt_result_category(const struct sg_pt_base * vp) 767 { 768 const struct sg_pt_linux_scsi * ptp = &vp->impl; 769 int dr_st = ptp->io_hdr.driver_status & SG_LIB_DRIVER_MASK; 770 int scsi_st = ptp->io_hdr.device_status & 0x7e; 771 772 if (ptp->os_err) 773 return SCSI_PT_RESULT_OS_ERR; 774 else if (ptp->io_hdr.transport_status) 775 return SCSI_PT_RESULT_TRANSPORT_ERR; 776 else if (dr_st && (SG_LIB_DRIVER_SENSE != dr_st)) 777 return SCSI_PT_RESULT_TRANSPORT_ERR; 778 else if ((SG_LIB_DRIVER_SENSE == dr_st) || 779 (SAM_STAT_CHECK_CONDITION == scsi_st) || 780 (SAM_STAT_COMMAND_TERMINATED == scsi_st)) 781 return SCSI_PT_RESULT_SENSE; 782 else if (scsi_st) 783 return SCSI_PT_RESULT_STATUS; 784 else 785 return SCSI_PT_RESULT_GOOD; 786 } 787 788 int 789 get_scsi_pt_os_err(const struct sg_pt_base * vp) 790 { 791 const struct sg_pt_linux_scsi * ptp = &vp->impl; 792 793 return ptp->os_err; 794 } 795 796 char * 797 get_scsi_pt_os_err_str(const struct sg_pt_base * vp, int max_b_len, char * b) 798 { 799 const struct sg_pt_linux_scsi * ptp = &vp->impl; 800 const char * cp; 801 802 cp = safe_strerror(ptp->os_err); 803 strncpy(b, cp, max_b_len); 804 if ((int)strlen(cp) >= max_b_len) 805 b[max_b_len - 1] = '\0'; 806 return b; 807 } 808 809 bool 810 pt_device_is_nvme(const struct sg_pt_base * vp) 811 { 812 const struct sg_pt_linux_scsi * ptp = &vp->impl; 813 814 return ptp->is_nvme; 815 } 816 817 /* If a NVMe block device (which includes the NSID) handle is associated 818 * with 'vp', then its NSID is returned (values range from 0x1 to 819 * 0xffffffe). Otherwise 0 is returned. */ 820 uint32_t 821 get_pt_nvme_nsid(const struct sg_pt_base * vp) 822 { 823 const struct sg_pt_linux_scsi * ptp = &vp->impl; 824 825 return ptp->nvme_nsid; 826 } 827 828 /* Executes SCSI command using sg v3 interface */ 829 static int 830 do_scsi_pt_v3(struct sg_pt_linux_scsi * ptp, int fd, int time_secs, 831 int verbose) 832 { 833 struct sg_io_hdr v3_hdr; 834 835 memset(&v3_hdr, 0, sizeof(v3_hdr)); 836 /* convert v4 to v3 header */ 837 v3_hdr.interface_id = 'S'; 838 v3_hdr.dxfer_direction = SG_DXFER_NONE; 839 v3_hdr.cmdp = (unsigned char *)(long)ptp->io_hdr.request; 840 v3_hdr.cmd_len = (unsigned char)ptp->io_hdr.request_len; 841 if (ptp->io_hdr.din_xfer_len > 0) { 842 if (ptp->io_hdr.dout_xfer_len > 0) { 843 if (verbose) 844 pr2ws("sgv3 doesn't support bidi\n"); 845 return SCSI_PT_DO_BAD_PARAMS; 846 } 847 v3_hdr.dxferp = (void *)(long)ptp->io_hdr.din_xferp; 848 v3_hdr.dxfer_len = (unsigned int)ptp->io_hdr.din_xfer_len; 849 v3_hdr.dxfer_direction = SG_DXFER_FROM_DEV; 850 } else if (ptp->io_hdr.dout_xfer_len > 0) { 851 v3_hdr.dxferp = (void *)(long)ptp->io_hdr.dout_xferp; 852 v3_hdr.dxfer_len = (unsigned int)ptp->io_hdr.dout_xfer_len; 853 v3_hdr.dxfer_direction = SG_DXFER_TO_DEV; 854 } 855 if (ptp->io_hdr.response && (ptp->io_hdr.max_response_len > 0)) { 856 v3_hdr.sbp = (unsigned char *)(long)ptp->io_hdr.response; 857 v3_hdr.mx_sb_len = (unsigned char)ptp->io_hdr.max_response_len; 858 } 859 v3_hdr.pack_id = (int)ptp->io_hdr.spare_in; 860 if (BSG_FLAG_Q_AT_HEAD & ptp->io_hdr.flags) 861 v3_hdr.flags |= SG_FLAG_Q_AT_HEAD; /* favour AT_HEAD */ 862 else if (BSG_FLAG_Q_AT_TAIL & ptp->io_hdr.flags) 863 v3_hdr.flags |= SG_FLAG_Q_AT_TAIL; 864 865 if (NULL == v3_hdr.cmdp) { 866 if (verbose) 867 pr2ws("No SCSI command (cdb) given\n"); 868 return SCSI_PT_DO_BAD_PARAMS; 869 } 870 /* io_hdr.timeout is in milliseconds, if greater than zero */ 871 v3_hdr.timeout = ((time_secs > 0) ? (time_secs * 1000) : DEF_TIMEOUT); 872 /* Finally do the v3 SG_IO ioctl */ 873 if (ioctl(fd, SG_IO, &v3_hdr) < 0) { 874 ptp->os_err = errno; 875 if (verbose > 1) 876 pr2ws("ioctl(SG_IO v3) failed: %s (errno=%d)\n", 877 safe_strerror(ptp->os_err), ptp->os_err); 878 return -ptp->os_err; 879 } 880 ptp->io_hdr.device_status = (__u32)v3_hdr.status; 881 ptp->io_hdr.driver_status = (__u32)v3_hdr.driver_status; 882 ptp->io_hdr.transport_status = (__u32)v3_hdr.host_status; 883 ptp->io_hdr.response_len = (__u32)v3_hdr.sb_len_wr; 884 ptp->io_hdr.duration = (__u32)v3_hdr.duration; 885 ptp->io_hdr.din_resid = (__s32)v3_hdr.resid; 886 /* v3_hdr.info not passed back since no mapping defined (yet) */ 887 return 0; 888 } 889 890 /* Executes SCSI command (or at least forwards it to lower layers). 891 * Returns 0 for success, negative numbers are negated 'errno' values from 892 * OS system calls. Positive return values are errors from this package. */ 893 int 894 do_scsi_pt(struct sg_pt_base * vp, int fd, int time_secs, int verbose) 895 { 896 int err; 897 struct sg_pt_linux_scsi * ptp = &vp->impl; 898 bool have_checked_for_type = (ptp->dev_fd >= 0); 899 900 if (! sg_bsg_nvme_char_major_checked) { 901 sg_bsg_nvme_char_major_checked = true; 902 sg_find_bsg_nvme_char_major(verbose); 903 } 904 if (ptp->in_err) { 905 if (verbose) 906 pr2ws("Replicated or unused set_scsi_pt... functions\n"); 907 return SCSI_PT_DO_BAD_PARAMS; 908 } 909 if (fd >= 0) { 910 if ((ptp->dev_fd >= 0) && (fd != ptp->dev_fd)) { 911 if (verbose) 912 pr2ws("%s: file descriptor given to create() and here " 913 "differ\n", __func__); 914 return SCSI_PT_DO_BAD_PARAMS; 915 } 916 ptp->dev_fd = fd; 917 } else if (ptp->dev_fd < 0) { 918 if (verbose) 919 pr2ws("%s: invalid file descriptors\n", __func__); 920 return SCSI_PT_DO_BAD_PARAMS; 921 } else 922 fd = ptp->dev_fd; 923 if (! have_checked_for_type) { 924 err = set_pt_file_handle(vp, ptp->dev_fd, verbose); 925 if (err) 926 return -ptp->os_err; 927 } 928 if (ptp->os_err) 929 return -ptp->os_err; 930 if (ptp->is_nvme) 931 return sg_do_nvme_pt(vp, -1, time_secs, verbose); 932 else if (sg_bsg_major <= 0) 933 return do_scsi_pt_v3(ptp, fd, time_secs, verbose); 934 else if (ptp->is_bsg) 935 ; /* drop through to sg v4 implementation */ 936 else 937 return do_scsi_pt_v3(ptp, fd, time_secs, verbose); 938 939 if (! ptp->io_hdr.request) { 940 if (verbose) 941 pr2ws("No SCSI command (cdb) given (v4)\n"); 942 return SCSI_PT_DO_BAD_PARAMS; 943 } 944 /* io_hdr.timeout is in milliseconds */ 945 ptp->io_hdr.timeout = ((time_secs > 0) ? (time_secs * 1000) : 946 DEF_TIMEOUT); 947 #if 0 948 /* sense buffer already zeroed */ 949 if (ptp->io_hdr.response && (ptp->io_hdr.max_response_len > 0)) { 950 void * p; 951 952 p = (void *)(long)ptp->io_hdr.response; 953 memset(p, 0, ptp->io_hdr.max_response_len); 954 } 955 #endif 956 if (ioctl(fd, SG_IO, &ptp->io_hdr) < 0) { 957 ptp->os_err = errno; 958 if (verbose > 1) 959 pr2ws("ioctl(SG_IO v4) failed: %s (errno=%d)\n", 960 safe_strerror(ptp->os_err), ptp->os_err); 961 return -ptp->os_err; 962 } 963 return 0; 964 } 965