7127 remove -Wno-missing-braces from Makefile.uts
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 /* Portions Copyright 2008 Hitachi Ltd. */
23
24 /*
25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28
29 /*
30 * Implementation of "scsi_vhci_f_sym_hds" asymmetric-active-active
31 * failover_ops. The device has a preferred(owner)/non-preferred
32 * with no action needed to use the non-preferred path. This is really
33 * more inline with symmetric device so am using that prefix.
34 *
35 * This file imports the standard "scsi_vhci_f_sym", but with HDS specific
36 * knowledge related to preferred/non-preferred path.
37 */
38
39 #include <sys/conf.h>
40 #include <sys/file.h>
41 #include <sys/ddi.h>
42 #include <sys/sunddi.h>
43 #include <sys/scsi/scsi.h>
44 #include <sys/scsi/adapters/scsi_vhci.h>
45
46 /* Supported device table entries. */
47 char *hds_sym_dev_table[] = {
48 /* " 111111" */
49 /* "012345670123456789012345" */
50 /* "|-VID--||-----PID------|" */
51
52 "HITACHI DF",
53 NULL
54 };
55
56 static int hds_sym_device_probe(struct scsi_device *,
57 struct scsi_inquiry *, void **);
58 static void hds_sym_device_unprobe(struct scsi_device *, void *);
59 static void hds_sym_init();
60 static int hds_sym_get_opinfo(struct scsi_device *sd,
61 struct scsi_path_opinfo *opinfo, void *ctpriv);
62
63 #ifdef lint
64 #define scsi_vhci_failover_ops scsi_vhci_failover_ops_f_sym_hds
65 #endif /* lint */
66 /*
67 * Use the following for the Asymmetric-Active-Active fops.
68 * A different fops may get used for the Symmetric-Active-Active.
69 */
70 struct scsi_failover_ops scsi_vhci_failover_ops = {
71 SFO_REV,
72 SFO_NAME_SYM "_hds",
73 hds_sym_dev_table,
74 hds_sym_init,
75 hds_sym_device_probe,
76 hds_sym_device_unprobe,
77 NULL,
78 NULL,
79 hds_sym_get_opinfo,
80 /* The rest of the implementation comes from SFO_NAME_SYM import */
81 };
82
83 static struct modlmisc modlmisc = {
84 &mod_miscops, "f_sym_hds"
85 };
86
87 static struct modlinkage modlinkage = {
88 MODREV_1, (void *)&modlmisc, NULL
89 };
90
91 #define HDS_MAX_INQ_BUF_SIZE 0xff
92 #define HDS_INQ_PAGE_E0 0xe0
93 #define HDS_SAA_TYPE "DF00"
94 #define ASYM_ACTIVE_ACTIVE 0
95 #define SYM_ACTIVE_ACTIVE 1
96
97 extern struct scsi_failover_ops *vhci_failover_ops_by_name(char *);
98
99 int
100 _init()
101 {
102 return (mod_install(&modlinkage));
103 }
104
105 int
106 _fini()
107 {
108 return (mod_remove(&modlinkage));
109 }
110
111 int
112 _info(struct modinfo *modinfop)
113 {
114 return (mod_info(&modlinkage, modinfop));
115 }
116
117 static void
118 hds_sym_init()
119 {
120 struct scsi_failover_ops *sfo, *ssfo, clone;
121
122 /* clone SFO_NAME_SYM implementation for most things */
123 ssfo = vhci_failover_ops_by_name(SFO_NAME_SYM);
124 if (ssfo == NULL) {
125 VHCI_DEBUG(4, (CE_NOTE, NULL, "!hds_sym_init: "
126 "can't import " SFO_NAME_SYM "\n"));
127 return;
128 }
129 sfo = &scsi_vhci_failover_ops;
130 clone = *ssfo;
131 clone.sfo_rev = sfo->sfo_rev;
132 clone.sfo_name = sfo->sfo_name;
133 clone.sfo_devices = sfo->sfo_devices;
134 clone.sfo_init = sfo->sfo_init;
135 clone.sfo_device_probe = sfo->sfo_device_probe;
136 clone.sfo_device_unprobe = sfo->sfo_device_unprobe;
137 clone.sfo_path_get_opinfo = sfo->sfo_path_get_opinfo;
138 *sfo = clone;
139 }
140
141 /* ARGSUSED */
142 static int
143 hds_sym_device_probe(struct scsi_device *sd, struct scsi_inquiry *stdinq,
144 void **ctprivp)
145 {
146 char **dt;
147 char *dftype;
148 unsigned char len;
149 unsigned char *inq_data = (unsigned char *)stdinq;
150 unsigned char pv;
151 int ret;
152
153 VHCI_DEBUG(6, (CE_NOTE, NULL, "hds_sym_device_probe: vidpid %s\n",
154 stdinq->inq_vid));
155 for (dt = hds_sym_dev_table; *dt; dt++) {
156 if (strncmp(stdinq->inq_vid, *dt, strlen(*dt)))
157 continue;
158 len = inq_data[4];
159 if (len < 128) {
160 vhci_log(CE_NOTE, NULL,
161 "hds_sym_device_probe: vidpid %s len error: %d\n",
162 stdinq->inq_vid, len);
163 return (SFO_DEVICE_PROBE_PHCI);
164 }
165
166 dftype = (char *)&inq_data[128];
167 if (*dftype == 0) {
168 VHCI_DEBUG(4, (CE_NOTE, NULL,
169 "hds_sym_device_probe: vidpid %s"
170 " ASYM_ACTIVE_ACTIVE\n", stdinq->inq_vid));
171 pv = ASYM_ACTIVE_ACTIVE;
172 ret = SFO_DEVICE_PROBE_VHCI;
173 } else if (strncmp(dftype, HDS_SAA_TYPE,
174 strlen(HDS_SAA_TYPE)) == 0) {
175 VHCI_DEBUG(4, (CE_NOTE, NULL,
176 "hds_sym_device_probe: vidpid %s"
177 " SYM_ACTIVE_ACTIVE\n", stdinq->inq_vid));
178 pv = SYM_ACTIVE_ACTIVE;
179 ret = SFO_DEVICE_PROBE_VHCI;
180 } else
181 ret = SFO_DEVICE_PROBE_PHCI;
182
183 if (ret == SFO_DEVICE_PROBE_VHCI) {
184 /* ctprivp is NULL for vhci_is_dev_supported() probe */
185 if (ctprivp) {
186 /*
187 * Allocate failover module's 'client' private
188 * data on the first successfull path probe.
189 * NOTE: 'client' private means per lun guid,
190 * not per-path.
191 */
192 if (*ctprivp == NULL)
193 *ctprivp = kmem_alloc(sizeof (pv),
194 KM_SLEEP);
195
196 /* update private data */
197 *((unsigned char *)*ctprivp) = pv;
198 }
199 } else {
200 VHCI_DEBUG(4, (CE_NOTE, NULL,
201 "hds_sym_device_probe: vidpid %s"
202 " - unknown dftype: %d\n",
203 stdinq->inq_vid, *dftype));
204 }
205 return (SFO_DEVICE_PROBE_PHCI);
206
207 }
208 return (SFO_DEVICE_PROBE_PHCI);
209 }
210
211 /* ARGSUSED */
212 static void
213 hds_sym_device_unprobe(struct scsi_device *sd, void *ctpriv)
214 {
215 if (ctpriv != NULL) {
216 kmem_free(ctpriv, sizeof (unsigned char));
217 }
218 }
219
220
221 /*
222 * Local routine to get inquiry VPD page from the device.
223 *
224 * return 1 for failure
225 * return 0 for success
226 */
227 static int
228 hds_get_inquiry_vpd_page(struct scsi_device *sd, unsigned char page,
229 unsigned char *buf, int size)
230 {
231 int retval = 0;
232 struct buf *bp;
233 struct scsi_pkt *pkt;
234 struct scsi_address *ap;
235
236 if ((buf == NULL) || (size == 0)) {
237 return (1);
238 }
239 bp = getrbuf(KM_NOSLEEP);
240 if (bp == NULL) {
241 return (1);
242 }
243 bp->b_un.b_addr = (char *)buf;
244 bp->b_flags = B_READ;
245 bp->b_bcount = size;
246 bp->b_resid = 0;
247
248 ap = &sd->sd_address;
249 pkt = scsi_init_pkt(ap, NULL, bp, CDB_GROUP0,
250 sizeof (struct scsi_arq_status), 0, 0, NULL, NULL);
251 if (pkt == NULL) {
252 VHCI_DEBUG(4, (CE_WARN, NULL,
253 "hds_get_inquiry_vpd_page:"
254 "Failed to initialize packet"));
255 freerbuf(bp);
256 return (1);
257 }
258
259 /*
260 * Send the inquiry command for page xx to the target.
261 * Data is returned in the buf pointed to by buf.
262 */
263
264 pkt->pkt_cdbp[0] = SCMD_INQUIRY;
265 pkt->pkt_cdbp[1] = 0x1;
266 pkt->pkt_cdbp[2] = page;
267 pkt->pkt_cdbp[4] = (unsigned char)size;
268 pkt->pkt_time = 90;
269 retval = vhci_do_scsi_cmd(pkt);
270 scsi_destroy_pkt(pkt);
271 freerbuf(bp);
272 return (!retval);
273
274 }
275
276 /* ARGSUSED */
277 static int
278 hds_sym_get_opinfo(struct scsi_device *sd, struct scsi_path_opinfo *opinfo,
279 void *ctpriv)
280 {
281 unsigned char inq_vpd_buf[HDS_MAX_INQ_BUF_SIZE];
282
283 opinfo->opinfo_rev = OPINFO_REV;
284 (void) strcpy(opinfo->opinfo_path_attr, "primary");
285 opinfo->opinfo_path_state = SCSI_PATH_ACTIVE;
286 opinfo->opinfo_pswtch_best = 0; /* N/A */
287 opinfo->opinfo_pswtch_worst = 0; /* N/A */
288 opinfo->opinfo_xlf_capable = 0;
289 opinfo->opinfo_mode = SCSI_NO_FAILOVER;
290 ASSERT(ctpriv != NULL);
291 if (*((unsigned char *)ctpriv) == SYM_ACTIVE_ACTIVE) {
292 VHCI_DEBUG(4, (CE_NOTE, NULL,
293 "hds_get_opinfo: sd(%p): sym_active_active "
294 "preferred bit set ", (void*)sd));
295 opinfo->opinfo_preferred = PCLASS_PREFERRED;
296 return (0);
297 }
298 /* check if this is the preferred path */
299 if (hds_get_inquiry_vpd_page(sd, HDS_INQ_PAGE_E0, inq_vpd_buf,
300 sizeof (inq_vpd_buf)) != 0) {
301 VHCI_DEBUG(4, (CE_WARN, NULL,
302 "hds_get_opinfo: sd(%p):Unable to "
303 "get inquiry Page %x", (void*)sd, HDS_INQ_PAGE_E0));
304 return (1);
305 }
306 if (inq_vpd_buf[4] & 0x80) {
307 if (inq_vpd_buf[4] & 0x40) {
308 VHCI_DEBUG(4, (CE_NOTE, NULL,
309 "hds_get_opinfo: sd(%p): preferred bit set ",
310 (void*)sd));
311 opinfo->opinfo_preferred = PCLASS_PREFERRED;
312 } else {
313 VHCI_DEBUG(4, (CE_NOTE, NULL,
314 "hds_get_opinfo: sd(%p): non-preferred bit set ",
315 (void*)sd));
316 opinfo->opinfo_preferred = PCLASS_NONPREFERRED;
317 }
318 } else {
319 vhci_log(CE_NOTE, NULL,
320 "hds_get_opinfo: sd(%p): "
321 "get inquiry Page %x has invalid P/SVid bit set",
322 (void*)sd, HDS_INQ_PAGE_E0);
323 return (1);
324 }
325
326 return (0);
327 }
--- EOF ---