2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * BSD 3 Clause License
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Redistribution and use in source and binary forms, with or without
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * modification, are permitted provided that the following conditions
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * are met:
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Redistributions of source code must retain the above copyright
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * notice, this list of conditions and the following disclaimer.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Redistributions in binary form must reproduce the above copyright
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * notice, this list of conditions and the following disclaimer in
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * the documentation and/or other materials provided with the
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * distribution.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * nor the names of its contributors may be used to endorse or promote
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * products derived from this software without specific prior written
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * permission.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * POSSIBILITY OF SUCH DAMAGE.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <sys/errno.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <sys/types.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <stdlib.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <unistd.h>
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs#include <ctype.h>
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs#include <sys/byteorder.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <sys/scsi/impl/uscsi.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <sys/scsi/scsi.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <tlm.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include <pthread.h>
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar#include "tlm_proto.h"
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * generic routine to read a SCSI page
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarread_scsi_page(scsi_link_t *slink, union scsi_cdb *cdb,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int command_size, caddr_t data, int size)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct uscsi_cmd uscsi_cmd;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *dname;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int dev;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (slink == 0 || slink->sl_sa == 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (EINVAL);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) memset(&uscsi_cmd, 0, sizeof (uscsi_cmd));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* Lun is in the 5th bit */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cdb->scc_lun = slink->sl_lun;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_flags |= USCSI_READ | USCSI_ISOLATE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_bufaddr = data;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_buflen = size;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_timeout = 1000;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_cdb = (char *)cdb;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (cdb->scc_cmd == SCMD_READ_ELEMENT_STATUS) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_flags |= USCSI_RQENABLE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_rqbuf = data;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_rqlen = size;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar uscsi_cmd.uscsi_cdblen = command_size;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dname = sasd_slink_name(slink);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dev = open(dname, O_RDWR | O_NDELAY);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (dev == -1) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Open failed for %s err=%d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dname, errno);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (errno);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (tlm_ioctl(dev, USCSICMD, &uscsi_cmd) < 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "SCSI cmd %d failed for %s err=%d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cdb->scc_cmd, dname, errno);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) close(dev);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (errno);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) close(dev);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (uscsi_cmd.uscsi_status);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Read the Inquiry Page.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarread_inquiry_page(scsi_link_t *slink, struct scsi_inquiry *inq)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar union scsi_cdb cdb;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) memset(&cdb, 0, sizeof (union scsi_cdb));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cdb.scc_cmd = SCMD_INQUIRY;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar cdb.g0_count0 = sizeof (struct scsi_inquiry);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (read_scsi_page(slink, &cdb, CDB_GROUP0,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (caddr_t)inq, sizeof (*inq)) ? -1 : 0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar/*
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar * Read the Product Data Page.
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar */
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdarstatic int
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdarread_data_page(scsi_link_t *slink, int pcode, char *snum, int size)
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar{
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar char cmd[CDB_GROUP0];
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) memset(cmd, 0, sizeof (cmd));
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar cmd[0] = SCMD_INQUIRY;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar cmd[1] = pcode ? 0x01 : 0x00;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar cmd[2] = pcode;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar cmd[4] = size;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar /* LINTED improper alignment */
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar return (read_scsi_page(slink, (union scsi_cdb *)&cmd, CDB_GROUP0,
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (caddr_t)snum, size) == -1 ? -1 : 0);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar}
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar/*
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar * Read the Serial Number Page.
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar */
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdarstatic int
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdarread_serial_num_page(scsi_link_t *slink, char *snum, int size)
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar{
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar scsi_serial_t serial;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar int rv;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) memset(&serial, 0, sizeof (scsi_serial_t));
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar rv = read_data_page(slink, SCSI_SERIAL_PAGE, (caddr_t)&serial,
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar sizeof (scsi_serial_t));
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) strlcpy(snum, serial.sr_num, size);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar return (rv == -1 ? -1 : 0);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar}
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar/*
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar * Read the Device Name Page.
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar */
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdarstatic int
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphsread_dev_name_page(scsi_link_t *slink, device_ident_header_t *devp, int len)
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar{
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs (void) memset(devp, 0, len);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar if (read_data_page(slink, SCSI_DEVICE_IDENT_PAGE, (caddr_t)devp,
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs len) == -1)
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar return (-1);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs if (devp->di_page_code != SCSI_DEVICE_IDENT_PAGE)
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs return (-1);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs return (0);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar}
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar/*
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar * Formatted print of WWN
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar */
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphsstatic void
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdarsnprintf_wwn(char *buf, int size, uint8_t *wwn)
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar{
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar if (wwn == NULL || buf == NULL)
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs return;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) snprintf(buf, size, "0x%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X%2.2X",
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar wwn[0], wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar}
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar/*
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar * Extract and print the world wide name (WWN)
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar */
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdarint
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdarread_device_wwn(scsi_link_t *slink, char *wwnp, int wsize)
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar{
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs device_ident_header_t *header;
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs name_ident_t *ident;
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs uint16_t page_len = sizeof (device_ident_header_t);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs uint16_t act_len;
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs int accessed;
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs uint8_t *designator_data;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) memset(wwnp, 0, wsize);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphsresize:
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs header = malloc(page_len);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs if (header == NULL)
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar return (-1);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs if (read_dev_name_page(slink, header, page_len) == -1) {
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs free(header);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs return (-1);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar }
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs act_len = BE_16(header->di_page_length);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs if (act_len > page_len) {
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs free(header);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs page_len = act_len;
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs goto resize;
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar }
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs ident = (name_ident_t *)&header[1];
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs accessed = sizeof (device_ident_header_t);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs while (accessed < act_len) {
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs accessed += sizeof (name_ident_t);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs accessed += ident->ni_ident_length;
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs designator_data = (uint8_t *)&ident[1];
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs /*
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * Looking for code set 1 (Binary) ident type NAA 64 bit
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * address that is associated with the node (0).
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs */
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs if ((ident->ni_code_set == 1) &&
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs (ident->ni_ident_type == 3)) {
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs snprintf_wwn(wwnp, wsize, designator_data);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs /*
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * If assc is zero (Node) this is the one we want.
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * If we find that we're done.
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs */
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs if (ident->ni_asso == 0)
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs break;
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs }
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs /*
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * If we find a EUI-64 we can use that also.
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs */
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs if ((ident->ni_code_set == 2) &&
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs (ident->ni_ident_type == 1) &&
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs (ident->ni_asso == 0) &&
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs (isprint(wwnp[0] == 0))) { /* Don't overwrite */
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs /*
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * This isn't our first choice but we'll print it
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * in case there is nothing else to use.
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs */
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs (void) snprintf(wwnp, wsize, "%.*s",
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs ident->ni_ident_length, designator_data);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs }
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs ident =
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs (name_ident_t *)&designator_data[ident->ni_ident_length];
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar }
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs free(header);
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs /*
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * See if we found something.
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs * Memset above would leave wwnp not printable.
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs */
e461e790745fa2b2374e5734984107c7672c6c49Randall Ralphs if (isprint(wwnp[0]))
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar return (0);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar return (-1);
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar}
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Add the tape library call back function (used while scanning the bus)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdaradd_lib(scsi_link_t *slink, struct scsi_inquiry *sd, void *arg)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int l;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int *nlp; /* pointer to library counter */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sasd_drive_t *ssd;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!slink || !sd) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument %x %x %x",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar slink, sd, arg);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-TLM_INVALID);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (sd->inq_dtype == DTYPE_CHANGER) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* This is a robot, which means this is also a library */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nlp = (int *)arg;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (*nlp)++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar l = tlm_insert_new_library(slink);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_enable_barcode(l);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "lib %d sid %d lun %d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar l, slink->sl_sid, slink->sl_lun);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((ssd = sasd_slink_drive(slink)) != NULL) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strlcpy(ssd->sd_vendor, sd->inq_vid,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sizeof (ssd->sd_vendor));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strlcpy(ssd->sd_id, sd->inq_pid,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sizeof (ssd->sd_id));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strlcpy(ssd->sd_rev, sd->inq_revision,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sizeof (ssd->sd_rev));
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) read_serial_num_page(slink, ssd->sd_serial,
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar sizeof (ssd->sd_serial));
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) read_device_wwn(slink, ssd->sd_wwn,
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar sizeof (ssd->sd_wwn));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (TLM_NO_ERRORS);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Create some virutal slots
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarmake_virtual_slot(int l, tlm_drive_t *dp)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int s;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_slot_t *sp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (l <= 0 || !dp) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument %d, %x", l, dp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-TLM_INVALID);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((s = tlm_insert_new_slot(l)) <= 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-TLM_NO_MEMORY);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!(sp = tlm_slot(l, s))) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Internal error: slot not found %d", s);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-TLM_ERROR_INTERNAL);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * For virtual slots element number is 0 and they are always full.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sp->ts_element = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sp->ts_status_full = TRUE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (TLM_NO_ERRORS);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Make the tape drive not part of a tape library (stand alone)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarmake_stand_alone_drive(scsi_link_t *slink, int l)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int d;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_drive_t *dp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!slink || l <= 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument %x %d", slink, l);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-TLM_INVALID);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar d = tlm_insert_new_drive(l);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!(dp = tlm_drive(l, d))) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Internal error: drive not found %d", d);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-TLM_ERROR_INTERNAL);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* For stand-alone drives, the element number is the drive number. */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dp->td_element = d;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dp->td_slink = slink;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dp->td_scsi_id = slink->sl_sid;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dp->td_lun = slink->sl_lun;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dp->td_exists = TRUE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Note: There is no way to remove library elements. We cannot clean
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * up if make_virtual_slot() fails.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) make_virtual_slot(l, dp);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (d);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Find the LIBRARY structure that has control of this DRIVE.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarnew_drive(scsi_link_t *slink, int *lib)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int d;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_drive_t *dp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_library_t *lp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* Walk through all libraries. */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (*lib = 1; *lib <= tlm_library_count(); (*lib)++) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!(lp = tlm_library(*lib)))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* Walk through drives that are already found. */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (d = 1; d <= lp->tl_drive_count; d++) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!(dp = tlm_drive(*lib, d)))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (dp->td_scsi_id == slink->sl_sid &&
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dp->td_lun == slink->sl_lun)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (d);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* Not part of any library, this is a newly found tape drive. */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (0);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Add the tape library call back function (used while scanning the bus)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdaradd_drv(scsi_link_t *slink, struct scsi_inquiry *sd, void *arg)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int l, d;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int *vlp; /* pointer to virtual library number */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sasd_drive_t *ssd;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_library_t *library;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_drive_t *drive;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!slink || !sd) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Invalid argument %x %x %x",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar slink, sd, arg);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-TLM_INVALID);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (sd->inq_dtype == DTYPE_SEQUENTIAL) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar vlp = (int *)arg;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar d = new_drive(slink, &l);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (d == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* This tape drive was not found inside any robot. */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (*vlp == 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * First, create a virtual library if it's not
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * done yet.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar *vlp = tlm_insert_new_library(slink);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((library = tlm_library(*vlp)) != NULL)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar library->tl_capability_robot = FALSE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((d = make_stand_alone_drive(slink, *vlp)) < 0) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* sorry, we can not clean up the vlib now * */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (-TLM_INVALID);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar l = *vlp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "vlib(%d, %d) sid %d lun %d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar l, d, slink->sl_sid, slink->sl_lun);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } else
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "(%d, %d) sid %d lun %d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar l, d, slink->sl_sid, slink->sl_lun);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((drive = tlm_drive(l, d)) != NULL) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar drive->td_exists = TRUE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar drive->td_slink = slink;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((ssd = sasd_slink_drive(slink)) != NULL) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strlcpy(ssd->sd_vendor,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sd->inq_vid, sizeof (ssd->sd_vendor));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strlcpy(ssd->sd_id, sd->inq_pid,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sizeof (ssd->sd_id));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) strlcpy(ssd->sd_rev, sd->inq_revision,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar sizeof (ssd->sd_rev));
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) read_serial_num_page(slink, ssd->sd_serial,
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar sizeof (ssd->sd_serial));
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar (void) read_device_wwn(slink, ssd->sd_wwn,
7bc22e45a20f905cdd06bb98c98a5c8be7fd25c0Reza Sabdar sizeof (ssd->sd_wwn));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (TLM_NO_ERRORS);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Scan the specified bus and call the handler function.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic int
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarscan_bus(scsi_adapter_t *sa, int(*hndlr)(), void *args)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int nerr;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar scsi_link_t *slink;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar struct scsi_inquiry scsi_data;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nerr = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar slink = sa->sa_link_head.sl_next;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (; slink != &sa->sa_link_head; slink = slink->sl_next) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) memset(&scsi_data, 0, sizeof (struct scsi_inquiry));
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (read_inquiry_page(slink, &scsi_data) == -1)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nerr++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar else
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((*hndlr)(slink, &scsi_data, args) != TLM_NO_ERRORS)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nerr++;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (nerr);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Marks the library/slots inaccessible if there are not enough drives
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * available on the library
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarstatic void
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarinaccbl_drv_warn(int start, int max)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar char *dname;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int l, d;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_library_t *lp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (l = start; l < max; l++) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!(lp = tlm_library(l)))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (lp->tl_drive_count <= 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "Warning: The following drives are not accessible:");
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (d = 1; d <= lp->tl_drive_count; d++)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!(dname = tlm_get_tape_name(l, d))) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG,
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar "Error getting drive(%d, %d)", l, d);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar } else
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "%s", dname);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Note: Make the slots inaccessible to prevent running
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * discovery on these libraries. The better idea is
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * removing these libraries, but we don't have that
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * feature available now.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar lp->tl_slot_count = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar/*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Initialize the tape library data structure, asks the libraries what
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * equipments they have.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdarint
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdartlm_init(void)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar{
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar static int nlibs; /* number of found libraries */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int i, nsa;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int l, vlibs, d;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar int rv;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar scsi_adapter_t *sa;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_library_t *lp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar tlm_drive_t *dp;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* Search through all SCSI adapters, look for tape robots. */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nlibs = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * We probe both changers and tape drives here
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * but later on this needs to be removed as the
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * probe will happen somewhere else.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
1e05b03fa76ee89d509f0c461b36cb865f1e6794Janice Chang if (probe_scsi() < 0)
1e05b03fa76ee89d509f0c461b36cb865f1e6794Janice Chang return (-1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar nsa = scsi_get_adapter_count();
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (i = 0; i < nsa; i++)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((sa = scsi_get_adapter(i)))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) scan_bus(sa, add_lib, (void *)&nlibs);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "nlibs %d", nlibs);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /* Search through all SCSI adapters, look for tape drives. */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar vlibs = 0;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (i = 0; i < nsa; i++)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if ((sa = scsi_get_adapter(i)))
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar (void) scan_bus(sa, add_drv, (void *)&vlibs);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "vlibs %d", vlibs);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (nlibs > 0 && vlibs > 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar inaccbl_drv_warn(nlibs + 1, vlibs + nlibs + 1);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (l = 1; l <= tlm_library_count(); l++) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (!(lp = tlm_library(l))) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "can't find lib %d", l);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Make sure all libraries have tape drives.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (lp->tl_drive_count == 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar /*
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * Make sure all tape drives exist. A drive that is not
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * linked into the SCSI chain will be seen by the library
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar * but we cannot talk to it.
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar */
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar for (d = 1; d <= lp->tl_drive_count; d++) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar dp = tlm_drive(l, d);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (dp && !dp->td_exists) {
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar NDMP_LOG(LOG_DEBUG, "Ghost drive found %d.%d",
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar l, d);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar lp->tl_ghost_drives = TRUE;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar continue;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar }
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar if (nlibs > 0)
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = (vlibs > 0) ? 0 : nlibs;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar else
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar rv = vlibs;
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar return (rv);
2654012f83cec5dc15b61dfe3e4a4915f186e7a6Reza Sabdar}