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 /*
23  * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 /*
27  * Implementation of "scsi_vhci_f_sym" symmetric failover_ops.
28  *
29  * This file was historically meant for only symmetric implementation.  It has
30  * been extended to manage SUN "supported" symmetric controllers. The supported
31  * VID/PID shall be listed in the symmetric_dev_table.
32  */
33 
34 #include <sys/conf.h>
35 #include <sys/file.h>
36 #include <sys/ddi.h>
37 #include <sys/sunddi.h>
38 #include <sys/scsi/scsi.h>
39 #include <sys/scsi/adapters/scsi_vhci.h>
40 
41 /* Supported device table entries.  */
42 char *symmetric_dev_table[] = {
43 /*	"                  111111" */
44 /*	"012345670123456789012345" */
45 /*	"|-VID--||-----PID------|" */
46 				/* disks */
47 	"IBM     DDYFT",
48 	"IBM     IC",
49 	"SEAGATE ST",
50 				/* enclosures */
51 	"SUN     SENA",			/* SES device */
52 	"SUN     SESS01",		/* VICOM SVE box */
53 	"SUNW    SUNWGS",		/* Daktari enclosure */
54 				/* arrays */
55 	"HITACHI OPEN",			/* Hitachi storage */
56 	"SUN     PSX1000",		/* Pirus Matterhorn */
57 	"SUN     SE6920",		/* Pirus */
58 	"SUN     SE6940",		/* DSP - Nauset */
59 	"SUN     StorEdge 3510",	/* Minnow FC */
60 	"SUN     StorEdge 3511",	/* Minnow SATA RAID */
61 	"SUN     StorageTek 6920",	/* DSP */
62 	"SUN     StorageTek 6940",	/* DSP - Nauset */
63 	"SUN     StorageTek NAS",	/* StorageTek NAS */
64 	"SUN     MRA300_R",		/* Shamrock - Controller */
65 	"SUN     MRA300_E",		/* Shamrock - Expansion */
66 	"STEC    ZeusIOPs",		/* Zeus SAS SSD */
67 
68 	NULL
69 };
70 
71 /* Failover module plumbing. */
72 SCSI_FAILOVER_OP(SFO_NAME_SYM, symmetric);
73 
74 /* ARGSUSED */
75 static int
symmetric_device_probe(struct scsi_device * sd,struct scsi_inquiry * stdinq,void ** ctpriv)76 symmetric_device_probe(struct scsi_device *sd, struct scsi_inquiry *stdinq,
77 void **ctpriv)
78 {
79 	char	**dt;
80 
81 	VHCI_DEBUG(6, (CE_NOTE, NULL, "!inq str: %s\n", stdinq->inq_vid));
82 	for (dt = symmetric_dev_table; *dt; dt++)
83 		if (strncmp(stdinq->inq_vid, *dt, strlen(*dt)) == 0)
84 			return (SFO_DEVICE_PROBE_VHCI);
85 
86 	/*
87 	 * No match, check for generic Sun supported disks:
88 	 *
89 	 *	"|-VID--||-----PID------|"
90 	 *	"012345670123456789012345"
91 	 *	".................SUN..G."
92 	 *	".................SUN..T."
93 	 *	".................SUN...G"
94 	 *	".................SUN...T"
95 	 */
96 	if (bcmp(&stdinq->inq_pid[9], "SUN", 3) == 0) {
97 		if ((stdinq->inq_pid[14] == 'G' || stdinq->inq_pid[15] == 'G' ||
98 		    stdinq->inq_pid[14] == 'T' || stdinq->inq_pid[15] == 'T') &&
99 		    (stdinq->inq_dtype == DTYPE_DIRECT)) {
100 			return (SFO_DEVICE_PROBE_VHCI);
101 		}
102 	}
103 	if (bcmp(&stdinq->inq_vid[0], "ATA     ", 8) == 0) {
104 		return (SFO_DEVICE_PROBE_VHCI);
105 	}
106 	return (SFO_DEVICE_PROBE_PHCI);
107 }
108 
109 /* ARGSUSED */
110 static void
symmetric_device_unprobe(struct scsi_device * sd,void * ctpriv)111 symmetric_device_unprobe(struct scsi_device *sd, void *ctpriv)
112 {
113 	/*
114 	 * NOP for symmetric
115 	 */
116 }
117 
118 /* ARGSUSED */
119 static int
symmetric_path_activate(struct scsi_device * sd,char * pathclass,void * ctpriv)120 symmetric_path_activate(struct scsi_device *sd, char *pathclass, void *ctpriv)
121 {
122 	return (0);
123 }
124 
125 /* ARGSUSED */
126 static int
symmetric_path_deactivate(struct scsi_device * sd,char * pathclass,void * ctpriv)127 symmetric_path_deactivate(struct scsi_device *sd, char *pathclass,
128 void *ctpriv)
129 {
130 	return (0);
131 }
132 
133 /* ARGSUSED */
134 static int
symmetric_path_get_opinfo(struct scsi_device * sd,struct scsi_path_opinfo * opinfo,void * ctpriv)135 symmetric_path_get_opinfo(struct scsi_device *sd,
136 struct scsi_path_opinfo *opinfo, void *ctpriv)
137 {
138 	opinfo->opinfo_rev = OPINFO_REV;
139 	(void) strcpy(opinfo->opinfo_path_attr, "primary");
140 	opinfo->opinfo_path_state  = SCSI_PATH_ACTIVE;
141 	opinfo->opinfo_pswtch_best = 0;		/* N/A */
142 	opinfo->opinfo_pswtch_worst = 0;	/* N/A */
143 	opinfo->opinfo_xlf_capable = 0;
144 	opinfo->opinfo_mode = SCSI_NO_FAILOVER;
145 	opinfo->opinfo_preferred = 1;
146 
147 	return (0);
148 }
149 
150 /* ARGSUSED */
151 static int
symmetric_path_ping(struct scsi_device * sd,void * ctpriv)152 symmetric_path_ping(struct scsi_device *sd, void *ctpriv)
153 {
154 	return (1);
155 }
156 
157 /* ARGSUSED */
158 static int
symmetric_analyze_sense(struct scsi_device * sd,uint8_t * sense,void * ctpriv)159 symmetric_analyze_sense(struct scsi_device *sd,
160 uint8_t *sense, void *ctpriv)
161 {
162 	return (SCSI_SENSE_NOFAILOVER);
163 }
164 
165 /* ARGSUSED */
166 static int
symmetric_pathclass_next(char * cur,char ** nxt,void * ctpriv)167 symmetric_pathclass_next(char *cur, char **nxt, void *ctpriv)
168 {
169 	if (cur == NULL) {
170 		*nxt = PCLASS_PRIMARY;
171 		return (0);
172 	} else if (strcmp(cur, PCLASS_PRIMARY) == 0) {
173 		return (ENOENT);
174 	} else {
175 		return (EINVAL);
176 	}
177 }
178