xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/scsi_vhci/fops/tpgs_tape.c (revision b07ce584f4e28873b8927d7f83d9d3275a0f3ed2)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * Implementation of "scsi_vhci_f_tpgs_tape" T10 standard based failover_ops.
28  *
29  * NOTE: for sequential devices only.
30  */
31 
32 #include <sys/conf.h>
33 #include <sys/file.h>
34 #include <sys/ddi.h>
35 #include <sys/sunddi.h>
36 #include <sys/scsi/scsi.h>
37 #include <sys/scsi/adapters/scsi_vhci.h>
38 #include <sys/scsi/adapters/scsi_vhci_tpgs.h>
39 
40 /* Supported device table entries.  */
41 char *tpgs_tape_dev_table[] = { NULL };
42 static void tpgs_tape_init(void);
43 static int tpgs_tape_device_probe(struct scsi_device *sd,
44     struct scsi_inquiry *inq, void **ctpriv);
45 
46 /* Failover module plumbing. */
47 #ifdef	lint
48 #define	scsi_vhci_failover_ops	scsi_vhci_failover_ops_f_tpgs_tape
49 #endif	/* lint */
50 struct scsi_failover_ops scsi_vhci_failover_ops = {
51 	SFO_REV,
52 	"f_tpgs_tape",
53 	tpgs_tape_dev_table,
54 	tpgs_tape_init,
55 	tpgs_tape_device_probe,
56 	/* The rest of the implementation comes from SFO_NAME_TPGS import  */
57 };
58 
59 static struct modlmisc modlmisc = {
60 	&mod_miscops, "f_tpgs_tape"
61 };
62 
63 static struct modlinkage modlinkage = {
64 	MODREV_1, (void *)&modlmisc, NULL
65 };
66 
67 
68 
69 /*
70  * External function definitions
71  */
72 extern struct scsi_failover_ops	*vhci_failover_ops_by_name(char *);
73 
74 int
75 _init()
76 {
77 	return (mod_install(&modlinkage));
78 }
79 
80 int
81 _fini()
82 {
83 	return (mod_remove(&modlinkage));
84 }
85 
86 int
87 _info(struct modinfo *modinfop)
88 {
89 	return (mod_info(&modlinkage, modinfop));
90 }
91 
92 
93 
94 /* ARGSUSED */
95 static int
96 tpgs_tape_device_probe(struct scsi_device *sd, struct scsi_inquiry *inq,
97     void **ctpriv)
98 {
99 	int		mode, state, xlf, preferred = 0;
100 
101 	VHCI_DEBUG(6, (CE_NOTE, NULL, "tpgs_tape_device_probe: vidpid %s\n",
102 	    inq->inq_vid));
103 
104 	if (inq->inq_tpgs == TPGS_FAILOVER_NONE) {
105 		VHCI_DEBUG(4, (CE_WARN, NULL,
106 		    "!tpgs_tape_device_probe: not a standard tpgs device"));
107 		return (SFO_DEVICE_PROBE_PHCI);
108 	}
109 
110 	if (inq->inq_dtype != DTYPE_SEQUENTIAL) {
111 		VHCI_DEBUG(4, (CE_NOTE, NULL,
112 		    "!tpgs_tape_device_probe: Detected a "
113 		    "Standard Asymmetric device "
114 		    "not yet supported\n"));
115 		return (SFO_DEVICE_PROBE_PHCI);
116 	}
117 
118 	if (vhci_tpgs_get_target_fo_mode(sd, &mode, &state, &xlf, &preferred)) {
119 		VHCI_DEBUG(4, (CE_WARN, NULL, "!unable to fetch fo "
120 		    "mode: sd(%p)", (void *) sd));
121 		return (SFO_DEVICE_PROBE_PHCI);
122 	}
123 
124 	if (inq->inq_tpgs == TPGS_FAILOVER_IMPLICIT) {
125 		VHCI_DEBUG(1, (CE_NOTE, NULL,
126 		    "!tpgs_tape_device_probe: Detected a "
127 		    "Standard Asymmetric device "
128 		    "with implicit failover\n"));
129 		return (SFO_DEVICE_PROBE_VHCI);
130 	}
131 	if (inq->inq_tpgs == TPGS_FAILOVER_EXPLICIT) {
132 		VHCI_DEBUG(1, (CE_NOTE, NULL,
133 		    "!tpgs_tape_device_probe: Detected a "
134 		    "Standard Asymmetric device "
135 		    "with explicit failover\n"));
136 		return (SFO_DEVICE_PROBE_VHCI);
137 	}
138 	if (inq->inq_tpgs == TPGS_FAILOVER_BOTH) {
139 		VHCI_DEBUG(1, (CE_NOTE, NULL,
140 		    "!tpgs_tape_device_probe: Detected a "
141 		    "Standard Asymmetric device "
142 		    "which supports both implicit and explicit failover\n"));
143 		return (SFO_DEVICE_PROBE_VHCI);
144 	}
145 	VHCI_DEBUG(1, (CE_WARN, NULL,
146 	    "!tpgs_tape_device_probe: "
147 	    "Unknown tpgs_bits: %x", inq->inq_tpgs));
148 	return (SFO_DEVICE_PROBE_PHCI);
149 }
150 
151 static void
152 tpgs_tape_init(void)
153 {
154 	struct scsi_failover_ops	*sfo, *ssfo, clone;
155 
156 	/* clone SFO_NAME_SYM implementation for most things */
157 	ssfo = vhci_failover_ops_by_name(SFO_NAME_TPGS);
158 	if (ssfo == NULL) {
159 		VHCI_DEBUG(4, (CE_NOTE, NULL, "!tpgs_tape: "
160 		    "can't import " SFO_NAME_SYM "\n"));
161 		return;
162 	}
163 	sfo			= &scsi_vhci_failover_ops;
164 	clone			= *ssfo;
165 	clone.sfo_rev		= sfo->sfo_rev;
166 	clone.sfo_name		= sfo->sfo_name;
167 	clone.sfo_devices	= sfo->sfo_devices;
168 	clone.sfo_init		= sfo->sfo_init;
169 	clone.sfo_device_probe	= sfo->sfo_device_probe;
170 	*sfo			= clone;
171 }
172