0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs/*
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * CDDL HEADER START
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs *
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * The contents of this file are subject to the terms of the
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * Common Development and Distribution License (the "License").
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * You may not use this file except in compliance with the License.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs *
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * or http://www.opensolaris.org/os/licensing.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * See the License for the specific language governing permissions
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * and limitations under the License.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs *
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * When distributing Covered Code, include this CDDL HEADER in each
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * If applicable, add the following below this CDDL HEADER, with the
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * fields enclosed by brackets "[]" replaced with your own identifying
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * information: Portions Copyright [yyyy] [name of copyright owner]
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs *
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * CDDL HEADER END
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs/*
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * Use is subject to license terms.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs/*
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * Implementation of "scsi_vhci_f_tpgs_tape" T10 standard based failover_ops.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs *
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * NOTE: for sequential devices only.
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#include <sys/conf.h>
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#include <sys/file.h>
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#include <sys/ddi.h>
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#include <sys/sunddi.h>
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#include <sys/scsi/scsi.h>
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#include <sys/scsi/adapters/scsi_vhci.h>
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#include <sys/scsi/adapters/scsi_vhci_tpgs.h>
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs/* Supported device table entries. */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphschar *tpgs_tape_dev_table[] = { NULL };
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic void tpgs_tape_init(void);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic int tpgs_tape_device_probe(struct scsi_device *sd,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs struct scsi_inquiry *inq, void **ctpriv);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs/* Failover module plumbing. */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#ifdef lint
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#define scsi_vhci_failover_ops scsi_vhci_failover_ops_f_tpgs_tape
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs#endif /* lint */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstruct scsi_failover_ops scsi_vhci_failover_ops = {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs SFO_REV,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "f_tpgs_tape",
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs tpgs_tape_dev_table,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs tpgs_tape_init,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs tpgs_tape_device_probe,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs /* The rest of the implementation comes from SFO_NAME_TPGS import */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs};
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic struct modlmisc modlmisc = {
39b361b2ebefcef5612a54ae5cbd2179e19be296Richard Bean &mod_miscops, "f_tpgs_tape"
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs};
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic struct modlinkage modlinkage = {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs MODREV_1, (void *)&modlmisc, NULL
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs};
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs/*
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs * External function definitions
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsextern struct scsi_failover_ops *vhci_failover_ops_by_name(char *);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsint
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs_init()
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs{
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs return (mod_install(&modlinkage));
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs}
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsint
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs_fini()
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs{
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs return (mod_remove(&modlinkage));
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs}
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsint
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs_info(struct modinfo *modinfop)
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs{
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs return (mod_info(&modlinkage, modinfop));
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs}
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs/* ARGSUSED */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic int
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphstpgs_tape_device_probe(struct scsi_device *sd, struct scsi_inquiry *inq,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs void **ctpriv)
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs{
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs int mode;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs int state;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs int xlf;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs int preferred = 0;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs int support;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs VHCI_DEBUG(6, (CE_NOTE, NULL, "tpgs_tape_device_probe: vidpid %s\n",
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs inq->inq_vid));
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
d91393a8e4d666dd6b6588c980c59cec667835f4Chris Horne if (inq->inq_tpgs == TPGS_FAILOVER_NONE) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs VHCI_DEBUG(4, (CE_WARN, NULL,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "!tpgs_tape_device_probe: not a standard tpgs device"));
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs support = SFO_DEVICE_PROBE_PHCI;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs } else if (inq->inq_dtype != DTYPE_SEQUENTIAL) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs VHCI_DEBUG(4, (CE_NOTE, NULL,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "!tpgs_tape_device_probe: Detected a "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "Standard Asymmetric device "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "not yet supported\n"));
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs support = SFO_DEVICE_PROBE_PHCI;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs } else if (vhci_tpgs_get_target_fo_mode(sd, &mode, &state, &xlf,
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs &preferred)) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs VHCI_DEBUG(4, (CE_WARN, NULL, "!unable to fetch fo "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "mode: sd(%p)", (void *) sd));
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs support = SFO_DEVICE_PROBE_PHCI;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs } else if (inq->inq_tpgs == TPGS_FAILOVER_IMPLICIT) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs VHCI_DEBUG(1, (CE_NOTE, NULL,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "!tpgs_tape_device_probe: Detected a "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "Standard Asymmetric device "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "with implicit failover\n"));
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs support = SFO_DEVICE_PROBE_VHCI;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs } else if (inq->inq_tpgs == TPGS_FAILOVER_EXPLICIT) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs VHCI_DEBUG(1, (CE_NOTE, NULL,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "!tpgs_tape_device_probe: Detected a "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "Standard Asymmetric device "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "with explicit failover\n"));
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs support = SFO_DEVICE_PROBE_VHCI;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs } else if (inq->inq_tpgs == TPGS_FAILOVER_BOTH) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs VHCI_DEBUG(1, (CE_NOTE, NULL,
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "!tpgs_tape_device_probe: Detected a "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "Standard Asymmetric device "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "which supports both implicit and explicit failover\n"));
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs support = SFO_DEVICE_PROBE_VHCI;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs } else {
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs VHCI_DEBUG(1, (CE_WARN, NULL,
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs "!tpgs_tape_device_probe: "
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs "Unknown tpgs_bits: %x", inq->inq_tpgs));
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs support = SFO_DEVICE_PROBE_PHCI;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs }
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs if (support == SFO_DEVICE_PROBE_VHCI) {
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs /*
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs * Policy only applies to 'client' probe, not
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs * vhci_is_dev_supported() pHCI probe. Detect difference
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs * based on ctpriv.
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs */
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs if (ctpriv &&
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs (mdi_set_lb_policy(sd->sd_dev, LOAD_BALANCE_NONE) !=
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs MDI_SUCCESS)) {
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs VHCI_DEBUG(6, (CE_NOTE, NULL, "!fail load balance none"
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs ": %s\n", inq->inq_vid));
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs support = SFO_DEVICE_PROBE_PHCI;
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs }
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs }
dd64cd4431d441dd94f19b4b5006ea1b83ac426dRandall Ralphs return (support);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs}
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphsstatic void
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphstpgs_tape_init(void)
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs{
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs struct scsi_failover_ops *sfo, *ssfo, clone;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs /* clone SFO_NAME_SYM implementation for most things */
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs ssfo = vhci_failover_ops_by_name(SFO_NAME_TPGS);
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs if (ssfo == NULL) {
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs VHCI_DEBUG(4, (CE_NOTE, NULL, "!tpgs_tape: "
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs "can't import " SFO_NAME_SYM "\n"));
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs return;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs }
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs sfo = &scsi_vhci_failover_ops;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs clone = *ssfo;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs clone.sfo_rev = sfo->sfo_rev;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs clone.sfo_name = sfo->sfo_name;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs clone.sfo_devices = sfo->sfo_devices;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs clone.sfo_init = sfo->sfo_init;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs clone.sfo_device_probe = sfo->sfo_device_probe;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs *sfo = clone;
0205780bc43902d17f94f07ceacb0cd8d5eab20frralphs}