12654012fSReza Sabdar /* 22654012fSReza Sabdar * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 32654012fSReza Sabdar * Use is subject to license terms. 42654012fSReza Sabdar */ 52654012fSReza Sabdar 62654012fSReza Sabdar /* 72654012fSReza Sabdar * BSD 3 Clause License 82654012fSReza Sabdar * 92654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 102654012fSReza Sabdar * 112654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 122654012fSReza Sabdar * modification, are permitted provided that the following conditions 132654012fSReza Sabdar * are met: 142654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 152654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 162654012fSReza Sabdar * 172654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 182654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 192654012fSReza Sabdar * the documentation and/or other materials provided with the 202654012fSReza Sabdar * distribution. 212654012fSReza Sabdar * 222654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 232654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 242654012fSReza Sabdar * products derived from this software without specific prior written 252654012fSReza Sabdar * permission. 262654012fSReza Sabdar * 272654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 282654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 292654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 302654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 312654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 322654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 332654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 342654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 352654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 362654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 372654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 382654012fSReza Sabdar */ 392654012fSReza Sabdar #include <sys/errno.h> 402654012fSReza Sabdar #include <sys/types.h> 412654012fSReza Sabdar #include <stdlib.h> 422654012fSReza Sabdar #include <unistd.h> 432654012fSReza Sabdar #include <sys/scsi/impl/uscsi.h> 442654012fSReza Sabdar #include <sys/scsi/scsi.h> 452654012fSReza Sabdar #include <tlm.h> 462654012fSReza Sabdar #include <pthread.h> 472654012fSReza Sabdar #include "tlm_proto.h" 482654012fSReza Sabdar 492654012fSReza Sabdar /* 502654012fSReza Sabdar * generic routine to read a SCSI page 512654012fSReza Sabdar */ 522654012fSReza Sabdar int 532654012fSReza Sabdar read_scsi_page(scsi_link_t *slink, union scsi_cdb *cdb, 542654012fSReza Sabdar int command_size, caddr_t data, int size) 552654012fSReza Sabdar { 562654012fSReza Sabdar struct uscsi_cmd uscsi_cmd; 572654012fSReza Sabdar char *dname; 582654012fSReza Sabdar int dev; 592654012fSReza Sabdar 602654012fSReza Sabdar if (slink == 0 || slink->sl_sa == 0) 612654012fSReza Sabdar return (EINVAL); 622654012fSReza Sabdar 632654012fSReza Sabdar (void) memset(&uscsi_cmd, 0, sizeof (uscsi_cmd)); 642654012fSReza Sabdar 652654012fSReza Sabdar /* Lun is in the 5th bit */ 662654012fSReza Sabdar cdb->scc_lun = slink->sl_lun; 672654012fSReza Sabdar uscsi_cmd.uscsi_flags |= USCSI_READ | USCSI_ISOLATE; 682654012fSReza Sabdar uscsi_cmd.uscsi_bufaddr = data; 692654012fSReza Sabdar uscsi_cmd.uscsi_buflen = size; 702654012fSReza Sabdar uscsi_cmd.uscsi_timeout = 1000; 712654012fSReza Sabdar uscsi_cmd.uscsi_cdb = (char *)cdb; 722654012fSReza Sabdar 732654012fSReza Sabdar if (cdb->scc_cmd == SCMD_READ_ELEMENT_STATUS) { 742654012fSReza Sabdar uscsi_cmd.uscsi_flags |= USCSI_RQENABLE; 752654012fSReza Sabdar uscsi_cmd.uscsi_rqbuf = data; 762654012fSReza Sabdar uscsi_cmd.uscsi_rqlen = size; 772654012fSReza Sabdar } 782654012fSReza Sabdar uscsi_cmd.uscsi_cdblen = command_size; 792654012fSReza Sabdar 802654012fSReza Sabdar dname = sasd_slink_name(slink); 812654012fSReza Sabdar dev = open(dname, O_RDWR | O_NDELAY); 822654012fSReza Sabdar if (dev == -1) { 832654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Open failed for %s err=%d", 842654012fSReza Sabdar dname, errno); 852654012fSReza Sabdar return (errno); 862654012fSReza Sabdar } 872654012fSReza Sabdar if (tlm_ioctl(dev, USCSICMD, &uscsi_cmd) < 0) { 882654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "SCSI cmd %d failed for %s err=%d", 892654012fSReza Sabdar cdb->scc_cmd, dname, errno); 902654012fSReza Sabdar (void) close(dev); 912654012fSReza Sabdar return (errno); 922654012fSReza Sabdar } 932654012fSReza Sabdar (void) close(dev); 942654012fSReza Sabdar return (uscsi_cmd.uscsi_status); 952654012fSReza Sabdar } 962654012fSReza Sabdar 972654012fSReza Sabdar /* 982654012fSReza Sabdar * Read the Inquiry Page. 992654012fSReza Sabdar */ 1002654012fSReza Sabdar static int 1012654012fSReza Sabdar read_inquiry_page(scsi_link_t *slink, struct scsi_inquiry *inq) 1022654012fSReza Sabdar { 1032654012fSReza Sabdar union scsi_cdb cdb; 1042654012fSReza Sabdar 1052654012fSReza Sabdar (void) memset(&cdb, 0, sizeof (union scsi_cdb)); 1062654012fSReza Sabdar cdb.scc_cmd = SCMD_INQUIRY; 1072654012fSReza Sabdar cdb.g0_count0 = sizeof (struct scsi_inquiry); 1082654012fSReza Sabdar 1092654012fSReza Sabdar return (read_scsi_page(slink, &cdb, CDB_GROUP0, 1102654012fSReza Sabdar (caddr_t)inq, sizeof (*inq)) ? -1 : 0); 1112654012fSReza Sabdar } 1122654012fSReza Sabdar 113*7bc22e45SReza Sabdar /* 114*7bc22e45SReza Sabdar * Read the Product Data Page. 115*7bc22e45SReza Sabdar */ 116*7bc22e45SReza Sabdar static int 117*7bc22e45SReza Sabdar read_data_page(scsi_link_t *slink, int pcode, char *snum, int size) 118*7bc22e45SReza Sabdar { 119*7bc22e45SReza Sabdar char cmd[CDB_GROUP0]; 120*7bc22e45SReza Sabdar 121*7bc22e45SReza Sabdar (void) memset(cmd, 0, sizeof (cmd)); 122*7bc22e45SReza Sabdar 123*7bc22e45SReza Sabdar cmd[0] = SCMD_INQUIRY; 124*7bc22e45SReza Sabdar cmd[1] = pcode ? 0x01 : 0x00; 125*7bc22e45SReza Sabdar cmd[2] = pcode; 126*7bc22e45SReza Sabdar cmd[4] = size; 127*7bc22e45SReza Sabdar 128*7bc22e45SReza Sabdar /* LINTED improper alignment */ 129*7bc22e45SReza Sabdar return (read_scsi_page(slink, (union scsi_cdb *)&cmd, CDB_GROUP0, 130*7bc22e45SReza Sabdar (caddr_t)snum, size) == -1 ? -1 : 0); 131*7bc22e45SReza Sabdar } 132*7bc22e45SReza Sabdar 133*7bc22e45SReza Sabdar 134*7bc22e45SReza Sabdar /* 135*7bc22e45SReza Sabdar * Read the Serial Number Page. 136*7bc22e45SReza Sabdar */ 137*7bc22e45SReza Sabdar static int 138*7bc22e45SReza Sabdar read_serial_num_page(scsi_link_t *slink, char *snum, int size) 139*7bc22e45SReza Sabdar { 140*7bc22e45SReza Sabdar scsi_serial_t serial; 141*7bc22e45SReza Sabdar int rv; 142*7bc22e45SReza Sabdar 143*7bc22e45SReza Sabdar (void) memset(&serial, 0, sizeof (scsi_serial_t)); 144*7bc22e45SReza Sabdar rv = read_data_page(slink, SCSI_SERIAL_PAGE, (caddr_t)&serial, 145*7bc22e45SReza Sabdar sizeof (scsi_serial_t)); 146*7bc22e45SReza Sabdar (void) strlcpy(snum, serial.sr_num, size); 147*7bc22e45SReza Sabdar 148*7bc22e45SReza Sabdar return (rv == -1 ? -1 : 0); 149*7bc22e45SReza Sabdar } 150*7bc22e45SReza Sabdar 151*7bc22e45SReza Sabdar 152*7bc22e45SReza Sabdar /* 153*7bc22e45SReza Sabdar * Read the Device Name Page. 154*7bc22e45SReza Sabdar */ 155*7bc22e45SReza Sabdar static int 156*7bc22e45SReza Sabdar read_dev_name_page(scsi_link_t *slink, device_name_page_t *devp) 157*7bc22e45SReza Sabdar { 158*7bc22e45SReza Sabdar (void) memset(devp, 0, sizeof (device_name_page_t)); 159*7bc22e45SReza Sabdar 160*7bc22e45SReza Sabdar if (read_data_page(slink, SCSI_DEVICE_IDENT_PAGE, (caddr_t)devp, 161*7bc22e45SReza Sabdar sizeof (device_name_page_t)) == -1) 162*7bc22e45SReza Sabdar return (-1); 163*7bc22e45SReza Sabdar 164*7bc22e45SReza Sabdar if (devp->np_header.di_page_code == SCSI_DEVICE_IDENT_PAGE && 165*7bc22e45SReza Sabdar devp->np_node.ni_code_set == 1 && 166*7bc22e45SReza Sabdar devp->np_node.ni_ident_type == 3 && 167*7bc22e45SReza Sabdar devp->np_node.ni_ident_length == 8) 168*7bc22e45SReza Sabdar return (0); 169*7bc22e45SReza Sabdar 170*7bc22e45SReza Sabdar if (devp->np_header.di_page_code == SCSI_DEVICE_IDENT_PAGE) 171*7bc22e45SReza Sabdar return (0); 172*7bc22e45SReza Sabdar 173*7bc22e45SReza Sabdar return (-1); 174*7bc22e45SReza Sabdar } 175*7bc22e45SReza Sabdar 176*7bc22e45SReza Sabdar /* 177*7bc22e45SReza Sabdar * Formatted print of WWN 178*7bc22e45SReza Sabdar */ 179*7bc22e45SReza Sabdar char * 180*7bc22e45SReza Sabdar snprintf_wwn(char *buf, int size, uint8_t *wwn) 181*7bc22e45SReza Sabdar { 182*7bc22e45SReza Sabdar if (wwn == NULL || buf == NULL) 183*7bc22e45SReza Sabdar return (0); 184*7bc22e45SReza Sabdar 185*7bc22e45SReza Sabdar (void) snprintf(buf, size, "0x%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X", 186*7bc22e45SReza Sabdar wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]); 187*7bc22e45SReza Sabdar return (buf); 188*7bc22e45SReza Sabdar } 189*7bc22e45SReza Sabdar 190*7bc22e45SReza Sabdar 191*7bc22e45SReza Sabdar /* 192*7bc22e45SReza Sabdar * Extract and print the world wide name (WWN) 193*7bc22e45SReza Sabdar */ 194*7bc22e45SReza Sabdar int 195*7bc22e45SReza Sabdar read_device_wwn(scsi_link_t *slink, char *wwnp, int wsize) 196*7bc22e45SReza Sabdar { 197*7bc22e45SReza Sabdar device_name_page_t dinfo; 198*7bc22e45SReza Sabdar 199*7bc22e45SReza Sabdar (void) memset(wwnp, 0, wsize); 200*7bc22e45SReza Sabdar if (read_dev_name_page(slink, &dinfo) == -1) 201*7bc22e45SReza Sabdar return (-1); 202*7bc22e45SReza Sabdar 203*7bc22e45SReza Sabdar if (dinfo.np_port.ni_code_set == 1 && 204*7bc22e45SReza Sabdar dinfo.np_port.ni_ident_type == 3) { 205*7bc22e45SReza Sabdar (void) snprintf_wwn(wwnp, wsize, dinfo.np_port_info.d_name); 206*7bc22e45SReza Sabdar return (0); 207*7bc22e45SReza Sabdar } 208*7bc22e45SReza Sabdar if (dinfo.np_node.ni_code_set == 1 && 209*7bc22e45SReza Sabdar dinfo.np_node.ni_ident_type == 3) { 210*7bc22e45SReza Sabdar (void) snprintf_wwn(wwnp, wsize, dinfo.np_node_info.d_name); 211*7bc22e45SReza Sabdar return (0); 212*7bc22e45SReza Sabdar } 213*7bc22e45SReza Sabdar if (dinfo.np_port.ni_code_set == 2 && 214*7bc22e45SReza Sabdar dinfo.np_port.ni_ident_type == 1) { 215*7bc22e45SReza Sabdar (void) snprintf(wwnp, wsize, "%.*s", 216*7bc22e45SReza Sabdar dinfo.np_port.ni_ident_length, dinfo.np_port_info.d_name); 217*7bc22e45SReza Sabdar return (0); 218*7bc22e45SReza Sabdar } 219*7bc22e45SReza Sabdar if (dinfo.np_node.ni_code_set == 2 && 220*7bc22e45SReza Sabdar dinfo.np_node.ni_ident_type == 1) { 221*7bc22e45SReza Sabdar (void) snprintf(wwnp, wsize, "%.*s", 222*7bc22e45SReza Sabdar dinfo.np_node.ni_ident_length, dinfo.np_node_info.d_name); 223*7bc22e45SReza Sabdar return (0); 224*7bc22e45SReza Sabdar } 225*7bc22e45SReza Sabdar return (-1); 226*7bc22e45SReza Sabdar } 227*7bc22e45SReza Sabdar 2282654012fSReza Sabdar /* 2292654012fSReza Sabdar * Add the tape library call back function (used while scanning the bus) 2302654012fSReza Sabdar */ 2312654012fSReza Sabdar static int 2322654012fSReza Sabdar add_lib(scsi_link_t *slink, struct scsi_inquiry *sd, void *arg) 2332654012fSReza Sabdar { 2342654012fSReza Sabdar int l; 2352654012fSReza Sabdar int *nlp; /* pointer to library counter */ 2362654012fSReza Sabdar sasd_drive_t *ssd; 2372654012fSReza Sabdar 2382654012fSReza Sabdar if (!slink || !sd) { 2392654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument %x %x %x", 2402654012fSReza Sabdar slink, sd, arg); 2412654012fSReza Sabdar return (-TLM_INVALID); 2422654012fSReza Sabdar } 2432654012fSReza Sabdar 2442654012fSReza Sabdar if (sd->inq_dtype == DTYPE_CHANGER) { 2452654012fSReza Sabdar /* This is a robot, which means this is also a library */ 2462654012fSReza Sabdar nlp = (int *)arg; 2472654012fSReza Sabdar (*nlp)++; 2482654012fSReza Sabdar l = tlm_insert_new_library(slink); 2492654012fSReza Sabdar tlm_enable_barcode(l); 2502654012fSReza Sabdar 2512654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "lib %d sid %d lun %d", 2522654012fSReza Sabdar l, slink->sl_sid, slink->sl_lun); 2532654012fSReza Sabdar 2542654012fSReza Sabdar if ((ssd = sasd_slink_drive(slink)) != NULL) { 2552654012fSReza Sabdar (void) strlcpy(ssd->sd_vendor, sd->inq_vid, 2562654012fSReza Sabdar sizeof (ssd->sd_vendor)); 2572654012fSReza Sabdar (void) strlcpy(ssd->sd_id, sd->inq_pid, 2582654012fSReza Sabdar sizeof (ssd->sd_id)); 2592654012fSReza Sabdar (void) strlcpy(ssd->sd_rev, sd->inq_revision, 2602654012fSReza Sabdar sizeof (ssd->sd_rev)); 261*7bc22e45SReza Sabdar (void) read_serial_num_page(slink, ssd->sd_serial, 262*7bc22e45SReza Sabdar sizeof (ssd->sd_serial)); 263*7bc22e45SReza Sabdar (void) read_device_wwn(slink, ssd->sd_wwn, 264*7bc22e45SReza Sabdar sizeof (ssd->sd_wwn)); 2652654012fSReza Sabdar } 2662654012fSReza Sabdar } 2672654012fSReza Sabdar 2682654012fSReza Sabdar return (TLM_NO_ERRORS); 2692654012fSReza Sabdar } 2702654012fSReza Sabdar 2712654012fSReza Sabdar /* 2722654012fSReza Sabdar * Create some virutal slots 2732654012fSReza Sabdar */ 2742654012fSReza Sabdar static int 2752654012fSReza Sabdar make_virtual_slot(int l, tlm_drive_t *dp) 2762654012fSReza Sabdar { 2772654012fSReza Sabdar int s; 2782654012fSReza Sabdar tlm_slot_t *sp; 2792654012fSReza Sabdar 2802654012fSReza Sabdar if (l <= 0 || !dp) { 2812654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument %d, %x", l, dp); 2822654012fSReza Sabdar return (-TLM_INVALID); 2832654012fSReza Sabdar } 2842654012fSReza Sabdar 2852654012fSReza Sabdar if ((s = tlm_insert_new_slot(l)) <= 0) 2862654012fSReza Sabdar return (-TLM_NO_MEMORY); 2872654012fSReza Sabdar 2882654012fSReza Sabdar if (!(sp = tlm_slot(l, s))) { 2892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Internal error: slot not found %d", s); 2902654012fSReza Sabdar return (-TLM_ERROR_INTERNAL); 2912654012fSReza Sabdar } 2922654012fSReza Sabdar /* 2932654012fSReza Sabdar * For virtual slots element number is 0 and they are always full. 2942654012fSReza Sabdar */ 2952654012fSReza Sabdar sp->ts_element = 0; 2962654012fSReza Sabdar sp->ts_status_full = TRUE; 2972654012fSReza Sabdar return (TLM_NO_ERRORS); 2982654012fSReza Sabdar } 2992654012fSReza Sabdar 3002654012fSReza Sabdar /* 3012654012fSReza Sabdar * Make the tape drive not part of a tape library (stand alone) 3022654012fSReza Sabdar */ 3032654012fSReza Sabdar static int 3042654012fSReza Sabdar make_stand_alone_drive(scsi_link_t *slink, int l) 3052654012fSReza Sabdar { 3062654012fSReza Sabdar int d; 3072654012fSReza Sabdar tlm_drive_t *dp; 3082654012fSReza Sabdar 3092654012fSReza Sabdar if (!slink || l <= 0) { 3102654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument %x %d", slink, l); 3112654012fSReza Sabdar return (-TLM_INVALID); 3122654012fSReza Sabdar } 3132654012fSReza Sabdar 3142654012fSReza Sabdar d = tlm_insert_new_drive(l); 3152654012fSReza Sabdar if (!(dp = tlm_drive(l, d))) { 3162654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Internal error: drive not found %d", d); 3172654012fSReza Sabdar return (-TLM_ERROR_INTERNAL); 3182654012fSReza Sabdar } 3192654012fSReza Sabdar 3202654012fSReza Sabdar /* For stand-alone drives, the element number is the drive number. */ 3212654012fSReza Sabdar dp->td_element = d; 3222654012fSReza Sabdar dp->td_slink = slink; 3232654012fSReza Sabdar dp->td_scsi_id = slink->sl_sid; 3242654012fSReza Sabdar dp->td_lun = slink->sl_lun; 3252654012fSReza Sabdar dp->td_exists = TRUE; 3262654012fSReza Sabdar 3272654012fSReza Sabdar /* 3282654012fSReza Sabdar * Note: There is no way to remove library elements. We cannot clean 3292654012fSReza Sabdar * up if make_virtual_slot() fails. 3302654012fSReza Sabdar */ 3312654012fSReza Sabdar (void) make_virtual_slot(l, dp); 3322654012fSReza Sabdar return (d); 3332654012fSReza Sabdar } 3342654012fSReza Sabdar 3352654012fSReza Sabdar /* 3362654012fSReza Sabdar * Find the LIBRARY structure that has control of this DRIVE. 3372654012fSReza Sabdar */ 3382654012fSReza Sabdar static int 3392654012fSReza Sabdar new_drive(scsi_link_t *slink, int *lib) 3402654012fSReza Sabdar { 3412654012fSReza Sabdar int d; 3422654012fSReza Sabdar tlm_drive_t *dp; 3432654012fSReza Sabdar tlm_library_t *lp; 3442654012fSReza Sabdar 3452654012fSReza Sabdar /* Walk through all libraries. */ 3462654012fSReza Sabdar for (*lib = 1; *lib <= tlm_library_count(); (*lib)++) { 3472654012fSReza Sabdar if (!(lp = tlm_library(*lib))) 3482654012fSReza Sabdar continue; 3492654012fSReza Sabdar /* Walk through drives that are already found. */ 3502654012fSReza Sabdar for (d = 1; d <= lp->tl_drive_count; d++) { 3512654012fSReza Sabdar if (!(dp = tlm_drive(*lib, d))) 3522654012fSReza Sabdar continue; 3532654012fSReza Sabdar if (dp->td_scsi_id == slink->sl_sid && 3542654012fSReza Sabdar dp->td_lun == slink->sl_lun) 3552654012fSReza Sabdar return (d); 3562654012fSReza Sabdar } 3572654012fSReza Sabdar } 3582654012fSReza Sabdar 3592654012fSReza Sabdar /* Not part of any library, this is a newly found tape drive. */ 3602654012fSReza Sabdar return (0); 3612654012fSReza Sabdar } 3622654012fSReza Sabdar 363*7bc22e45SReza Sabdar 3642654012fSReza Sabdar /* 3652654012fSReza Sabdar * Add the tape library call back function (used while scanning the bus) 3662654012fSReza Sabdar */ 3672654012fSReza Sabdar static int 3682654012fSReza Sabdar add_drv(scsi_link_t *slink, struct scsi_inquiry *sd, void *arg) 3692654012fSReza Sabdar { 3702654012fSReza Sabdar int l, d; 3712654012fSReza Sabdar int *vlp; /* pointer to virtual library number */ 3722654012fSReza Sabdar sasd_drive_t *ssd; 3732654012fSReza Sabdar tlm_library_t *library; 3742654012fSReza Sabdar tlm_drive_t *drive; 3752654012fSReza Sabdar 3762654012fSReza Sabdar if (!slink || !sd) { 3772654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument %x %x %x", 3782654012fSReza Sabdar slink, sd, arg); 3792654012fSReza Sabdar return (-TLM_INVALID); 3802654012fSReza Sabdar } 3812654012fSReza Sabdar 3822654012fSReza Sabdar if (sd->inq_dtype == DTYPE_SEQUENTIAL) { 3832654012fSReza Sabdar vlp = (int *)arg; 3842654012fSReza Sabdar d = new_drive(slink, &l); 3852654012fSReza Sabdar if (d == 0) { 3862654012fSReza Sabdar /* This tape drive was not found inside any robot. */ 3872654012fSReza Sabdar if (*vlp == 0) { 3882654012fSReza Sabdar /* 3892654012fSReza Sabdar * First, create a virtual library if it's not 3902654012fSReza Sabdar * done yet. 3912654012fSReza Sabdar */ 3922654012fSReza Sabdar *vlp = tlm_insert_new_library(slink); 3932654012fSReza Sabdar if ((library = tlm_library(*vlp)) != NULL) 3942654012fSReza Sabdar library->tl_capability_robot = FALSE; 3952654012fSReza Sabdar } 3962654012fSReza Sabdar if ((d = make_stand_alone_drive(slink, *vlp)) < 0) { 3972654012fSReza Sabdar /* sorry, we can not clean up the vlib now * */ 3982654012fSReza Sabdar return (-TLM_INVALID); 3992654012fSReza Sabdar } 4002654012fSReza Sabdar l = *vlp; 4012654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "vlib(%d, %d) sid %d lun %d", 4022654012fSReza Sabdar l, d, slink->sl_sid, slink->sl_lun); 4032654012fSReza Sabdar } else 4042654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "(%d, %d) sid %d lun %d", 4052654012fSReza Sabdar l, d, slink->sl_sid, slink->sl_lun); 4062654012fSReza Sabdar 4072654012fSReza Sabdar if ((drive = tlm_drive(l, d)) != NULL) { 4082654012fSReza Sabdar drive->td_exists = TRUE; 4092654012fSReza Sabdar drive->td_slink = slink; 4102654012fSReza Sabdar } 4112654012fSReza Sabdar if ((ssd = sasd_slink_drive(slink)) != NULL) { 4122654012fSReza Sabdar (void) strlcpy(ssd->sd_vendor, 4132654012fSReza Sabdar sd->inq_vid, sizeof (ssd->sd_vendor)); 4142654012fSReza Sabdar (void) strlcpy(ssd->sd_id, sd->inq_pid, 4152654012fSReza Sabdar sizeof (ssd->sd_id)); 4162654012fSReza Sabdar (void) strlcpy(ssd->sd_rev, sd->inq_revision, 4172654012fSReza Sabdar sizeof (ssd->sd_rev)); 418*7bc22e45SReza Sabdar (void) read_serial_num_page(slink, ssd->sd_serial, 419*7bc22e45SReza Sabdar sizeof (ssd->sd_serial)); 420*7bc22e45SReza Sabdar (void) read_device_wwn(slink, ssd->sd_wwn, 421*7bc22e45SReza Sabdar sizeof (ssd->sd_wwn)); 4222654012fSReza Sabdar } 4232654012fSReza Sabdar } 4242654012fSReza Sabdar 4252654012fSReza Sabdar return (TLM_NO_ERRORS); 4262654012fSReza Sabdar } 4272654012fSReza Sabdar 4282654012fSReza Sabdar /* 4292654012fSReza Sabdar * Scan the specified bus and call the handler function. 4302654012fSReza Sabdar */ 4312654012fSReza Sabdar static int 4322654012fSReza Sabdar scan_bus(scsi_adapter_t *sa, int(*hndlr)(), void *args) 4332654012fSReza Sabdar { 4342654012fSReza Sabdar int nerr; 4352654012fSReza Sabdar scsi_link_t *slink; 4362654012fSReza Sabdar struct scsi_inquiry scsi_data; 4372654012fSReza Sabdar 4382654012fSReza Sabdar nerr = 0; 4392654012fSReza Sabdar slink = sa->sa_link_head.sl_next; 4402654012fSReza Sabdar for (; slink != &sa->sa_link_head; slink = slink->sl_next) { 4412654012fSReza Sabdar (void) memset(&scsi_data, 0, sizeof (struct scsi_inquiry)); 4422654012fSReza Sabdar if (read_inquiry_page(slink, &scsi_data) == -1) 4432654012fSReza Sabdar nerr++; 4442654012fSReza Sabdar else 4452654012fSReza Sabdar if ((*hndlr)(slink, &scsi_data, args) != TLM_NO_ERRORS) 4462654012fSReza Sabdar nerr++; 4472654012fSReza Sabdar } 4482654012fSReza Sabdar 4492654012fSReza Sabdar return (nerr); 4502654012fSReza Sabdar } 4512654012fSReza Sabdar 4522654012fSReza Sabdar /* 4532654012fSReza Sabdar * Marks the library/slots inaccessible if there are not enough drives 4542654012fSReza Sabdar * available on the library 4552654012fSReza Sabdar */ 4562654012fSReza Sabdar static void 4572654012fSReza Sabdar inaccbl_drv_warn(int start, int max) 4582654012fSReza Sabdar { 4592654012fSReza Sabdar char *dname; 4602654012fSReza Sabdar int l, d; 4612654012fSReza Sabdar tlm_library_t *lp; 4622654012fSReza Sabdar 4632654012fSReza Sabdar for (l = start; l < max; l++) { 4642654012fSReza Sabdar if (!(lp = tlm_library(l))) 4652654012fSReza Sabdar continue; 4662654012fSReza Sabdar if (lp->tl_drive_count <= 0) 4672654012fSReza Sabdar continue; 4682654012fSReza Sabdar 4692654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 4702654012fSReza Sabdar "Warning: The following drives are not accessible:"); 4712654012fSReza Sabdar for (d = 1; d <= lp->tl_drive_count; d++) 4722654012fSReza Sabdar if (!(dname = tlm_get_tape_name(l, d))) { 4732654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, 4742654012fSReza Sabdar "Error getting drive(%d, %d)", l, d); 4752654012fSReza Sabdar } else 4762654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "%s", dname); 4772654012fSReza Sabdar 4782654012fSReza Sabdar /* 4792654012fSReza Sabdar * Note: Make the slots inaccessible to prevent running 4802654012fSReza Sabdar * discovery on these libraries. The better idea is 4812654012fSReza Sabdar * removing these libraries, but we don't have that 4822654012fSReza Sabdar * feature available now. 4832654012fSReza Sabdar */ 4842654012fSReza Sabdar lp->tl_slot_count = 0; 4852654012fSReza Sabdar } 4862654012fSReza Sabdar } 4872654012fSReza Sabdar 4882654012fSReza Sabdar /* 4892654012fSReza Sabdar * Initialize the tape library data structure, asks the libraries what 4902654012fSReza Sabdar * equipments they have. 4912654012fSReza Sabdar */ 4922654012fSReza Sabdar int 4932654012fSReza Sabdar tlm_init(void) 4942654012fSReza Sabdar { 4952654012fSReza Sabdar static int nlibs; /* number of found libraries */ 4962654012fSReza Sabdar int i, nsa; 4972654012fSReza Sabdar int l, vlibs, d; 4982654012fSReza Sabdar int rv; 4992654012fSReza Sabdar scsi_adapter_t *sa; 5002654012fSReza Sabdar tlm_library_t *lp; 5012654012fSReza Sabdar tlm_drive_t *dp; 5022654012fSReza Sabdar 5032654012fSReza Sabdar /* Search through all SCSI adapters, look for tape robots. */ 5042654012fSReza Sabdar nlibs = 0; 5052654012fSReza Sabdar 5062654012fSReza Sabdar /* 5072654012fSReza Sabdar * We probe both changers and tape drives here 5082654012fSReza Sabdar * but later on this needs to be removed as the 5092654012fSReza Sabdar * probe will happen somewhere else. 5102654012fSReza Sabdar */ 5112654012fSReza Sabdar (void) probe_scsi(); 5122654012fSReza Sabdar 5132654012fSReza Sabdar nsa = scsi_get_adapter_count(); 5142654012fSReza Sabdar for (i = 0; i < nsa; i++) 5152654012fSReza Sabdar if ((sa = scsi_get_adapter(i))) 5162654012fSReza Sabdar (void) scan_bus(sa, add_lib, (void *)&nlibs); 5172654012fSReza Sabdar 5182654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "nlibs %d", nlibs); 5192654012fSReza Sabdar 5202654012fSReza Sabdar /* Search through all SCSI adapters, look for tape drives. */ 5212654012fSReza Sabdar vlibs = 0; 5222654012fSReza Sabdar for (i = 0; i < nsa; i++) 5232654012fSReza Sabdar if ((sa = scsi_get_adapter(i))) 5242654012fSReza Sabdar (void) scan_bus(sa, add_drv, (void *)&vlibs); 5252654012fSReza Sabdar 5262654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "vlibs %d", vlibs); 5272654012fSReza Sabdar 5282654012fSReza Sabdar if (nlibs > 0 && vlibs > 0) 5292654012fSReza Sabdar inaccbl_drv_warn(nlibs + 1, vlibs + nlibs + 1); 5302654012fSReza Sabdar 5312654012fSReza Sabdar for (l = 1; l <= tlm_library_count(); l++) { 5322654012fSReza Sabdar if (!(lp = tlm_library(l))) { 5332654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "can't find lib %d", l); 5342654012fSReza Sabdar continue; 5352654012fSReza Sabdar } 5362654012fSReza Sabdar 5372654012fSReza Sabdar /* 5382654012fSReza Sabdar * Make sure all libraries have tape drives. 5392654012fSReza Sabdar */ 5402654012fSReza Sabdar if (lp->tl_drive_count == 0) 5412654012fSReza Sabdar continue; 5422654012fSReza Sabdar 5432654012fSReza Sabdar /* 5442654012fSReza Sabdar * Make sure all tape drives exist. A drive that is not 5452654012fSReza Sabdar * linked into the SCSI chain will be seen by the library 5462654012fSReza Sabdar * but we cannot talk to it. 5472654012fSReza Sabdar */ 5482654012fSReza Sabdar for (d = 1; d <= lp->tl_drive_count; d++) { 5492654012fSReza Sabdar dp = tlm_drive(l, d); 5502654012fSReza Sabdar if (dp && !dp->td_exists) { 5512654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "Ghost drive found %d.%d", 5522654012fSReza Sabdar l, d); 5532654012fSReza Sabdar lp->tl_ghost_drives = TRUE; 5542654012fSReza Sabdar continue; 5552654012fSReza Sabdar } 5562654012fSReza Sabdar } 5572654012fSReza Sabdar } 5582654012fSReza Sabdar 5592654012fSReza Sabdar if (nlibs > 0) 5602654012fSReza Sabdar rv = (vlibs > 0) ? 0 : nlibs; 5612654012fSReza Sabdar else 5622654012fSReza Sabdar rv = vlibs; 5632654012fSReza Sabdar 5642654012fSReza Sabdar return (rv); 5652654012fSReza Sabdar } 566