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.  */
42char *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. */
72SCSI_FAILOVER_OP(SFO_NAME_SYM, symmetric);
73
74/* ARGSUSED */
75static int
76symmetric_device_probe(struct scsi_device *sd, struct scsi_inquiry *stdinq,
77void **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 */
110static void
111symmetric_device_unprobe(struct scsi_device *sd, void *ctpriv)
112{
113	/*
114	 * NOP for symmetric
115	 */
116}
117
118/* ARGSUSED */
119static int
120symmetric_path_activate(struct scsi_device *sd, char *pathclass, void *ctpriv)
121{
122	return (0);
123}
124
125/* ARGSUSED */
126static int
127symmetric_path_deactivate(struct scsi_device *sd, char *pathclass,
128void *ctpriv)
129{
130	return (0);
131}
132
133/* ARGSUSED */
134static int
135symmetric_path_get_opinfo(struct scsi_device *sd,
136struct 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 */
151static int
152symmetric_path_ping(struct scsi_device *sd, void *ctpriv)
153{
154	return (1);
155}
156
157/* ARGSUSED */
158static int
159symmetric_analyze_sense(struct scsi_device *sd,
160uint8_t *sense, void *ctpriv)
161{
162	return (SCSI_SENSE_NOFAILOVER);
163}
164
165/* ARGSUSED */
166static int
167symmetric_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