"Fossies" - the Fresh Open Source Software Archive

Member "open-fcoe-3.19/libhbalinux/sg.c" (15 Apr 2015, 7330 Bytes) of package /linux/misc/open-fcoe-3.19.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "sg.c" see the Fossies "Dox" file reference documentation.

    1 /*
    2  * Copyright (c) 2008, Intel Corporation.
    3  *
    4  * This program is free software; you can redistribute it and/or modify it
    5  * under the terms and conditions of the GNU Lesser General Public License,
    6  * version 2.1, as published by the Free Software Foundation.
    7  *
    8  * This program is distributed in the hope it will be useful, but WITHOUT
    9  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   10  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   11  * for more details.
   12  *
   13  * You should have received a copy of the GNU Lesser General Public License
   14  * along with this program; if not, write to the Free Software Foundation, Inc.,
   15  * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
   16  *
   17  */
   18 
   19 #include <sys/ioctl.h>
   20 #include "utils.h"
   21 #include "api_lib.h"
   22 #include "adapt_impl.h"
   23 #include "fc_scsi.h"
   24 
   25 /*
   26  * Perform INQUIRY of SCSI-generic device.
   27  */
   28 HBA_STATUS
   29 sg_issue_inquiry(const char *file, HBA_UINT8 cdb_byte1,
   30            HBA_UINT8 cdb_byte2, void *buf, HBA_UINT32 *lenp,
   31            HBA_UINT8 *statp, void *sense, HBA_UINT32 *sense_lenp)
   32 {
   33     struct sg_io_hdr hdr;
   34     struct scsi_inquiry cmd;
   35     size_t len;
   36     HBA_UINT32 slen;
   37     int fd;
   38     int rc;
   39 
   40     len = *lenp;
   41     slen = *sense_lenp;
   42     if (slen > 255)
   43         slen = 255;   /* must fit in an 8-bit field */
   44     if (len > 255)
   45         len = 255;    /* sometimes must fit in 8-byte field */
   46     *lenp = 0;
   47     *statp = 0;
   48     fd = open(file, O_RDWR);
   49     if (fd < 0) {
   50         fprintf(stderr, "%s: open of %s failed, errno=0x%x\n",
   51             __func__, file, errno);
   52         return HBA_STATUS_ERROR;
   53     }
   54     memset(&hdr, 0, sizeof(hdr));
   55     memset(&cmd, 0, sizeof(cmd));
   56     memset(buf, 0, len);
   57 
   58     cmd.in_op = SCSI_OP_INQUIRY;
   59     cmd.in_flags = cdb_byte1;
   60     cmd.in_page_code = cdb_byte2;
   61     ua_net16_put(&cmd.in_alloc_len, len); /* field may actually be 8 bits */
   62 
   63     hdr.interface_id = 'S';
   64     hdr.dxfer_direction = SG_DXFER_FROM_DEV;
   65     hdr.cmd_len = sizeof(cmd);
   66     hdr.mx_sb_len = slen;
   67     hdr.dxfer_len = len;
   68     hdr.dxferp = (unsigned char *) buf;
   69     hdr.cmdp = (unsigned char *) &cmd;
   70     hdr.sbp = (unsigned char *) sense;
   71     hdr.timeout = 3000;                     /* mS to wait for result */
   72 
   73     rc = ioctl(fd, SG_IO, &hdr);
   74     if (rc < 0) {
   75         rc = errno;
   76         fprintf(stderr, "%s: SG_IO error. file %s, errno=0x%x\n",
   77             __func__, file, errno);
   78         close(fd);
   79         return HBA_STATUS_ERROR;
   80     }
   81     close(fd);
   82     *lenp = len - hdr.resid;
   83     *sense_lenp = hdr.sb_len_wr;
   84     *statp = hdr.status;
   85     return HBA_STATUS_OK;
   86 }
   87 
   88 static inline unsigned int
   89 sg_get_id_type(struct scsi_inquiry_desc *dp)
   90 {
   91     return dp->id_type_flags & SCSI_INQT_TYPE_MASK;
   92 }
   93 
   94 /*
   95  * Get device ID information for HBA-API.
   96  * See the spec.  We get the "best" information and leave the rest.
   97  * The buffer is left empty if nothing is gotten.
   98  */
   99 void
  100 sg_get_dev_id(const char *name, char *buf, size_t result_len)
  101 {
  102     struct scsi_inquiry_dev_id *idp;
  103     struct scsi_inquiry_desc *dp;
  104     struct scsi_inquiry_desc *best = NULL;
  105     char sense[252];
  106     HBA_UINT32 len;
  107     HBA_UINT32 slen;
  108     u_char scsi_stat;
  109     size_t rlen;
  110     size_t dlen;
  111     unsigned int type;
  112 
  113     memset(buf, 0, result_len);
  114     len = result_len;
  115     slen = sizeof(sense);
  116     idp = (struct scsi_inquiry_dev_id *) buf;
  117     sg_issue_inquiry(name, SCSI_INQF_EVPD, SCSI_INQP_DEV_ID,
  118             buf, &len, &scsi_stat, sense, &slen);
  119     if (len < sizeof(*idp))
  120         return;
  121     if (idp->is_page_code != SCSI_INQP_DEV_ID)
  122         return;
  123     len -= sizeof(*idp);
  124     rlen = net16_get(&idp->is_page_len);
  125     if (rlen > len)
  126         rlen = len;
  127     dp = (struct scsi_inquiry_desc *) (idp + 1);
  128     for (; rlen >= sizeof(*dp);
  129          rlen -= dlen,
  130          dp = (struct scsi_inquiry_desc *) ((char *) dp + dlen)) {
  131         dlen = dp->id_designator_len + sizeof(*dp) -
  132                sizeof(dp->id_designator[0]);
  133         if (dlen > rlen)
  134             break;
  135         type = sg_get_id_type(dp);
  136         if (type > SCSI_DTYPE_NAA)
  137             continue;
  138         if (best == NULL)
  139             best = dp;
  140         else if (type == sg_get_id_type(best) &&
  141                (dp->id_designator_len < best->id_designator_len ||
  142                (dp->id_designator_len == best->id_designator_len &&
  143                memcmp(dp->id_designator, best->id_designator,
  144                best->id_designator_len) < 0))) {
  145             best = dp;
  146         } else if (type > sg_get_id_type(best))
  147             best = dp;
  148     }
  149     if (best) {
  150         dp = best;
  151         dlen = dp->id_designator_len + sizeof(*dp) -
  152             sizeof(dp->id_designator[0]);
  153         if (dlen > result_len)
  154             dlen = 0;                       /* can't happen */
  155         else
  156             memmove(buf, dp, dlen);         /* areas may overlap */
  157         memset(buf +  dlen, 0, result_len - dlen);
  158     }
  159 }
  160 
  161 /*
  162  * Read Capacity for HBA-API.
  163  */
  164 HBA_STATUS
  165 sg_issue_read_capacity(const char *file, void *resp, HBA_UINT32 *resp_lenp,
  166         HBA_UINT8 *statp, void *sense, HBA_UINT32 *sense_lenp)
  167 {
  168     struct sg_io_hdr hdr;
  169     struct scsi_rcap10 cmd;
  170     struct scsi_rcap16 cmd_16;
  171     size_t len;
  172     int fd;
  173     int rc;
  174 
  175     len = *resp_lenp;
  176     *resp_lenp = 0;
  177     fd = open(file, O_RDWR);
  178     if (fd < 0) {
  179         fprintf(stderr, "%s: open of %s failed, errno=0x%x\n",
  180             __func__, file, errno);
  181         return errno;
  182     }
  183     memset(&hdr, 0, sizeof(hdr));
  184 
  185     /* If the response buffer size is enough to
  186      * accomodate READ CAPACITY(16) response issue
  187      * SCSI READ CAPACITY(16) else issue
  188      * SCSI READ CAPACITY(10)
  189      */
  190     if (len >= sizeof(struct scsi_rcap16_resp)) {
  191         memset(&cmd_16, 0, sizeof(cmd_16));
  192         cmd_16.rc_op = SCSI_OP_SA_IN_16;
  193         cmd_16.rc_sa = SCSI_SA_READ_CAP16;
  194         ua_net32_put(&cmd_16.rc_alloc_len, len);
  195         hdr.cmd_len = sizeof(cmd_16);
  196         hdr.cmdp = (unsigned char *) &cmd_16;
  197     } else {
  198         memset(&cmd, 0, sizeof(cmd));
  199         cmd.rc_op = SCSI_OP_READ_CAP10;
  200         hdr.cmd_len = sizeof(cmd);
  201         hdr.cmdp = (unsigned char *) &cmd;
  202     }
  203 
  204     hdr.interface_id = 'S';
  205     hdr.dxfer_direction = SG_DXFER_FROM_DEV;
  206     hdr.mx_sb_len = *sense_lenp;
  207     hdr.dxfer_len = len;
  208     hdr.dxferp = (unsigned char *) resp;
  209     hdr.sbp = (unsigned char *) sense;
  210     hdr.timeout = UINT_MAX;
  211     hdr.timeout = 3000;                     /* mS to wait for result */
  212 
  213     rc = ioctl(fd, SG_IO, &hdr);
  214     if (rc < 0) {
  215         rc = errno;
  216         fprintf(stderr, "%s: SG_IO error. file %s, errno=0x%x\n",
  217             __func__, file, errno);
  218         close(fd);
  219         return HBA_STATUS_ERROR;
  220     }
  221     close(fd);
  222     *resp_lenp = len - hdr.resid;
  223     *sense_lenp = hdr.sb_len_wr;
  224     *statp = hdr.status;
  225     return HBA_STATUS_OK;
  226 }
  227 
  228 /*
  229  * Report LUNs for HBA-API.
  230  */
  231 HBA_STATUS
  232 sg_issue_report_luns(const char *file, void *resp, HBA_UINT32 *resp_lenp,
  233            HBA_UINT8 *statp, void *sense, HBA_UINT32 *sense_lenp)
  234 {
  235     struct sg_io_hdr hdr;
  236     struct scsi_report_luns cmd;
  237     size_t len;
  238     int fd;
  239     int rc;
  240 
  241     len = *resp_lenp;
  242     *resp_lenp = 0;
  243     fd = open(file, O_RDWR);
  244     if (fd < 0) {
  245         fprintf(stderr, "%s: open of %s failed, errno=0x%x\n",
  246             __func__, file, errno);
  247         return errno;
  248     }
  249     memset(&hdr, 0, sizeof(hdr));
  250     memset(&cmd, 0, sizeof(cmd));
  251 
  252     cmd.rl_op = SCSI_OP_REPORT_LUNS;
  253     ua_net32_put(&cmd.rl_alloc_len, len);
  254 
  255     hdr.interface_id = 'S';
  256     hdr.dxfer_direction = SG_DXFER_FROM_DEV;
  257     hdr.cmd_len = sizeof(cmd);
  258     hdr.mx_sb_len = *sense_lenp;
  259     hdr.dxfer_len = len;
  260     hdr.dxferp = (unsigned char *) resp;
  261     hdr.cmdp = (unsigned char *) &cmd;
  262     hdr.sbp = (unsigned char *) sense;
  263     hdr.timeout = UINT_MAX;
  264     hdr.timeout = 3000;                     /* mS to wait for result */
  265 
  266     rc = ioctl(fd, SG_IO, &hdr);
  267     if (rc < 0) {
  268         rc = errno;
  269         fprintf(stderr, "%s: SG_IO error. file %s, errno=0x%x\n",
  270             __func__, file, errno);
  271         close(fd);
  272         return HBA_STATUS_ERROR;
  273     }
  274     close(fd);
  275     *resp_lenp = len - hdr.resid;
  276     *sense_lenp = hdr.sb_len_wr;
  277     *statp = hdr.status;
  278     return HBA_STATUS_OK;
  279 }
  280