Ticket #782: sgio.2.patch
File sgio.2.patch, 10.7 KB (added by , 8 years ago) |
---|
-
os_linux.cpp
63 63 #include <scsi/scsi.h> 64 64 #include <scsi/scsi_ioctl.h> 65 65 #include <scsi/sg.h> 66 #include <linux/bsg.h> 66 67 #include <stdlib.h> 67 68 #include <string.h> 68 69 #include <sys/ioctl.h> … … 510 511 #define SCSI_IOCTL_SEND_COMMAND 1 511 512 #endif 512 513 513 #define SG_IO_PRESENT_UNKNOWN 0 514 #define SG_IO_PRESENT_YES 1 515 #define SG_IO_PRESENT_NO 2 514 #define SG_IO_USE_DETECT 0 515 #define SG_IO_UNSUPP 1 516 #define SG_IO_USE_V3 3 517 #define SG_IO_USE_V4 4 516 518 517 519 static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report, 518 int unknown);520 int sgio_ver); 519 521 static int sisc_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report); 520 522 521 static int sg_io_state = SG_IO_ PRESENT_UNKNOWN;523 static int sg_io_state = SG_IO_USE_DETECT; 522 524 523 525 /* Preferred implementation for issuing SCSI commands in linux. This 524 526 * function uses the SG_IO ioctl. Return 0 if command issued successfully 525 527 * (various status values should still be checked). If the SCSI command 526 528 * cannot be issued then a negative errno value is returned. */ 527 529 static int sg_io_cmnd_io(int dev_fd, struct scsi_cmnd_io * iop, int report, 528 int unknown)530 int sg_io_ver) 529 531 { 530 532 #ifndef SG_IO 531 533 ARGUSED(dev_fd); ARGUSED(iop); ARGUSED(report); 532 534 return -ENOTTY; 533 535 #else 534 struct sg_io_hdr io_hdr;535 536 537 /* we are filling structures for both versions, but using only one requested */ 538 struct sg_io_hdr io_hdr_v3; 539 struct sg_io_v4 io_hdr_v4; 540 536 541 if (report > 0) { 537 542 int k, j; 538 543 const unsigned char * ucp = iop->cmnd; … … 540 545 char buff[256]; 541 546 const int sz = (int)sizeof(buff); 542 547 548 pout(">>>> do_scsi_cmnd_io: sg_io_ver=%d\n", sg_io_ver); 543 549 np = scsi_get_opcode_name(ucp[0]); 544 550 j = snprintf(buff, sz, " [%s: ", np ? np : "<unknown opcode>"); 545 551 for (k = 0; k < (int)iop->cmnd_len; ++k) … … 558 564 snprintf(&buff[j], (sz > j ? (sz - j) : 0), "]\n"); 559 565 pout("%s", buff); 560 566 } 561 memset(&io_hdr, 0, sizeof(struct sg_io_hdr)); 562 io_hdr.interface_id = 'S'; 563 io_hdr.cmd_len = iop->cmnd_len; 564 io_hdr.mx_sb_len = iop->max_sense_len; 565 io_hdr.dxfer_len = iop->dxfer_len; 566 io_hdr.dxferp = iop->dxferp; 567 io_hdr.cmdp = iop->cmnd; 568 io_hdr.sbp = iop->sensep; 567 memset(&io_hdr_v3, 0, sizeof(struct sg_io_hdr)); 568 memset(&io_hdr_v4, 0, sizeof(struct sg_io_v4)); 569 570 io_hdr_v3.interface_id = 'S'; 571 io_hdr_v3.cmd_len = iop->cmnd_len; 572 io_hdr_v3.mx_sb_len = iop->max_sense_len; 573 io_hdr_v3.dxfer_len = iop->dxfer_len; 574 io_hdr_v3.dxferp = iop->dxferp; 575 io_hdr_v3.cmdp = iop->cmnd; 576 io_hdr_v3.sbp = iop->sensep; 569 577 /* sg_io_hdr interface timeout has millisecond units. Timeout of 0 570 578 defaults to 60 seconds. */ 571 io_hdr.timeout = ((0 == iop->timeout) ? 60 : iop->timeout) * 1000; 579 io_hdr_v3.timeout = ((0 == iop->timeout) ? 60 : iop->timeout) * 1000; 580 581 io_hdr_v4.guard = 'Q'; 582 io_hdr_v4.request_len = iop->cmnd_len; 583 io_hdr_v4.request = __u64(iop->cmnd); 584 io_hdr_v4.max_response_len = iop->max_sense_len; 585 io_hdr_v4.response = __u64(iop->sensep); 586 io_hdr_v4.timeout = ((0 == iop->timeout) ? 60 : iop->timeout) * 1000; // msec 587 572 588 switch (iop->dxfer_dir) { 573 589 case DXFER_NONE: 574 io_hdr .dxfer_direction = SG_DXFER_NONE;590 io_hdr_v3.dxfer_direction = SG_DXFER_NONE; 575 591 break; 576 592 case DXFER_FROM_DEVICE: 577 io_hdr.dxfer_direction = SG_DXFER_FROM_DEV; 593 io_hdr_v3.dxfer_direction = SG_DXFER_FROM_DEV; 594 io_hdr_v4.din_xfer_len = iop->dxfer_len; 595 io_hdr_v4.din_xferp = __u64(iop->dxferp); 578 596 break; 579 597 case DXFER_TO_DEVICE: 580 io_hdr.dxfer_direction = SG_DXFER_TO_DEV; 598 io_hdr_v3.dxfer_direction = SG_DXFER_TO_DEV; 599 io_hdr_v4.dout_xfer_len = iop->dxfer_len; 600 io_hdr_v4.dout_xferp = __u64(iop->dxferp); 581 601 break; 582 602 default: 583 603 pout("do_scsi_cmnd_io: bad dxfer_dir\n"); 584 604 return -EINVAL; 585 605 } 606 586 607 iop->resp_sense_len = 0; 587 608 iop->scsi_status = 0; 588 609 iop->resid = 0; 589 if (ioctl(dev_fd, SG_IO, &io_hdr) < 0) { 590 if (report && (! unknown)) 591 pout(" SG_IO ioctl failed, errno=%d [%s]\n", errno, 592 strerror(errno)); 610 611 void * io_hdr = NULL; 612 613 switch (sg_io_ver) { 614 case SG_IO_USE_V3: 615 io_hdr = &io_hdr_v3; 616 break; 617 case SG_IO_USE_V4: 618 io_hdr = &io_hdr_v4; 619 break; 620 default: 621 // should never be reached 622 errno = EOPNOTSUPP; 623 return -errno; 624 } 625 626 if (ioctl(dev_fd, SG_IO, io_hdr) < 0) { 627 if (report) 628 pout(" SG_IO ioctl failed, errno=%d [%s], SG_IO_V%d\n", errno, 629 strerror(errno), sg_io_ver); 593 630 return -errno; 594 631 } 595 iop->resid = io_hdr.resid; 596 iop->scsi_status = io_hdr.status; 632 633 unsigned int sg_driver_status = 0, sg_transport_status = 0, sg_info = 0, 634 sg_duration = 0; 635 636 if (sg_io_ver == SG_IO_USE_V3) { 637 iop->resid = io_hdr_v3.resid; 638 iop->scsi_status = io_hdr_v3.status; 639 sg_driver_status = io_hdr_v3.driver_status; 640 sg_transport_status = io_hdr_v3.host_status; 641 sg_info = io_hdr_v3.info; 642 iop->resp_sense_len = io_hdr_v3.sb_len_wr; 643 sg_duration = io_hdr_v3.duration; 644 } 645 646 if (sg_io_ver == SG_IO_USE_V4) { 647 switch (iop->dxfer_dir) { 648 case DXFER_NONE: 649 iop->resid = 0; 650 break; 651 case DXFER_FROM_DEVICE: 652 iop->resid = io_hdr_v4.din_resid; 653 break; 654 case DXFER_TO_DEVICE: 655 iop->resid = io_hdr_v4.dout_resid; 656 break; 657 } 658 iop->scsi_status = io_hdr_v4.device_status; 659 sg_driver_status = io_hdr_v4.driver_status; 660 sg_transport_status = io_hdr_v4.transport_status; 661 sg_info = io_hdr_v4.info; 662 iop->resp_sense_len = io_hdr_v4.response_len; 663 sg_duration = io_hdr_v4.duration; 664 } 665 597 666 if (report > 0) { 598 pout(" scsi_status=0x%x, host_status=0x%x, driver_status=0x%x\n" 599 " info=0x%x duration=%d milliseconds resid=%d\n", io_hdr.status, 600 io_hdr.host_status, io_hdr.driver_status, io_hdr.info, 601 io_hdr.duration, io_hdr.resid); 667 pout(" scsi_status=0x%x, sg_transport_status=0x%x, sg_driver_status=0x%x\n" 668 " sg_info=0x%x sg_duration=%d milliseconds resid=%d\n", iop->scsi_status, 669 sg_transport_status, sg_driver_status, sg_info, 670 sg_duration, iop->resid); 671 602 672 if (report > 1) { 603 673 if (DXFER_FROM_DEVICE == iop->dxfer_dir) { 604 674 int trunc, len; … … 616 686 } 617 687 } 618 688 619 if ( io_hdr.info & SG_INFO_CHECK) { /* error or warning */620 int masked_driver_status = (LSCSI_DRIVER_MASK & io_hdr.driver_status);689 if (sg_info & SG_INFO_CHECK) { /* error or warning */ 690 int masked_driver_status = (LSCSI_DRIVER_MASK & sg_driver_status); 621 691 622 if (0 != io_hdr.host_status) {623 if ((LSCSI_DID_NO_CONNECT == io_hdr.host_status) ||624 (LSCSI_DID_BUS_BUSY == io_hdr.host_status) ||625 (LSCSI_DID_TIME_OUT == io_hdr.host_status))692 if (0 != sg_transport_status) { 693 if ((LSCSI_DID_NO_CONNECT == sg_transport_status) || 694 (LSCSI_DID_BUS_BUSY == sg_transport_status) || 695 (LSCSI_DID_TIME_OUT == sg_transport_status)) 626 696 return -ETIMEDOUT; 627 697 else 628 698 /* Check for DID_ERROR - workaround for aacraid driver quirk */ 629 if (LSCSI_DID_ERROR != io_hdr.host_status) {699 if (LSCSI_DID_ERROR != sg_transport_status) { 630 700 return -EIO; /* catch all if not DID_ERR */ 631 701 } 632 702 } … … 638 708 } 639 709 if (LSCSI_DRIVER_SENSE == masked_driver_status) 640 710 iop->scsi_status = SCSI_STATUS_CHECK_CONDITION; 641 iop->resp_sense_len = io_hdr.sb_len_wr;642 711 if ((SCSI_STATUS_CHECK_CONDITION == iop->scsi_status) && 643 712 iop->sensep && (iop->resp_sense_len > 0)) { 644 713 if (report > 1) { … … 807 876 * other than ENODEV (no device) or permission then assume 808 877 * SCSI_IOCTL_SEND_COMMAND is the only option. */ 809 878 switch (sg_io_state) { 810 case SG_IO_ PRESENT_UNKNOWN:879 case SG_IO_USE_DETECT: 811 880 /* ignore report argument */ 812 if (0 == (res = sg_io_cmnd_io(dev_fd, iop, report, 1))) { 813 sg_io_state = SG_IO_PRESENT_YES; 881 /* Try SG_IO V3 first */ 882 if (0 == (res = sg_io_cmnd_io(dev_fd, iop, report, SG_IO_USE_V3))) { 883 sg_io_state = SG_IO_USE_V3; 814 884 return 0; 815 885 } else if ((-ENODEV == res) || (-EACCES == res) || (-EPERM == res)) 816 886 return res; /* wait until we see a device */ 817 sg_io_state = SG_IO_PRESENT_NO; 887 /* See if we can use SG_IO V4 * */ 888 if (0 == (res = sg_io_cmnd_io(dev_fd, iop, report, SG_IO_USE_V4))) { 889 sg_io_state = SG_IO_USE_V4; 890 return 0; 891 } else if ((-ENODEV == res) || (-EACCES == res) || (-EPERM == res)) 892 return res; /* wait until we see a device */ 893 /* fallback to the SCSI_IOCTL_SEND_COMMAND */ 894 sg_io_state = SG_IO_UNSUPP; 818 895 /* drop through by design */ 819 case SG_IO_PRESENT_NO: 896 case SG_IO_UNSUPP: 897 /* depricated SCSI_IOCTL_SEND_COMMAND ioctl */ 820 898 return sisc_cmnd_io(dev_fd, iop, report); 821 case SG_IO_PRESENT_YES: 822 return sg_io_cmnd_io(dev_fd, iop, report, 0); 899 case SG_IO_USE_V3: 900 case SG_IO_USE_V4: 901 /* use SG_IO V3 or V4 ioctl, depending on availabiliy */ 902 return sg_io_cmnd_io(dev_fd, iop, report, sg_io_state); 823 903 default: 824 904 pout(">>>> do_scsi_cmnd_io: bad sg_io_state=%d\n", sg_io_state); 825 sg_io_state = SG_IO_ PRESENT_UNKNOWN;905 sg_io_state = SG_IO_USE_DETECT; 826 906 return -EIO; /* report error and reset state */ 827 907 } 828 908 } … … 3199 3279 if (str_starts_with(test_name, "scsi/")) 3200 3280 return new linux_scsi_device(this, name, ""); 3201 3281 3282 // form /dev/bsg/* or bsg/* 3283 if (str_starts_with(test_name, "bsg/")) 3284 return new linux_scsi_device(this, name, ""); 3285 3202 3286 // form /dev/ns* or ns* 3203 3287 if (str_starts_with(test_name, "ns")) 3204 3288 return new linux_scsi_device(this, name, "");