1 /*
   2  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 
   5 /*
   6  * BSD 3 Clause License
   7  *
   8  * Copyright (c) 2007, The Storage Networking Industry Association.
   9  *
  10  * Redistribution and use in source and binary forms, with or without
  11  * modification, are permitted provided that the following conditions
  12  * are met:
  13  *      - Redistributions of source code must retain the above copyright
  14  *        notice, this list of conditions and the following disclaimer.
  15  *
  16  *      - Redistributions in binary form must reproduce the above copyright
  17  *        notice, this list of conditions and the following disclaimer in
  18  *        the documentation and/or other materials provided with the
  19  *        distribution.
  20  *
  21  *      - Neither the name of The Storage Networking Industry Association (SNIA)
  22  *        nor the names of its contributors may be used to endorse or promote
  23  *        products derived from this software without specific prior written
  24  *        permission.
  25  *
  26  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  27  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  28  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  29  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  30  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  31  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  32  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  33  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  34  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  35  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  36  * POSSIBILITY OF SUCH DAMAGE.
  37  */
  38 /* Copyright 2016 Nexenta Systems, Inc. All rights reserved. */
  39 
  40 #include <sys/errno.h>
  41 #include <sys/types.h>
  42 #include <syslog.h>
  43 #include <stdlib.h>
  44 #include <unistd.h>
  45 #include <ctype.h>
  46 #include <sys/byteorder.h>
  47 #include <sys/scsi/impl/uscsi.h>
  48 #include <sys/scsi/scsi.h>
  49 #include <tlm.h>
  50 #include <pthread.h>
  51 #include "tlm_proto.h"
  52 
  53 /*
  54  * generic routine to read a SCSI page
  55  */
  56 int
  57 read_scsi_page(scsi_link_t *slink, union scsi_cdb *cdb,
  58     int command_size, caddr_t data, int size)
  59 {
  60         struct uscsi_cmd uscsi_cmd;
  61         char *dname;
  62         int dev;
  63 
  64         if (slink == 0 || slink->sl_sa == 0)
  65                 return (EINVAL);
  66 
  67         (void) memset(&uscsi_cmd, 0, sizeof (uscsi_cmd));
  68 
  69         /* Lun is in the 5th bit */
  70         cdb->scc_lun = slink->sl_lun;
  71         uscsi_cmd.uscsi_flags |= USCSI_READ | USCSI_ISOLATE;
  72         uscsi_cmd.uscsi_bufaddr = data;
  73         uscsi_cmd.uscsi_buflen = size;
  74         uscsi_cmd.uscsi_timeout = 1000;
  75         uscsi_cmd.uscsi_cdb = (char *)cdb;
  76 
  77         if (cdb->scc_cmd == SCMD_READ_ELEMENT_STATUS) {
  78                 uscsi_cmd.uscsi_flags |= USCSI_RQENABLE;
  79                 uscsi_cmd.uscsi_rqbuf = data;
  80                 uscsi_cmd.uscsi_rqlen = size;
  81         }
  82         uscsi_cmd.uscsi_cdblen = command_size;
  83 
  84         dname = sasd_slink_name(slink);
  85         dev = open(dname, O_RDWR | O_NDELAY);
  86         if (dev == -1) {
  87                 syslog(LOG_DEBUG, "Open failed for %s err=%d",
  88                     dname, errno);
  89                 return (errno);
  90         }
  91         if (tlm_ioctl(dev, USCSICMD, &uscsi_cmd) < 0) {
  92                 syslog(LOG_DEBUG, "SCSI cmd %d failed for %s err=%d",
  93                     cdb->scc_cmd, dname, errno);
  94                 (void) close(dev);
  95                 return (errno);
  96         }
  97         (void) close(dev);
  98         return (uscsi_cmd.uscsi_status);
  99 }
 100 
 101 /*
 102  * Read the Inquiry Page.
 103  */
 104 static int
 105 read_inquiry_page(scsi_link_t *slink, struct scsi_inquiry *inq)
 106 {
 107         union scsi_cdb cdb;
 108 
 109         (void) memset(&cdb, 0, sizeof (union scsi_cdb));
 110         cdb.scc_cmd = SCMD_INQUIRY;
 111         cdb.g0_count0 = sizeof (struct scsi_inquiry);
 112 
 113         return (read_scsi_page(slink, &cdb, CDB_GROUP0,
 114             (caddr_t)inq, sizeof (*inq)) ? -1 : 0);
 115 }
 116 
 117 /*
 118  * Read the Product Data Page.
 119  */
 120 static int
 121 read_data_page(scsi_link_t *slink, int pcode, char *snum, int size)
 122 {
 123         char cmd[CDB_GROUP0];
 124 
 125         (void) memset(cmd, 0, sizeof (cmd));
 126 
 127         cmd[0] = SCMD_INQUIRY;
 128         cmd[1] = pcode ? 0x01 : 0x00;
 129         cmd[2] = pcode;
 130         cmd[4] = size;
 131 
 132         /* LINTED improper alignment */
 133         return (read_scsi_page(slink, (union scsi_cdb *)&cmd, CDB_GROUP0,
 134             (caddr_t)snum, size) == -1 ? -1 : 0);
 135 }
 136 
 137 
 138 /*
 139  * Read the Serial Number Page.
 140  */
 141 static int
 142 read_serial_num_page(scsi_link_t *slink, char *snum, int size)
 143 {
 144         scsi_serial_t serial;
 145         int rv;
 146 
 147         (void) memset(&serial, 0, sizeof (scsi_serial_t));
 148         rv = read_data_page(slink, SCSI_SERIAL_PAGE, (caddr_t)&serial,
 149             sizeof (scsi_serial_t));
 150         (void) strlcpy(snum, serial.sr_num, size);
 151 
 152         return (rv == -1 ? -1 : 0);
 153 }
 154 
 155 
 156 /*
 157  * Read the Device Name Page.
 158  */
 159 static int
 160 read_dev_name_page(scsi_link_t *slink, device_ident_header_t *devp, int len)
 161 {
 162         (void) memset(devp, 0, len);
 163 
 164         if (read_data_page(slink, SCSI_DEVICE_IDENT_PAGE, (caddr_t)devp,
 165             len) == -1)
 166                 return (-1);
 167 
 168         if (devp->di_page_code != SCSI_DEVICE_IDENT_PAGE)
 169                 return (-1);
 170 
 171         return (0);
 172 }
 173 
 174 /*
 175  * Formatted print of WWN
 176  */
 177 static void
 178 snprintf_wwn(char *buf, int size, uint8_t *wwn)
 179 {
 180         if (wwn == NULL || buf == NULL)
 181                 return;
 182 
 183         (void) snprintf(buf, size, "0x%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
 184             wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
 185 }
 186 
 187 
 188 /*
 189  * Extract and print the world wide name (WWN)
 190  */
 191 int
 192 read_device_wwn(scsi_link_t *slink, char *wwnp, int wsize)
 193 {
 194         device_ident_header_t *header;
 195         name_ident_t *ident;
 196         uint16_t page_len = sizeof (device_ident_header_t);
 197         uint16_t act_len;
 198         int accessed;
 199         uint8_t *designator_data;
 200 
 201         (void) memset(wwnp, 0, wsize);
 202 resize:
 203         header = malloc(page_len);
 204         if (header == NULL)
 205                 return (-1);
 206 
 207         if (read_dev_name_page(slink, header, page_len) == -1) {
 208                 free(header);
 209                 return (-1);
 210         }
 211 
 212         act_len = BE_16(header->di_page_length);
 213         if (act_len > page_len) {
 214                 free(header);
 215                 page_len = act_len;
 216                 goto resize;
 217         }
 218 
 219         ident = (name_ident_t *)&header[1];
 220         accessed = sizeof (device_ident_header_t);
 221 
 222         while (accessed < act_len) {
 223 
 224                 accessed += sizeof (name_ident_t);
 225                 accessed += ident->ni_ident_length;
 226                 designator_data = (uint8_t *)&ident[1];
 227                 /*
 228                  * Looking for code set 1 (Binary) ident type NAA 64 bit
 229                  * address that is associated with the node (0).
 230                  */
 231                 if ((ident->ni_code_set == 1) &&
 232                     (ident->ni_ident_type == 3)) {
 233                         snprintf_wwn(wwnp, wsize, designator_data);
 234                         /*
 235                          * If assc is zero (Node) this is the one we want.
 236                          * If we find that we're done.
 237                          */
 238                         if (ident->ni_asso == 0)
 239                                 break;
 240                 }
 241                 /*
 242                  * If we find a EUI-64 we can use that also.
 243                  */
 244                 if ((ident->ni_code_set == 2) &&
 245                     (ident->ni_ident_type == 1) &&
 246                     (ident->ni_asso == 0) &&
 247                     (isprint(wwnp[0] == 0))) { /* Don't overwrite */
 248                         /*
 249                          * This isn't our first choice but we'll print it
 250                          * in case there is nothing else to use.
 251                          */
 252                         (void) snprintf(wwnp, wsize, "%.*s",
 253                             ident->ni_ident_length, designator_data);
 254                 }
 255                 ident =
 256                     (name_ident_t *)&designator_data[ident->ni_ident_length];
 257         }
 258         free(header);
 259         /*
 260          * See if we found something.
 261          * Memset above would leave wwnp not printable.
 262          */
 263         if (isprint(wwnp[0]))
 264                 return (0);
 265         return (-1);
 266 }
 267 
 268 /*
 269  * Add the tape library call back function (used while scanning the bus)
 270  */
 271 static int
 272 add_lib(scsi_link_t *slink, struct scsi_inquiry *sd, void *arg)
 273 {
 274         int l;
 275         int *nlp; /* pointer to library counter */
 276         sasd_drive_t *ssd;
 277 
 278         if (!slink || !sd) {
 279                 syslog(LOG_DEBUG, "Invalid argument %x %x %x",
 280                     slink, sd, arg);
 281                 return (-TLM_INVALID);
 282         }
 283 
 284         if (sd->inq_dtype == DTYPE_CHANGER) {
 285                 /* This is a robot, which means this is also a library */
 286                 nlp = (int *)arg;
 287                 (*nlp)++;
 288                 l = tlm_insert_new_library(slink);
 289                 tlm_enable_barcode(l);
 290 
 291                 syslog(LOG_DEBUG, "lib %d sid %d lun %d",
 292                     l, slink->sl_sid, slink->sl_lun);
 293 
 294                 if ((ssd = sasd_slink_drive(slink)) != NULL) {
 295                         (void) strlcpy(ssd->sd_vendor, sd->inq_vid,
 296                             sizeof (ssd->sd_vendor));
 297                         (void) strlcpy(ssd->sd_id, sd->inq_pid,
 298                             sizeof (ssd->sd_id));
 299                         (void) strlcpy(ssd->sd_rev, sd->inq_revision,
 300                             sizeof (ssd->sd_rev));
 301                         (void) read_serial_num_page(slink, ssd->sd_serial,
 302                             sizeof (ssd->sd_serial));
 303                         (void) read_device_wwn(slink, ssd->sd_wwn,
 304                             sizeof (ssd->sd_wwn));
 305                 }
 306         }
 307 
 308         return (TLM_NO_ERRORS);
 309 }
 310 
 311 /*
 312  * Create some virutal slots
 313  */
 314 static int
 315 make_virtual_slot(int l, tlm_drive_t *dp)
 316 {
 317         int s;
 318         tlm_slot_t *sp;
 319 
 320         if (l <= 0 || !dp) {
 321                 syslog(LOG_DEBUG, "Invalid argument %d, %x", l, dp);
 322                 return (-TLM_INVALID);
 323         }
 324 
 325         if ((s = tlm_insert_new_slot(l)) <= 0)
 326                 return (-TLM_NO_MEMORY);
 327 
 328         if (!(sp = tlm_slot(l, s))) {
 329                 syslog(LOG_DEBUG, "Internal error: slot not found %d", s);
 330                 return (-TLM_ERROR_INTERNAL);
 331         }
 332         /*
 333          * For virtual slots element number is 0 and they are always full.
 334          */
 335         sp->ts_element = 0;
 336         sp->ts_status_full = TRUE;
 337         return (TLM_NO_ERRORS);
 338 }
 339 
 340 /*
 341  * Make the tape drive not part of a tape library (stand alone)
 342  */
 343 static int
 344 make_stand_alone_drive(scsi_link_t *slink, int l)
 345 {
 346         int d;
 347         tlm_drive_t *dp;
 348 
 349         if (!slink || l <= 0) {
 350                 syslog(LOG_DEBUG, "Invalid argument %x %d", slink, l);
 351                 return (-TLM_INVALID);
 352         }
 353 
 354         d = tlm_insert_new_drive(l);
 355         if (!(dp = tlm_drive(l, d))) {
 356                 syslog(LOG_DEBUG, "Internal error: drive not found %d", d);
 357                 return (-TLM_ERROR_INTERNAL);
 358         }
 359 
 360         /* For stand-alone drives, the element number is the drive number. */
 361         dp->td_element = d;
 362         dp->td_slink = slink;
 363         dp->td_scsi_id = slink->sl_sid;
 364         dp->td_lun = slink->sl_lun;
 365         dp->td_exists = TRUE;
 366 
 367         /*
 368          * Note: There is no way to remove library elements.  We cannot clean
 369          * up if make_virtual_slot() fails.
 370          */
 371         (void) make_virtual_slot(l, dp);
 372         return (d);
 373 }
 374 
 375 /*
 376  * Find the LIBRARY structure that has control of this DRIVE.
 377  */
 378 static int
 379 new_drive(scsi_link_t *slink, int *lib)
 380 {
 381         int d;
 382         tlm_drive_t *dp;
 383         tlm_library_t *lp;
 384 
 385         /* Walk through all libraries. */
 386         for (*lib = 1; *lib <= tlm_library_count(); (*lib)++) {
 387                 if (!(lp = tlm_library(*lib)))
 388                         continue;
 389                 /* Walk through drives that are already found. */
 390                 for (d = 1; d <= lp->tl_drive_count; d++) {
 391                         if (!(dp = tlm_drive(*lib, d)))
 392                                 continue;
 393                         if (dp->td_scsi_id == slink->sl_sid &&
 394                             dp->td_lun == slink->sl_lun)
 395                                 return (d);
 396                 }
 397         }
 398 
 399         /* Not part of any library, this is a newly found tape drive. */
 400         return (0);
 401 }
 402 
 403 
 404 /*
 405  * Add the tape library call back function (used while scanning the bus)
 406  */
 407 static int
 408 add_drv(scsi_link_t *slink, struct scsi_inquiry *sd, void *arg)
 409 {
 410         int l, d;
 411         int *vlp; /* pointer to virtual library number */
 412         sasd_drive_t *ssd;
 413         tlm_library_t *library;
 414         tlm_drive_t *drive;
 415 
 416         if (!slink || !sd) {
 417                 syslog(LOG_DEBUG, "Invalid argument %x %x %x",
 418                     slink, sd, arg);
 419                 return (-TLM_INVALID);
 420         }
 421 
 422         if (sd->inq_dtype == DTYPE_SEQUENTIAL) {
 423                 vlp = (int *)arg;
 424                 d = new_drive(slink, &l);
 425                 if (d == 0) {
 426                         /* This tape drive was not found inside any robot. */
 427                         if (*vlp == 0) {
 428                                 /*
 429                                  * First, create a virtual library if it's not
 430                                  * done yet.
 431                                  */
 432                                 *vlp = tlm_insert_new_library(slink);
 433                                 if ((library = tlm_library(*vlp)) != NULL)
 434                                         library->tl_capability_robot = FALSE;
 435                         }
 436                         if ((d = make_stand_alone_drive(slink, *vlp)) < 0) {
 437                                 /* sorry, we can not clean up the vlib now * */
 438                                 return (-TLM_INVALID);
 439                         }
 440                         l = *vlp;
 441                         syslog(LOG_DEBUG, "vlib(%d, %d) sid %d lun %d",
 442                             l, d, slink->sl_sid, slink->sl_lun);
 443                 } else
 444                         syslog(LOG_DEBUG, "(%d, %d) sid %d lun %d",
 445                             l, d, slink->sl_sid, slink->sl_lun);
 446 
 447                 if ((drive = tlm_drive(l, d)) != NULL) {
 448                         drive->td_exists = TRUE;
 449                         drive->td_slink = slink;
 450                 }
 451                 if ((ssd = sasd_slink_drive(slink)) != NULL) {
 452                         (void) strlcpy(ssd->sd_vendor,
 453                             sd->inq_vid, sizeof (ssd->sd_vendor));
 454                         (void) strlcpy(ssd->sd_id, sd->inq_pid,
 455                             sizeof (ssd->sd_id));
 456                         (void) strlcpy(ssd->sd_rev, sd->inq_revision,
 457                             sizeof (ssd->sd_rev));
 458                         (void) read_serial_num_page(slink, ssd->sd_serial,
 459                             sizeof (ssd->sd_serial));
 460                         (void) read_device_wwn(slink, ssd->sd_wwn,
 461                             sizeof (ssd->sd_wwn));
 462                 }
 463         }
 464 
 465         return (TLM_NO_ERRORS);
 466 }
 467 
 468 /*
 469  * Scan the specified bus and call the handler function.
 470  */
 471 static int
 472 scan_bus(scsi_adapter_t *sa, int(*hndlr)(), void *args)
 473 {
 474         int nerr;
 475         scsi_link_t *slink;
 476         struct scsi_inquiry scsi_data;
 477 
 478         nerr = 0;
 479         slink = sa->sa_link_head.sl_next;
 480         for (; slink != &sa->sa_link_head; slink = slink->sl_next) {
 481                 (void) memset(&scsi_data, 0, sizeof (struct scsi_inquiry));
 482                 if (read_inquiry_page(slink, &scsi_data) == -1)
 483                         nerr++;
 484                 else
 485                         if ((*hndlr)(slink, &scsi_data, args) != TLM_NO_ERRORS)
 486                                 nerr++;
 487         }
 488 
 489         return (nerr);
 490 }
 491 
 492 /*
 493  * Marks the library/slots inaccessible if there are not enough drives
 494  * available on the library
 495  */
 496 static void
 497 inaccbl_drv_warn(int start, int max)
 498 {
 499         char *dname;
 500         int l, d;
 501         tlm_library_t *lp;
 502 
 503         for (l = start; l < max; l++) {
 504                 if (!(lp = tlm_library(l)))
 505                         continue;
 506                 if (lp->tl_drive_count <= 0)
 507                         continue;
 508 
 509                 syslog(LOG_DEBUG,
 510                     "Warning: The following drives are not accessible:");
 511                 for (d = 1; d <= lp->tl_drive_count; d++)
 512                         if (!(dname = tlm_get_tape_name(l, d))) {
 513                                 syslog(LOG_DEBUG,
 514                                     "Error getting drive(%d, %d)", l, d);
 515                         } else
 516                                 syslog(LOG_DEBUG, "%s", dname);
 517 
 518                 /*
 519                  * Note: Make the slots inaccessible to prevent running
 520                  * discovery on these libraries.  The better idea is
 521                  * removing these libraries, but we don't have that
 522                  * feature available now.
 523                  */
 524                 lp->tl_slot_count = 0;
 525         }
 526 }
 527 
 528 /*
 529  * Initialize the tape library data structure, asks the libraries what
 530  * equipments they have.
 531  */
 532 int
 533 tlm_init(void)
 534 {
 535         static int nlibs; /* number of found libraries */
 536         int i, nsa;
 537         int l, vlibs, d;
 538         int rv;
 539         scsi_adapter_t *sa;
 540         tlm_library_t *lp;
 541         tlm_drive_t *dp;
 542 
 543         /* Search through all SCSI adapters, look for tape robots. */
 544         nlibs = 0;
 545 
 546         /*
 547          * We probe both changers and tape drives here
 548          * but later on this needs to be removed as the
 549          * probe will happen somewhere else.
 550          */
 551         if (probe_scsi() < 0)
 552                 return (-1);
 553 
 554         nsa = scsi_get_adapter_count();
 555         for (i = 0; i < nsa; i++)
 556                 if ((sa = scsi_get_adapter(i)))
 557                         (void) scan_bus(sa, add_lib, (void *)&nlibs);
 558 
 559         /* Search through all SCSI adapters, look for tape drives. */
 560         vlibs = 0;
 561         for (i = 0; i < nsa; i++)
 562                 if ((sa = scsi_get_adapter(i)))
 563                         (void) scan_bus(sa, add_drv, (void *)&vlibs);
 564 
 565         if (nlibs > 0 && vlibs > 0)
 566                 inaccbl_drv_warn(nlibs + 1, vlibs + nlibs + 1);
 567 
 568         for (l = 1; l <= tlm_library_count(); l++) {
 569                 if (!(lp = tlm_library(l))) {
 570                         syslog(LOG_DEBUG, "can't find lib %d", l);
 571                         continue;
 572                 }
 573 
 574                 /*
 575                  * Make sure all libraries have tape drives.
 576                  */
 577                 if (lp->tl_drive_count == 0)
 578                         continue;
 579 
 580                 /*
 581                  * Make sure all tape drives exist. A drive that is not
 582                  * linked into the SCSI chain will be seen by the library
 583                  * but we cannot talk to it.
 584                  */
 585                 for (d = 1; d <= lp->tl_drive_count; d++) {
 586                         dp = tlm_drive(l, d);
 587                         if (dp && !dp->td_exists) {
 588                                 syslog(LOG_DEBUG, "Ghost drive found %d.%d",
 589                                     l, d);
 590                                 lp->tl_ghost_drives = TRUE;
 591                                 continue;
 592                         }
 593                 }
 594         }
 595 
 596         if (nlibs > 0)
 597                 rv = (vlibs > 0) ? 0 : nlibs;
 598         else
 599                 rv = vlibs;
 600 
 601         return (rv);
 602 }