chiark / gitweb /
Merge branch 'docs/README' of git://github.com/mfwitten/udev
[elogind.git] / extras / scsi_id / scsi_serial.c
index 8752e14971bd6b531fb31087464e130491e6f1be..5cde9a54a06a0633c654da89ac2973aab214c32e 100644 (file)
@@ -1,17 +1,20 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+/*
+ * Copyright (C) IBM Corp. 2003
  *
- * scsi_serial.c
+ * Author: Patrick Mansfield<patmans@us.ibm.com>
  *
- * Code related to requesting and getting an id from a scsi device
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
  *
- * Copyright (C) IBM Corp. 2003
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  *
- * Author:
- *     Patrick Mansfield<patmans@us.ibm.com>
- *
- *     This program is free software; you can redistribute it and/or modify it
- *     under the terms of the GNU General Public License as published by the
- *     Free Software Foundation version 2 of the License.
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <sys/types.h>
@@ -45,6 +48,7 @@
  * is normally one or some small number of descriptors.
  */
 static const struct scsi_id_search_values id_search_list[] = {
+       { SCSI_ID_TGTGROUP,     SCSI_ID_NAA_DONT_CARE,  SCSI_ID_BINARY },
        { SCSI_ID_NAA,  SCSI_ID_NAA_IEEE_REG_EXTENDED,  SCSI_ID_BINARY },
        { SCSI_ID_NAA,  SCSI_ID_NAA_IEEE_REG_EXTENDED,  SCSI_ID_ASCII },
        { SCSI_ID_NAA,  SCSI_ID_NAA_IEEE_REG,   SCSI_ID_BINARY },
@@ -137,13 +141,13 @@ static int sg_err_category_new(struct udev *udev,
                }
                return SG_ERR_CAT_SENSE;
        }
-       if (!host_status) {
+       if (host_status) {
                if ((host_status == DID_NO_CONNECT) ||
                    (host_status == DID_BUS_BUSY) ||
                    (host_status == DID_TIME_OUT))
                        return SG_ERR_CAT_TIMEOUT;
        }
-       if (!driver_status) {
+       if (driver_status) {
                if (driver_status == DRIVER_TIMEOUT)
                        return SG_ERR_CAT_TIMEOUT;
        }
@@ -318,8 +322,10 @@ static int scsi_inquiry(struct udev *udev,
                { INQUIRY_CMD, evpd, page, 0, buflen, 0 };
        unsigned char sense[SENSE_BUFF_LEN];
        void *io_buf;
-       int retval;
+       struct sg_io_v4 io_v4;
+       struct sg_io_hdr io_hdr;
        int retry = 3; /* rather random */
+       int retval;
 
        if (buflen > SCSI_INQ_BUFF_LEN) {
                info(udev, "buflen %d too long\n", buflen);
@@ -330,8 +336,6 @@ resend:
        dbg(udev, "%s evpd %d, page 0x%x\n", dev_scsi->kernel, evpd, page);
 
        if (dev_scsi->use_sg == 4) {
-               struct sg_io_v4 io_v4;
-
                memset(&io_v4, 0, sizeof(struct sg_io_v4));
                io_v4.guard = 'Q';
                io_v4.protocol = BSG_PROTOCOL_SCSI;
@@ -344,8 +348,6 @@ resend:
                io_v4.din_xferp = (uintptr_t)buf;
                io_buf = (void *)&io_v4;
        } else {
-               struct sg_io_hdr io_hdr;
-
                memset(&io_hdr, 0, sizeof(struct sg_io_hdr));
                io_hdr.interface_id = 'S';
                io_hdr.cmd_len = sizeof(inq_cmd);
@@ -482,17 +484,22 @@ static int check_fill_0x83_id(struct udev *udev,
                              struct scsi_id_device *dev_scsi,
                              unsigned char *page_83,
                              const struct scsi_id_search_values
-                             *id_search, char *serial, char *serial_short, int max_len,
-                              char *wwn,
-                             char *wwn_vendor_extension)
+                             *id_search, char *serial, char *serial_short,
+                             int max_len, char *wwn,
+                             char *wwn_vendor_extension, char *tgpt_group)
 {
        int i, j, s, len;
 
        /*
         * ASSOCIATION must be with the device (value 0)
+        * or with the target port for SCSI_ID_TGTPORT
         */
-       if ((page_83[1] & 0x30) != 0)
+       if ((page_83[1] & 0x30) == 0x10) {
+               if (id_search->id_type != SCSI_ID_TGTGROUP)
+                       return 1;
+       } else if ((page_83[1] & 0x30) != 0) {
                return 1;
+       }
 
        if ((page_83[1] & 0x0f) != id_search->id_type)
                return 1;
@@ -533,6 +540,14 @@ static int check_fill_0x83_id(struct udev *udev,
                return 1;
        }
 
+       if (id_search->id_type == SCSI_ID_TGTGROUP && tgpt_group != NULL) {
+               unsigned int group;
+
+               group = ((unsigned int)page_83[6] << 8) | page_83[7];
+               sprintf(tgpt_group,"%x", group);
+               return 1;
+       }
+
        serial[0] = hex_str[id_search->id_type];
 
        /*
@@ -569,12 +584,13 @@ static int check_fill_0x83_id(struct udev *udev,
 
        strcpy(serial_short, &serial[s]);
 
-        if (id_search->id_type == SCSI_ID_NAA && wwn != NULL) {
-                strncpy(wwn, &serial[s], 16);
+       if (id_search->id_type == SCSI_ID_NAA && wwn != NULL) {
+               strncpy(wwn, &serial[s], 16);
                if (wwn_vendor_extension != NULL) {
                        strncpy(wwn_vendor_extension, &serial[s + 16], 16);
                }
-        }
+       }
+
        return 0;
 }
 
@@ -606,14 +622,14 @@ static int check_fill_0x83_prespc3(struct udev *udev,
 static int do_scsi_page83_inquiry(struct udev *udev,
                                  struct scsi_id_device *dev_scsi, int fd,
                                  char *serial, char *serial_short, int len,
-                                  char *unit_serial_number, char *wwn,
-                                 char *wwn_vendor_extension)
+                                 char *unit_serial_number, char *wwn,
+                                 char *wwn_vendor_extension, char *tgpt_group)
 {
        int retval;
        unsigned int id_ind, j;
        unsigned char page_83[SCSI_INQ_BUFF_LEN];
 
-        /* also pick up the page 80 serial number */
+       /* also pick up the page 80 serial number */
         do_scsi_page80_inquiry(udev, dev_scsi, fd, NULL, unit_serial_number, MAX_SERIAL_LEN);
 
        memset(page_83, 0, SCSI_INQ_BUFF_LEN);
@@ -677,8 +693,8 @@ static int do_scsi_page83_inquiry(struct udev *udev,
                                                    dev_scsi, &page_83[j],
                                                    &id_search_list[id_ind],
                                                    serial, serial_short, len,
-                                                    wwn,
-                                                   wwn_vendor_extension);
+                                                   wwn, wwn_vendor_extension,
+                                                   tgpt_group);
                        dbg(udev, "%s id desc %d/%d/%d\n", dev_scsi->kernel,
                                id_search_list[id_ind].id_type,
                                id_search_list[id_ind].naa_type,
@@ -892,7 +908,7 @@ int scsi_get_serial(struct udev *udev,
                        goto completed;
                }
        } else if (page_code == PAGE_83) {
-               if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension)) {
+               if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
                        retval = 1;
                        goto completed;
                } else  {
@@ -908,7 +924,7 @@ int scsi_get_serial(struct udev *udev,
                         * conform to pre-SPC3 expectations.
                         */
                        if (retval == 2) {
-                               if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension)) {
+                               if (do_scsi_page83_inquiry(udev, dev_scsi, fd, dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
                                        retval = 1;
                                        goto completed;
                                } else  {
@@ -948,7 +964,7 @@ int scsi_get_serial(struct udev *udev,
        for (ind = 4; ind <= page0[3] + 3; ind++)
                if (page0[ind] == PAGE_83)
                        if (!do_scsi_page83_inquiry(udev, dev_scsi, fd,
-                                                   dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension)) {
+                                                   dev_scsi->serial, dev_scsi->serial_short, len, dev_scsi->unit_serial_number, dev_scsi->wwn, dev_scsi->wwn_vendor_extension, dev_scsi->tgpt_group)) {
                                /*
                                 * Success
                                 */