xref: /illumos-gate/usr/src/uts/common/io/scsi/adapters/scsi_vhci/fops/tape.c (revision 0205780bc43902d17f94f07ceacb0cd8d5eab20f)
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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
26 
27 /*
28  * Implementation of "scsi_vhci_f_tape" tape failover_ops.
29  *
30  * This file was historically meant for only tape implementation.  It has
31  * been extended to manage SUN "supported" tape controllers. The supported
32  * VID/PID shall be listed in the tape_dev_table.
33  */
34 
35 #include <sys/conf.h>
36 #include <sys/file.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 #include <sys/scsi/scsi.h>
40 #include <sys/scsi/adapters/scsi_vhci.h>
41 
42 /* Supported device table entries.  */
43 static char *tape_dev_table[] = {
44 /*	"                  111111" */
45 /*	"012345670123456789012345" */
46 /*	"|-VID--||-----PID------|" */
47 	"IBM     ULTRIUM-TD3",
48 	"IBM     ULTRIUM-TD4",
49 	NULL
50 };
51 
52 /* Failover module plumbing. */
53 SCSI_FAILOVER_OP("f_tape", tape, "%I%");
54 
55 /* ARGSUSED */
56 static int
57 tape_device_probe(struct scsi_device *sd, struct scsi_inquiry *inquiry,
58     void **ctpriv)
59 {
60 	int i;
61 	int rval = SFO_DEVICE_PROBE_PHCI;
62 
63 	VHCI_DEBUG(6, (CE_NOTE, NULL, "!tape_device_probe: inquiry string %s\n",
64 	    inquiry->inq_vid));
65 	/*
66 	 * See if this a device type that we want to care about.
67 	 */
68 	switch (inquiry->inq_dtype & DTYPE_MASK) {
69 	case DTYPE_SEQUENTIAL:
70 		break;
71 	case DTYPE_CHANGER:
72 		rval = SFO_DEVICE_PROBE_VHCI;
73 		goto done;
74 	default:
75 		/*
76 		 * Not interested.
77 		 */
78 		return (rval);
79 	}
80 
81 	/*
82 	 * If it reports that it supports tpgs and it got here it may have
83 	 * failed the tpgs commands. It might or might not support dual port
84 	 * but we'll go with it.
85 	 */
86 	if (inquiry->inq_tpgs) {
87 		VHCI_DEBUG(6, (CE_NOTE, NULL, "!has tpgs bits: %s\n",
88 		    inquiry->inq_vid));
89 		rval = SFO_DEVICE_PROBE_VHCI;
90 	} else if (inquiry->inq_dualp) {
91 		/*
92 		 * Looks like it claims to have more then one port.
93 		 */
94 		VHCI_DEBUG(6, (CE_NOTE, NULL, "!has dual port bits: %s\n",
95 		    inquiry->inq_vid));
96 		rval = SFO_DEVICE_PROBE_VHCI;
97 	} else {
98 
99 		/*
100 		 * See if this device is on the list.
101 		 */
102 		for (i = 0; tape_dev_table[i]; i++) {
103 
104 			if (strncmp(inquiry->inq_vid, tape_dev_table[i],
105 			    strlen(tape_dev_table[i])) == 0) {
106 				VHCI_DEBUG(6, (CE_NOTE, NULL,
107 				    "!was on the list: %s\n",
108 				    inquiry->inq_vid));
109 				rval = SFO_DEVICE_PROBE_VHCI;
110 				break;
111 			}
112 		}
113 	}
114 done:
115 	if (rval == SFO_DEVICE_PROBE_VHCI) {
116 		if (mdi_set_lb_policy(sd->sd_dev, LOAD_BALANCE_NONE) !=
117 		    MDI_SUCCESS) {
118 			VHCI_DEBUG(6, (CE_NOTE, NULL, "!fail load balance none"
119 			    ": %s\n", inquiry->inq_vid));
120 			return (SFO_DEVICE_PROBE_PHCI);
121 		}
122 
123 	}
124 	return (rval);
125 }
126 
127 /* ARGSUSED */
128 static void
129 tape_device_unprobe(struct scsi_device *sd, void *ctpriv)
130 {
131 	/*
132 	 * NO OP for tape.
133 	 */
134 
135 }
136 
137 /* ARGSUSED */
138 static int
139 tape_path_activate(struct scsi_device *sd, char *pathclass, void *ctpriv)
140 {
141 	return (0);
142 }
143 
144 /* ARGSUSED */
145 static int
146 tape_path_deactivate(struct scsi_device *sd, char *pathclass, void *ctpriv)
147 {
148 	return (0);
149 }
150 
151 /* ARGSUSED */
152 static int
153 tape_path_get_opinfo(struct scsi_device *sd, struct scsi_path_opinfo *opinfo,
154     void *ctpriv)
155 {
156 	opinfo->opinfo_rev = OPINFO_REV;
157 	(void) strcpy(opinfo->opinfo_path_attr, PCLASS_PRIMARY);
158 	opinfo->opinfo_path_state  = SCSI_PATH_ACTIVE;
159 	opinfo->opinfo_pswtch_best = 0;		/* N/A */
160 	opinfo->opinfo_pswtch_worst = 0;	/* N/A */
161 	opinfo->opinfo_xlf_capable = 0;
162 	opinfo->opinfo_mode = SCSI_NO_FAILOVER;
163 	opinfo->opinfo_preferred = 1;
164 
165 	return (0);
166 }
167 
168 /* ARGSUSED */
169 static int
170 tape_path_ping(struct scsi_device *sd, void *ctpriv)
171 {
172 	return (1);
173 }
174 
175 /* ARGSUSED */
176 static int
177 tape_analyze_sense(struct scsi_device *sd, struct scsi_extended_sense *sense,
178     void *ctpriv)
179 {
180 	if (sense->es_key == KEY_ABORTED_COMMAND &&
181 	    sense->es_add_code == 0x4b &&
182 	    sense->es_qual_code == 0x83) {
183 		return (SCSI_SENSE_INACTIVE);
184 	}
185 	if (sense->es_key == KEY_NOT_READY &&
186 	    sense->es_add_code == 0x4 &&
187 	    sense->es_qual_code == 0x1) {
188 		return (SCSI_SENSE_NOT_READY);
189 	}
190 	return (SCSI_SENSE_NOFAILOVER);
191 }
192 
193 /* ARGSUSED */
194 static int
195 tape_pathclass_next(char *cur, char **nxt, void *ctpriv)
196 {
197 	if (cur == NULL) {
198 		*nxt = PCLASS_PRIMARY;
199 		return (0);
200 	} else if (strcmp(cur, PCLASS_PRIMARY) == 0) {
201 		return (ENOENT);
202 	}
203 	return (EINVAL);
204 }
205