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 2009 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <emlxs.h>
29 
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_DFC_C);
32 
33 static int32_t		emlxs_dfc_get_rev(emlxs_hba_t *hba, dfc_t *dfc,
34 				int32_t mode);
35 static int32_t		emlxs_dfc_get_hbainfo(emlxs_hba_t *hba, dfc_t *dfc,
36 				int32_t mode);
37 static int32_t		emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc,
38 				int32_t mode);
39 static int32_t		emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc,
40 				int32_t mode);
41 static int32_t		emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc,
42 				int32_t mode);
43 static int32_t		emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc,
44 				int32_t mode);
45 static int32_t		emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc,
46 				int32_t mode);
47 static int32_t		emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc,
48 				int32_t mode);
49 static int32_t		emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc,
50 				int32_t mode);
51 static int32_t		emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc,
52 				int32_t mode);
53 static int32_t		emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc,
54 				int32_t mode);
55 static int32_t		emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc,
56 				int32_t mode);
57 static int32_t		emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc,
58 				int32_t mode);
59 static int32_t		emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc,
60 				int32_t mode);
61 static int32_t		emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc,
62 				int32_t mode);
63 static int32_t		emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc,
64 				int32_t mode);
65 static int32_t		emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc,
66 				int32_t mode);
67 static int32_t		emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc,
68 				int32_t mode);
69 static int32_t		emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc,
70 				int32_t mode);
71 static int32_t		emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc,
72 				int32_t mode);
73 static int32_t		emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc,
74 				int32_t mode);
75 static int32_t		emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc,
76 				int32_t mode);
77 static int32_t		emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc,
78 				int32_t mode);
79 static int32_t		emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc,
80 				int32_t mode);
81 static int32_t		emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc,
82 				int32_t mode);
83 static int32_t		emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc,
84 				int32_t mode);
85 static int32_t		emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc,
86 				int32_t mode);
87 static int32_t		emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc,
88 				int32_t mode);
89 static int32_t		emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc,
90 				int32_t mode);
91 
92 #ifdef SFCT_SUPPORT
93 static int32_t		emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc,
94 				int32_t mode);
95 #endif /* SFCT_SUPPORT */
96 
97 static int32_t		emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc,
98 				int32_t mode);
99 static int32_t		emlxs_dfc_destroy_vport(emlxs_hba_t *hba, dfc_t *dfc,
100 				int32_t mode);
101 static int32_t		emlxs_dfc_get_vportinfo(emlxs_hba_t *hba, dfc_t *dfc,
102 				int32_t mode);
103 static int32_t		emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc,
104 				int32_t mode);
105 static int32_t		emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc,
106 				int32_t mode);
107 static emlxs_port_t	*emlxs_vport_find_wwpn(emlxs_hba_t *hba, uint8_t *wwpn);
108 
109 #ifdef DHCHAP_SUPPORT
110 static int32_t		emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc,
111 				int32_t mode);
112 static int32_t		emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc,
113 				int32_t mode);
114 static int32_t		emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc,
115 				int32_t mode);
116 static int32_t		emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc,
117 				int32_t mode);
118 static int32_t		emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc,
119 				int32_t mode);
120 static int32_t		emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc,
121 				int32_t mode);
122 static int32_t		emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba,
123 				dfc_t *dfc, int32_t mode);
124 static int32_t		emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba,
125 				dfc_t *dfc, int32_t mode);
126 #endif	/* DHCHAP_SUPPORT */
127 
128 #ifdef SAN_DIAG_SUPPORT
129 static int32_t		emlxs_dfc_sd_set_bucket(dfc_t *dfc, int32_t mode);
130 static int32_t		emlxs_dfc_sd_destroy_bucket(dfc_t *dfc);
131 static int32_t		emlxs_dfc_sd_get_bucket(dfc_t *dfc, int32_t mode);
132 static int32_t		emlxs_dfc_sd_start_collection(emlxs_hba_t *hba,
133 				dfc_t *dfc, int32_t mode);
134 static int32_t		emlxs_dfc_sd_stop_collection(emlxs_hba_t *hba,
135 				dfc_t *dfc, int32_t mode);
136 static int32_t		emlxs_dfc_sd_reset_collection(emlxs_hba_t *hba,
137 				dfc_t *dfc, int32_t mode);
138 static int32_t		emlxs_dfc_sd_get_data(emlxs_hba_t *hba, dfc_t *dfc,
139 				int32_t mode);
140 static int32_t		emlxs_dfc_sd_set_event(emlxs_hba_t *hba, dfc_t *dfc,
141 				int32_t mode);
142 static int32_t		emlxs_dfc_sd_get_event(emlxs_hba_t *hba, dfc_t *dfc,
143 				int32_t mode);
144 #endif	/* SAN_DIAG_SUPPORT */
145 
146 static int32_t		emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc,
147 				int32_t mode);
148 #ifdef FCIO_SUPPORT
149 static int32_t		emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc,
150 				int32_t mode);
151 #endif	/* FCIO_SUPPORT */
152 
153 static int32_t		emlxs_dfc_get_persist_linkdown(emlxs_hba_t *hba,
154 				dfc_t *dfc, int32_t mode);
155 static int32_t		emlxs_dfc_set_persist_linkdown(emlxs_hba_t *hba,
156 				dfc_t *dfc, int32_t mode);
157 
158 /* SLI-4 ioctls */
159 static int32_t		emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc,
160 				int32_t mode);
161 static int32_t		emlxs_dfc_send_mbox4(emlxs_hba_t *hba, dfc_t *dfc,
162 				int32_t mode);
163 static int		emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc,
164 			    int32_t mode);
165 static int		emlxs_dfc_set_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc,
166 			    int32_t mode);
167 static int		emlxs_dfc_get_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc,
168 			    int32_t mode);
169 
170 
171 uint32_t	emlxs_loopback_tmo = 60;
172 
173 emlxs_table_t emlxs_dfc_table[] = {
174 	{EMLXS_GET_HBAINFO, "GET_HBAINFO"},
175 	{EMLXS_GET_REV, "GET_REV"},
176 	{EMLXS_SET_DIAG, "SET_DIAG"},
177 	{EMLXS_SEND_MBOX, "SEND_MBOX"},
178 	{EMLXS_READ_PCI, "READ_PCI"},
179 	{EMLXS_WRITE_PCI, "WRITE_PCI"},
180 	{EMLXS_GET_CFG, "GET_CFG"},
181 	{EMLXS_SET_CFG, "SET_CFG"},
182 	{EMLXS_SEND_CT, "SEND_CT"},
183 	{EMLXS_SEND_CT_RSP, "SEND_CT_RSP"},
184 	{EMLXS_SEND_MENLO, "SEND_MENLO"},
185 	{EMLXS_WRITE_FLASH, "WRITE_FLASH"},
186 	{EMLXS_READ_FLASH, "READ_FLASH"},
187 	{EMLXS_SEND_ELS, "SEND_ELS"},
188 	{EMLXS_LOOPBACK_TEST, "LOOPBACK_TEST"},
189 	{EMLXS_GET_DUMPREGION, "GET_DUMPREGION"},
190 	{EMLXS_LOOPBACK_MODE, "LOOPBACK_MODE"},
191 	{EMLXS_GET_IOINFO, "GET_IOINFO"},
192 	{EMLXS_GET_LINKINFO, "GET_LINKINFO"},
193 	{EMLXS_GET_NODEINFO, "GET_NODEINFO"},
194 	{EMLXS_READ_MEM, "READ_MEM"},
195 	{EMLXS_WRITE_MEM, "WRITE_MEM"},
196 	{EMLXS_WRITE_CTLREG, "WRITE_CTLREG"},
197 	{EMLXS_READ_CTLREG, "READ_CTLREG"},
198 	{EMLXS_SEND_SCSI, "SEND_SCSI"},
199 	{EMLXS_GET_EVENT, "GET_EVENT"},
200 	{EMLXS_SET_EVENT, "SET_EVENT"},
201 	{EMLXS_GET_EVENTINFO, "GET_EVENTINFO"},
202 	{EMLXS_GET_HBASTATS, "GET_HBASTATS"},
203 	{EMLXS_GET_DRVSTATS, "GET_DRVSTATS"},
204 	{EMLXS_CREATE_VPORT, "CREATE_VPORT"},
205 	{EMLXS_DESTROY_VPORT, "DESTROY_VPORT"},
206 	{EMLXS_GET_VPORTINFO, "GET_VPORTINFO"},
207 	{EMLXS_NPIV_RESOURCE, "NPIV_RESOURCE"},
208 	{EMLXS_NPIV_TEST, "NPIV_TEST"},
209 	{EMLXS_INIT_AUTH, "INIT_AUTH"},
210 	{EMLXS_GET_AUTH_CFG, "GET_AUTH_CFG"},
211 	{EMLXS_SET_AUTH_CFG, "SET_AUTH_CFG"},
212 	{EMLXS_GET_AUTH_PASSWORD, "GET_AUTH_PASSWORD"},
213 	{EMLXS_SET_AUTH_PASSWORD, "SET_AUTH_PASSWORD"},
214 	{EMLXS_GET_AUTH_STATUS, "GET_AUTH_STATUS"},
215 	{EMLXS_GET_AUTH_CFG_TABLE, "GET_AUTH_CFG_TABLE"},
216 	{EMLXS_GET_AUTH_KEY_TABLE, "GET_AUTH_KEY_TABLE"},
217 	{EMLXS_FCIO_CMD, "FCIO_CMD"},
218 	{EMLXS_GET_FCTSTAT, "GET_FCTSTAT"},
219 	{EMLXS_GET_PERSIST_LINKDOWN, "GET_PERSIST_LINKDOWN"},
220 	{EMLXS_SET_PERSIST_LINKDOWN, "SET_PERSIST_LINKDOWN"},
221 	{EMLXS_GET_FCOE_FCFLIST, "GET_FCOE_FCFLIST"},
222 	{EMLXS_SEND_MBOX4, "SEND_MBOX4"},
223 	{EMLXS_RD_BE_FCF, "RD_BE_FCF"},
224 	{EMLXS_SET_BE_DCBX, "SET_BE_DCBX"},
225 	{EMLXS_GET_BE_DCBX, "GET_BE_DCBX"},
226 
227 };	/* emlxs_dfc_table */
228 
229 
230 emlxs_table_t emlxs_dfc_event_table[] = {
231 	{FC_REG_LINK_EVENT,		"LINK_EVENT"},
232 	{FC_REG_RSCN_EVENT,		"RSCN_EVENT"},
233 	{FC_REG_CT_EVENT,		"CT_EVENT"},
234 	{FC_REG_DUMP_EVENT,		"DUMP_EVENT"},
235 	{FC_REG_TEMP_EVENT,		"TEMP_EVENT"},
236 	{FC_REG_VPORTRSCN_EVENT,	"VPORTRSCN_EVENT"},
237 	{FC_REG_FCOE_EVENT,		"FCOE_EVENT"},
238 
239 };	/* emlxs_dfc_event_table */
240 
241 
242 #ifdef SAN_DIAG_SUPPORT
243 kmutex_t		sd_bucket_mutex;
244 sd_bucket_info_t	sd_bucket;
245 #endif	/* SAN_DIAG_SUPPORT */
246 
247 extern char    *
248 emlxs_dfc_xlate(uint16_t cmd)
249 {
250 	static char	buffer[32];
251 	uint32_t	i;
252 	uint32_t	count;
253 
254 	count = sizeof (emlxs_dfc_table) / sizeof (emlxs_table_t);
255 	for (i = 0; i < count; i++) {
256 		if (cmd == emlxs_dfc_table[i].code) {
257 			return (emlxs_dfc_table[i].string);
258 		}
259 	}
260 
261 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
262 	return (buffer);
263 
264 } /* emlxs_dfc_xlate() */
265 
266 
267 extern char    *
268 emlxs_dfc_event_xlate(uint32_t event)
269 {
270 	static char	buffer[32];
271 	uint32_t	i;
272 	uint32_t	count;
273 
274 	count = sizeof (emlxs_dfc_event_table) / sizeof (emlxs_table_t);
275 	for (i = 0; i < count; i++) {
276 		if (event == emlxs_dfc_event_table[i].code) {
277 			return (emlxs_dfc_event_table[i].string);
278 		}
279 	}
280 
281 	(void) sprintf(buffer, "Event=0x%x", event);
282 	return (buffer);
283 
284 } /* emlxs_dfc_event_xlate() */
285 
286 
287 
288 extern int32_t
289 emlxs_dfc_manage(emlxs_hba_t *hba, void *arg, int32_t mode)
290 {
291 	emlxs_port_t	*port = &PPORT;
292 	int		rval = 0;
293 	dfc_t		*dfc;
294 
295 	dfc = (dfc_t *)kmem_zalloc(sizeof (dfc_t), KM_SLEEP);
296 
297 #ifdef	_MULTI_DATAMODEL
298 	switch (ddi_model_convert_from(mode & FMODELS)) {
299 	case DDI_MODEL_ILP32:
300 		{
301 			dfc32_t		dfc32;
302 
303 			if (ddi_copyin((void *)arg, (void *)&dfc32,
304 			    sizeof (dfc32_t), mode)) {
305 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
306 				    "%s: ddi_copyin failed.",
307 				    emlxs_dfc_xlate(dfc->cmd));
308 
309 				rval = DFC_COPYIN_ERROR;
310 				break;
311 			}
312 
313 			dfc->cmd = dfc32.cmd;
314 			dfc->flag = dfc32.flag;
315 			dfc->buf1 = (void *)((unsigned long)dfc32.buf1);
316 			dfc->buf1_size = dfc32.buf1_size;
317 			dfc->data1 = dfc32.data1;
318 			dfc->buf2 = (void *)((unsigned long)dfc32.buf2);
319 			dfc->buf2_size = dfc32.buf2_size;
320 			dfc->data2 = dfc32.data2;
321 			dfc->buf3 = (void *)((unsigned long)dfc32.buf3);
322 			dfc->buf3_size = dfc32.buf3_size;
323 			dfc->data3 = dfc32.data3;
324 			dfc->buf4 = (void *)((unsigned long)dfc32.buf4);
325 			dfc->buf4_size = dfc32.buf4_size;
326 			dfc->data4 = dfc32.data4;
327 
328 			break;
329 		}
330 
331 	case DDI_MODEL_NONE:
332 		if (ddi_copyin((void *)arg, (void *)dfc, sizeof (dfc_t),
333 		    mode)) {
334 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
335 			    "%s: ddi_copyin failed.",
336 			    emlxs_dfc_xlate(dfc->cmd));
337 
338 			rval = DFC_COPYIN_ERROR;
339 		}
340 		break;
341 	}
342 #else	/* _MULTI_DATAMODEL */
343 	if (ddi_copyin((void *)arg, (void *)dfc, sizeof (dfc_t), mode)) {
344 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
345 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
346 
347 		rval = DFC_COPYIN_ERROR;
348 	}
349 #endif	/* _MULTI_DATAMODEL */
350 
351 
352 	switch (dfc->cmd) {
353 	case EMLXS_GET_HBAINFO:
354 		{
355 
356 			rval = emlxs_dfc_get_hbainfo(hba, dfc, mode);
357 
358 			break;
359 		}
360 
361 	case EMLXS_GET_HBASTATS:
362 		{
363 
364 			rval = emlxs_dfc_get_hbastats(hba, dfc, mode);
365 
366 			break;
367 		}
368 
369 	case EMLXS_GET_DRVSTATS:
370 		{
371 
372 			rval = emlxs_dfc_get_drvstats(hba, dfc, mode);
373 
374 			break;
375 		}
376 
377 	case EMLXS_GET_NODEINFO:
378 		{
379 
380 			rval = emlxs_dfc_get_nodeinfo(hba, dfc, mode);
381 
382 			break;
383 		}
384 
385 	case EMLXS_SET_DIAG:
386 		{
387 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
388 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
389 
390 			rval = emlxs_dfc_set_diag(hba, dfc, mode);
391 
392 			break;
393 		}
394 
395 	case EMLXS_SEND_MBOX:
396 		{
397 			rval = emlxs_dfc_send_mbox(hba, dfc, mode);
398 
399 			break;
400 		}
401 
402 	case EMLXS_READ_PCI:
403 		{
404 			rval = emlxs_dfc_read_pci(hba, dfc, mode);
405 
406 			break;
407 		}
408 
409 	case EMLXS_WRITE_PCI:
410 		{
411 			rval = emlxs_dfc_write_pci(hba, dfc, mode);
412 
413 			break;
414 		}
415 
416 	case EMLXS_GET_CFG:
417 		{
418 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
419 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
420 
421 			rval = emlxs_dfc_get_cfg(hba, dfc, mode);
422 
423 			break;
424 		}
425 
426 	case EMLXS_SET_CFG:
427 		{
428 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
429 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
430 
431 			rval = emlxs_dfc_set_cfg(hba, dfc, mode);
432 
433 			break;
434 		}
435 
436 	case EMLXS_SEND_CT:
437 		{
438 			rval = emlxs_dfc_send_ct(hba, dfc, mode);
439 
440 			break;
441 		}
442 
443 	case EMLXS_SEND_CT_RSP:
444 		{
445 			rval = emlxs_dfc_send_ct_rsp(hba, dfc, mode);
446 
447 			break;
448 		}
449 
450 #ifdef MENLO_SUPPORT
451 	case EMLXS_SEND_MENLO:
452 		{
453 			rval = emlxs_dfc_send_menlo(hba, dfc, mode);
454 
455 			break;
456 		}
457 #endif /* MENLO_SUPPORT */
458 
459 	case EMLXS_WRITE_FLASH:
460 		{
461 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
462 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
463 
464 			rval = emlxs_dfc_write_flash(hba, dfc, mode);
465 
466 			break;
467 		}
468 
469 	case EMLXS_READ_FLASH:
470 		{
471 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
472 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
473 
474 			rval = emlxs_dfc_read_flash(hba, dfc, mode);
475 
476 			break;
477 		}
478 
479 	case EMLXS_SEND_ELS:
480 		{
481 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
482 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
483 
484 			rval = emlxs_dfc_send_els(hba, dfc, mode);
485 
486 			break;
487 		}
488 
489 	case EMLXS_LOOPBACK_TEST:
490 		{
491 			rval = emlxs_dfc_loopback_test(hba, dfc, mode);
492 
493 			break;
494 		}
495 
496 	case EMLXS_GET_DUMPREGION:
497 		{
498 
499 			rval = emlxs_dfc_get_dump_region(hba, dfc, mode);
500 
501 			break;
502 		}
503 
504 	case EMLXS_LOOPBACK_MODE:
505 		{
506 			rval = emlxs_dfc_loopback_mode(hba, dfc, mode);
507 
508 			break;
509 		}
510 
511 	case EMLXS_GET_IOINFO:
512 		{
513 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
514 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
515 
516 			rval = emlxs_dfc_get_ioinfo(hba, dfc, mode);
517 
518 			break;
519 		}
520 
521 	case EMLXS_GET_LINKINFO:
522 		{
523 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
524 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
525 
526 			rval = emlxs_dfc_get_linkinfo(hba, dfc, mode);
527 
528 			break;
529 		}
530 
531 #ifdef SFCT_SUPPORT
532 	case EMLXS_GET_FCTSTAT:
533 		{
534 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
535 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
536 
537 			rval = emlxs_dfc_get_fctstat(hba, dfc, mode);
538 
539 			break;
540 		}
541 #endif /* SFCT_SUPPORT */
542 
543 	case EMLXS_READ_MEM:
544 		{
545 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
546 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
547 
548 			rval = emlxs_dfc_read_mem(hba, dfc, mode);
549 
550 			break;
551 		}
552 
553 	case EMLXS_WRITE_MEM:
554 		{
555 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
556 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
557 
558 			rval = emlxs_dfc_write_mem(hba, dfc, mode);
559 
560 			break;
561 		}
562 
563 	case EMLXS_WRITE_CTLREG:
564 		{
565 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
566 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
567 
568 			rval = emlxs_dfc_write_ctlreg(hba, dfc, mode);
569 
570 			break;
571 		}
572 
573 	case EMLXS_READ_CTLREG:
574 		{
575 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
576 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
577 
578 			rval = emlxs_dfc_read_ctlreg(hba, dfc, mode);
579 
580 			break;
581 		}
582 
583 
584 	case EMLXS_GET_EVENTINFO:
585 		{
586 			rval = emlxs_dfc_get_eventinfo(hba, dfc, mode);
587 
588 			break;
589 		}
590 
591 	case EMLXS_GET_EVENT:
592 		{
593 			rval = emlxs_dfc_get_event(hba, dfc, mode);
594 
595 			break;
596 		}
597 
598 	case EMLXS_SET_EVENT:
599 		{
600 			rval = emlxs_dfc_set_event(hba, dfc, mode);
601 
602 			break;
603 		}
604 
605 	case EMLXS_GET_REV:
606 		{
607 			rval = emlxs_dfc_get_rev(hba, dfc, mode);
608 
609 			break;
610 		}
611 
612 	case EMLXS_SEND_SCSI:
613 		{
614 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
615 		    "%s requested.", emlxs_dfc_xlate(dfc->cmd));
616 			rval = emlxs_dfc_send_scsi_fcp(hba, dfc, mode);
617 			break;
618 		}
619 
620 	case EMLXS_CREATE_VPORT:
621 		{
622 
623 			rval = emlxs_dfc_create_vport(hba, dfc, mode);
624 
625 			break;
626 		}
627 
628 	case EMLXS_DESTROY_VPORT:
629 		{
630 
631 			rval = emlxs_dfc_destroy_vport(hba, dfc, mode);
632 
633 			break;
634 		}
635 
636 	case EMLXS_GET_VPORTINFO:
637 		{
638 
639 			rval = emlxs_dfc_get_vportinfo(hba, dfc, mode);
640 
641 			break;
642 		}
643 
644 	case EMLXS_NPIV_RESOURCE:
645 		{
646 			rval = emlxs_dfc_npiv_resource(hba, dfc, mode);
647 
648 			break;
649 		}
650 
651 	case EMLXS_NPIV_TEST:
652 		{
653 			rval = emlxs_dfc_npiv_test(hba, dfc, mode);
654 
655 			break;
656 		}
657 
658 #ifdef DHCHAP_SUPPORT
659 	case EMLXS_INIT_AUTH:
660 		{
661 			rval = emlxs_dfc_init_auth(hba, dfc, mode);
662 
663 			break;
664 		}
665 
666 	case EMLXS_GET_AUTH_CFG:
667 		{
668 			rval = emlxs_dfc_get_auth_cfg(hba, dfc, mode);
669 
670 			break;
671 		}
672 
673 	case EMLXS_SET_AUTH_CFG:
674 		{
675 			rval = emlxs_dfc_set_auth_cfg(hba, dfc, mode);
676 
677 			break;
678 		}
679 
680 	case EMLXS_GET_AUTH_PASSWORD:
681 		{
682 			rval = emlxs_dfc_get_auth_pwd(hba, dfc, mode);
683 
684 			break;
685 		}
686 
687 	case EMLXS_SET_AUTH_PASSWORD:
688 		{
689 			rval = emlxs_dfc_set_auth_pwd(hba, dfc, mode);
690 
691 			break;
692 		}
693 
694 	case EMLXS_GET_AUTH_STATUS:
695 		{
696 			rval = emlxs_dfc_get_auth_status(hba, dfc, mode);
697 
698 			break;
699 		}
700 
701 	case EMLXS_GET_AUTH_CFG_TABLE:
702 		{
703 			rval = emlxs_dfc_get_auth_cfg_table(hba, dfc, mode);
704 			break;
705 		}
706 
707 	case EMLXS_GET_AUTH_KEY_TABLE:
708 		{
709 			rval = emlxs_dfc_get_auth_key_table(hba, dfc, mode);
710 			break;
711 		}
712 
713 #endif	/* DHCHAP_SUPPORT */
714 
715 #ifdef FCIO_SUPPORT
716 	case EMLXS_FCIO_CMD:
717 		rval = emlxs_fcio_manage(hba, dfc, mode);
718 		break;
719 #endif /* FCIO_SUPPORT */
720 
721 #ifdef SAN_DIAG_SUPPORT
722 	case EMLXS_SD_SET_BUCKET:
723 		rval = emlxs_dfc_sd_set_bucket(dfc, mode);
724 		break;
725 
726 	case EMLXS_SD_DESTROY_BUCKET:
727 		rval = emlxs_dfc_sd_destroy_bucket(dfc);
728 		break;
729 
730 	case EMLXS_SD_GET_BUCKET:
731 		rval = emlxs_dfc_sd_get_bucket(dfc, mode);
732 		break;
733 
734 	case EMLXS_SD_START_DATA_COLLECTION:
735 		rval = emlxs_dfc_sd_start_collection(hba, dfc, mode);
736 		break;
737 
738 	case EMLXS_SD_STOP_DATA_COLLECTION:
739 		rval = emlxs_dfc_sd_stop_collection(hba, dfc, mode);
740 		break;
741 
742 	case EMLXS_SD_RESET_DATA_COLLECTION:
743 		rval = emlxs_dfc_sd_reset_collection(hba, dfc, mode);
744 		break;
745 
746 	case EMLXS_SD_GET_DATA:
747 		rval = emlxs_dfc_sd_get_data(hba, dfc, mode);
748 		break;
749 
750 	case EMLXS_SD_SET_EVENT:
751 		rval = emlxs_dfc_sd_set_event(hba, dfc, mode);
752 		break;
753 
754 	case EMLXS_SD_GET_EVENT:
755 		rval = emlxs_dfc_sd_get_event(hba, dfc, mode);
756 		break;
757 #endif	/* SAN_DIAG_SUPPORT */
758 
759 	case EMLXS_GET_PERSIST_LINKDOWN:
760 		rval = emlxs_dfc_get_persist_linkdown(hba, dfc, mode);
761 		break;
762 
763 	case EMLXS_SET_PERSIST_LINKDOWN:
764 		rval = emlxs_dfc_set_persist_linkdown(hba, dfc, mode);
765 		break;
766 
767 	case EMLXS_GET_FCOE_FCFLIST:
768 		rval = emlxs_dfc_get_fcflist(hba, dfc, mode);
769 		break;
770 
771 	case EMLXS_SEND_MBOX4:
772 		rval = emlxs_dfc_send_mbox4(hba, dfc, mode);
773 		break;
774 
775 	case EMLXS_RD_BE_FCF:
776 		rval = emlxs_dfc_rd_be_fcf(hba, dfc, mode);
777 		break;
778 
779 	case EMLXS_SET_BE_DCBX:
780 		rval = emlxs_dfc_set_be_dcbx(hba, dfc, mode);
781 		break;
782 
783 	case EMLXS_GET_BE_DCBX:
784 		rval = emlxs_dfc_get_be_dcbx(hba, dfc, mode);
785 		break;
786 
787 	default:
788 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
789 		    "Unknown command received. (0x%x)", dfc->cmd);
790 		rval = DFC_ARG_INVALID;
791 
792 	}	/* switch() */
793 
794 	kmem_free(dfc, sizeof (dfc_t));
795 	return (rval);
796 
797 } /* emlxs_dfc_manage() */
798 
799 
800 #ifdef FCIO_SUPPORT
801 
802 emlxs_table_t emlxs_fcio_table[] = {
803 	{FCIO_GET_NUM_DEVS, "GET_NUM_DEVS"},
804 	{FCIO_GET_DEV_LIST, "GET_DEV_LIST"},
805 	{FCIO_GET_SYM_PNAME, "GET_SYM_PNAME"},
806 	{FCIO_GET_SYM_NNAME, "GET_SYM_NNAME"},
807 	{FCIO_SET_SYM_PNAME, "SET_SYM_PNAME"},
808 	{FCIO_SET_SYM_NNAME, "SET_SYM_NNAME"},
809 	{FCIO_GET_LOGI_PARAMS, "GET_LOGI_PARAMS"},
810 	{FCIO_DEV_LOGIN, "DEV_LOGIN"},
811 	{FCIO_DEV_LOGOUT, "DEV_LOGOUT"},
812 	{FCIO_GET_STATE, "GET_STATE"},
813 	{FCIO_DEV_REMOVE, "DEV_REMOVE"},
814 	{FCIO_GET_FCODE_REV, "GET_FCODE_REV"},
815 	{FCIO_GET_FW_REV, "GET_FW_REV"},
816 	{FCIO_GET_DUMP_SIZE, "GET_DUMP_SIZE"},
817 	{FCIO_FORCE_DUMP, "FORCE_DUMP"},
818 	{FCIO_GET_DUMP, "GET_DUMP"},
819 	{FCIO_GET_TOPOLOGY, "GET_TOPOLOGY"},
820 	{FCIO_RESET_LINK, "RESET_LINK"},
821 	{FCIO_RESET_HARD, "RESET_HARD"},
822 	{FCIO_RESET_HARD_CORE, "RESET_HARD_CORE"},
823 	{FCIO_DIAG, "DIAG"},
824 	{FCIO_NS, "NS"},
825 	{FCIO_DOWNLOAD_FW, "DOWNLOAD_FW"},
826 	{FCIO_GET_HOST_PARAMS, "GET_HOST_PARAMS"},
827 	{FCIO_LINK_STATUS, "LINK_STATUS"},
828 	{FCIO_DOWNLOAD_FCODE, "DOWNLOAD_FCODE"},
829 	{FCIO_GET_NODE_ID, "GET_NODE_ID"},
830 	{FCIO_SET_NODE_ID, "SET_NODE_ID"},
831 	{FCIO_SEND_NODE_ID, "SEND_NODE_ID"},
832 	/* {FCIO_GET_P2P_INFO, "GET_P2P_INFO"}, */
833 	{FCIO_GET_ADAPTER_ATTRIBUTES, "GET_ADAPTER_ATTRIBUTES"},
834 	{FCIO_GET_OTHER_ADAPTER_PORTS, "GET_OTHER_ADAPTER_PORTS"},
835 	{FCIO_GET_ADAPTER_PORT_ATTRIBUTES, "GET_ADAPTER_PORT_ATTRIBUTES"},
836 	{FCIO_GET_DISCOVERED_PORT_ATTRIBUTES, "GET_DISCOVERED_PORT_ATTRIBUTES"},
837 	{FCIO_GET_PORT_ATTRIBUTES, "GET_PORT_ATTRIBUTES"},
838 	{FCIO_GET_ADAPTER_PORT_STATS, "GET_ADAPTER_PORT_STATS"},
839 };	/* emlxs_fcio_table */
840 
841 
842 extern char    *
843 emlxs_fcio_xlate(uint16_t cmd)
844 {
845 	static char	buffer[32];
846 	uint32_t	i;
847 	uint32_t	count;
848 
849 	count = sizeof (emlxs_fcio_table) / sizeof (emlxs_table_t);
850 	for (i = 0; i < count; i++) {
851 		if (cmd == emlxs_fcio_table[i].code) {
852 			return (emlxs_fcio_table[i].string);
853 		}
854 	}
855 
856 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
857 	return (buffer);
858 
859 } /* emlxs_fcio_xlate() */
860 
861 
862 static int32_t
863 emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
864 {
865 	emlxs_port_t			*port = &PPORT;
866 	emlxs_config_t			*cfg  = &CFG;
867 	int				rval = 0;
868 	fcio_t				local_fcio;
869 	fcio_t				*fcio = &local_fcio;
870 	emlxs_vpd_t			*vpd = &VPD;
871 	fc_hba_port_attributes_t	*port_attrs;
872 	emlxs_node_t			*ndlp;
873 	uint8_t				*wwpn;
874 	uint32_t			use32 = 0;
875 
876 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s: %s: requested.",
877 	    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1));
878 
879 	if (!dfc->buf4 || !dfc->buf4_size) {
880 		EMLXS_MSGF(EMLXS_CONTEXT,
881 		    &emlxs_dfc_error_msg, "%s: %s: Null buffer4 found.",
882 		    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1));
883 
884 		return (EFAULT);
885 	}
886 
887 	if (dfc->buf4_size < sizeof (uint32_t)) {
888 		EMLXS_MSGF(EMLXS_CONTEXT,
889 		    &emlxs_dfc_error_msg,
890 		    "%s: %s: Buffer4 too small. (size=%d)",
891 		    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1),
892 		    dfc->buf4_size);
893 
894 		return (EFAULT);
895 	}
896 
897 	/* Map DFC to FCIO */
898 	bzero(fcio, sizeof (fcio_t));
899 	fcio->fcio_flags	= dfc->flag;
900 	fcio->fcio_cmd		= dfc->data1;
901 	fcio->fcio_cmd_flags	= dfc->data2;
902 	fcio->fcio_xfer		= dfc->data3;
903 	fcio->fcio_errno	= 0; /* dfc->buf4 on return */
904 
905 	if (dfc->buf1_size && dfc->buf1) {
906 		fcio->fcio_ilen = dfc->buf1_size;
907 		fcio->fcio_ibuf = kmem_zalloc(dfc->buf1_size, KM_SLEEP);
908 
909 		if (ddi_copyin(dfc->buf1, fcio->fcio_ibuf, fcio->fcio_ilen,
910 		    mode)) {
911 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
912 			    "%s: %s: ddi_copyin failed. (size=%d)",
913 			    emlxs_dfc_xlate(dfc->cmd),
914 			    emlxs_fcio_xlate(dfc->data1), fcio->fcio_ilen);
915 
916 			rval = EFAULT;
917 			goto done;
918 		}
919 	}
920 
921 	if (dfc->buf2_size && dfc->buf2) {
922 		fcio->fcio_olen = dfc->buf2_size;
923 		fcio->fcio_obuf = kmem_zalloc(dfc->buf2_size, KM_SLEEP);
924 
925 		if (ddi_copyin(dfc->buf2, fcio->fcio_obuf, fcio->fcio_olen,
926 		    mode)) {
927 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
928 			    "%s: %s: ddi_copyin failed. (size=%d)",
929 			    emlxs_dfc_xlate(dfc->cmd),
930 			    emlxs_fcio_xlate(dfc->data1), fcio->fcio_olen);
931 
932 			rval = EFAULT;
933 			goto done;
934 		}
935 	}
936 
937 	if (dfc->buf3_size && dfc->buf3) {
938 		fcio->fcio_alen = dfc->buf3_size;
939 		fcio->fcio_abuf = kmem_zalloc(dfc->buf3_size, KM_SLEEP);
940 
941 		if (ddi_copyin(dfc->buf3, fcio->fcio_abuf, fcio->fcio_alen,
942 		    mode)) {
943 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
944 			    "%s: %s: ddi_copyin failed. (size=%d)",
945 			    emlxs_dfc_xlate(dfc->cmd),
946 			    emlxs_fcio_xlate(dfc->data1), fcio->fcio_alen);
947 
948 			rval = EFAULT;
949 			goto done;
950 		}
951 	}
952 
953 #ifdef	_MULTI_DATAMODEL
954 	if (ddi_model_convert_from(mode & FMODELS) == DDI_MODEL_ILP32) {
955 		use32 = 1;
956 	}
957 #endif	/* _MULTI_DATAMODEL */
958 
959 	/* FCIO command */
960 	switch (fcio->fcio_cmd) {
961 	case FCIO_DIAG:
962 	{
963 		fc_fca_pm_t pm;
964 
965 		bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
966 
967 		pm.pm_cmd_len   = fcio->fcio_ilen;
968 		pm.pm_cmd_buf   = fcio->fcio_ibuf;
969 		pm.pm_data_len  = fcio->fcio_alen;
970 		pm.pm_data_buf  = fcio->fcio_abuf;
971 		pm.pm_stat_len  = fcio->fcio_olen;
972 		pm.pm_stat_buf  = fcio->fcio_obuf;
973 		pm.pm_cmd_code  = FC_PORT_DIAG;
974 		pm.pm_cmd_flags = fcio->fcio_cmd_flags;
975 
976 		rval = emlxs_port_manage(port, &pm);
977 
978 		if (rval != FC_SUCCESS) {
979 			fcio->fcio_errno = rval;
980 
981 			if (rval == FC_INVALID_REQUEST) {
982 				rval = ENOTTY;
983 			} else {
984 				rval = EIO;
985 			}
986 		}
987 		if (fcio->fcio_olen > pm.pm_stat_len) {
988 			fcio->fcio_olen = pm.pm_stat_len;
989 		}
990 
991 		break;
992 	}
993 
994 	case FCIO_GET_HOST_PARAMS:
995 	{
996 		if (use32) {
997 			fc_port_dev32_t *port_dev;
998 			uint32_t i;
999 
1000 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1001 			    fcio->fcio_olen != sizeof (fc_port_dev32_t)) {
1002 				rval = EINVAL;
1003 				break;
1004 			}
1005 
1006 			port_dev = (fc_port_dev32_t *)fcio->fcio_obuf;
1007 			port_dev->dev_did.port_id = port->did;
1008 			port_dev->dev_hard_addr.hard_addr =
1009 			    cfg[CFG_ASSIGN_ALPA].current;
1010 			port_dev->dev_state = port->ulp_statec;
1011 			bcopy((caddr_t)&port->wwpn,
1012 			    (caddr_t)&port_dev->dev_pwwn, 8);
1013 			bcopy((caddr_t)&port->wwnn,
1014 			    (caddr_t)&port_dev->dev_nwwn, 8);
1015 
1016 			if (hba->topology == TOPOLOGY_LOOP) {
1017 				for (i = 0; i < port->alpa_map[0]; i++) {
1018 			if (port->alpa_map[i + 1] == port->did) {
1019 				port_dev->dev_did.priv_lilp_posit =
1020 				    (uint8_t)(i & 0xff);
1021 				break;
1022 			}
1023 				}
1024 			}
1025 
1026 			port_dev->dev_type[0] = LE_SWAP32(0x00000120);
1027 			port_dev->dev_type[1] = LE_SWAP32(0x00000001);
1028 
1029 		} else {
1030 
1031 			fc_port_dev_t *port_dev;
1032 			uint32_t i;
1033 
1034 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1035 			    fcio->fcio_olen != sizeof (fc_port_dev_t)) {
1036 				rval = EINVAL;
1037 				break;
1038 			}
1039 
1040 			port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
1041 			port_dev->dev_did.port_id = port->did;
1042 			port_dev->dev_hard_addr.hard_addr =
1043 			    cfg[CFG_ASSIGN_ALPA].current;
1044 			port_dev->dev_state = port->ulp_statec;
1045 			bcopy((caddr_t)&port->wwpn,
1046 			    (caddr_t)&port_dev->dev_pwwn, 8);
1047 			bcopy((caddr_t)&port->wwnn,
1048 			    (caddr_t)&port_dev->dev_nwwn, 8);
1049 
1050 			if (hba->topology == TOPOLOGY_LOOP) {
1051 				for (i = 0; i < port->alpa_map[0]; i++) {
1052 			if (port->alpa_map[i + 1] == port->did) {
1053 				port_dev->dev_did.priv_lilp_posit =
1054 				    (uint8_t)(i & 0xff);
1055 				break;
1056 			}
1057 				}
1058 			}
1059 
1060 			port_dev->dev_type[0] = LE_SWAP32(0x00000120);
1061 			port_dev->dev_type[1] = LE_SWAP32(0x00000001);
1062 		}
1063 
1064 		break;
1065 	}
1066 
1067 	case FCIO_RESET_LINK:
1068 	{
1069 		uint8_t null_wwn[8];
1070 
1071 		if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1072 		    fcio->fcio_ilen != 8) {
1073 			rval = EINVAL;
1074 			break;
1075 		}
1076 
1077 		bzero(null_wwn, 8);
1078 
1079 		if (bcmp((uint8_t *)fcio->fcio_ibuf, null_wwn, 8) == 0) {
1080 			rval = emlxs_reset(port, FC_FCA_LINK_RESET);
1081 
1082 			if (rval != FC_SUCCESS) {
1083 				fcio->fcio_errno = rval;
1084 				rval = EIO;
1085 			}
1086 		} else {
1087 			rval = ENOTSUP;
1088 		}
1089 		break;
1090 	}
1091 
1092 	case FCIO_RESET_HARD:
1093 	case FCIO_RESET_HARD_CORE:
1094 	{
1095 		rval = emlxs_reset(port, FC_FCA_RESET);
1096 
1097 		if (rval != FC_SUCCESS) {
1098 			fcio->fcio_errno = rval;
1099 			rval = EIO;
1100 		}
1101 		break;
1102 	}
1103 
1104 	case FCIO_DOWNLOAD_FW:
1105 	{
1106 		fc_fca_pm_t	pm;
1107 
1108 		if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1109 		    fcio->fcio_ilen <= 0) {
1110 			rval = EINVAL;
1111 			break;
1112 		}
1113 
1114 		bzero((caddr_t)&pm, sizeof (pm));
1115 
1116 		pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1117 		pm.pm_cmd_code  = FC_PORT_DOWNLOAD_FW;
1118 		pm.pm_data_len  = fcio->fcio_ilen;
1119 		pm.pm_data_buf  = fcio->fcio_ibuf;
1120 
1121 		rval = emlxs_port_manage(port, &pm);
1122 
1123 		if (rval != FC_SUCCESS) {
1124 			fcio->fcio_errno = rval;
1125 			rval = EIO;
1126 		}
1127 		break;
1128 	}
1129 
1130 	case FCIO_GET_FW_REV:
1131 	{
1132 		fc_fca_pm_t	pm;
1133 
1134 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1135 		    fcio->fcio_olen < FC_FW_REV_SIZE) {
1136 			rval = EINVAL;
1137 			break;
1138 		}
1139 
1140 		bzero((caddr_t)&pm, sizeof (pm));
1141 
1142 		pm.pm_cmd_flags = FC_FCA_PM_READ;
1143 		pm.pm_cmd_code  = FC_PORT_GET_FW_REV;
1144 		pm.pm_data_len  = fcio->fcio_olen;
1145 		pm.pm_data_buf  = fcio->fcio_obuf;
1146 
1147 		rval = emlxs_port_manage(port, &pm);
1148 
1149 		if (rval != FC_SUCCESS) {
1150 			fcio->fcio_errno = rval;
1151 			rval = EIO;
1152 		}
1153 		break;
1154 	}
1155 
1156 	case FCIO_GET_FCODE_REV:
1157 	{
1158 		fc_fca_pm_t	pm;
1159 
1160 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1161 		    fcio->fcio_olen < FC_FCODE_REV_SIZE) {
1162 			rval = EINVAL;
1163 			break;
1164 		}
1165 
1166 		bzero((caddr_t)&pm, sizeof (pm));
1167 
1168 		pm.pm_cmd_flags = FC_FCA_PM_READ;
1169 		pm.pm_cmd_code  = FC_PORT_GET_FCODE_REV;
1170 		pm.pm_data_len  = fcio->fcio_olen;
1171 		pm.pm_data_buf  = fcio->fcio_obuf;
1172 
1173 		rval = emlxs_port_manage(port, &pm);
1174 
1175 		if (rval != FC_SUCCESS) {
1176 			fcio->fcio_errno = rval;
1177 			rval = EIO;
1178 		}
1179 		break;
1180 	}
1181 
1182 	case FCIO_DOWNLOAD_FCODE:
1183 	{
1184 		fc_fca_pm_t	pm;
1185 
1186 		if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1187 		    fcio->fcio_ilen <= 0) {
1188 			rval = EINVAL;
1189 			break;
1190 		}
1191 
1192 		bzero((caddr_t)&pm, sizeof (pm));
1193 
1194 		pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1195 		pm.pm_cmd_code  = FC_PORT_DOWNLOAD_FCODE;
1196 		pm.pm_data_len  = fcio->fcio_ilen;
1197 		pm.pm_data_buf  = fcio->fcio_ibuf;
1198 
1199 		rval = emlxs_port_manage(port, &pm);
1200 
1201 		if (rval != FC_SUCCESS) {
1202 			fcio->fcio_errno = rval;
1203 			rval = EIO;
1204 		}
1205 		break;
1206 	}
1207 
1208 	case FCIO_GET_ADAPTER_ATTRIBUTES:
1209 	{
1210 		if (use32) {
1211 			fc_hba_adapter_attributes32_t	*hba_attrs;
1212 
1213 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1214 			    fcio->fcio_olen <
1215 			    sizeof (fc_hba_adapter_attributes32_t)) {
1216 				rval = EINVAL;
1217 				break;
1218 			}
1219 
1220 			hba_attrs =
1221 			    (fc_hba_adapter_attributes32_t *)fcio->fcio_obuf;
1222 
1223 			hba_attrs->version = FC_HBA_ADAPTER_ATTRIBUTES_VERSION;
1224 			(void) strncpy(hba_attrs->Manufacturer, "Emulex",
1225 			    sizeof (hba_attrs->Manufacturer));
1226 			(void) strncpy(hba_attrs->SerialNumber, vpd->serial_num,
1227 			    sizeof (hba_attrs->SerialNumber));
1228 			(void) strncpy(hba_attrs->Model, hba->model_info.model,
1229 			    sizeof (hba_attrs->Model));
1230 			(void) strncpy(hba_attrs->ModelDescription,
1231 			    hba->model_info.model_desc,
1232 			    sizeof (hba_attrs->ModelDescription));
1233 			bcopy((caddr_t)&port->wwnn,
1234 			    (caddr_t)&hba_attrs->NodeWWN, 8);
1235 			(void) strncpy((caddr_t)hba_attrs->NodeSymbolicName,
1236 			    (caddr_t)port->snn,
1237 			    sizeof (hba_attrs->NodeSymbolicName));
1238 			(void) sprintf(hba_attrs->HardwareVersion, "%x",
1239 			    vpd->biuRev);
1240 			(void) sprintf(hba_attrs->DriverVersion, "%s (%s)",
1241 			    emlxs_version, emlxs_revision);
1242 			(void) strncpy(hba_attrs->OptionROMVersion,
1243 			    vpd->fcode_version,
1244 			    sizeof (hba_attrs->OptionROMVersion));
1245 			(void) sprintf(hba_attrs->FirmwareVersion, "%s (%s)",
1246 			    vpd->fw_version, vpd->fw_label);
1247 			(void) strncpy(hba_attrs->DriverName, DRIVER_NAME,
1248 			    sizeof (hba_attrs->DriverName));
1249 			hba_attrs->VendorSpecificID =
1250 			    ((hba->model_info.device_id << 16) |
1251 			    PCI_VENDOR_ID_EMULEX);
1252 			hba_attrs->NumberOfPorts = hba->num_of_ports;
1253 		} else {
1254 			fc_hba_adapter_attributes_t	*hba_attrs;
1255 
1256 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1257 			    fcio->fcio_olen <
1258 			    sizeof (fc_hba_adapter_attributes_t)) {
1259 				rval = EINVAL;
1260 				break;
1261 			}
1262 
1263 			hba_attrs =
1264 			    (fc_hba_adapter_attributes_t *)fcio->fcio_obuf;
1265 
1266 			hba_attrs->version = FC_HBA_ADAPTER_ATTRIBUTES_VERSION;
1267 			(void) strncpy(hba_attrs->Manufacturer, "Emulex",
1268 			    sizeof (hba_attrs->Manufacturer));
1269 			(void) strncpy(hba_attrs->SerialNumber, vpd->serial_num,
1270 			    sizeof (hba_attrs->SerialNumber));
1271 			(void) strncpy(hba_attrs->Model, hba->model_info.model,
1272 			    sizeof (hba_attrs->Model));
1273 			(void) strncpy(hba_attrs->ModelDescription,
1274 			    hba->model_info.model_desc,
1275 			    sizeof (hba_attrs->ModelDescription));
1276 			bcopy((caddr_t)&port->wwnn,
1277 			    (caddr_t)&hba_attrs->NodeWWN, 8);
1278 			(void) strncpy((caddr_t)hba_attrs->NodeSymbolicName,
1279 			    (caddr_t)port->snn,
1280 			    sizeof (hba_attrs->NodeSymbolicName));
1281 			(void) sprintf(hba_attrs->HardwareVersion, "%x",
1282 			    vpd->biuRev);
1283 			(void) sprintf(hba_attrs->DriverVersion, "%s (%s)",
1284 			    emlxs_version, emlxs_revision);
1285 			(void) strncpy(hba_attrs->OptionROMVersion,
1286 			    vpd->fcode_version,
1287 			    sizeof (hba_attrs->OptionROMVersion));
1288 			(void) sprintf(hba_attrs->FirmwareVersion, "%s (%s)",
1289 			    vpd->fw_version, vpd->fw_label);
1290 			(void) strncpy(hba_attrs->DriverName, DRIVER_NAME,
1291 			    sizeof (hba_attrs->DriverName));
1292 			hba_attrs->VendorSpecificID =
1293 			    ((hba->model_info.device_id << 16) |
1294 			    PCI_VENDOR_ID_EMULEX);
1295 			hba_attrs->NumberOfPorts = hba->num_of_ports;
1296 		}
1297 		break;
1298 	}
1299 
1300 	case FCIO_GET_ADAPTER_PORT_ATTRIBUTES:
1301 	{
1302 		if (use32) {
1303 			fc_hba_port_attributes32_t  *port_attrs;
1304 			uint32_t value1;
1305 			uint32_t value2;
1306 
1307 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1308 			    fcio->fcio_olen <
1309 			    sizeof (fc_hba_port_attributes32_t)) {
1310 				rval = EINVAL;
1311 				break;
1312 			}
1313 
1314 			port_attrs =
1315 			    (fc_hba_port_attributes32_t *)fcio->fcio_obuf;
1316 
1317 			port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
1318 			port_attrs->lastChange = 0;
1319 			port_attrs->fp_minor   = 0;
1320 			bcopy((caddr_t)&port->wwnn,
1321 			    (caddr_t)&port_attrs->NodeWWN, 8);
1322 			bcopy((caddr_t)&port->wwpn,
1323 			    (caddr_t)&port_attrs->PortWWN, 8);
1324 
1325 			if (hba->state <= FC_LINK_DOWN) {
1326 				/* port_attrs->PortFcId   */
1327 				/* port_attrs->PortType   */
1328 				/* port_attrs->PortSpeed  */
1329 				/* port_attrs->FabricName */
1330 				port_attrs->PortState =
1331 				    FC_HBA_PORTSTATE_OFFLINE;
1332 			} else {
1333 				port_attrs->PortFcId  = port->did;
1334 				port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
1335 
1336 				if (hba->topology == TOPOLOGY_LOOP) {
1337 					port_attrs->PortType =
1338 					    FC_HBA_PORTTYPE_LPORT;
1339 				} else {
1340 					port_attrs->PortType =
1341 					    FC_HBA_PORTTYPE_NPORT;
1342 				}
1343 
1344 				ndlp = emlxs_node_find_did(port, FABRIC_DID);
1345 
1346 				if (ndlp) {
1347 					bcopy(&ndlp->nlp_portname,
1348 					    (caddr_t)&port_attrs->FabricName,
1349 					    sizeof (port_attrs->FabricName));
1350 				}
1351 
1352 				switch (hba->linkspeed) {
1353 				case 0:
1354 					port_attrs->PortSpeed =
1355 					    HBA_PORTSPEED_1GBIT;
1356 					break;
1357 				case LA_1GHZ_LINK:
1358 					port_attrs->PortSpeed =
1359 					    HBA_PORTSPEED_1GBIT;
1360 					break;
1361 				case LA_2GHZ_LINK:
1362 					port_attrs->PortSpeed =
1363 					    HBA_PORTSPEED_2GBIT;
1364 					break;
1365 				case LA_4GHZ_LINK:
1366 					port_attrs->PortSpeed =
1367 					    HBA_PORTSPEED_4GBIT;
1368 					break;
1369 				case LA_8GHZ_LINK:
1370 					port_attrs->PortSpeed =
1371 					    HBA_PORTSPEED_8GBIT;
1372 					break;
1373 				case LA_10GHZ_LINK:
1374 					port_attrs->PortSpeed =
1375 					    HBA_PORTSPEED_10GBIT;
1376 					break;
1377 				default:
1378 					port_attrs->PortSpeed =
1379 					    HBA_PORTSPEED_UNKNOWN;
1380 				}
1381 			}
1382 
1383 			port_attrs->PortSupportedClassofService =
1384 			    LE_SWAP32(FC_NS_CLASS3);
1385 			(void) strncpy((caddr_t)port_attrs->PortSymbolicName,
1386 			    (caddr_t)port->spn,
1387 			    sizeof (port_attrs->PortSymbolicName));
1388 
1389 			/* Set the hba speed limit */
1390 			if (vpd->link_speed & LMT_10GB_CAPABLE) {
1391 				port_attrs->PortSupportedSpeed |=
1392 				    FC_HBA_PORTSPEED_10GBIT;
1393 			}
1394 			if (vpd->link_speed & LMT_8GB_CAPABLE) {
1395 				port_attrs->PortSupportedSpeed |=
1396 				    FC_HBA_PORTSPEED_8GBIT;
1397 			}
1398 			if (vpd->link_speed & LMT_4GB_CAPABLE) {
1399 				port_attrs->PortSupportedSpeed |=
1400 				    FC_HBA_PORTSPEED_4GBIT;
1401 			}
1402 			if (vpd->link_speed & LMT_2GB_CAPABLE) {
1403 				port_attrs->PortSupportedSpeed |=
1404 				    FC_HBA_PORTSPEED_2GBIT;
1405 			}
1406 			if (vpd->link_speed & LMT_1GB_CAPABLE) {
1407 				port_attrs->PortSupportedSpeed |=
1408 				    FC_HBA_PORTSPEED_1GBIT;
1409 			}
1410 
1411 			value1 = 0x00000120;
1412 			value2 = 0x00000001;
1413 
1414 			bcopy((caddr_t)&value1,
1415 			    (caddr_t)&port_attrs->PortSupportedFc4Types[0], 4);
1416 			bcopy((caddr_t)&value2,
1417 			    (caddr_t)&port_attrs->PortSupportedFc4Types[4], 4);
1418 
1419 			bcopy((caddr_t)&value1,
1420 			    (caddr_t)&port_attrs->PortActiveFc4Types[0], 4);
1421 			bcopy((caddr_t)&value2,
1422 			    (caddr_t)&port_attrs->PortActiveFc4Types[4], 4);
1423 
1424 			port_attrs->PortMaxFrameSize = FF_FRAME_SIZE;
1425 			port_attrs->NumberofDiscoveredPorts =
1426 			    emlxs_nport_count(port);
1427 
1428 		} else {
1429 
1430 			fc_hba_port_attributes_t  *port_attrs;
1431 			uint32_t value1;
1432 			uint32_t value2;
1433 
1434 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1435 			    fcio->fcio_olen <
1436 			    sizeof (fc_hba_port_attributes_t)) {
1437 				rval = EINVAL;
1438 				break;
1439 			}
1440 
1441 			port_attrs =
1442 			    (fc_hba_port_attributes_t *)fcio->fcio_obuf;
1443 
1444 			port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
1445 			port_attrs->lastChange = 0;
1446 			port_attrs->fp_minor   = 0;
1447 			bcopy((caddr_t)&port->wwnn,
1448 			    (caddr_t)&port_attrs->NodeWWN, 8);
1449 			bcopy((caddr_t)&port->wwpn,
1450 			    (caddr_t)&port_attrs->PortWWN, 8);
1451 
1452 			if (hba->state <= FC_LINK_DOWN) {
1453 				/* port_attrs->PortFcId   */
1454 				/* port_attrs->PortType   */
1455 				/* port_attrs->PortSpeed  */
1456 				/* port_attrs->FabricName */
1457 				port_attrs->PortState =
1458 				    FC_HBA_PORTSTATE_OFFLINE;
1459 			} else {
1460 				port_attrs->PortFcId  = port->did;
1461 				port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
1462 
1463 				if (hba->topology == TOPOLOGY_LOOP) {
1464 					port_attrs->PortType =
1465 					    FC_HBA_PORTTYPE_LPORT;
1466 				} else {
1467 					port_attrs->PortType =
1468 					    FC_HBA_PORTTYPE_NPORT;
1469 				}
1470 
1471 				ndlp = emlxs_node_find_did(port, FABRIC_DID);
1472 
1473 				if (ndlp) {
1474 					bcopy(&ndlp->nlp_portname,
1475 					    (caddr_t)&port_attrs->FabricName,
1476 					    sizeof (port_attrs->FabricName));
1477 				}
1478 
1479 				switch (hba->linkspeed) {
1480 				case 0:
1481 					port_attrs->PortSpeed =
1482 					    HBA_PORTSPEED_1GBIT;
1483 					break;
1484 				case LA_1GHZ_LINK:
1485 					port_attrs->PortSpeed =
1486 					    HBA_PORTSPEED_1GBIT;
1487 					break;
1488 				case LA_2GHZ_LINK:
1489 					port_attrs->PortSpeed =
1490 					    HBA_PORTSPEED_2GBIT;
1491 					break;
1492 				case LA_4GHZ_LINK:
1493 					port_attrs->PortSpeed =
1494 					    HBA_PORTSPEED_4GBIT;
1495 					break;
1496 				case LA_8GHZ_LINK:
1497 					port_attrs->PortSpeed =
1498 					    HBA_PORTSPEED_8GBIT;
1499 					break;
1500 				case LA_10GHZ_LINK:
1501 					port_attrs->PortSpeed =
1502 					    HBA_PORTSPEED_10GBIT;
1503 					break;
1504 				default:
1505 					port_attrs->PortSpeed =
1506 					    HBA_PORTSPEED_UNKNOWN;
1507 				}
1508 			}
1509 
1510 			port_attrs->PortSupportedClassofService =
1511 			    LE_SWAP32(FC_NS_CLASS3);
1512 			(void) strncpy((caddr_t)port_attrs->PortSymbolicName,
1513 			    (caddr_t)port->spn,
1514 			    sizeof (port_attrs->PortSymbolicName));
1515 
1516 			/* Set the hba speed limit */
1517 			if (vpd->link_speed & LMT_10GB_CAPABLE) {
1518 				port_attrs->PortSupportedSpeed |=
1519 				    FC_HBA_PORTSPEED_10GBIT;
1520 			}
1521 			if (vpd->link_speed & LMT_8GB_CAPABLE) {
1522 				port_attrs->PortSupportedSpeed |=
1523 				    FC_HBA_PORTSPEED_8GBIT;
1524 			}
1525 			if (vpd->link_speed & LMT_4GB_CAPABLE) {
1526 				port_attrs->PortSupportedSpeed |=
1527 				    FC_HBA_PORTSPEED_4GBIT;
1528 			}
1529 			if (vpd->link_speed & LMT_2GB_CAPABLE) {
1530 				port_attrs->PortSupportedSpeed |=
1531 				    FC_HBA_PORTSPEED_2GBIT;
1532 			}
1533 			if (vpd->link_speed & LMT_1GB_CAPABLE) {
1534 				port_attrs->PortSupportedSpeed |=
1535 				    FC_HBA_PORTSPEED_1GBIT;
1536 			}
1537 
1538 			value1 = 0x00000120;
1539 			value2 = 0x00000001;
1540 
1541 			bcopy((caddr_t)&value1,
1542 			    (caddr_t)&port_attrs->PortSupportedFc4Types[0], 4);
1543 			bcopy((caddr_t)&value2,
1544 			    (caddr_t)&port_attrs->PortSupportedFc4Types[4], 4);
1545 
1546 			bcopy((caddr_t)&value1,
1547 			    (caddr_t)&port_attrs->PortActiveFc4Types[0], 4);
1548 			bcopy((caddr_t)&value2,
1549 			    (caddr_t)&port_attrs->PortActiveFc4Types[4], 4);
1550 
1551 			port_attrs->PortMaxFrameSize = FF_FRAME_SIZE;
1552 			port_attrs->NumberofDiscoveredPorts =
1553 			    emlxs_nport_count(port);
1554 		}
1555 
1556 		break;
1557 	}
1558 
1559 	case FCIO_GET_NODE_ID:
1560 	{
1561 		fc_fca_pm_t	pm;
1562 
1563 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1564 		    fcio->fcio_olen < sizeof (fc_rnid_t)) {
1565 			rval = EINVAL;
1566 			break;
1567 		}
1568 
1569 		bzero((caddr_t)&pm, sizeof (pm));
1570 
1571 		pm.pm_cmd_flags = FC_FCA_PM_READ;
1572 		pm.pm_cmd_code  = FC_PORT_GET_NODE_ID;
1573 		pm.pm_data_len  = fcio->fcio_olen;
1574 		pm.pm_data_buf  = fcio->fcio_obuf;
1575 
1576 		rval = emlxs_port_manage(port, &pm);
1577 
1578 		if (rval != FC_SUCCESS) {
1579 			fcio->fcio_errno = rval;
1580 			rval = EIO;
1581 		}
1582 		break;
1583 	}
1584 
1585 	case FCIO_SET_NODE_ID:
1586 	{
1587 		fc_fca_pm_t	pm;
1588 
1589 		if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1590 		    fcio->fcio_ilen < sizeof (fc_rnid_t)) {
1591 			rval = EINVAL;
1592 			break;
1593 		}
1594 
1595 		bzero((caddr_t)&pm, sizeof (pm));
1596 
1597 		pm.pm_cmd_flags = FC_FCA_PM_READ;
1598 		pm.pm_cmd_code  = FC_PORT_SET_NODE_ID;
1599 		pm.pm_data_len  = fcio->fcio_ilen;
1600 		pm.pm_data_buf  = fcio->fcio_ibuf;
1601 
1602 		rval = emlxs_port_manage(port, &pm);
1603 
1604 		if (rval != FC_SUCCESS) {
1605 			fcio->fcio_errno = rval;
1606 			rval = EIO;
1607 		}
1608 		break;
1609 	}
1610 
1611 
1612 	case FCIO_GET_NUM_DEVS:
1613 	{
1614 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1615 		    fcio->fcio_olen < sizeof (uint32_t)) {
1616 			rval = EINVAL;
1617 			break;
1618 		}
1619 
1620 		*(uint32_t *)fcio->fcio_obuf = emlxs_nport_count(port);
1621 
1622 		break;
1623 	}
1624 
1625 	case FCIO_GET_DEV_LIST:
1626 	{
1627 		if (use32) {
1628 			fc_port_dev32_t *port_dev;
1629 			uint32_t max_count;
1630 			uint32_t i;
1631 			uint32_t j;
1632 			emlxs_node_t *nlp;
1633 			uint32_t nport_count;
1634 
1635 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1636 			    fcio->fcio_alen < sizeof (uint32_t)) {
1637 				rval = EINVAL;
1638 				break;
1639 			}
1640 
1641 			port_dev = (fc_port_dev32_t *)fcio->fcio_obuf;
1642 			max_count = fcio->fcio_olen / sizeof (fc_port_dev32_t);
1643 
1644 			rw_enter(&port->node_rwlock, RW_READER);
1645 
1646 			nport_count = emlxs_nport_count(port);
1647 			*(uint32_t *)fcio->fcio_abuf = nport_count;
1648 
1649 			if (nport_count == 0) {
1650 				rw_exit(&port->node_rwlock);
1651 
1652 				fcio->fcio_errno = FC_NO_MAP;
1653 				rval = EIO;
1654 				break;
1655 			}
1656 
1657 			if (nport_count > max_count) {
1658 				rw_exit(&port->node_rwlock);
1659 
1660 				fcio->fcio_errno = FC_TOOMANY;
1661 				rval = EIO;
1662 				break;
1663 			}
1664 
1665 			for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1666 				nlp = port->node_table[i];
1667 				while (nlp != NULL) {
1668 				if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
1669 					port_dev->dev_dtype = 0;
1670 					port_dev->dev_type[0] =
1671 					    BE_SWAP32(0x00000100);
1672 					port_dev->dev_state =
1673 					    PORT_DEVICE_LOGGED_IN;
1674 					port_dev->dev_did.port_id =
1675 					    nlp->nlp_DID;
1676 					port_dev->dev_did.priv_lilp_posit = 0;
1677 					port_dev->dev_hard_addr.hard_addr = 0;
1678 
1679 	if (hba->topology == TOPOLOGY_LOOP) {
1680 		for (j = 1; j < port->alpa_map[0]; j++) {
1681 			if (nlp->nlp_DID == port->alpa_map[j]) {
1682 				port_dev->dev_did.priv_lilp_posit = j-1;
1683 				break;
1684 			}
1685 		}
1686 		port_dev->dev_hard_addr.hard_addr = nlp->nlp_DID;
1687 	}
1688 
1689 					bcopy((caddr_t)&nlp->nlp_portname,
1690 					    (caddr_t)&port_dev->dev_pwwn, 8);
1691 					bcopy((caddr_t)&nlp->nlp_nodename,
1692 					    (caddr_t)&port_dev->dev_nwwn, 8);
1693 					port_dev++;
1694 				}
1695 
1696 				nlp = (NODELIST *) nlp->nlp_list_next;
1697 				}
1698 			}
1699 			rw_exit(&port->node_rwlock);
1700 
1701 		} else {
1702 
1703 			fc_port_dev_t *port_dev;
1704 			uint32_t max_count;
1705 			uint32_t i;
1706 			uint32_t j;
1707 			emlxs_node_t *nlp;
1708 			uint32_t nport_count;
1709 
1710 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1711 			    fcio->fcio_alen < sizeof (uint32_t)) {
1712 				rval = EINVAL;
1713 				break;
1714 			}
1715 
1716 			port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
1717 			max_count = fcio->fcio_olen / sizeof (fc_port_dev_t);
1718 
1719 			rw_enter(&port->node_rwlock, RW_READER);
1720 
1721 			nport_count = emlxs_nport_count(port);
1722 			*(uint32_t *)fcio->fcio_abuf = nport_count;
1723 
1724 			if (nport_count == 0) {
1725 				rw_exit(&port->node_rwlock);
1726 
1727 				fcio->fcio_errno = FC_NO_MAP;
1728 				rval = EIO;
1729 				break;
1730 			}
1731 
1732 			if (nport_count > max_count) {
1733 				rw_exit(&port->node_rwlock);
1734 
1735 				fcio->fcio_errno = FC_TOOMANY;
1736 				rval = EIO;
1737 				break;
1738 			}
1739 
1740 			for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1741 				nlp = port->node_table[i];
1742 				while (nlp != NULL) {
1743 				if ((nlp->nlp_DID & 0xFFF000) != 0xFFF000) {
1744 					port_dev->dev_dtype = 0;
1745 					port_dev->dev_type[0] =
1746 					    BE_SWAP32(0x00000100);
1747 					port_dev->dev_state =
1748 					    PORT_DEVICE_LOGGED_IN;
1749 					port_dev->dev_did.port_id =
1750 					    nlp->nlp_DID;
1751 					port_dev->dev_did.priv_lilp_posit = 0;
1752 					port_dev->dev_hard_addr.hard_addr = 0;
1753 
1754 	if (hba->topology == TOPOLOGY_LOOP) {
1755 		for (j = 1; j < port->alpa_map[0]; j++) {
1756 			if (nlp->nlp_DID == port->alpa_map[j]) {
1757 				port_dev->dev_did.priv_lilp_posit = j-1;
1758 				break;
1759 			}
1760 		}
1761 		port_dev->dev_hard_addr.hard_addr = nlp->nlp_DID;
1762 	}
1763 
1764 					bcopy((caddr_t)&nlp->nlp_portname,
1765 					    (caddr_t)&port_dev->dev_pwwn, 8);
1766 					bcopy((caddr_t)&nlp->nlp_nodename,
1767 					    (caddr_t)&port_dev->dev_nwwn, 8);
1768 					port_dev++;
1769 				}
1770 
1771 				nlp = (NODELIST *) nlp->nlp_list_next;
1772 				}
1773 			}
1774 			rw_exit(&port->node_rwlock);
1775 		}
1776 
1777 		break;
1778 	}
1779 
1780 	case FCIO_GET_LOGI_PARAMS:
1781 	{
1782 		uint8_t null_wwn[8];
1783 
1784 		if (fcio->fcio_ilen != sizeof (la_wwn_t) ||
1785 		    (fcio->fcio_xfer & FCIO_XFER_READ) == 0 ||
1786 		    (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0) {
1787 			rval = EINVAL;
1788 			break;
1789 		}
1790 
1791 		bzero(null_wwn, 8);
1792 		wwpn = (uint8_t *)fcio->fcio_ibuf;
1793 
1794 		if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1795 		    (bcmp((caddr_t)wwpn, (caddr_t)&port->wwpn, 8) == 0)) {
1796 			bcopy((caddr_t)&port->sparam,
1797 			    (caddr_t)fcio->fcio_obuf, fcio->fcio_olen);
1798 		} else {
1799 			ndlp = emlxs_node_find_wwpn(port, wwpn);
1800 
1801 			if (ndlp) {
1802 				bcopy((caddr_t)&ndlp->sparm,
1803 				    (caddr_t)fcio->fcio_obuf,
1804 				    fcio->fcio_olen);
1805 			} else {
1806 				rval = ENXIO;
1807 			}
1808 		}
1809 
1810 		break;
1811 	}
1812 
1813 	case FCIO_GET_STATE:
1814 	{
1815 		uint8_t null_wwn[8];
1816 		uint32_t *statep;
1817 
1818 		if (fcio->fcio_ilen != 8 ||
1819 		    fcio->fcio_olen != 4 ||
1820 		    (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0 ||
1821 		    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1822 			rval = EINVAL;
1823 			break;
1824 		}
1825 
1826 		bzero(null_wwn, 8);
1827 		wwpn   = (uint8_t *)fcio->fcio_ibuf;
1828 		statep = (uint32_t *)fcio->fcio_obuf;
1829 
1830 		if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1831 		    (bcmp((caddr_t)wwpn, (caddr_t)&port->wwpn, 8) == 0)) {
1832 			*statep = PORT_DEVICE_VALID;
1833 		} else {
1834 			ndlp = emlxs_node_find_wwpn(port, wwpn);
1835 
1836 			if (ndlp) {
1837 				*statep = PORT_DEVICE_VALID;
1838 			} else {
1839 				*statep = PORT_DEVICE_INVALID;
1840 			}
1841 		}
1842 
1843 		break;
1844 	}
1845 
1846 	case FCIO_GET_TOPOLOGY:
1847 	{
1848 		uint32_t *tp;
1849 
1850 		if (fcio->fcio_olen != 4 ||
1851 		    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1852 			rval = EINVAL;
1853 			break;
1854 		}
1855 
1856 		tp = (uint32_t *)fcio->fcio_obuf;
1857 
1858 		if (hba->state <= FC_LINK_DOWN) {
1859 			*tp = FC_TOP_UNKNOWN;
1860 		} else {
1861 			ndlp = emlxs_node_find_did(port, FABRIC_DID);
1862 
1863 			if (hba->topology == TOPOLOGY_LOOP) {
1864 				if (ndlp) {
1865 					*tp = FC_TOP_PUBLIC_LOOP;
1866 				} else {
1867 					*tp = FC_TOP_PRIVATE_LOOP;
1868 				}
1869 			} else {
1870 				if (ndlp) {
1871 					*tp = FC_TOP_FABRIC;
1872 				} else {
1873 					*tp = FC_TOP_PT_PT;
1874 				}
1875 			}
1876 		}
1877 
1878 		break;
1879 	}
1880 
1881 	case FCIO_LINK_STATUS:
1882 	{
1883 		fc_portid_t	*portid;
1884 		fc_rls_acc_t	*rls;
1885 		fc_fca_pm_t	pm;
1886 
1887 		if (fcio->fcio_ilen != sizeof (fc_portid_t) ||
1888 		    fcio->fcio_olen != sizeof (fc_rls_acc_t) ||
1889 		    fcio->fcio_xfer != FCIO_XFER_RW) {
1890 			rval = EINVAL;
1891 			break;
1892 		}
1893 
1894 		if ((fcio->fcio_cmd_flags != FCIO_CFLAGS_RLS_DEST_FPORT) &&
1895 		    (fcio->fcio_cmd_flags != FCIO_CFLAGS_RLS_DEST_NPORT)) {
1896 			rval = EINVAL;
1897 			break;
1898 		}
1899 
1900 		portid = (fc_portid_t *)fcio->fcio_ibuf;
1901 		rls    = (fc_rls_acc_t *)fcio->fcio_obuf;
1902 
1903 		if (portid->port_id == 0 || portid->port_id == port->did) {
1904 			bzero((caddr_t)&pm, sizeof (pm));
1905 
1906 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1907 			pm.pm_cmd_code  = FC_PORT_RLS;
1908 			pm.pm_data_len  = sizeof (fc_rls_acc_t);
1909 			pm.pm_data_buf  = (caddr_t)rls;
1910 
1911 			rval = emlxs_port_manage(port, &pm);
1912 
1913 			if (rval != FC_SUCCESS) {
1914 				fcio->fcio_errno = rval;
1915 				rval = EIO;
1916 			}
1917 		} else {
1918 			rval = ENOTSUP;
1919 		}
1920 		break;
1921 	}
1922 
1923 	case FCIO_GET_OTHER_ADAPTER_PORTS:
1924 	{
1925 		uint32_t	index;
1926 		char		*path;
1927 
1928 		if (fcio->fcio_olen < MAXPATHLEN ||
1929 		    fcio->fcio_ilen != sizeof (uint32_t)) {
1930 			rval = EINVAL;
1931 			break;
1932 		}
1933 
1934 		index = *(uint32_t *)fcio->fcio_ibuf;
1935 		path  = (char *)fcio->fcio_obuf;
1936 
1937 		if (index > hba->vpi_max) {
1938 			fcio->fcio_errno = FC_BADPORT;
1939 			rval = EFAULT;
1940 			break;
1941 		}
1942 
1943 		(void) ddi_pathname(hba->dip, path);
1944 
1945 		break;
1946 	}
1947 
1948 	case FCIO_GET_DISCOVERED_PORT_ATTRIBUTES:
1949 	{
1950 		uint32_t index;
1951 
1952 		if (fcio->fcio_xfer != FCIO_XFER_READ ||
1953 		    fcio->fcio_ilen < sizeof (uint32_t) ||
1954 		    fcio->fcio_olen < sizeof (fc_hba_port_attributes_t)) {
1955 			rval = EINVAL;
1956 			break;
1957 		}
1958 
1959 		index = *(uint32_t *)fcio->fcio_ibuf;
1960 		ndlp  = emlxs_node_find_index(port, index, 1);
1961 
1962 		if (!ndlp) {
1963 			fcio->fcio_errno = FC_OUTOFBOUNDS;
1964 			rval = EINVAL;
1965 			break;
1966 		}
1967 
1968 		goto get_node_attrs;
1969 	}
1970 
1971 	/* Same as FCIO_GET_DISCOVERED_PORT_ATTRIBUTES */
1972 	/* except WWPN is used instead of index */
1973 	case FCIO_GET_PORT_ATTRIBUTES:
1974 	{
1975 		emlxs_node_t *ndlp2;
1976 
1977 		if ((fcio->fcio_xfer != FCIO_XFER_READ) ||
1978 		    (fcio->fcio_ilen < 8) ||
1979 		    (fcio->fcio_olen < sizeof (fc_hba_port_attributes_t))) {
1980 			rval = EINVAL;
1981 			break;
1982 		}
1983 
1984 		wwpn  = (uint8_t *)fcio->fcio_ibuf;
1985 		ndlp  = emlxs_node_find_wwpn(port, wwpn);
1986 
1987 		if (!ndlp) {
1988 			fcio->fcio_errno = FC_NOMAP;
1989 			rval = EINVAL;
1990 			break;
1991 		}
1992 
1993 		/* Filter fabric ports */
1994 		if ((ndlp->nlp_DID & 0xFFF000) == 0xFFF000) {
1995 			fcio->fcio_errno = FC_NOMAP;
1996 			rval = EINVAL;
1997 			break;
1998 		}
1999 
2000 get_node_attrs:
2001 
2002 		port_attrs = (fc_hba_port_attributes_t *)fcio->fcio_obuf;
2003 
2004 		port_attrs->version    = FC_HBA_PORT_ATTRIBUTES_VERSION;
2005 		/* port_attrs->lastChange */
2006 		/* port_attrs->fp_minor   */
2007 		bcopy((caddr_t)&ndlp->nlp_nodename,
2008 		    (caddr_t)&port_attrs->NodeWWN, 8);
2009 		bcopy((caddr_t)&ndlp->nlp_portname,
2010 		    (caddr_t)&port_attrs->PortWWN, 8);
2011 
2012 		port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
2013 		port_attrs->PortType  = FC_HBA_PORTTYPE_UNKNOWN;
2014 		port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
2015 
2016 		if (hba->state > FC_LINK_UP) {
2017 			ndlp2 = emlxs_node_find_did(port, FABRIC_DID);
2018 
2019 			port_attrs->PortFcId  = ndlp->nlp_DID;
2020 			port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
2021 
2022 			/* no switch */
2023 			if (!ndlp2) {
2024 				if (hba->topology == TOPOLOGY_LOOP) {
2025 					port_attrs->PortType =
2026 					    FC_HBA_PORTTYPE_LPORT;
2027 				} else {
2028 					port_attrs->PortType =
2029 					    FC_HBA_PORTTYPE_PTP;
2030 				}
2031 
2032 				/* We share a common speed */
2033 				switch (hba->linkspeed) {
2034 				case 0:
2035 					port_attrs->PortSpeed =
2036 					    HBA_PORTSPEED_1GBIT;
2037 					break;
2038 				case LA_1GHZ_LINK:
2039 					port_attrs->PortSpeed =
2040 					    HBA_PORTSPEED_1GBIT;
2041 					break;
2042 				case LA_2GHZ_LINK:
2043 					port_attrs->PortSpeed =
2044 					    HBA_PORTSPEED_2GBIT;
2045 					break;
2046 				case LA_4GHZ_LINK:
2047 					port_attrs->PortSpeed =
2048 					    HBA_PORTSPEED_4GBIT;
2049 					break;
2050 				case LA_8GHZ_LINK:
2051 					port_attrs->PortSpeed =
2052 					    HBA_PORTSPEED_8GBIT;
2053 					break;
2054 				case LA_10GHZ_LINK:
2055 					port_attrs->PortSpeed =
2056 					    HBA_PORTSPEED_10GBIT;
2057 					break;
2058 				}
2059 			}
2060 			/* public loop */
2061 			else if (hba->topology == TOPOLOGY_LOOP) {
2062 				/* Check for common area and domain */
2063 				if ((ndlp->nlp_DID & 0xFFFF00) ==
2064 				    (port->did & 0xFFFF00)) {
2065 					port_attrs->PortType =
2066 					    FC_HBA_PORTTYPE_NLPORT;
2067 
2068 					/* We share a common speed */
2069 					switch (hba->linkspeed) {
2070 					case 0:
2071 						port_attrs->PortSpeed =
2072 						    HBA_PORTSPEED_1GBIT;
2073 						break;
2074 					case LA_1GHZ_LINK:
2075 						port_attrs->PortSpeed =
2076 						    HBA_PORTSPEED_1GBIT;
2077 						break;
2078 					case LA_2GHZ_LINK:
2079 						port_attrs->PortSpeed =
2080 						    HBA_PORTSPEED_2GBIT;
2081 						break;
2082 					case LA_4GHZ_LINK:
2083 						port_attrs->PortSpeed =
2084 						    HBA_PORTSPEED_4GBIT;
2085 						break;
2086 					case LA_8GHZ_LINK:
2087 						port_attrs->PortSpeed =
2088 						    HBA_PORTSPEED_8GBIT;
2089 						break;
2090 					case LA_10GHZ_LINK:
2091 						port_attrs->PortSpeed =
2092 						    HBA_PORTSPEED_10GBIT;
2093 						break;
2094 					}
2095 				}
2096 			}
2097 		}
2098 
2099 		port_attrs->PortSupportedClassofService =
2100 		    LE_SWAP32(FC_NS_CLASS3);
2101 		/* port_attrs->PortSymbolicName		*/
2102 		/* port_attrs->PortSupportedSpeed	*/
2103 		/* port_attrs->PortSupportedFc4Types	*/
2104 		/* port_attrs->PortActiveFc4Types	*/
2105 		/* port_attrs->PortMaxFrameSize		*/
2106 		/* port_attrs->NumberofDiscoveredPorts	*/
2107 
2108 		break;
2109 	}
2110 
2111 	case FCIO_GET_SYM_PNAME:
2112 	{
2113 		if (fcio->fcio_olen < (strlen(port->spn)+1) ||
2114 		    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2115 			rval = EINVAL;
2116 			break;
2117 		}
2118 
2119 		(void) strcpy((caddr_t)fcio->fcio_obuf, (caddr_t)port->spn);
2120 
2121 		break;
2122 	}
2123 
2124 	case FCIO_GET_SYM_NNAME:
2125 	{
2126 		if (fcio->fcio_olen < (strlen(port->snn)+1) ||
2127 		    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
2128 			rval = EINVAL;
2129 			break;
2130 		}
2131 
2132 		(void) strcpy((caddr_t)fcio->fcio_obuf, (caddr_t)port->snn);
2133 
2134 		break;
2135 	}
2136 
2137 	case FCIO_FORCE_DUMP:
2138 	{
2139 		rval = emlxs_reset(port, FC_FCA_CORE);
2140 
2141 		if (rval != FC_SUCCESS) {
2142 			fcio->fcio_errno = rval;
2143 			rval = EIO;
2144 			break;
2145 		}
2146 
2147 		break;
2148 	}
2149 
2150 	case FCIO_GET_DUMP_SIZE:
2151 	{
2152 		fc_fca_pm_t pm;
2153 
2154 		if (fcio->fcio_olen != sizeof (uint32_t) ||
2155 		    fcio->fcio_xfer != FCIO_XFER_READ) {
2156 			rval = EINVAL;
2157 			break;
2158 		}
2159 
2160 		bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2161 
2162 		pm.pm_data_len  = fcio->fcio_olen;
2163 		pm.pm_data_buf  = fcio->fcio_obuf;
2164 		pm.pm_cmd_code  = FC_PORT_GET_DUMP_SIZE;
2165 		pm.pm_cmd_flags = FC_FCA_PM_READ;
2166 
2167 		rval = emlxs_port_manage(port, &pm);
2168 
2169 		if (rval != FC_SUCCESS) {
2170 			fcio->fcio_errno = rval;
2171 
2172 			if (rval == FC_INVALID_REQUEST) {
2173 				rval = ENOTTY;
2174 			} else {
2175 				rval = EIO;
2176 			}
2177 		}
2178 
2179 		break;
2180 	}
2181 
2182 	case FCIO_GET_DUMP:
2183 	{
2184 		fc_fca_pm_t pm;
2185 		uint32_t dump_size;
2186 
2187 		if (fcio->fcio_xfer != FCIO_XFER_READ) {
2188 			rval = EINVAL;
2189 			break;
2190 		}
2191 
2192 		bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2193 
2194 		pm.pm_data_len  = sizeof (uint32_t);
2195 		pm.pm_data_buf  = (caddr_t)&dump_size;
2196 		pm.pm_cmd_code  = FC_PORT_GET_DUMP_SIZE;
2197 		pm.pm_cmd_flags = FC_FCA_PM_READ;
2198 
2199 		rval = emlxs_port_manage(port, &pm);
2200 
2201 		if (rval != FC_SUCCESS) {
2202 			fcio->fcio_errno = rval;
2203 
2204 			if (rval == FC_INVALID_REQUEST) {
2205 				rval = ENOTTY;
2206 			} else {
2207 				rval = EIO;
2208 			}
2209 			break;
2210 		}
2211 
2212 		if (fcio->fcio_olen != dump_size) {
2213 			fcio->fcio_errno = FC_NOMEM;
2214 			rval = EINVAL;
2215 			break;
2216 		}
2217 
2218 		bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
2219 
2220 		pm.pm_data_len  = fcio->fcio_olen;
2221 		pm.pm_data_buf  = fcio->fcio_obuf;
2222 		pm.pm_cmd_code  = FC_PORT_GET_DUMP;
2223 		pm.pm_cmd_flags = FC_FCA_PM_READ;
2224 
2225 		rval = emlxs_port_manage(port, &pm);
2226 
2227 		if (rval != FC_SUCCESS) {
2228 			fcio->fcio_errno = rval;
2229 
2230 			if (rval == FC_INVALID_REQUEST) {
2231 				rval = ENOTTY;
2232 			} else {
2233 				rval = EIO;
2234 			}
2235 		}
2236 
2237 		break;
2238 	}
2239 
2240 	case FCIO_SET_SYM_PNAME:
2241 	case FCIO_SET_SYM_NNAME:
2242 	case FCIO_DEV_LOGIN:
2243 	case FCIO_DEV_LOGOUT:
2244 	case FCIO_DEV_REMOVE:
2245 	case FCIO_NS:
2246 	case FCIO_SEND_NODE_ID:
2247 	case FCIO_GET_ADAPTER_PORT_STATS:
2248 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2249 		    "%s: Unsupported FCIO command.",
2250 		    emlxs_fcio_xlate(fcio->fcio_cmd));
2251 		rval = ENOTSUP;
2252 		break;
2253 
2254 	default:
2255 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2256 		    "Unknown FCIO command. (0x%x)", fcio->fcio_cmd);
2257 		rval = EFAULT;
2258 
2259 	}	/* switch() */
2260 
2261 done:
2262 
2263 	if (rval != 0 && fcio->fcio_errno == 0) {
2264 		fcio->fcio_errno = FC_FAILURE;
2265 	}
2266 
2267 	if (fcio->fcio_ibuf) {
2268 		if (ddi_copyout(fcio->fcio_ibuf, dfc->buf1, fcio->fcio_ilen,
2269 		    mode)) {
2270 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2271 			    "%s: %s: ddi_copyout failed. (size=%d)",
2272 			    emlxs_dfc_xlate(dfc->cmd),
2273 			    emlxs_fcio_xlate(dfc->data1), fcio->fcio_ilen);
2274 
2275 			rval = EFAULT;
2276 		}
2277 
2278 		kmem_free(fcio->fcio_ibuf, fcio->fcio_ilen);
2279 	}
2280 
2281 	if (fcio->fcio_obuf) {
2282 		if (ddi_copyout(fcio->fcio_obuf, dfc->buf2, fcio->fcio_olen,
2283 		    mode)) {
2284 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2285 			    "%s: %s: ddi_copyout failed. (size=%d)",
2286 			    emlxs_dfc_xlate(dfc->cmd),
2287 			    emlxs_fcio_xlate(dfc->data1), fcio->fcio_olen);
2288 
2289 			rval = EFAULT;
2290 		}
2291 
2292 		kmem_free(fcio->fcio_obuf, fcio->fcio_olen);
2293 	}
2294 
2295 	if (fcio->fcio_abuf) {
2296 		if (ddi_copyout(fcio->fcio_abuf, dfc->buf3, fcio->fcio_alen,
2297 		    mode)) {
2298 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2299 			    "%s: %s: ddi_copyout failed. (size=%d)",
2300 			    emlxs_dfc_xlate(dfc->cmd),
2301 			    emlxs_fcio_xlate(dfc->data1), fcio->fcio_alen);
2302 
2303 			rval = EFAULT;
2304 		}
2305 
2306 		kmem_free(fcio->fcio_abuf, fcio->fcio_alen);
2307 	}
2308 
2309 	if (ddi_copyout((void *)&fcio->fcio_errno, (void *)dfc->buf4,
2310 	    dfc->buf4_size, mode) != 0) {
2311 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2312 		    "%s: %s: ddi_copyout failed. (size=%d)",
2313 		    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1),
2314 		    dfc->buf4_size);
2315 
2316 			rval = EFAULT;
2317 	}
2318 
2319 	return (rval);
2320 
2321 } /* emlxs_fcio_manage() */
2322 
2323 #endif /* FCIO_SUPPORT */
2324 
2325 
2326 static int32_t
2327 emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2328 {
2329 	emlxs_port_t	*port = &PPORT;
2330 	emlxs_config_t	*cfg = &CFG;
2331 	emlxs_port_t	*vport;
2332 	emlxs_port_t	*tport;
2333 	dfc_vportinfo_t	dfc_vport;
2334 	uint32_t	vpi;
2335 	uint32_t	options;
2336 	char		name[256];
2337 	uint8_t		wwn[8];
2338 
2339 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
2340 	    emlxs_dfc_xlate(dfc->cmd));
2341 
2342 	options = dfc->data1;
2343 
2344 	if (!dfc->buf1 || !dfc->buf1_size) {
2345 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2346 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
2347 
2348 		return (DFC_ARG_NULL);
2349 	}
2350 
2351 	if (dfc->buf1_size < sizeof (dfc_vportinfo_t)) {
2352 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2353 		    "%s: Buffer1 too small. (size=%d)",
2354 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2355 
2356 		return (DFC_ARG_TOOSMALL);
2357 	}
2358 
2359 	/* Read the dfc_vport object */
2360 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_vport,
2361 	    sizeof (dfc_vportinfo_t), mode) != 0) {
2362 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2363 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
2364 
2365 		return (DFC_COPYIN_ERROR);
2366 	}
2367 
2368 	if (!(options & VPORT_OPT_AUTORETRY)) {
2369 		if (!(hba->flag & FC_NPIV_ENABLED)) {
2370 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2371 			    "%s: NPIV currently not enabled.",
2372 			    emlxs_dfc_xlate(dfc->cmd));
2373 
2374 			return (DFC_NPIV_DISABLED);
2375 		}
2376 
2377 		if (!(hba->flag & FC_NPIV_SUPPORTED)) {
2378 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2379 			    "%s: NPIV currently not supported.",
2380 			    emlxs_dfc_xlate(dfc->cmd));
2381 
2382 			return (DFC_NPIV_UNSUPPORTED);
2383 		}
2384 	}
2385 
2386 	/*
2387 	 * Only the same WWNN and WWPN can be re-created
2388 	 */
2389 	bzero(wwn, 8);
2390 	if (bcmp(wwn, dfc_vport.wwpn, 8) || bcmp(wwn, dfc_vport.wwnn, 0)) {
2391 		for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
2392 			vport = &VPORT(vpi);
2393 
2394 			if ((bcmp((caddr_t)&vport->wwnn,
2395 			    (caddr_t)dfc_vport.wwnn, 8) == 0) &&
2396 			    (bcmp((caddr_t)&vport->wwpn,
2397 			    (caddr_t)dfc_vport.wwpn, 8) == 0)) {
2398 				if (!(vport->flag & EMLXS_PORT_CONFIG) &&
2399 				    (vport->flag & EMLXS_PORT_BOUND)) {
2400 					dfc_vport.vpi = vpi;
2401 					break;
2402 				} else {
2403 					EMLXS_MSGF(EMLXS_CONTEXT,
2404 					    &emlxs_dfc_error_msg,
2405 					    "%s: VPI already in use.",
2406 					    emlxs_dfc_xlate(dfc->cmd));
2407 
2408 					return (DFC_ARG_INVALID);
2409 				}
2410 			}
2411 		}
2412 	}
2413 
2414 	/* else auto assign */
2415 	/* Acquire a VPI */
2416 	if (dfc_vport.vpi == 0) {
2417 		/* Auto Assign VPI */
2418 		for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
2419 			vport = &VPORT(vpi);
2420 
2421 			if (!(vport->flag & EMLXS_PORT_CONFIG)) {
2422 				break;
2423 			}
2424 		}
2425 
2426 		if (vpi > hba->vpi_max) {
2427 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2428 			    "%s: Out of resources.",
2429 			    emlxs_dfc_xlate(dfc->cmd));
2430 
2431 			return (DFC_DRVRES_ERROR);
2432 		}
2433 
2434 		dfc_vport.vpi = vpi;
2435 	}
2436 
2437 	/* Establish a WWPN */
2438 	bzero(wwn, 8);
2439 	if (!(bcmp(wwn, dfc_vport.wwpn, 8))) {
2440 		/* Generate new WWPN */
2441 		bcopy((caddr_t)&hba->wwpn, (caddr_t)dfc_vport.wwpn, 8);
2442 		dfc_vport.wwpn[0] = 0x20;
2443 		dfc_vport.wwpn[1] = vpi;
2444 	} else {	/* use one provided */
2445 
2446 		/* Make sure WWPN is unique */
2447 		if (tport = emlxs_vport_find_wwpn(hba, dfc_vport.wwpn)) {
2448 			if ((tport->flag & EMLXS_PORT_CONFIG) &&
2449 			    (tport->flag & EMLXS_PORT_BOUND)) {
2450 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2451 				    "%s: WWPN already exists. vpi=%d",
2452 				    emlxs_dfc_xlate(dfc->cmd), vpi);
2453 				return (DFC_ARG_INVALID);
2454 			}
2455 		}
2456 	}
2457 
2458 	/* Establish a WWNN */
2459 	bzero(wwn, 8);
2460 	if (!(bcmp(wwn, dfc_vport.wwnn, 8))) {
2461 		/* Generate new WWNN */
2462 		bcopy((caddr_t)&hba->wwnn, (caddr_t)dfc_vport.wwnn, 8);
2463 		dfc_vport.wwnn[0] = 0x28;
2464 		dfc_vport.wwnn[1] = vpi;
2465 	}
2466 	/* else use WWNN provided */
2467 
2468 	/* Generate the symbolic node name */
2469 	if (dfc_vport.snn[0]) {
2470 		(void) strcpy(name, dfc_vport.snn);
2471 		(void) sprintf(dfc_vport.snn, "%s %s", hba->snn, name);
2472 	} else {
2473 		(void) strcpy(dfc_vport.snn, hba->snn);
2474 	}
2475 
2476 	/* Generate the symbolic port name */
2477 	if (dfc_vport.spn[0]) {
2478 		(void) strcpy(name, dfc_vport.spn);
2479 		(void) sprintf(dfc_vport.spn, "%s VPort-%d VName-%s", hba->spn,
2480 		    vpi, name);
2481 	} else {
2482 		(void) sprintf(dfc_vport.spn, "%s VPort-%d", hba->spn, vpi);
2483 	}
2484 
2485 	dfc_vport.port_id = 0;
2486 	dfc_vport.ulp_statec = FC_STATE_OFFLINE;
2487 	dfc_vport.flags = VPORT_CONFIG;
2488 
2489 	/* Set the highest configured vpi */
2490 	if (dfc_vport.vpi >= hba->vpi_high) {
2491 		hba->vpi_high = dfc_vport.vpi;
2492 	}
2493 
2494 	/* Configure the port object */
2495 	bcopy((caddr_t)dfc_vport.wwnn, (caddr_t)&vport->wwnn, 8);
2496 	bcopy((caddr_t)dfc_vport.wwpn, (caddr_t)&vport->wwpn, 8);
2497 	(void) strncpy((caddr_t)vport->snn, (caddr_t)dfc_vport.snn, 256);
2498 	(void) strncpy((caddr_t)vport->spn, (caddr_t)dfc_vport.spn, 256);
2499 	vport->flag |= (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
2500 
2501 	/* Adjust restricted flags */
2502 	vport->options &= ~EMLXS_OPT_RESTRICT_MASK;
2503 	vport->flag &= ~EMLXS_PORT_RESTRICTED;
2504 	if (options & VPORT_OPT_RESTRICT) {
2505 		vport->options |= EMLXS_OPT_RESTRICT;
2506 		vport->flag |= EMLXS_PORT_RESTRICTED;
2507 		dfc_vport.flags |= VPORT_RESTRICTED;
2508 	} else if (options & VPORT_OPT_UNRESTRICT) {
2509 		vport->options |= EMLXS_OPT_UNRESTRICT;
2510 	} else if (cfg[CFG_VPORT_RESTRICTED].current) {
2511 		vport->flag |= EMLXS_PORT_RESTRICTED;
2512 		dfc_vport.flags |= VPORT_RESTRICTED;
2513 	}
2514 #ifdef SFCT_SUPPORT
2515 	if (vport->tgt_mode) {
2516 		emlxs_fct_bind_port(vport);
2517 	}
2518 #endif /* SFCT_SUPPORT */
2519 
2520 	if (ddi_copyout((void *)&dfc_vport, (void *)dfc->buf1,
2521 	    sizeof (dfc_vportinfo_t), mode) != 0) {
2522 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2523 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
2524 
2525 		return (DFC_COPYOUT_ERROR);
2526 	}
2527 
2528 	if (vport->flag & EMLXS_PORT_BOUND) {
2529 		/*
2530 		 * The same WWNN, WWPN and VPI has been re-created.
2531 		 * Bring up the vport now!
2532 		 */
2533 		emlxs_port_online(vport);
2534 	}
2535 
2536 	return (0);
2537 
2538 } /* emlxs_dfc_create_vport() */
2539 
2540 
2541 static int32_t
2542 emlxs_dfc_destroy_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2543 {
2544 	emlxs_port_t	*port = &PPORT;
2545 	emlxs_port_t	*vport;
2546 	uint8_t		wwpn[8];
2547 	fc_packet_t	*pkt = NULL;
2548 	uint32_t	rval = 0;
2549 	ELS_PKT		*els;
2550 	char		buffer[256];
2551 
2552 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
2553 	    emlxs_dfc_xlate(dfc->cmd));
2554 
2555 	if (!dfc->buf1 || !dfc->buf1_size) {
2556 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2557 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
2558 
2559 		rval = DFC_ARG_NULL;
2560 		goto done;
2561 	}
2562 
2563 	if (dfc->buf1_size < 8) {
2564 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2565 		    "%s: Buffer1 too small. (size=%d)",
2566 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2567 
2568 		rval = DFC_ARG_TOOSMALL;
2569 		goto done;
2570 	}
2571 
2572 	/* Read the wwn object */
2573 	if (ddi_copyin((void *)dfc->buf1, (void *)wwpn, 8, mode) != 0) {
2574 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2575 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
2576 
2577 		rval = DFC_COPYIN_ERROR;
2578 		goto done;
2579 	}
2580 
2581 	/* Make sure WWPN is unique */
2582 	vport = emlxs_vport_find_wwpn(hba, wwpn);
2583 
2584 	/* Physical does not have EMLXS_PORT_CONFIG set */
2585 	if (!vport || !(vport->flag & EMLXS_PORT_CONFIG)) {
2586 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2587 		    "%s: WWPN does not exists. %s", emlxs_dfc_xlate(dfc->cmd),
2588 		    emlxs_wwn_xlate(buffer, wwpn));
2589 
2590 		rval = DFC_ARG_INVALID;
2591 		goto done;
2592 	}
2593 
2594 	if (vport->did) {
2595 		/* Fabric Logout */
2596 		if (!(pkt = emlxs_pkt_alloc(vport,
2597 		    sizeof (uint32_t) + sizeof (LOGO),
2598 		    sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
2599 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2600 			    "%s: Unable to allocate packet.",
2601 			    emlxs_dfc_xlate(dfc->cmd));
2602 
2603 			rval = DFC_SYSRES_ERROR;
2604 			goto done;
2605 		}
2606 
2607 		/* Make this a polled IO */
2608 		pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
2609 		pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
2610 		pkt->pkt_comp = NULL;
2611 
2612 		pkt->pkt_tran_type = FC_PKT_EXCHANGE;
2613 		pkt->pkt_timeout = 60;
2614 
2615 		/* Build the fc header */
2616 		pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
2617 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
2618 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(vport->did);
2619 		pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2620 		pkt->pkt_cmd_fhdr.f_ctl =
2621 		    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
2622 		pkt->pkt_cmd_fhdr.seq_id = 0;
2623 		pkt->pkt_cmd_fhdr.df_ctl = 0;
2624 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
2625 		pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2626 		pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
2627 		pkt->pkt_cmd_fhdr.ro = 0;
2628 
2629 		/* Build the command */
2630 		els = (ELS_PKT *) pkt->pkt_cmd;
2631 		els->elsCode = 0x05;	/* LOGO */
2632 		els->un.logo.un.nPortId32 = LE_SWAP32(vport->did);
2633 		bcopy(&vport->wwpn, &els->un.logo.portName, 8);
2634 
2635 		/*
2636 		 * Just send LOGO. Don't worry about result.
2637 		 * This is just a courtesy anyway.
2638 		 */
2639 		(void) emlxs_pkt_send(pkt, 1);
2640 
2641 
2642 		/* Take the port offline */
2643 		(void) emlxs_port_offline(vport, 0xffffffff);
2644 	}
2645 
2646 	vport->flag &= ~(EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
2647 
2648 	rval = 0;
2649 
2650 done:
2651 
2652 	if (pkt) {
2653 		emlxs_pkt_free(pkt);
2654 	}
2655 
2656 	return (rval);
2657 
2658 } /* emlxs_dfc_destroy_vport() */
2659 
2660 
2661 static int32_t
2662 emlxs_dfc_get_vportinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2663 {
2664 	emlxs_port_t	*port = &PPORT;
2665 	emlxs_port_t	*vport;
2666 	dfc_vportinfo_t	*dfc_vport;
2667 	dfc_vportinfo_t	*dfc_vport_list = NULL;
2668 	uint32_t	i;
2669 	uint32_t	size;
2670 	uint32_t	max_count;
2671 	uint32_t	rval = DFC_SUCCESS;
2672 
2673 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
2674 	    emlxs_dfc_xlate(dfc->cmd));
2675 
2676 	if (!dfc->buf1 || !dfc->buf1_size) {
2677 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2678 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
2679 
2680 		return (DFC_ARG_NULL);
2681 	}
2682 
2683 	size = (sizeof (dfc_vportinfo_t) * MAX_VPORTS);
2684 
2685 	if (!(dfc_vport_list =
2686 	    (dfc_vportinfo_t *)kmem_zalloc(size, KM_NOSLEEP))) {
2687 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2688 		    "%s: Unable to allocate memory.",
2689 		    emlxs_dfc_xlate(dfc->cmd));
2690 
2691 		return (DFC_SYSRES_ERROR);
2692 	}
2693 
2694 	max_count = 0;
2695 	for (i = 0; i <= hba->vpi_max; i++) {
2696 		vport = &VPORT(i);
2697 		dfc_vport = &dfc_vport_list[i];
2698 
2699 		if (!(vport->flag & EMLXS_PORT_CONFIG)) {
2700 			continue;
2701 		}
2702 
2703 		bcopy(vport->snn, dfc_vport->snn, 256);
2704 		bcopy(vport->spn, dfc_vport->spn, 256);
2705 		bcopy(&vport->wwpn, dfc_vport->wwpn, 8);
2706 		bcopy(&vport->wwnn, dfc_vport->wwnn, 8);
2707 		dfc_vport->port_id = vport->did;
2708 		dfc_vport->vpi = vport->vpi;
2709 		dfc_vport->ulp_statec = vport->ulp_statec;
2710 		dfc_vport->flags = VPORT_CONFIG;
2711 
2712 		if (vport->flag & EMLXS_PORT_ENABLE) {
2713 			dfc_vport->flags |= VPORT_ENABLED;
2714 		}
2715 
2716 		if (vport->flag & EMLXS_PORT_BOUND) {
2717 			dfc_vport->flags |= VPORT_BOUND;
2718 		}
2719 
2720 		if (vport->flag & EMLXS_PORT_IP_UP) {
2721 			dfc_vport->flags |= VPORT_IP;
2722 		}
2723 
2724 		if (vport->flag & EMLXS_PORT_RESTRICTED) {
2725 			dfc_vport->flags |= VPORT_RESTRICTED;
2726 		}
2727 
2728 		max_count++;
2729 	}
2730 
2731 	max_count *= sizeof (dfc_vportinfo_t);
2732 
2733 	if (max_count > dfc->buf1_size) {
2734 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2735 		    "%s: Buffer1 too small. (%d > %d)",
2736 		    emlxs_dfc_xlate(dfc->cmd), max_count, dfc->buf1_size);
2737 
2738 		rval = DFC_ARG_TOOSMALL;
2739 		goto done;
2740 	}
2741 
2742 	if (ddi_copyout((void *)dfc_vport_list, (void *)dfc->buf1,
2743 	    dfc->buf1_size, mode) != 0) {
2744 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2745 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
2746 
2747 		rval = DFC_COPYOUT_ERROR;
2748 		goto done;
2749 	}
2750 
2751 done:
2752 
2753 	if (dfc_vport_list) {
2754 		kmem_free(dfc_vport_list, size);
2755 	}
2756 
2757 	return (rval);
2758 
2759 } /* emlxs_dfc_get_vportinfo() */
2760 
2761 
2762 static emlxs_port_t *
2763 emlxs_vport_find_wwpn(emlxs_hba_t *hba, uint8_t *wwpn)
2764 {
2765 	emlxs_port_t	*port;
2766 	NODELIST	*nlp;
2767 	int		i, j;
2768 
2769 	for (i = 0; i <= hba->vpi_max; i++) {
2770 		port = &VPORT(i);
2771 
2772 		/* Check Local N-port, including physical port */
2773 		if (bcmp(&port->wwpn, wwpn, 8) == 0) {
2774 			return (port);
2775 		}
2776 
2777 		/* Check Remote N-port */
2778 		rw_enter(&port->node_rwlock, RW_READER);
2779 		for (j = 0; j < EMLXS_NUM_HASH_QUES; j++) {
2780 			nlp = port->node_table[j];
2781 			while (nlp != NULL) {
2782 				/* Check Local N-port */
2783 				if (bcmp(&nlp->nlp_portname, wwpn, 8) == 0) {
2784 					rw_exit(&port->node_rwlock);
2785 					return (port);
2786 				}
2787 				nlp = nlp->nlp_list_next;
2788 			}
2789 		}
2790 
2791 		rw_exit(&port->node_rwlock);
2792 	}
2793 
2794 	return (0);
2795 
2796 } /* emlxs_vport_find_wwpn() */
2797 
2798 
2799 static int32_t
2800 emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2801 {
2802 	emlxs_port_t		*port = &PPORT;
2803 	dfc_vport_resource_t	vres;
2804 	MAILBOXQ		*mbq = NULL;
2805 	MAILBOX			*mb;
2806 	uint32_t		rval = DFC_SUCCESS;
2807 
2808 	if (!dfc->buf1 || !dfc->buf1_size) {
2809 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2810 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
2811 
2812 		return (DFC_ARG_NULL);
2813 	}
2814 
2815 	if (dfc->buf1_size < sizeof (dfc_vport_resource_t)) {
2816 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2817 		    "%s: Buffer1 too small. (size=%d)",
2818 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2819 
2820 		return (DFC_ARG_TOOSMALL);
2821 	}
2822 
2823 	bzero(&vres, sizeof (dfc_vport_resource_t));
2824 
2825 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2826 		int i;
2827 		int total_rpi;
2828 		emlxs_port_t *vport;
2829 
2830 		total_rpi = 0;
2831 		for (i = 0; i < hba->sli.sli4.VPICount; i++) {
2832 			vport = &VPORT(i);
2833 			total_rpi += vport->outstandingRPIs;
2834 		}
2835 
2836 		vres.vpi_max = hba->sli.sli4.VPICount - 1;
2837 		vres.vpi_inuse = (port->VFIp == NULL) ? 0 :
2838 		    port->VFIp->outstandingVPIs - 1;
2839 		vres.rpi_max = hba->sli.sli4.RPICount;
2840 		vres.rpi_inuse = total_rpi;
2841 
2842 		if (ddi_copyout((void *)&vres, (void *)dfc->buf1,
2843 		    sizeof (dfc_vport_resource_t), mode) != 0) {
2844 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2845 			    "%s: ddi_copyout failed.",
2846 			    emlxs_dfc_xlate(dfc->cmd));
2847 
2848 			rval = DFC_COPYOUT_ERROR;
2849 		}
2850 		return (rval);
2851 	}
2852 
2853 	mbq =
2854 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
2855 
2856 	mb = (MAILBOX *) mbq;
2857 
2858 	emlxs_mb_read_config(hba, mbq);
2859 
2860 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
2861 
2862 	if (rval == MBX_TIMEOUT) {
2863 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2864 		    "%s: Mailbox timed out. cmd=%x",
2865 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
2866 
2867 		rval = DFC_TIMEOUT;
2868 		goto done;
2869 	}
2870 
2871 	if (rval) {
2872 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2873 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
2874 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
2875 
2876 		rval = DFC_IO_ERROR;
2877 		goto done;
2878 	}
2879 
2880 	vres.vpi_max = mb->un.varRdConfig.max_vpi;
2881 	vres.vpi_inuse =
2882 	    (mb->un.varRdConfig.max_vpi <=
2883 	    mb->un.varRdConfig.avail_vpi) ? 0 : mb->un.varRdConfig.max_vpi -
2884 	    mb->un.varRdConfig.avail_vpi;
2885 
2886 	vres.rpi_max = mb->un.varRdConfig.max_rpi;
2887 	vres.rpi_inuse =
2888 	    (mb->un.varRdConfig.max_rpi <=
2889 	    mb->un.varRdConfig.avail_rpi) ? 0 : mb->un.varRdConfig.max_rpi -
2890 	    mb->un.varRdConfig.avail_rpi;
2891 
2892 	if (ddi_copyout((void *)&vres, (void *)dfc->buf1,
2893 	    sizeof (dfc_vport_resource_t), mode) != 0) {
2894 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2895 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
2896 
2897 		rval = DFC_COPYOUT_ERROR;
2898 	}
2899 
2900 done:
2901 
2902 	/* Free allocated mbox memory */
2903 	if (mbq) {
2904 		kmem_free(mbq, sizeof (MAILBOXQ));
2905 	}
2906 
2907 	return (rval);
2908 
2909 } /* emlxs_dfc_npiv_resource() */
2910 
2911 
2912 static int32_t
2913 emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2914 {
2915 	emlxs_port_t	*port = &PPORT;
2916 	emlxs_port_t	*vport = &VPORT(hba->vpi_max);
2917 	emlxs_config_t	*cfg = &CFG;
2918 	fc_packet_t	*pkt = NULL;
2919 	fc_packet_t	*pkt1 = NULL;
2920 	ELS_PKT		*els;
2921 	LS_RJT		*lsrjt;
2922 	uint32_t	checklist = 0;
2923 	uint32_t	mask = 0;
2924 	uint32_t	rval = DFC_SUCCESS;
2925 	uint8_t		wwn[8];
2926 	emlxs_vpd_t	*vpd = &VPD;
2927 	int		i;
2928 
2929 	if (!dfc->buf1 || !dfc->buf1_size) {
2930 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2931 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
2932 
2933 		return (DFC_ARG_NULL);
2934 	}
2935 
2936 	if (dfc->buf1_size < sizeof (uint32_t)) {
2937 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2938 		    "%s: Buffer1 too small. (size=%d)",
2939 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2940 
2941 		return (DFC_ARG_TOOSMALL);
2942 	}
2943 
2944 	if (cfg[CFG_NPIV_ENABLE].current) {
2945 		checklist |= CL_NPIV_PARM_ENABLE;
2946 	}
2947 
2948 	if (hba->sli_mode >= 3) {
2949 		checklist |= CL_SLI3_ENABLE;
2950 	}
2951 
2952 
2953 	if ((vpd->feaLevelHigh >= 0x09) || (hba->sli_mode >= 4)) {
2954 		checklist |= CL_HBA_SUPPORT_NPIV;
2955 	}
2956 
2957 
2958 	if (hba->num_of_ports <= hba->vpi_max) {
2959 		checklist |= CL_HBA_HAS_RESOURCES;
2960 	}
2961 
2962 	if (hba->state < FC_LINK_UP) {
2963 		goto done;
2964 	}
2965 
2966 	checklist |= CL_HBA_LINKUP;
2967 
2968 	if (hba->topology == TOPOLOGY_LOOP) {
2969 		goto done;
2970 	}
2971 
2972 	if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2973 		goto done;
2974 	}
2975 
2976 	checklist |= CL_P2P_TOPOLOGY;
2977 
2978 	if (!(hba->flag & FC_NPIV_SUPPORTED)) {
2979 		goto done;
2980 	}
2981 
2982 	checklist |= CL_FABRIC_SUPPORTS_NPIV;
2983 
2984 	mask =
2985 	    (CL_NPIV_PARM_ENABLE | CL_SLI3_ENABLE | CL_HBA_SUPPORT_NPIV |
2986 	    CL_HBA_HAS_RESOURCES);
2987 
2988 	/*
2989 	 * Check if those four conditions are met
2990 	 */
2991 	if ((checklist & mask) != mask) {
2992 		/*
2993 		 * One or more conditions are not met
2994 		 */
2995 		goto done;
2996 	}
2997 
2998 		/* Now check if fabric have resources */
2999 	for (i = 1; i <= hba->vpi_max; i++) {
3000 			vport = &VPORT(i);
3001 		if (vport->did) {
3002 				checklist |= CL_FABRIC_HAS_RESOURCES;
3003 				goto done;
3004 			}
3005 		}
3006 
3007 	vport->vpi = hba->vpi_max;
3008 	vport->hba = hba;
3009 
3010 	if (!(pkt = emlxs_pkt_alloc(vport,
3011 	    sizeof (uint32_t) + sizeof (SERV_PARM), sizeof (FCP_RSP),
3012 	    0, KM_NOSLEEP))) {
3013 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3014 		    "Unable to allocate packet.");
3015 		goto done;
3016 	}
3017 
3018 	/* Build (FDISC) the fc header */
3019 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
3020 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_EXTENDED_SVC | R_CTL_UNSOL_CONTROL;
3021 	pkt->pkt_cmd_fhdr.s_id = 0;
3022 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3023 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
3024 	pkt->pkt_cmd_fhdr.seq_id = 0;
3025 	pkt->pkt_cmd_fhdr.df_ctl = 0;
3026 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
3027 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
3028 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
3029 	pkt->pkt_cmd_fhdr.ro = 0;
3030 
3031 	/* Build the command (FDISC) */
3032 	els = (ELS_PKT *) pkt->pkt_cmd;
3033 	els->elsCode = 0x04;	/* FLOGI - This will be changed automatically */
3034 				/* by the drive (See emlxs_send_els()) */
3035 
3036 	els->un.logi.cmn.fcphHigh = 0x09;
3037 	els->un.logi.cmn.fcphLow = 0x08;
3038 	els->un.logi.cmn.bbCreditMsb = 0xff;
3039 	els->un.logi.cmn.bbCreditlsb = 0xff;
3040 	els->un.logi.cmn.reqMultipleNPort = 1;
3041 	els->un.logi.cmn.bbRcvSizeMsb = 0x08;
3042 	els->un.logi.cmn.bbRcvSizeLsb = 0x00;
3043 	els->un.logi.cmn.w2.nPort.totalConcurrSeq = 0xff;
3044 	els->un.logi.cmn.w2.nPort.roByCategoryMsb = 0xff;
3045 	els->un.logi.cmn.w2.nPort.roByCategoryLsb = 0xff;
3046 	els->un.logi.cmn.e_d_tov = 0x7d0;
3047 
3048 	bcopy((caddr_t)&hba->wwnn, (caddr_t)wwn, 8);
3049 	wwn[0] = 0x28;
3050 	wwn[1] = hba->vpi_max;
3051 	bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.nodeName, 8);
3052 
3053 	bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
3054 	wwn[0] = 0x20;
3055 	wwn[1] = hba->vpi_max;
3056 	bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.portName, 8);
3057 
3058 	els->un.logi.cls1.openSeqPerXchgMsb = 0x00;
3059 	els->un.logi.cls1.openSeqPerXchgLsb = 0x01;
3060 
3061 	els->un.logi.cls2.classValid = 1;
3062 	els->un.logi.cls2.rcvDataSizeMsb = 0x08;
3063 	els->un.logi.cls2.rcvDataSizeLsb = 0x00;
3064 	els->un.logi.cls2.concurrentSeqMsb = 0x00;
3065 	els->un.logi.cls2.concurrentSeqLsb = 0xff;
3066 	els->un.logi.cls2.EeCreditSeqMsb = 0x00;
3067 	els->un.logi.cls2.EeCreditSeqLsb = 0x0c;
3068 	els->un.logi.cls2.openSeqPerXchgMsb = 0x00;
3069 	els->un.logi.cls2.openSeqPerXchgLsb = 0x01;
3070 
3071 	els->un.logi.cls3.classValid = 1;
3072 	els->un.logi.cls3.rcvDataSizeMsb = 0x08;
3073 	els->un.logi.cls3.rcvDataSizeLsb = 0x00;
3074 	els->un.logi.cls3.concurrentSeqMsb = 0x00;
3075 	els->un.logi.cls3.concurrentSeqLsb = 0xff;
3076 	els->un.logi.cls3.openSeqPerXchgMsb = 0x00;
3077 	els->un.logi.cls3.openSeqPerXchgLsb = 0x01;
3078 
3079 	bcopy((void *)&els->un.logi, (void *)&vport->sparam,
3080 	    sizeof (SERV_PARM));
3081 
3082 	/* Make this a polled IO */
3083 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
3084 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
3085 	pkt->pkt_comp = NULL;
3086 
3087 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
3088 	pkt->pkt_timeout = 60;
3089 
3090 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
3091 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3092 		    "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
3093 
3094 		goto done;
3095 	}
3096 
3097 	if (pkt->pkt_state == FC_PKT_SUCCESS) {
3098 		if (!(pkt1 = emlxs_pkt_alloc(vport,
3099 		    sizeof (uint32_t) + sizeof (LOGO), sizeof (FCP_RSP),
3100 		    0, KM_NOSLEEP))) {
3101 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3102 			    "Unable to allocate LOGO packet.");
3103 			goto free_resc;
3104 		}
3105 
3106 		/* Make this a polled IO */
3107 		pkt1->pkt_tran_flags &= ~FC_TRAN_INTR;
3108 		pkt1->pkt_tran_flags |= FC_TRAN_NO_INTR;
3109 		pkt1->pkt_comp = NULL;
3110 
3111 		pkt1->pkt_tran_type = FC_PKT_EXCHANGE;
3112 		pkt1->pkt_timeout = 60;
3113 
3114 		/* Build (LOGO) the fc header */
3115 		pkt1->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(FABRIC_DID);
3116 		pkt1->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
3117 		pkt1->pkt_cmd_fhdr.s_id =
3118 		    LE_SWAP24_LO(pkt->pkt_resp_fhdr.d_id);
3119 		pkt1->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
3120 		pkt1->pkt_cmd_fhdr.f_ctl =
3121 		    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
3122 		pkt1->pkt_cmd_fhdr.seq_id = 0;
3123 		pkt1->pkt_cmd_fhdr.df_ctl = 0;
3124 		pkt1->pkt_cmd_fhdr.seq_cnt = 0;
3125 		pkt1->pkt_cmd_fhdr.ox_id = 0xFFFF;
3126 		pkt1->pkt_cmd_fhdr.rx_id = 0xFFFF;
3127 		pkt1->pkt_cmd_fhdr.ro = 0;
3128 
3129 		/* Build the command (LOGO) */
3130 		els = (ELS_PKT *) pkt1->pkt_cmd;
3131 		els->elsCode = 0x05;	/* LOGO */
3132 		els->un.logo.un.nPortId32 =
3133 		    LE_SWAP32(pkt->pkt_resp_fhdr.d_id);
3134 		bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
3135 		wwn[0] = 0x20;
3136 		wwn[1] = hba->vpi_max;
3137 		bcopy(wwn, &els->un.logo.portName, 8);
3138 
3139 		if (emlxs_pkt_send(pkt1, 1) != FC_SUCCESS) {
3140 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3141 			    "%s: Unable to send packet.",
3142 			    emlxs_dfc_xlate(dfc->cmd));
3143 
3144 			goto free_resc;
3145 		}
3146 
3147 		if (pkt1->pkt_state != FC_PKT_SUCCESS) {
3148 			if (pkt1->pkt_state == FC_PKT_TIMEOUT) {
3149 				EMLXS_MSGF(EMLXS_CONTEXT,
3150 				    &emlxs_dfc_error_msg,
3151 				    "%s: Pkt Transport error. Pkt Timeout.",
3152 				    emlxs_dfc_xlate(dfc->cmd));
3153 			} else {
3154 				EMLXS_MSGF(EMLXS_CONTEXT,
3155 				    &emlxs_dfc_error_msg,
3156 				    "%s: Pkt Transport error. state=%x",
3157 				    emlxs_dfc_xlate(dfc->cmd),
3158 				    pkt1->pkt_state);
3159 			}
3160 			goto free_resc;
3161 		}
3162 
3163 		checklist |= CL_FABRIC_HAS_RESOURCES;
3164 	} else if (pkt->pkt_state == FC_PKT_LS_RJT) {
3165 		lsrjt = (LS_RJT *) pkt->pkt_resp;
3166 		if (lsrjt->un.b.lsRjtRsnCodeExp != LSEXP_OUT_OF_RESOURCE) {
3167 			checklist |= CL_FABRIC_HAS_RESOURCES;
3168 		}
3169 	}
3170 
3171 	/*
3172 	 * Free up default RPIs and VPI
3173 	 */
3174 free_resc:
3175 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3176 		(void) emlxs_sli4_unreg_all_rpi_by_port(vport);
3177 	} else {
3178 		(void) emlxs_mb_unreg_rpi(vport, 0xffff, 0, 0, 0);
3179 	}
3180 	(void) emlxs_mb_unreg_vpi(vport);
3181 
3182 done:
3183 	if (ddi_copyout((void *)&checklist, (void *)dfc->buf1,
3184 	    sizeof (uint32_t), mode) != 0) {
3185 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3186 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
3187 		rval = DFC_COPYOUT_ERROR;
3188 	}
3189 
3190 	if (pkt) {
3191 		/* Free the pkt */
3192 		emlxs_pkt_free(pkt);
3193 	}
3194 
3195 	if (pkt1) {
3196 		/* Free the pkt */
3197 		emlxs_pkt_free(pkt1);
3198 	}
3199 
3200 	return (rval);
3201 
3202 } /* emlxs_dfc_npiv_test() */
3203 
3204 
3205 static int32_t
3206 emlxs_dfc_get_rev(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3207 {
3208 	emlxs_port_t	*port = &PPORT;
3209 	uint32_t	rev;
3210 
3211 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
3212 	    emlxs_dfc_xlate(dfc->cmd));
3213 
3214 	if (!dfc->buf1 || !dfc->buf1_size) {
3215 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3216 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3217 
3218 		return (DFC_ARG_NULL);
3219 	}
3220 
3221 	if (dfc->buf1_size < sizeof (uint32_t)) {
3222 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3223 		    "%s: Buffer1 too small. (size=%d)",
3224 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3225 
3226 		return (DFC_ARG_TOOSMALL);
3227 	}
3228 
3229 	rev = DFC_REV;
3230 
3231 	if (ddi_copyout((void *)&rev, (void *)dfc->buf1, sizeof (uint32_t),
3232 	    mode) != 0) {
3233 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3234 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
3235 
3236 		return (DFC_COPYOUT_ERROR);
3237 	}
3238 
3239 	return (0);
3240 
3241 } /* emlxs_dfc_get_rev() */
3242 
3243 
3244 static int32_t
3245 emlxs_dfc_get_hbainfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3246 {
3247 	emlxs_port_t	*port = &PPORT;
3248 	emlxs_vpd_t	*vpd = &VPD;
3249 	emlxs_config_t	*cfg = &CFG;
3250 	dfc_hbainfo_t	hbainfo;
3251 	NODELIST	*ndlp;
3252 	char		pathname[256];
3253 
3254 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
3255 	    emlxs_dfc_xlate(dfc->cmd));
3256 
3257 	if (!dfc->buf1 || !dfc->buf1_size) {
3258 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3259 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3260 
3261 		return (DFC_ARG_NULL);
3262 	}
3263 
3264 	if (dfc->buf1_size < sizeof (dfc_hbainfo_t)) {
3265 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3266 		    "%s: Buffer1 too small. (size=%d)",
3267 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3268 
3269 		return (DFC_ARG_TOOSMALL);
3270 	}
3271 
3272 	bzero((void *) &hbainfo, sizeof (dfc_hbainfo_t));
3273 
3274 	(void) strncpy(hbainfo.vpd_serial_num, vpd->serial_num,
3275 	    sizeof (hbainfo.vpd_serial_num));
3276 	(void) strncpy(hbainfo.vpd_part_num, vpd->part_num,
3277 	    sizeof (hbainfo.vpd_part_num));
3278 	(void) strncpy(hbainfo.vpd_port_num, vpd->port_num,
3279 	    sizeof (hbainfo.vpd_port_num));
3280 	(void) strncpy(hbainfo.vpd_eng_change, vpd->eng_change,
3281 	    sizeof (hbainfo.vpd_eng_change));
3282 	(void) strncpy(hbainfo.vpd_manufacturer, vpd->manufacturer,
3283 	    sizeof (hbainfo.vpd_manufacturer));
3284 	(void) strncpy(hbainfo.vpd_model, vpd->model,
3285 	    sizeof (hbainfo.vpd_model));
3286 	(void) strncpy(hbainfo.vpd_model_desc, vpd->model_desc,
3287 	    sizeof (hbainfo.vpd_model_desc));
3288 	(void) strncpy(hbainfo.vpd_prog_types, vpd->prog_types,
3289 	    sizeof (hbainfo.vpd_prog_types));
3290 	(void) strncpy(hbainfo.vpd_id, vpd->id, sizeof (hbainfo.vpd_id));
3291 
3292 	hbainfo.device_id = hba->model_info.device_id;
3293 	hbainfo.vendor_id =
3294 	    ddi_get32(hba->pci_acc_handle,
3295 	    (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)) & 0xffff;
3296 
3297 	hbainfo.ports = hba->num_of_ports;
3298 	hbainfo.port_index = vpd->port_index;
3299 
3300 	bcopy(&hba->wwnn, hbainfo.wwnn, sizeof (hbainfo.wwnn));
3301 	(void) strncpy(hbainfo.snn, port->snn, sizeof (hbainfo.snn));
3302 
3303 	bcopy(&hba->wwpn, hbainfo.wwpn, sizeof (hbainfo.wwpn));
3304 	(void) strncpy(hbainfo.spn, port->spn, sizeof (hbainfo.spn));
3305 
3306 	hbainfo.biuRev = vpd->biuRev;
3307 	hbainfo.smRev = vpd->smRev;
3308 	hbainfo.smFwRev = vpd->smFwRev;
3309 	hbainfo.endecRev = vpd->endecRev;
3310 	hbainfo.rBit = vpd->rBit;
3311 	hbainfo.fcphHigh = vpd->fcphHigh;
3312 	hbainfo.fcphLow = vpd->fcphLow;
3313 	hbainfo.feaLevelHigh = vpd->feaLevelHigh;
3314 	hbainfo.feaLevelLow = vpd->feaLevelLow;
3315 
3316 	hbainfo.kern_rev = vpd->postKernRev;
3317 	(void) strncpy(hbainfo.kern_name, vpd->postKernName,
3318 	    sizeof (hbainfo.kern_name));
3319 
3320 	hbainfo.stub_rev = vpd->opFwRev;
3321 	(void) strncpy(hbainfo.stub_name, vpd->opFwName,
3322 	    sizeof (hbainfo.stub_name));
3323 
3324 	hbainfo.sli1_rev = vpd->sli1FwRev;
3325 	(void) strncpy(hbainfo.sli1_name, vpd->sli1FwName,
3326 	    sizeof (hbainfo.sli1_name));
3327 
3328 	hbainfo.sli2_rev = vpd->sli2FwRev;
3329 	(void) strncpy(hbainfo.sli2_name, vpd->sli2FwName,
3330 	    sizeof (hbainfo.sli2_name));
3331 
3332 	hbainfo.sli3_rev = vpd->sli3FwRev;
3333 	(void) strncpy(hbainfo.sli3_name, vpd->sli3FwName,
3334 	    sizeof (hbainfo.sli3_name));
3335 
3336 	hbainfo.sli4_rev = vpd->sli4FwRev;
3337 	(void) strncpy(hbainfo.sli4_name, vpd->sli4FwName,
3338 	    sizeof (hbainfo.sli4_name));
3339 
3340 	hbainfo.sli_mode = hba->sli_mode;
3341 	hbainfo.vpi_max  = hba->vpi_max;
3342 	hbainfo.vpi_high = hba->vpi_high;
3343 	hbainfo.flags = 0;
3344 
3345 	/* Set support flags */
3346 	hbainfo.flags  = HBA_FLAG_DYN_WWN;
3347 	hbainfo.flags |= HBA_FLAG_NPIV;
3348 
3349 #ifdef DHCHAP_SUPPORT
3350 	hbainfo.flags |= HBA_FLAG_DHCHAP;
3351 
3352 	if (cfg[CFG_AUTH_E2E].current) {
3353 		hbainfo.flags |= HBA_FLAG_E2E_AUTH;
3354 	}
3355 #endif	/* DHCHAP_SUPPORT */
3356 
3357 #ifdef SAN_DIAG_SUPPORT
3358 	hbainfo.flags |= HBA_FLAG_SAN_DIAG;
3359 #endif	/* SAN_DIAG_SUPPORT */
3360 
3361 #ifdef SFCT_SUPPORT
3362 	hbainfo.flags |= HBA_FLAG_TARGET_MODE;
3363 	if (hba->tgt_mode) {
3364 		hbainfo.flags |= HBA_FLAG_TARGET_MODE_ENA;
3365 	}
3366 #endif /* SFCT_SUPPORT */
3367 
3368 	hbainfo.flags |= HBA_FLAG_FCOE;
3369 
3370 	if (! (hba->model_info.flags & EMLXS_FCOE_SUPPORTED)) {
3371 		hbainfo.flags |= HBA_FLAG_PERSISTLINK;
3372 	}
3373 
3374 	(void) strncpy(hbainfo.fcode_version, vpd->fcode_version,
3375 	    sizeof (hbainfo.fcode_version));
3376 	(void) strncpy(hbainfo.boot_version, vpd->boot_version,
3377 	    sizeof (hbainfo.boot_version));
3378 	(void) strncpy(hbainfo.fw_version, vpd->fw_version,
3379 	    sizeof (hbainfo.fw_version));
3380 	(void) strncpy(hbainfo.drv_label, emlxs_label,
3381 	    sizeof (hbainfo.drv_label));
3382 	(void) strncpy(hbainfo.drv_module, emlxs_name,
3383 	    sizeof (hbainfo.drv_module));
3384 	(void) strncpy(hbainfo.drv_name, DRIVER_NAME,
3385 	    sizeof (hbainfo.drv_name));
3386 	(void) strncpy(hbainfo.drv_version, emlxs_version,
3387 	    sizeof (hbainfo.drv_version));
3388 	(void) strncpy(hbainfo.drv_revision, emlxs_revision,
3389 	    sizeof (hbainfo.drv_revision));
3390 	(void) strncpy(hbainfo.hostname, (char *)utsname.nodename,
3391 	    sizeof (hbainfo.hostname));
3392 
3393 	(void) ddi_pathname(hba->dip, pathname);
3394 	(void) sprintf(hbainfo.os_devname, "/devices%s", pathname);
3395 
3396 	if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
3397 		hbainfo.flags |= HBA_FLAG_OFFLINE;
3398 	}
3399 
3400 	hbainfo.drv_instance = hba->ddiinst;
3401 	hbainfo.port_id = port->did;
3402 	hbainfo.port_type = HBA_PORTTYPE_UNKNOWN;
3403 
3404 #ifdef MENLO_SUPPORT
3405 	if (hba->flag & FC_MENLO_MODE) {
3406 		hbainfo.topology  = LNK_MENLO_MAINTENANCE;
3407 	} else
3408 #endif /* MENLO_SUPPORT */
3409 
3410 	if (hba->state >= FC_LINK_UP) {
3411 		ndlp = emlxs_node_find_did(port, FABRIC_DID);
3412 
3413 		if (hba->topology == TOPOLOGY_LOOP) {
3414 			if (ndlp) {
3415 				hbainfo.port_type = HBA_PORTTYPE_NLPORT;
3416 				hbainfo.topology = LNK_PUBLIC_LOOP;
3417 			} else {
3418 				hbainfo.port_type = HBA_PORTTYPE_LPORT;
3419 				hbainfo.topology = LNK_LOOP;
3420 			}
3421 
3422 			hbainfo.alpa_count = port->alpa_map[0];
3423 			bcopy((void *)&port->alpa_map[1], hbainfo.alpa_map,
3424 			    hbainfo.alpa_count);
3425 		} else {
3426 			if (ndlp) {
3427 				hbainfo.port_type = HBA_PORTTYPE_NPORT;
3428 				hbainfo.topology = LNK_FABRIC;
3429 			} else {
3430 				hbainfo.port_type = HBA_PORTTYPE_PTP;
3431 				hbainfo.topology = LNK_PT2PT;
3432 			}
3433 		}
3434 
3435 		if (ndlp) {
3436 			bcopy(&ndlp->nlp_nodename, hbainfo.fabric_wwnn,
3437 			    sizeof (hbainfo.fabric_wwnn));
3438 			bcopy(&ndlp->nlp_portname, hbainfo.fabric_wwpn,
3439 			    sizeof (hbainfo.fabric_wwpn));
3440 		}
3441 
3442 		if (hba->linkspeed == LA_2GHZ_LINK) {
3443 			hbainfo.port_speed = HBA_PORTSPEED_2GBIT;
3444 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
3445 			hbainfo.port_speed = HBA_PORTSPEED_4GBIT;
3446 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
3447 			hbainfo.port_speed = HBA_PORTSPEED_8GBIT;
3448 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
3449 			hbainfo.port_speed = HBA_PORTSPEED_10GBIT;
3450 		} else {
3451 			hbainfo.port_speed = HBA_PORTSPEED_1GBIT;
3452 		}
3453 
3454 		hbainfo.node_count = port->node_count;
3455 	}
3456 
3457 	hbainfo.hard_alpa = cfg[CFG_ASSIGN_ALPA].current;
3458 	hbainfo.supported_cos = LE_SWAP32((FC_NS_CLASS3 | FC_NS_CLASS2));
3459 
3460 	hbainfo.supported_types[0] = LE_SWAP32(0x00000120);
3461 	hbainfo.supported_types[1] = LE_SWAP32(0x00000001);
3462 
3463 	hbainfo.active_types[0] = LE_SWAP32(0x00000120);
3464 	hbainfo.active_types[1] = LE_SWAP32(0x00000001);
3465 
3466 	if (!cfg[CFG_NETWORK_ON].current) {
3467 		hbainfo.active_types[0] &= ~(LE_SWAP32(0x00000020));
3468 	}
3469 
3470 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
3471 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_10GBIT;
3472 	}
3473 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
3474 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_8GBIT;
3475 	}
3476 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
3477 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_4GBIT;
3478 	}
3479 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
3480 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_2GBIT;
3481 	}
3482 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
3483 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_1GBIT;
3484 	}
3485 
3486 	hbainfo.max_frame_size = FF_FRAME_SIZE;
3487 
3488 	if (hba->bus_type == SBUS_FC) {
3489 		hbainfo.flags |= HBA_FLAG_SBUS;
3490 	}
3491 
3492 	if (hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE)) {
3493 		hbainfo.flags |= HBA_FLAG_OFFLINE;
3494 		hbainfo.port_state = HBA_PORTSTATE_UNKNOWN;
3495 	} else if (hba->flag & FC_ONLINE_MODE) {
3496 		if (hba->flag & FC_LOOPBACK_MODE) {
3497 			hbainfo.port_state = HBA_PORTSTATE_LOOPBACK;
3498 		} else if (hba->state <= FC_LINK_DOWN) {
3499 			hbainfo.port_state = HBA_PORTSTATE_LINKDOWN;
3500 		}
3501 #ifdef MENLO_SUPPORT
3502 		else if (hba->flag & FC_MENLO_MODE) {
3503 			hbainfo.port_state = HBA_PORTSTATE_LINKDOWN;
3504 		}
3505 #endif /* MENLO_SUPPORT */
3506 		else {
3507 			hbainfo.port_state = HBA_PORTSTATE_ONLINE;
3508 		}
3509 	} else {
3510 		hbainfo.flags |= HBA_FLAG_OFFLINE;
3511 
3512 		if (hba->state == FC_ERROR) {
3513 			hbainfo.port_state = HBA_PORTSTATE_ERROR;
3514 		} else {
3515 			hbainfo.port_state = HBA_PORTSTATE_OFFLINE;
3516 		}
3517 	}
3518 
3519 	hbainfo.pci_function_number = hba->pci_function_number;
3520 	hbainfo.pci_device_number = hba->pci_device_number;
3521 	hbainfo.pci_bus_number = hba->pci_bus_number;
3522 
3523 	if (ddi_copyout((void *)&hbainfo, (void *)dfc->buf1,
3524 	    sizeof (dfc_hbainfo_t), mode) != 0) {
3525 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3526 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
3527 
3528 		return (DFC_COPYOUT_ERROR);
3529 	}
3530 
3531 #ifdef FMA_SUPPORT
3532 	/* Access handle validation */
3533 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
3534 	    != DDI_FM_OK) {
3535 		EMLXS_MSGF(EMLXS_CONTEXT,
3536 		    &emlxs_invalid_access_handle_msg, NULL);
3537 		return (DFC_DRV_ERROR);
3538 	}
3539 #endif  /* FMA_SUPPORT */
3540 
3541 	return (0);
3542 
3543 } /* emlxs_dfc_get_hbainfo() */
3544 
3545 
3546 
3547 static int32_t
3548 emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3549 {
3550 	emlxs_port_t	*port = &PPORT;
3551 	dfc_hbastats_t	stats;
3552 	MAILBOX		*mb = NULL;
3553 	MAILBOXQ	*mbq = NULL;
3554 	uint32_t	rval = 0;
3555 
3556 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
3557 	    emlxs_dfc_xlate(dfc->cmd));
3558 
3559 	if (!dfc->buf1 || !dfc->buf1_size) {
3560 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3561 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3562 
3563 		return (DFC_ARG_NULL);
3564 	}
3565 
3566 	if (dfc->buf1_size < sizeof (dfc_hbastats_t)) {
3567 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3568 		    "%s: Buffer1 too small. (size=%d)",
3569 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3570 
3571 		return (DFC_ARG_TOOSMALL);
3572 	}
3573 
3574 	mbq =
3575 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
3576 
3577 	mb = (MAILBOX *)mbq;
3578 
3579 	emlxs_mb_read_status(hba, mbq);
3580 
3581 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
3582 
3583 	if (rval == MBX_TIMEOUT) {
3584 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3585 		    "%s: Mailbox timed out. cmd=%x",
3586 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3587 
3588 		rval = DFC_TIMEOUT;
3589 		goto done;
3590 	}
3591 
3592 	if (rval) {
3593 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3594 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
3595 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
3596 
3597 		rval = DFC_IO_ERROR;
3598 		goto done;
3599 	}
3600 
3601 	bzero((void *) &stats, sizeof (dfc_hbastats_t));
3602 
3603 	stats.tx_frame_cnt = mb->un.varRdStatus.xmitFrameCnt;
3604 	stats.rx_frame_cnt = mb->un.varRdStatus.rcvFrameCnt;
3605 	stats.tx_kbyte_cnt = mb->un.varRdStatus.xmitByteCnt;
3606 	stats.rx_kbyte_cnt = mb->un.varRdStatus.rcvByteCnt;
3607 	stats.tx_seq_cnt = mb->un.varRdStatus.xmitSeqCnt;
3608 	stats.rx_seq_cnt = mb->un.varRdStatus.rcvSeqCnt;
3609 	stats.orig_exch_cnt = mb->un.varRdStatus.totalOrigExchanges;
3610 	stats.resp_exch_cnt = mb->un.varRdStatus.totalRespExchanges;
3611 	stats.pbsy_cnt = mb->un.varRdStatus.rcvPbsyCnt;
3612 	stats.fbsy_cnt = mb->un.varRdStatus.rcvFbsyCnt;
3613 
3614 	emlxs_mb_read_lnk_stat(hba, mbq);
3615 
3616 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
3617 
3618 	if (rval == MBX_TIMEOUT) {
3619 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3620 		    "%s: Mailbox timed out. cmd=%x",
3621 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3622 
3623 		rval = DFC_TIMEOUT;
3624 		goto done;
3625 	}
3626 
3627 	if (rval) {
3628 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3629 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
3630 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
3631 
3632 		rval = DFC_IO_ERROR;
3633 		goto done;
3634 	}
3635 
3636 	stats.link_failure_cnt = mb->un.varRdLnk.linkFailureCnt;
3637 	stats.loss_sync_cnt = mb->un.varRdLnk.lossSyncCnt;
3638 	stats.loss_signal_cnt = mb->un.varRdLnk.lossSignalCnt;
3639 	stats.seq_error_cnt = mb->un.varRdLnk.primSeqErrCnt;
3640 	stats.inval_tx_word_cnt = mb->un.varRdLnk.invalidXmitWord;
3641 	stats.crc_error_cnt = mb->un.varRdLnk.crcCnt;
3642 	stats.seq_timeout_cnt = mb->un.varRdLnk.primSeqTimeout;
3643 	stats.elastic_overrun_cnt = mb->un.varRdLnk.elasticOverrun;
3644 	stats.arb_timeout_cnt = mb->un.varRdLnk.arbTimeout;
3645 	stats.rx_buf_credit = mb->un.varRdLnk.rxBufCredit;
3646 	stats.rx_buf_cnt = mb->un.varRdLnk.rxBufCreditCur;
3647 	stats.tx_buf_credit = mb->un.varRdLnk.txBufCredit;
3648 	stats.tx_buf_cnt = mb->un.varRdLnk.txBufCreditCur;
3649 	stats.EOFa_cnt = mb->un.varRdLnk.EOFaCnt;
3650 	stats.EOFdti_cnt = mb->un.varRdLnk.EOFdtiCnt;
3651 	stats.EOFni_cnt = mb->un.varRdLnk.EOFniCnt;
3652 	stats.SOFf_cnt = mb->un.varRdLnk.SOFfCnt;
3653 	stats.link_event_tag = hba->link_event_tag;
3654 	stats.last_reset_time = hba->timer_tics - hba->stats.ResetTime;
3655 	stats.port_type = HBA_PORTTYPE_UNKNOWN;
3656 
3657 #ifdef MENLO_SUPPORT
3658 	if (hba->flag & FC_MENLO_MODE) {
3659 		stats.topology = LNK_MENLO_MAINTENANCE;
3660 	} else
3661 #endif /* MENLO_SUPPORT */
3662 
3663 	if (hba->state >= FC_LINK_UP) {
3664 		if (hba->topology == TOPOLOGY_LOOP) {
3665 			if (hba->flag & FC_FABRIC_ATTACHED) {
3666 				stats.port_type = HBA_PORTTYPE_NLPORT;
3667 				stats.topology = LNK_PUBLIC_LOOP;
3668 			} else {
3669 				stats.port_type = HBA_PORTTYPE_LPORT;
3670 				stats.topology = LNK_LOOP;
3671 			}
3672 		} else {
3673 			if (hba->flag & FC_FABRIC_ATTACHED) {
3674 				stats.port_type = HBA_PORTTYPE_NPORT;
3675 				stats.topology = LNK_FABRIC;
3676 			} else {
3677 				stats.port_type = HBA_PORTTYPE_PTP;
3678 				stats.topology = LNK_PT2PT;
3679 			}
3680 		}
3681 
3682 		if (hba->linkspeed == LA_2GHZ_LINK) {
3683 			stats.link_speed = HBA_PORTSPEED_2GBIT;
3684 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
3685 			stats.link_speed = HBA_PORTSPEED_4GBIT;
3686 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
3687 			stats.link_speed = HBA_PORTSPEED_8GBIT;
3688 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
3689 			stats.link_speed = HBA_PORTSPEED_10GBIT;
3690 		} else {
3691 			stats.link_speed = HBA_PORTSPEED_1GBIT;
3692 		}
3693 	}
3694 
3695 	if (ddi_copyout((void *)&stats, (void *)dfc->buf1,
3696 	    sizeof (dfc_hbastats_t), mode) != 0) {
3697 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3698 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
3699 
3700 		return (DFC_COPYOUT_ERROR);
3701 	}
3702 
3703 done:
3704 
3705 	/* Free allocated mbox memory */
3706 	if (mbq) {
3707 		kmem_free(mbq, sizeof (MAILBOXQ));
3708 	}
3709 
3710 	return (rval);
3711 
3712 } /* emlxs_dfc_get_hbastats() */
3713 
3714 
3715 
3716 static int32_t
3717 emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3718 {
3719 	emlxs_port_t	*port = &PPORT;
3720 	dfc_drvstats_t	stats;
3721 	uint32_t	rval = 0;
3722 
3723 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
3724 	    emlxs_dfc_xlate(dfc->cmd));
3725 
3726 	if (!dfc->buf1 || !dfc->buf1_size) {
3727 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3728 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
3729 
3730 		return (DFC_ARG_NULL);
3731 	}
3732 
3733 	bzero((void *) &stats, sizeof (dfc_drvstats_t));
3734 
3735 	stats.LinkUp = hba->stats.LinkUp;
3736 	stats.LinkDown = hba->stats.LinkDown;
3737 	stats.LinkEvent = hba->stats.LinkEvent;
3738 	stats.LinkMultiEvent = hba->stats.LinkMultiEvent;
3739 
3740 	stats.MboxIssued = hba->stats.MboxIssued;
3741 	stats.MboxCompleted = hba->stats.MboxCompleted;
3742 	stats.MboxGood = hba->stats.MboxGood;
3743 	stats.MboxError = hba->stats.MboxError;
3744 	stats.MboxBusy = hba->stats.MboxBusy;
3745 	stats.MboxInvalid = hba->stats.MboxInvalid;
3746 
3747 	stats.IocbIssued[0] = hba->stats.IocbIssued[0];
3748 	stats.IocbIssued[1] = hba->stats.IocbIssued[1];
3749 	stats.IocbIssued[2] = hba->stats.IocbIssued[2];
3750 	stats.IocbIssued[3] = hba->stats.IocbIssued[3];
3751 	stats.IocbReceived[0] = hba->stats.IocbReceived[0];
3752 	stats.IocbReceived[1] = hba->stats.IocbReceived[1];
3753 	stats.IocbReceived[2] = hba->stats.IocbReceived[2];
3754 	stats.IocbReceived[3] = hba->stats.IocbReceived[3];
3755 	stats.IocbTxPut[0] = hba->stats.IocbTxPut[0];
3756 	stats.IocbTxPut[1] = hba->stats.IocbTxPut[1];
3757 	stats.IocbTxPut[2] = hba->stats.IocbTxPut[2];
3758 	stats.IocbTxPut[3] = hba->stats.IocbTxPut[3];
3759 	stats.IocbTxGet[0] = hba->stats.IocbTxGet[0];
3760 	stats.IocbTxGet[1] = hba->stats.IocbTxGet[1];
3761 	stats.IocbTxGet[2] = hba->stats.IocbTxGet[2];
3762 	stats.IocbTxGet[3] = hba->stats.IocbTxGet[3];
3763 	stats.IocbRingFull[0] = hba->stats.IocbRingFull[0];
3764 	stats.IocbRingFull[1] = hba->stats.IocbRingFull[1];
3765 	stats.IocbRingFull[2] = hba->stats.IocbRingFull[2];
3766 	stats.IocbRingFull[3] = hba->stats.IocbRingFull[3];
3767 
3768 	stats.IntrEvent[0] = hba->stats.IntrEvent[0];
3769 	stats.IntrEvent[1] = hba->stats.IntrEvent[1];
3770 	stats.IntrEvent[2] = hba->stats.IntrEvent[2];
3771 	stats.IntrEvent[3] = hba->stats.IntrEvent[3];
3772 	stats.IntrEvent[4] = hba->stats.IntrEvent[4];
3773 	stats.IntrEvent[5] = hba->stats.IntrEvent[5];
3774 	stats.IntrEvent[6] = hba->stats.IntrEvent[6];
3775 	stats.IntrEvent[7] = hba->stats.IntrEvent[7];
3776 
3777 	stats.FcpIssued = hba->stats.FcpIssued;
3778 	stats.FcpCompleted = hba->stats.FcpCompleted;
3779 	stats.FcpGood = hba->stats.FcpGood;
3780 	stats.FcpError = hba->stats.FcpError;
3781 
3782 	stats.FcpEvent = hba->stats.FcpEvent;
3783 	stats.FcpStray = hba->stats.FcpStray;
3784 
3785 	stats.ElsEvent = hba->stats.ElsEvent;
3786 	stats.ElsStray = hba->stats.ElsStray;
3787 
3788 	stats.ElsCmdIssued = hba->stats.ElsCmdIssued;
3789 	stats.ElsCmdCompleted = hba->stats.ElsCmdCompleted;
3790 	stats.ElsCmdGood = hba->stats.ElsCmdGood;
3791 	stats.ElsCmdError = hba->stats.ElsCmdError;
3792 
3793 	stats.ElsRspIssued = hba->stats.ElsRspIssued;
3794 	stats.ElsRspCompleted = hba->stats.ElsRspCompleted;
3795 
3796 	stats.ElsRcvEvent = hba->stats.ElsRcvEvent;
3797 	stats.ElsRcvError = hba->stats.ElsRcvError;
3798 	stats.ElsRcvDropped = hba->stats.ElsRcvDropped;
3799 	stats.ElsCmdReceived = hba->stats.ElsCmdReceived;
3800 	stats.ElsRscnReceived = hba->stats.ElsRscnReceived;
3801 	stats.ElsPlogiReceived = hba->stats.ElsPlogiReceived;
3802 	stats.ElsPrliReceived = hba->stats.ElsPrliReceived;
3803 	stats.ElsPrloReceived = hba->stats.ElsPrloReceived;
3804 	stats.ElsLogoReceived = hba->stats.ElsLogoReceived;
3805 	stats.ElsAdiscReceived = hba->stats.ElsAdiscReceived;
3806 	stats.ElsGenReceived = hba->stats.ElsGenReceived;
3807 
3808 	stats.CtEvent = hba->stats.CtEvent;
3809 	stats.CtStray = hba->stats.CtStray;
3810 
3811 	stats.CtCmdIssued = hba->stats.CtCmdIssued;
3812 	stats.CtCmdCompleted = hba->stats.CtCmdCompleted;
3813 	stats.CtCmdGood = hba->stats.CtCmdGood;
3814 	stats.CtCmdError = hba->stats.CtCmdError;
3815 
3816 	stats.CtRspIssued = hba->stats.CtRspIssued;
3817 	stats.CtRspCompleted = hba->stats.CtRspCompleted;
3818 
3819 	stats.CtRcvEvent = hba->stats.CtRcvEvent;
3820 	stats.CtRcvError = hba->stats.CtRcvError;
3821 	stats.CtRcvDropped = hba->stats.CtRcvDropped;
3822 	stats.CtCmdReceived = hba->stats.CtCmdReceived;
3823 
3824 	stats.IpEvent = hba->stats.IpEvent;
3825 	stats.IpStray = hba->stats.IpStray;
3826 
3827 	stats.IpSeqIssued = hba->stats.IpSeqIssued;
3828 	stats.IpSeqCompleted = hba->stats.IpSeqCompleted;
3829 	stats.IpSeqGood = hba->stats.IpSeqGood;
3830 	stats.IpSeqError = hba->stats.IpSeqError;
3831 
3832 	stats.IpBcastIssued = hba->stats.IpBcastIssued;
3833 	stats.IpBcastCompleted = hba->stats.IpBcastCompleted;
3834 	stats.IpBcastGood = hba->stats.IpBcastGood;
3835 	stats.IpBcastError = hba->stats.IpBcastError;
3836 
3837 	stats.IpRcvEvent = hba->stats.IpRcvEvent;
3838 	stats.IpDropped = hba->stats.IpDropped;
3839 	stats.IpSeqReceived = hba->stats.IpSeqReceived;
3840 	stats.IpBcastReceived = hba->stats.IpBcastReceived;
3841 
3842 	stats.IpUbPosted = hba->stats.IpUbPosted;
3843 	stats.ElsUbPosted = hba->stats.ElsUbPosted;
3844 	stats.CtUbPosted = hba->stats.CtUbPosted;
3845 
3846 #if (DFC_REV >= 2)
3847 	stats.IocbThrottled   = hba->stats.IocbThrottled;
3848 	stats.ElsAuthReceived = hba->stats.ElsAuthReceived;
3849 #endif
3850 
3851 	if (ddi_copyout((void *)&stats, (void *)dfc->buf1, dfc->buf1_size,
3852 	    mode) != 0) {
3853 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3854 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
3855 
3856 		return (DFC_COPYOUT_ERROR);
3857 	}
3858 
3859 	return (rval);
3860 
3861 } /* emlxs_dfc_get_drvstats() */
3862 
3863 
3864 extern uint32_t
3865 emlxs_set_hba_mode(emlxs_hba_t *hba, uint32_t mode)
3866 {
3867 	emlxs_port_t	*port = &PPORT;
3868 	uint32_t	i;
3869 
3870 	mutex_enter(&EMLXS_PORT_LOCK);
3871 
3872 	/* Wait if adapter is in transition */
3873 	i = 0;
3874 	while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
3875 		if (i++ > 30) {
3876 			break;
3877 		}
3878 
3879 		mutex_exit(&EMLXS_PORT_LOCK);
3880 		delay(drv_usectohz(1000000));
3881 		mutex_enter(&EMLXS_PORT_LOCK);
3882 	}
3883 
3884 	switch (mode) {
3885 	case DDI_SHOW:
3886 		break;
3887 
3888 	case DDI_ONDI:
3889 		if (hba->flag & FC_OFFLINE_MODE) {
3890 			mutex_exit(&EMLXS_PORT_LOCK);
3891 			(void) emlxs_online(hba);
3892 			mutex_enter(&EMLXS_PORT_LOCK);
3893 		}
3894 		break;
3895 
3896 
3897 		/* Killed + Restart state */
3898 	case DDI_OFFDI:
3899 		if (hba->flag & FC_ONLINE_MODE) {
3900 			mutex_exit(&EMLXS_PORT_LOCK);
3901 
3902 			(void) emlxs_offline(hba);
3903 
3904 			/* Reset with restart */
3905 			EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
3906 
3907 			mutex_enter(&EMLXS_PORT_LOCK);
3908 		} else if (hba->state < FC_INIT_START) {
3909 			mutex_exit(&EMLXS_PORT_LOCK);
3910 
3911 			/* Reset with restart */
3912 			EMLXS_SLI_HBA_RESET(hba, 1, 1, 0);
3913 
3914 			mutex_enter(&EMLXS_PORT_LOCK);
3915 		}
3916 
3917 		break;
3918 
3919 		/* Killed + Reset state */
3920 	case DDI_WARMDI:
3921 		if (hba->flag & FC_ONLINE_MODE) {
3922 			mutex_exit(&EMLXS_PORT_LOCK);
3923 
3924 			(void) emlxs_offline(hba);
3925 
3926 			/* Reset with no restart */
3927 			EMLXS_SLI_HBA_RESET(hba, 0, 0, 0);
3928 
3929 			mutex_enter(&EMLXS_PORT_LOCK);
3930 		} else if (hba->state != FC_WARM_START) {
3931 			mutex_exit(&EMLXS_PORT_LOCK);
3932 
3933 			/* Reset with no restart */
3934 			EMLXS_SLI_HBA_RESET(hba, 0, 0, 0);
3935 
3936 			mutex_enter(&EMLXS_PORT_LOCK);
3937 		}
3938 
3939 		break;
3940 
3941 		/* Killed */
3942 	case DDI_DIAGDI:
3943 		if (hba->flag & FC_ONLINE_MODE) {
3944 			mutex_exit(&EMLXS_PORT_LOCK);
3945 
3946 			(void) emlxs_offline(hba);
3947 
3948 			mutex_enter(&EMLXS_PORT_LOCK);
3949 		} else if (hba->state != FC_KILLED) {
3950 			mutex_exit(&EMLXS_PORT_LOCK);
3951 
3952 			EMLXS_SLI_HBA_KILL(hba);
3953 
3954 			mutex_enter(&EMLXS_PORT_LOCK);
3955 		}
3956 
3957 		break;
3958 
3959 	default:
3960 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3961 		    "emlxs_set_hba_mode: Invalid mode. mode%x", mode);
3962 	}
3963 
3964 	/* Wait if adapter is in transition */
3965 	i = 0;
3966 	while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
3967 		if (i++ > 30) {
3968 			break;
3969 		}
3970 
3971 		mutex_exit(&EMLXS_PORT_LOCK);
3972 		delay(drv_usectohz(1000000));
3973 		mutex_enter(&EMLXS_PORT_LOCK);
3974 	}
3975 
3976 	/* Return current state */
3977 	if (hba->flag & FC_ONLINE_MODE) {
3978 		mode = DDI_ONDI;
3979 	} else if (hba->state == FC_KILLED) {
3980 		mode = DDI_DIAGDI;
3981 	} else if (hba->state == FC_WARM_START) {
3982 		mode = DDI_WARMDI;
3983 	} else {
3984 		mode = DDI_OFFDI;
3985 	}
3986 
3987 	mutex_exit(&EMLXS_PORT_LOCK);
3988 
3989 	return (mode);
3990 
3991 } /* emlxs_set_hba_mode() */
3992 
3993 
3994 static int32_t
3995 emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3996 {
3997 	emlxs_port_t	*port = &PPORT;
3998 	int32_t		rval = 0;
3999 	int32_t		flag;
4000 
4001 	if (!dfc->buf1 || !dfc->buf1_size) {
4002 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4003 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4004 
4005 		return (DFC_ARG_NULL);
4006 	}
4007 
4008 	if (dfc->buf1_size < sizeof (uint32_t)) {
4009 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4010 		    "%s: Buffer1 too small. (size=%d)",
4011 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
4012 
4013 		return (DFC_ARG_TOOSMALL);
4014 	}
4015 
4016 	flag = emlxs_set_hba_mode(hba, dfc->flag);
4017 
4018 	if (ddi_copyout((void *)&flag, (void *)dfc->buf1, sizeof (uint32_t),
4019 	    mode) != 0) {
4020 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4021 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
4022 
4023 		return (DFC_COPYOUT_ERROR);
4024 	}
4025 
4026 	return (rval);
4027 
4028 } /* emlxs_dfc_set_diag() */
4029 
4030 
4031 
4032 static int32_t
4033 emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4034 {
4035 	emlxs_port_t	*port  = &PPORT;
4036 	MAILBOX		*mb    = NULL;
4037 	MAILBOXQ	*mbq   = NULL;
4038 	uint32_t	size  = 0;
4039 	MATCHMAP	*rx_mp = NULL;
4040 	MATCHMAP	*tx_mp = NULL;
4041 	uintptr_t	lptr;
4042 	int32_t		rval  = 0;
4043 	int32_t		mbxstatus = 0;
4044 	NODELIST	*ndlp;
4045 	uint32_t	did;
4046 	uint32_t	extsize = 0;
4047 	uint8_t		*extbuf  = NULL;
4048 
4049 	if (!dfc->buf1 || !dfc->buf1_size) {
4050 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4051 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4052 
4053 		return (DFC_ARG_NULL);
4054 	}
4055 
4056 	if (!dfc->buf2 || !dfc->buf2_size) {
4057 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4058 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
4059 
4060 		return (DFC_ARG_NULL);
4061 	}
4062 
4063 	if (dfc->buf1_size > MAILBOX_CMD_BSIZE) {
4064 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4065 		    "%s: Buffer1 too large. (size=%d)",
4066 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
4067 
4068 		return (DFC_ARG_TOOBIG);
4069 	}
4070 #ifdef MBOX_EXT_SUPPORT
4071 	if (dfc->buf3_size || dfc->buf4_size) {
4072 		if (dfc->buf3_size && !dfc->buf3) {
4073 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4074 			    "%s: Null buffer3 found.",
4075 			    emlxs_dfc_xlate(dfc->cmd));
4076 
4077 			return (DFC_ARG_NULL);
4078 		}
4079 
4080 		if (dfc->buf3_size > MBOX_EXTENSION_SIZE) {
4081 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4082 			    "%s: buffer3 too large. (size=%d)",
4083 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
4084 
4085 			return (DFC_ARG_TOOBIG);
4086 		}
4087 
4088 		if (dfc->buf4_size && !dfc->buf4) {
4089 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4090 			    "%s: Null buffer4 found.",
4091 			    emlxs_dfc_xlate(dfc->cmd));
4092 
4093 			return (DFC_ARG_NULL);
4094 		}
4095 
4096 		if (dfc->buf4_size > MBOX_EXTENSION_SIZE) {
4097 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4098 			    "%s: buffer4 too large. (size=%d)",
4099 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
4100 
4101 			return (DFC_ARG_TOOBIG);
4102 		}
4103 
4104 		extsize =
4105 		    (dfc->buf3_size >
4106 		    dfc->buf4_size) ? dfc->buf3_size : dfc->buf4_size;
4107 		extbuf =
4108 		    (uint8_t *)kmem_zalloc(extsize, KM_SLEEP);
4109 
4110 		if (dfc->buf3_size) {
4111 			if (ddi_copyin((void *)dfc->buf3, (void *)extbuf,
4112 			    dfc->buf3_size, mode) != 0) {
4113 				EMLXS_MSGF(EMLXS_CONTEXT,
4114 				    &emlxs_dfc_error_msg,
4115 				    "%s: ddi_copyin mbox extension data "
4116 				    "failed.", emlxs_dfc_xlate(dfc->cmd));
4117 
4118 				rval = DFC_COPYIN_ERROR;
4119 				goto done;
4120 			}
4121 		}
4122 	}
4123 #endif /* MBOX_EXT_SUPPORT */
4124 
4125 	mbq =
4126 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
4127 
4128 	mb = (MAILBOX *) mbq;
4129 
4130 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
4131 
4132 	if (ddi_copyin((void *)dfc->buf1, (void *)mb, dfc->buf1_size,
4133 	    mode) != 0) {
4134 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4135 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
4136 
4137 		rval = DFC_COPYIN_ERROR;
4138 		goto done;
4139 	}
4140 #ifdef _LP64
4141 	if ((mb->mbxCommand == MBX_READ_SPARM) ||
4142 	    (mb->mbxCommand == MBX_READ_RPI) ||
4143 	    (mb->mbxCommand == MBX_REG_LOGIN) ||
4144 	    (mb->mbxCommand == MBX_READ_LA) ||
4145 	    (mb->mbxCommand == MBX_RUN_BIU_DIAG)) {
4146 
4147 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4148 		    "%s: Invalid mailbox command. Must use 64bit version. "
4149 		    "cmd=%x", emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4150 
4151 		/* Must use 64 bit versions of these mbox cmds */
4152 		rval = DFC_ARG_INVALID;
4153 		goto done;
4154 	}
4155 #endif
4156 
4157 	lptr = 0;
4158 	size = 0;
4159 	switch (mb->mbxCommand) {
4160 	/* Offline only */
4161 	case MBX_CONFIG_LINK:	/* 0x07 */
4162 	case MBX_PART_SLIM:	    /* 0x08 */
4163 	case MBX_CONFIG_RING:	/* 0x09 */
4164 	case MBX_DUMP_CONTEXT:	/* 0x18 */
4165 	case MBX_RUN_DIAGS:	    /* 0x19 */
4166 	case MBX_RESTART:	    /* 0x1A */
4167 	case MBX_SET_MASK:	    /* 0x20 */
4168 	case MBX_FLASH_WR_ULA:	/* 0x98 */
4169 		if (!(hba->flag & FC_OFFLINE_MODE)) {
4170 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4171 			    "%s: Adapter not offline. cmd=%x",
4172 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4173 
4174 			rval = DFC_ONLINE_ERROR;
4175 			goto done;
4176 		}
4177 		break;
4178 
4179 	/* Online / Offline */
4180 	case MBX_UNREG_LOGIN:	/* 0x14 */
4181 		ndlp = emlxs_node_find_rpi(port, mb->un.varUnregLogin.rpi);
4182 
4183 		if (ndlp) {
4184 			did = ndlp->nlp_DID;
4185 
4186 			/* remove it */
4187 			emlxs_node_rm(port, ndlp);
4188 
4189 			/*
4190 			 * If we just unregistered the host node then
4191 			 * clear the host DID
4192 			 */
4193 			if (did == port->did) {
4194 				port->did = 0;
4195 			}
4196 		} else {
4197 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4198 			    "%s: Node not found. cmd=%x rpi=%x",
4199 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand,
4200 			    mb->un.varUnregLogin.rpi);
4201 
4202 			/* Node does not exist */
4203 			rval = DFC_ARG_INVALID;
4204 			goto done;
4205 		}
4206 
4207 		/* Send it */
4208 		break;
4209 
4210 	case MBX_UNREG_D_ID:	/* 0x23 */
4211 
4212 		did = mb->un.varRegLogin.did;
4213 
4214 		if (did == 0) {
4215 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4216 			    "%s: Node not found. cmd=%x did=%x",
4217 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
4218 
4219 			rval = DFC_ARG_INVALID;
4220 			goto done;
4221 		}
4222 
4223 		if (did == 0xffffffff) {
4224 			emlxs_node_destroy_all(port);
4225 			break;
4226 		}
4227 
4228 		/* Check for base node */
4229 		if (did == BCAST_DID) {
4230 			/* just flush base node */
4231 			(void) emlxs_tx_node_flush(port, &port->node_base,
4232 			    0, 0, 0);
4233 			(void) emlxs_chipq_node_flush(port, 0, &port->node_base,
4234 			    0);
4235 
4236 			/* Return now */
4237 			rval = 0;
4238 			goto done;
4239 		}
4240 
4241 		/* Make sure the node does already exist */
4242 		ndlp = emlxs_node_find_did(port, did);
4243 
4244 		if (ndlp) {
4245 			/* remove it */
4246 			emlxs_node_rm(port, ndlp);
4247 
4248 			/*
4249 			 * If we just unregistered the host node then
4250 			 * clear the host DID
4251 			 */
4252 			if (did == port->did) {
4253 				port->did = 0;
4254 			}
4255 		} else {
4256 
4257 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4258 			    "%s: Node not found. cmd=%x did=%x",
4259 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
4260 
4261 			/* Node does not exist */
4262 			rval = DFC_ARG_INVALID;
4263 			goto done;
4264 		}
4265 
4266 		/* Send it */
4267 		break;
4268 
4269 	/* Online / Offline - with DMA */
4270 	case MBX_READ_EVENT_LOG:	/* 0x38 */
4271 		lptr =
4272 		    (uintptr_t)PADDR(mb->un.varRdEvtLog.un.sp64.addrHigh,
4273 		    mb->un.varRdEvtLog.un.sp64.addrLow);
4274 		size = (int)mb->un.varRdEvtLog.un.sp64.tus.f.bdeSize;
4275 
4276 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4277 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4278 			    "%s: Invalid BDE. cmd=%x",
4279 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4280 
4281 			rval = DFC_ARG_INVALID;
4282 			goto done;
4283 		}
4284 
4285 		/* Allocate receive buffer */
4286 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4287 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4288 			    "%s: Unable to allocate receive buffer. cmd=%x",
4289 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4290 
4291 			rval = DFC_DRVRES_ERROR;
4292 			goto done;
4293 		}
4294 
4295 		mb->un.varRdEvtLog.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4296 		mb->un.varRdEvtLog.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4297 		mb->un.varRdEvtLog.un.sp64.tus.f.bdeFlags = 0;
4298 
4299 		break;
4300 
4301 	case MBX_READ_SPARM:	/* 0x0D */
4302 	case MBX_READ_SPARM64:	/* 0x8D */
4303 		lptr =
4304 		    (uintptr_t)PADDR(mb->un.varRdSparm.un.sp64.addrHigh,
4305 		    mb->un.varRdSparm.un.sp64.addrLow);
4306 		size = (int)mb->un.varRdSparm.un.sp64.tus.f.bdeSize;
4307 
4308 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4309 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4310 			    "%s: Invalid BDE. cmd=%x",
4311 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4312 
4313 			rval = DFC_ARG_INVALID;
4314 			goto done;
4315 		}
4316 
4317 		/* Allocate receive buffer */
4318 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4319 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4320 			    "%s: Unable to allocate receive buffer. cmd=%x",
4321 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4322 
4323 			rval = DFC_DRVRES_ERROR;
4324 			goto done;
4325 		}
4326 
4327 		mb->un.varRdSparm.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4328 		mb->un.varRdSparm.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4329 		mb->un.varRdSparm.un.sp64.tus.f.bdeFlags = 0;
4330 
4331 		break;
4332 
4333 	case MBX_READ_RPI:	/* 0x0F */
4334 	case MBX_READ_RPI64:	/* 0x8F */
4335 		lptr =
4336 		    (uintptr_t)PADDR(mb->un.varRdRPI.un.sp64.addrHigh,
4337 		    mb->un.varRdRPI.un.sp64.addrLow);
4338 		size = (int)mb->un.varRdRPI.un.sp64.tus.f.bdeSize;
4339 
4340 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4341 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4342 			    "%s: Invalid BDE. cmd=%x",
4343 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4344 
4345 			rval = DFC_ARG_INVALID;
4346 			goto done;
4347 		}
4348 
4349 		/* Allocate receive buffer */
4350 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4351 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4352 			    "%s: Unable to allocate receive buffer. cmd=%x",
4353 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4354 
4355 			rval = DFC_DRVRES_ERROR;
4356 			goto done;
4357 		}
4358 
4359 		mb->un.varRdRPI.un.sp64.addrHigh = PADDR_HI(rx_mp->phys);
4360 		mb->un.varRdRPI.un.sp64.addrLow = PADDR_LO(rx_mp->phys);
4361 		mb->un.varRdRPI.un.sp64.tus.f.bdeFlags = 0;
4362 
4363 		break;
4364 
4365 	case MBX_RUN_BIU_DIAG:	 /* 0x04 */
4366 	case MBX_RUN_BIU_DIAG64: /* 0x84 */
4367 		lptr =
4368 		    (uintptr_t)PADDR(mb->un.varBIUdiag.un.s2.xmit_bde64.
4369 		    addrHigh, mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow);
4370 		size = (int)mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize;
4371 
4372 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4373 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4374 			    "%s: Invalid xmit BDE. cmd=%x",
4375 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4376 
4377 			rval = DFC_ARG_INVALID;
4378 			goto done;
4379 		}
4380 
4381 		/* Allocate xmit buffer */
4382 		if ((tx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4383 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4384 			    "%s: Unable to allocate xmit buffer. cmd=%x",
4385 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4386 
4387 			rval = DFC_DRVRES_ERROR;
4388 			goto done;
4389 		}
4390 
4391 		/* Initialize the xmit buffer */
4392 		if (ddi_copyin((void *)lptr, (void *)tx_mp->virt, size,
4393 		    mode) != 0) {
4394 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4395 			    "%s: ddi_copyin failed. cmd=%x",
4396 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4397 
4398 			rval = DFC_COPYIN_ERROR;
4399 			goto done;
4400 		}
4401 		EMLXS_MPDATA_SYNC(tx_mp->dma_handle, 0, size,
4402 		    DDI_DMA_SYNC_FORDEV);
4403 
4404 		mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
4405 		    PADDR_HI(tx_mp->phys);
4406 		mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
4407 		    PADDR_LO(tx_mp->phys);
4408 		mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeFlags = 0;
4409 
4410 		/* Initialize the receive buffer */
4411 		lptr =
4412 		    (uintptr_t)PADDR(mb->un.varBIUdiag.un.s2.rcv_bde64.
4413 		    addrHigh, mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow);
4414 		size = (int)mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize;
4415 
4416 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4417 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4418 			    "%s: Invalid rcv BDE. cmd=%x",
4419 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4420 
4421 			rval = DFC_ARG_INVALID;
4422 			goto done;
4423 		}
4424 
4425 		/* Allocate receive buffer */
4426 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4427 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4428 			    "%s: Unable to allocate receive buffer. cmd=%x",
4429 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4430 
4431 			rval = DFC_DRVRES_ERROR;
4432 			goto done;
4433 		}
4434 
4435 		mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
4436 		    PADDR_HI(rx_mp->phys);
4437 		mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
4438 		    PADDR_LO(rx_mp->phys);
4439 		mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeFlags = 0;
4440 
4441 		break;
4442 
4443 	case MBX_REG_LOGIN:	/* 0x13 */
4444 	case MBX_REG_LOGIN64:	/* 0x93 */
4445 
4446 		did = mb->un.varRegLogin.did;
4447 
4448 		/* Check for invalid node ids to register */
4449 		if (did == 0 || (did & 0xff000000)) {
4450 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4451 			    "%s: Invalid node id. cmd=%x did=%x",
4452 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
4453 
4454 			rval = DFC_ARG_INVALID;
4455 			goto done;
4456 		}
4457 
4458 		/* Check if the node limit has been reached */
4459 		if (port->node_count >= hba->max_nodes) {
4460 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4461 			    "%s: Too many nodes. cmd=%x",
4462 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4463 
4464 			rval = DFC_HBARES_ERROR;
4465 			goto done;
4466 		}
4467 
4468 		lptr =
4469 		    (uintptr_t)PADDR(mb->un.varRegLogin.un.sp64.addrHigh,
4470 		    mb->un.varRegLogin.un.sp64.addrLow);
4471 		size = (int)mb->un.varRegLogin.un.sp64.tus.f.bdeSize;
4472 
4473 		if (!lptr || (size > MEM_BUF_SIZE)) {
4474 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4475 			    "%s: Invalid BDE. cmd=%x",
4476 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4477 
4478 			rval = DFC_ARG_INVALID;
4479 			goto done;
4480 		}
4481 
4482 		/* Allocate xmit buffer */
4483 		if ((tx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4484 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4485 			    "%s: Unable to allocate xmit buffer. cmd=%x",
4486 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4487 
4488 			rval = DFC_DRVRES_ERROR;
4489 			goto done;
4490 		}
4491 
4492 		/* Initialize the xmit buffer */
4493 		if (ddi_copyin((void *)lptr, (void *)tx_mp->virt, size,
4494 		    mode) != 0) {
4495 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4496 			    "%s: Unable to allocate xmit buffer. cmd=%x",
4497 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4498 
4499 			rval = DFC_COPYIN_ERROR;
4500 			goto done;
4501 		}
4502 		EMLXS_MPDATA_SYNC(tx_mp->dma_handle, 0, size,
4503 		    DDI_DMA_SYNC_FORDEV);
4504 
4505 		mb->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(tx_mp->phys);
4506 		mb->un.varRegLogin.un.sp64.addrLow = PADDR_LO(tx_mp->phys);
4507 		mb->un.varRegLogin.un.sp64.tus.f.bdeFlags = 0;
4508 
4509 		break;
4510 
4511 	case MBX_READ_LA:	/* 0x15 */
4512 	case MBX_READ_LA64:	/* 0x95 */
4513 		lptr =
4514 		    (uintptr_t)PADDR(mb->un.varReadLA.un.lilpBde64.
4515 		    addrHigh, mb->un.varReadLA.un.lilpBde64.addrLow);
4516 		size = (int)mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize;
4517 
4518 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
4519 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4520 			    "%s: Invalid BDE. cmd=%x",
4521 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4522 
4523 			rval = DFC_ARG_INVALID;
4524 			goto done;
4525 		}
4526 
4527 		/* Allocate receive buffer */
4528 		if ((rx_mp = emlxs_mem_buf_alloc(hba, MEM_BUF_SIZE)) == 0) {
4529 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4530 			    "%s: Unable to allocate receive buffer. cmd=%x",
4531 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4532 
4533 			rval = DFC_DRVRES_ERROR;
4534 			goto done;
4535 		}
4536 
4537 		mb->un.varReadLA.un.lilpBde64.addrHigh =
4538 		    PADDR_HI(rx_mp->phys);
4539 		mb->un.varReadLA.un.lilpBde64.addrLow =
4540 		    PADDR_LO(rx_mp->phys);
4541 		mb->un.varReadLA.un.lilpBde64.tus.f.bdeFlags = 0;
4542 
4543 		break;
4544 
4545 
4546 		/* Do not allow these commands */
4547 	case MBX_CONFIG_PORT:	/* 0x88 */
4548 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4549 		    "%s: Command not allowed. cmd=%x",
4550 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4551 
4552 		rval = DFC_ARG_INVALID;
4553 		goto done;
4554 
4555 
4556 	/* Online / Offline */
4557 	default:
4558 		break;
4559 
4560 	}	/* switch() */
4561 
4562 	mb->mbxOwner = OWN_HOST;
4563 
4564 	/* Set or don't set the PASSTHRU bit. */
4565 	/* Setting will prevent the driver from processing it as its own */
4566 	switch (mb->mbxCommand) {
4567 	case MBX_REG_LOGIN:	/* 0x13 */
4568 	case MBX_REG_LOGIN64:	/* 0x93 */
4569 		break;
4570 
4571 	default:
4572 		mbq->flag |= MBQ_PASSTHRU;
4573 	}
4574 
4575 #ifdef MBOX_EXT_SUPPORT
4576 	if (extbuf) {
4577 		mbq->extbuf  = extbuf;
4578 		mbq->extsize = extsize;
4579 	}
4580 #endif /* MBOX_EXT_SUPPORT */
4581 
4582 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4583 	    "%s: %s sent.  (%x %x %x %x)", emlxs_dfc_xlate(dfc->cmd),
4584 	    emlxs_mb_cmd_xlate(mb->mbxCommand), mb->un.varWords[0],
4585 	    mb->un.varWords[1], mb->un.varWords[2], mb->un.varWords[3]);
4586 
4587 	/* issue the mbox cmd to the sli */
4588 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
4589 
4590 	if (mbxstatus) {
4591 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4592 		    "%s: %s failed. mbxstatus=0x%x",
4593 		    emlxs_dfc_xlate(dfc->cmd),
4594 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
4595 
4596 	}
4597 
4598 	if (ddi_copyout((void *)mb, (void *)dfc->buf2, dfc->buf2_size,
4599 	    mode) != 0) {
4600 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4601 		    "%s: ddi_copyout failed. cmd=%x",
4602 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4603 
4604 		rval = DFC_COPYOUT_ERROR;
4605 		goto done;
4606 	}
4607 
4608 	if (rx_mp) {
4609 		EMLXS_MPDATA_SYNC(rx_mp->dma_handle, 0, size,
4610 		    DDI_DMA_SYNC_FORKERNEL);
4611 
4612 		if (ddi_copyout((void *)rx_mp->virt, (void *)lptr, size,
4613 		    mode) != 0) {
4614 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4615 			    "%s: ddi_copyout failed for receive buffer. cmd=%x",
4616 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4617 
4618 			rval = DFC_COPYOUT_ERROR;
4619 			goto done;
4620 		}
4621 	}
4622 #ifdef MBOX_EXT_SUPPORT
4623 	/*  Any data needs to copy to mbox extension area */
4624 	if (dfc->buf4_size) {
4625 		if (ddi_copyout((void *)extbuf, (void *)dfc->buf4,
4626 		    dfc->buf4_size, mode) != 0) {
4627 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4628 			    "%s: ddi_copyout failed for mbox extension data.",
4629 			    emlxs_dfc_xlate(dfc->cmd));
4630 
4631 			rval = DFC_COPYIN_ERROR;
4632 			goto done;
4633 		}
4634 	}
4635 #endif /* MBOX_EXT_SUPPORT */
4636 
4637 	rval = 0;
4638 
4639 done:
4640 
4641 	/* Free allocated mbox memory */
4642 	if (extbuf) {
4643 		kmem_free(extbuf, extsize);
4644 	}
4645 
4646 	/* Free allocated mbox memory */
4647 	if (mbq) {
4648 		kmem_free(mbq, sizeof (MAILBOXQ));
4649 	}
4650 
4651 	/* Free allocated mbuf memory */
4652 	if (rx_mp) {
4653 		(void) emlxs_mem_buf_free(hba, rx_mp);
4654 	}
4655 
4656 	if (tx_mp) {
4657 		(void) emlxs_mem_buf_free(hba, tx_mp);
4658 	}
4659 
4660 	return (rval);
4661 
4662 } /* emlxs_dfc_send_mbox() */
4663 
4664 
4665 static int32_t
4666 emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4667 {
4668 	emlxs_port_t	*port = &PPORT;
4669 	uint32_t	offset;
4670 	uint32_t	cnt;
4671 	uint32_t	outsz;
4672 	uint32_t	i;
4673 	uint32_t	*buffer;
4674 	uint32_t	*bptr;
4675 	uint32_t	value;
4676 	uint32_t	size;
4677 	uint32_t	max = 4096;
4678 
4679 	offset = dfc->data1;
4680 	cnt = dfc->data2;
4681 	outsz = dfc->buf1_size;
4682 
4683 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4684 	    "%s: offset=%x count=%d", emlxs_dfc_xlate(dfc->cmd), offset, cnt);
4685 
4686 	if (!dfc->buf1_size || !dfc->buf1) {
4687 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4688 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4689 
4690 		return (DFC_ARG_NULL);
4691 	}
4692 
4693 	if (offset & 0x3) {
4694 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4695 		    "%s: Offset misaligned. (offset=%d)",
4696 		    emlxs_dfc_xlate(dfc->cmd), offset);
4697 
4698 		return (DFC_ARG_MISALIGNED);
4699 	}
4700 
4701 	if (cnt & 0x3) {
4702 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4703 		    "%s: Count misaligned. (count=%d)",
4704 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4705 
4706 		return (DFC_ARG_MISALIGNED);
4707 	}
4708 
4709 	if (outsz & 0x3) {
4710 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4711 		    "%s: Output size misaligned. (size=%d)",
4712 		    emlxs_dfc_xlate(dfc->cmd), outsz);
4713 
4714 		return (DFC_ARG_MISALIGNED);
4715 	}
4716 
4717 	/* Get max PCI config range */
4718 	if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
4719 		max = 256;
4720 	} else {
4721 		max = 4096;
4722 	}
4723 
4724 	if ((cnt + offset) > max) {
4725 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4726 		    "%s: Offset+Count too large. (offset=%d count=%d max=%d)",
4727 		    emlxs_dfc_xlate(dfc->cmd), offset, cnt, max);
4728 
4729 		return (DFC_ARG_TOOBIG);
4730 	}
4731 
4732 	if (outsz > max) {
4733 		outsz = max;
4734 	}
4735 
4736 	if (cnt > outsz) {
4737 		cnt = outsz;
4738 	}
4739 
4740 	size = cnt;
4741 
4742 	if (!(buffer = (uint32_t *)kmem_zalloc(size, KM_NOSLEEP))) {
4743 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4744 		    "%s: Unable to allocate buffer.",
4745 		    emlxs_dfc_xlate(dfc->cmd));
4746 
4747 		return (DFC_SYSRES_ERROR);
4748 	}
4749 
4750 	bptr = buffer;
4751 	for (i = offset; i < (offset + cnt); i += 4) {
4752 		value =
4753 		    ddi_get32(hba->pci_acc_handle,
4754 		    (uint32_t *)(hba->pci_addr + i));
4755 		*bptr++ = BE_SWAP32(value);
4756 	}
4757 
4758 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1, outsz, mode) != 0) {
4759 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4760 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
4761 
4762 		kmem_free(buffer, size);
4763 		return (DFC_COPYOUT_ERROR);
4764 	}
4765 
4766 	kmem_free(buffer, size);
4767 
4768 #ifdef FMA_SUPPORT
4769 	/* Access handle validation */
4770 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
4771 	    != DDI_FM_OK) {
4772 		EMLXS_MSGF(EMLXS_CONTEXT,
4773 		    &emlxs_invalid_access_handle_msg, NULL);
4774 		return (DFC_DRV_ERROR);
4775 	}
4776 #endif  /* FMA_SUPPORT */
4777 
4778 	return (0);
4779 
4780 } /* emlxs_dfc_read_pci() */
4781 
4782 
4783 static int32_t
4784 emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4785 {
4786 	emlxs_port_t	*port = &PPORT;
4787 	uint32_t	offset;
4788 	uint32_t	cnt;
4789 	uint32_t	value;
4790 	uint32_t	i;
4791 	uint32_t	max;
4792 	uint8_t		buffer[256];
4793 	uint32_t	*bptr;
4794 	uint16_t	word0;
4795 	uint16_t	word1;
4796 
4797 	offset = dfc->data1;
4798 	cnt = dfc->data2;
4799 
4800 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4801 	    "%s: offset=%x count=%d", emlxs_dfc_xlate(dfc->cmd), offset, cnt);
4802 
4803 	if (!dfc->buf1 || !dfc->buf1_size) {
4804 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4805 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4806 
4807 		return (DFC_ARG_NULL);
4808 	}
4809 
4810 	if (offset & 0x3) {
4811 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4812 		    "%s: Offset misaligned. (offset=%d)",
4813 		    emlxs_dfc_xlate(dfc->cmd), offset);
4814 
4815 		return (DFC_ARG_MISALIGNED);
4816 	}
4817 
4818 	if (cnt > dfc->buf1_size) {
4819 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4820 		    "%s: Count too large. (count=%d)",
4821 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4822 
4823 		return (DFC_ARG_TOOBIG);
4824 	}
4825 
4826 	if (cnt & 0x3) {
4827 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4828 		    "%s: Count misaligned. (count=%d)",
4829 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4830 
4831 		return (DFC_ARG_MISALIGNED);
4832 	}
4833 
4834 	/* Get max PCI config range */
4835 	if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
4836 		max = 256;
4837 	} else {
4838 		max = 4096;
4839 	}
4840 
4841 	if ((cnt + offset) > max) {
4842 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4843 		    "%s: Count+Offset too large. (offset=%d count=%d max=%d)",
4844 		    emlxs_dfc_xlate(dfc->cmd), offset, cnt, max);
4845 
4846 		return (DFC_ARG_TOOBIG);
4847 	}
4848 
4849 	bzero(buffer, sizeof (buffer));
4850 
4851 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer, cnt, mode) != 0) {
4852 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4853 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
4854 
4855 		return (DFC_COPYIN_ERROR);
4856 	}
4857 
4858 	bptr = (uint32_t *)buffer;
4859 	for (i = offset; i < (offset + cnt); i += 4) {
4860 		value = *bptr++;
4861 		value = BE_SWAP32(value);
4862 
4863 		word0 = value & 0xFFFF;
4864 		word1 = value >> 16;
4865 
4866 		/*
4867 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
4868 		 * "%s: Writing. offset=%x cnt=%d value=%08x %04x %04x",
4869 		 * emlxs_dfc_xlate(dfc->cmd), i, value, word0, word1);
4870 		 */
4871 
4872 		/* word0 = PCIMEM_SHORT(word0); */
4873 		ddi_put16(hba->pci_acc_handle,
4874 		    (uint16_t *)(hba->pci_addr + i), (uint16_t)word0);
4875 
4876 		/* word1 = PCIMEM_SHORT(word1); */
4877 		ddi_put16(hba->pci_acc_handle,
4878 		    (uint16_t *)(hba->pci_addr + i + 2), (uint16_t)word1);
4879 	}
4880 
4881 #ifdef FMA_SUPPORT
4882 	/* Access handle validation */
4883 	if (emlxs_fm_check_acc_handle(hba, hba->pci_acc_handle)
4884 	    != DDI_FM_OK) {
4885 		EMLXS_MSGF(EMLXS_CONTEXT,
4886 		    &emlxs_invalid_access_handle_msg, NULL);
4887 		return (DFC_DRV_ERROR);
4888 	}
4889 #endif  /* FMA_SUPPORT */
4890 
4891 	return (0);
4892 
4893 } /* emlxs_dfc_write_pci() */
4894 
4895 
4896 static int32_t
4897 emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4898 {
4899 	emlxs_port_t	*port = &PPORT;
4900 	dfc_cfgparam_t	*cfgparam;
4901 	uint32_t	size;
4902 	uint32_t	count;
4903 	uint32_t	i;
4904 	int32_t		rval = 0;
4905 	emlxs_config_t	*cfg;
4906 
4907 	if (!dfc->buf1 || !dfc->buf1_size) {
4908 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4909 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
4910 
4911 		return (DFC_ARG_NULL);
4912 	}
4913 
4914 	count = dfc->buf1_size / sizeof (dfc_cfgparam_t);
4915 
4916 	if (count > MAX_CFG_PARAM) {
4917 		count = MAX_CFG_PARAM;
4918 	}
4919 
4920 	if (count > NUM_CFG_PARAM) {
4921 		count = NUM_CFG_PARAM;
4922 	}
4923 
4924 	size = count * sizeof (dfc_cfgparam_t);
4925 
4926 	if (!(cfgparam = (dfc_cfgparam_t *)kmem_zalloc(size, KM_NOSLEEP))) {
4927 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4928 		    "%s: Unable to allocate cfgparm buffer.",
4929 		    emlxs_dfc_xlate(dfc->cmd));
4930 
4931 		return (DFC_SYSRES_ERROR);
4932 	}
4933 
4934 	cfg = &CFG;
4935 	for (i = 0; i < count; i++) {
4936 		(void) strncpy(cfgparam[i].a_string, cfg[i].string,
4937 		    sizeof (cfgparam[i].a_string));
4938 		cfgparam[i].a_low = cfg[i].low;
4939 		cfgparam[i].a_hi = cfg[i].hi;
4940 		cfgparam[i].a_default = cfg[i].def;
4941 		cfgparam[i].a_current = cfg[i].current;
4942 
4943 		if (!(cfg[i].flags & PARM_HIDDEN)) {
4944 			cfgparam[i].a_flag |= CFG_EXPORT;
4945 		}
4946 		cfgparam[i].a_flag |= CFG_COMMON;
4947 
4948 		/* Adjust a_flag based on the hba model */
4949 		switch (i) {
4950 			case CFG_NETWORK_ON:
4951 			case CFG_TOPOLOGY:
4952 			case CFG_LINK_SPEED:
4953 			case CFG_CR_DELAY:
4954 			case CFG_CR_COUNT:
4955 #ifdef SFCT_SUPPORT
4956 			case CFG_TARGET_MODE:
4957 #endif /* SFCT_SUPPORT */
4958 			if (!(hba->model_info.flags & EMLXS_FCOE_SUPPORTED)) {
4959 				cfgparam[i].a_flag |= CFG_APPLICABLE;
4960 			}
4961 			break;
4962 
4963 			case CFG_NUM_WQ:
4964 			if (hba->model_info.flags & EMLXS_FCOE_SUPPORTED) {
4965 				cfgparam[i].a_flag |= CFG_APPLICABLE;
4966 			}
4967 			break;
4968 
4969 			case CFG_PERSIST_LINKDOWN:
4970 			cfgparam[i].a_flag &= ~CFG_EXPORT;
4971 			break;
4972 
4973 			default:
4974 			cfgparam[i].a_flag |= CFG_APPLICABLE;
4975 			break;
4976 		}
4977 
4978 		if ((cfg[i].flags & PARM_DYNAMIC)) {
4979 			if ((cfg[i].flags & PARM_DYNAMIC_RESET) ==
4980 			    PARM_DYNAMIC_RESET) {
4981 				cfgparam[i].a_changestate = CFG_RESTART;
4982 			} else if ((cfg[i].flags & PARM_DYNAMIC_LINK) ==
4983 			    PARM_DYNAMIC_LINK) {
4984 				cfgparam[i].a_changestate = CFG_LINKRESET;
4985 			} else {
4986 				cfgparam[i].a_changestate = CFG_DYMANIC;
4987 			}
4988 		} else {
4989 			cfgparam[i].a_changestate = CFG_REBOOT;
4990 		}
4991 
4992 		(void) strncpy(cfgparam[i].a_help, cfg[i].help,
4993 		    sizeof (cfgparam[i].a_help));
4994 	}
4995 
4996 	if (ddi_copyout((void *)cfgparam, (void *)dfc->buf1, size, mode) != 0) {
4997 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4998 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
4999 
5000 		rval = DFC_COPYOUT_ERROR;
5001 	}
5002 
5003 	rval = 0;
5004 
5005 	kmem_free(cfgparam, size);
5006 
5007 	return (rval);
5008 
5009 } /* emlxs_dfc_get_cfg() */
5010 
5011 
5012 /* ARGSUSED */
5013 static int32_t
5014 emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5015 {
5016 	emlxs_port_t	*port = &PPORT;
5017 	uint32_t	index;
5018 	uint32_t	new_value;
5019 	uint32_t	rc;
5020 
5021 	index = dfc->data1;
5022 	new_value = dfc->data2;
5023 
5024 	rc = emlxs_set_parm(hba, index, new_value);
5025 
5026 	if (rc) {
5027 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5028 		    "%s: Unable to set parameter. code=%d",
5029 		    emlxs_dfc_xlate(dfc->cmd), rc);
5030 
5031 		switch (rc) {
5032 		case 2:
5033 			return (DFC_NPIV_ACTIVE);
5034 
5035 		default:
5036 			return (DFC_ARG_INVALID);
5037 		}
5038 	}
5039 
5040 	return (0);
5041 
5042 } /* emlxs_dfc_set_cfg() */
5043 
5044 
5045 static int32_t
5046 emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5047 {
5048 	emlxs_port_t	*port = &PPORT;
5049 	uint8_t		*rsp_buf;
5050 	uint8_t		*cmd_buf;
5051 	uint32_t	did;
5052 	uint32_t	rsp_size;
5053 	uint32_t	cmd_size;
5054 	uint32_t	timeout;
5055 	fc_packet_t	*pkt = NULL;
5056 	uint32_t	rval = 0;
5057 	dfc_destid_t	destid;
5058 	NODELIST	*nlp;
5059 	char		buffer[128];
5060 
5061 	cmd_buf = dfc->buf1;
5062 	cmd_size = dfc->buf1_size;
5063 	rsp_buf = dfc->buf2;
5064 	rsp_size = dfc->buf2_size;
5065 	timeout = dfc->data1;
5066 
5067 	if (timeout < (2 * hba->fc_ratov)) {
5068 		timeout = 2 * hba->fc_ratov;
5069 	}
5070 
5071 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5072 	    "%s: csize=%d rsize=%d", emlxs_dfc_xlate(dfc->cmd), cmd_size,
5073 	    rsp_size);
5074 
5075 
5076 	if (!cmd_size || !cmd_buf) {
5077 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5078 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5079 
5080 		rval = DFC_ARG_NULL;
5081 		goto done;
5082 	}
5083 
5084 	if (!rsp_size || !rsp_buf) {
5085 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5086 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
5087 
5088 		rval = DFC_ARG_NULL;
5089 		goto done;
5090 	}
5091 
5092 	if (!dfc->buf3 || !dfc->buf3_size) {
5093 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5094 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
5095 
5096 		rval = DFC_ARG_NULL;
5097 		goto done;
5098 	}
5099 
5100 	if (!dfc->buf4 || !dfc->buf4_size) {
5101 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5102 		    "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
5103 
5104 		rval = DFC_ARG_NULL;
5105 		goto done;
5106 	}
5107 
5108 	if (rsp_size > MAX_CT_PAYLOAD) {
5109 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5110 		    "%s: Buffer2 too large. size=%d",
5111 		    emlxs_dfc_xlate(dfc->cmd), rsp_size);
5112 
5113 		rval = DFC_ARG_TOOBIG;
5114 		goto done;
5115 	}
5116 
5117 	if (cmd_size > MAX_CT_PAYLOAD) {
5118 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5119 		    "%s: Buffer1 too large. size=%d",
5120 		    emlxs_dfc_xlate(dfc->cmd), cmd_size);
5121 
5122 		rval = DFC_ARG_TOOBIG;
5123 		goto done;
5124 	}
5125 
5126 	if (dfc->buf3_size < sizeof (dfc_destid_t)) {
5127 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5128 		    "%s: Buffer3 too small. (size=%d)",
5129 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
5130 
5131 		rval = DFC_ARG_TOOSMALL;
5132 		goto done;
5133 	}
5134 
5135 	if (dfc->buf4_size < sizeof (uint32_t)) {
5136 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5137 		    "%s: Buffer4 too small. (size=%d)",
5138 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
5139 
5140 		rval = DFC_ARG_TOOSMALL;
5141 		goto done;
5142 	}
5143 
5144 	if (ddi_copyin((void *)dfc->buf3, (void *)&destid,
5145 	    sizeof (dfc_destid_t), mode) != 0) {
5146 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5147 		    "%s: Unable to read destination id.",
5148 		    emlxs_dfc_xlate(dfc->cmd));
5149 
5150 		rval = DFC_COPYIN_ERROR;
5151 		goto done;
5152 	}
5153 
5154 	if (destid.idType == 0) {
5155 		if ((nlp = emlxs_node_find_wwpn(port, destid.wwpn)) == NULL) {
5156 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5157 			    "%s: WWPN does not exists. %s",
5158 			    emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
5159 			    destid.wwpn));
5160 
5161 			rval = DFC_ARG_INVALID;
5162 			goto done;
5163 		}
5164 		did = nlp->nlp_DID;
5165 	} else {
5166 		if (emlxs_node_find_did(port, destid.d_id) == NULL) {
5167 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5168 			    "%s: DID does not exist. did=%x",
5169 			    emlxs_dfc_xlate(dfc->cmd), destid.d_id);
5170 
5171 			rval = DFC_ARG_INVALID;
5172 			goto done;
5173 		}
5174 		did = destid.d_id;
5175 	}
5176 
5177 	if (did == 0) {
5178 		did = port->did;
5179 	}
5180 
5181 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
5182 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5183 		    "%s: Unable to allocate packet.",
5184 		    emlxs_dfc_xlate(dfc->cmd));
5185 
5186 		rval = DFC_SYSRES_ERROR;
5187 		goto done;
5188 	}
5189 
5190 	/* Make this a polled IO */
5191 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5192 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5193 	pkt->pkt_comp = NULL;
5194 
5195 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5196 	pkt->pkt_timeout = (timeout) ? timeout : 30;
5197 
5198 	/* Build the fc header */
5199 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
5200 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
5201 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
5202 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
5203 	pkt->pkt_cmd_fhdr.f_ctl =
5204 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
5205 	pkt->pkt_cmd_fhdr.seq_id = 0;
5206 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5207 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5208 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5209 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5210 	pkt->pkt_cmd_fhdr.ro = 0;
5211 
5212 	/* Copy in the command buffer */
5213 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size,
5214 	    mode) != 0) {
5215 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5216 		    "%s: Unable to read command buffer.",
5217 		    emlxs_dfc_xlate(dfc->cmd));
5218 
5219 		rval = DFC_COPYIN_ERROR;
5220 		goto done;
5221 	}
5222 
5223 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5224 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5225 		    "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
5226 
5227 		rval = DFC_IO_ERROR;
5228 		goto done;
5229 	}
5230 
5231 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
5232 	    (pkt->pkt_state != FC_PKT_FS_RJT)) {
5233 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5234 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5235 			    "Pkt Transport error. Pkt Timeout.");
5236 			rval = DFC_TIMEOUT;
5237 		} else {
5238 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5239 			    "Pkt Transport error. state=%x", pkt->pkt_state);
5240 			rval = DFC_IO_ERROR;
5241 		}
5242 		goto done;
5243 	}
5244 
5245 	if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf, rsp_size,
5246 	    mode) != 0) {
5247 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5248 		    "%s: Unable to read response.",
5249 		    emlxs_dfc_xlate(dfc->cmd));
5250 
5251 		rval = DFC_COPYOUT_ERROR;
5252 		goto done;
5253 	}
5254 
5255 	rsp_size -= pkt->pkt_resp_resid;
5256 	if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf4, dfc->buf4_size,
5257 	    mode) != 0) {
5258 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5259 		    "%s: Unable to write response.",
5260 		    emlxs_dfc_xlate(dfc->cmd));
5261 
5262 		rval = DFC_COPYOUT_ERROR;
5263 		goto done;
5264 	}
5265 
5266 	rval = 0;
5267 
5268 done:
5269 
5270 	if (pkt) {
5271 		emlxs_pkt_free(pkt);
5272 	}
5273 
5274 	return (rval);
5275 
5276 } /* emlxs_dfc_send_ct() */
5277 
5278 
5279 static int32_t
5280 emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5281 {
5282 	emlxs_port_t	*port = &PPORT;
5283 	uint8_t		*cmd_buf;
5284 	uint32_t	rx_id;
5285 	uint32_t	cmd_size;
5286 	uint32_t	timeout;
5287 	fc_packet_t	*pkt = NULL;
5288 	uint32_t	rval = 0;
5289 
5290 	cmd_buf = dfc->buf1;
5291 	cmd_size = dfc->buf1_size;
5292 	rx_id = dfc->flag;
5293 	timeout = 2 * hba->fc_ratov;
5294 
5295 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s: csize=%d",
5296 	    emlxs_dfc_xlate(dfc->cmd), cmd_size);
5297 
5298 	if (!cmd_size || !cmd_buf) {
5299 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5300 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5301 
5302 		rval = DFC_ARG_NULL;
5303 		goto done;
5304 	}
5305 
5306 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, 0, 0, KM_NOSLEEP))) {
5307 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5308 		    "%s: Unable to allocate packet.",
5309 		    emlxs_dfc_xlate(dfc->cmd));
5310 
5311 		rval = DFC_SYSRES_ERROR;
5312 		goto done;
5313 	}
5314 
5315 	/* Make this a polled IO */
5316 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5317 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5318 	pkt->pkt_comp = NULL;
5319 
5320 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
5321 	pkt->pkt_timeout = (timeout) ? timeout : 30;
5322 
5323 	/* Build the fc header */
5324 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(0);
5325 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_SOLICITED_CONTROL;
5326 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
5327 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
5328 	pkt->pkt_cmd_fhdr.f_ctl =
5329 	    F_CTL_LAST_SEQ | F_CTL_END_SEQ | F_CTL_XCHG_CONTEXT;
5330 	pkt->pkt_cmd_fhdr.seq_id = 0;
5331 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5332 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5333 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
5334 	pkt->pkt_cmd_fhdr.rx_id = rx_id;
5335 	pkt->pkt_cmd_fhdr.ro = 0;
5336 
5337 	/* Copy in the command buffer */
5338 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size,
5339 	    mode) != 0) {
5340 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5341 		    "%s: Unable to read command buffer.",
5342 		    emlxs_dfc_xlate(dfc->cmd));
5343 
5344 		rval = DFC_COPYIN_ERROR;
5345 		goto done;
5346 	}
5347 
5348 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5349 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5350 		    "%s: Unable to send packet.", emlxs_dfc_xlate(dfc->cmd));
5351 
5352 		rval = DFC_IO_ERROR;
5353 		goto done;
5354 	}
5355 
5356 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
5357 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5358 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5359 			    "Pkt Transport error. Pkt Timeout.");
5360 			rval = DFC_TIMEOUT;
5361 		} else {
5362 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5363 			    "Pkt Transport error. state=%x", pkt->pkt_state);
5364 			rval = DFC_IO_ERROR;
5365 		}
5366 		goto done;
5367 	}
5368 
5369 	rval = 0;
5370 
5371 done:
5372 
5373 	if (pkt) {
5374 		emlxs_pkt_free(pkt);
5375 	}
5376 
5377 	return (rval);
5378 
5379 } /* emlxs_dfc_send_ct_rsp() */
5380 
5381 
5382 #ifdef MENLO_SUPPORT
5383 
5384 static int32_t
5385 emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5386 {
5387 	emlxs_port_t	*port = &PPORT;
5388 	uint8_t		*rsp_buf = NULL;
5389 	uint8_t		*cmd_buf = NULL;
5390 	uint32_t	rsp_size = 0;
5391 	uint32_t	cmd_size = 0;
5392 	uint32_t	rval = 0;
5393 
5394 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5395 	    "%s: csize=%d rsize=%d", emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size,
5396 	    dfc->buf2_size);
5397 
5398 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
5399 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5400 		    "%s: Menlo device not present. device=%x,%x",
5401 		    emlxs_dfc_xlate(dfc->cmd), hba->model_info.device_id,
5402 		    hba->model_info.ssdid);
5403 
5404 		rval = DFC_INVALID_ADAPTER;
5405 		goto done;
5406 	}
5407 
5408 	if (!dfc->buf1_size || !dfc->buf1) {
5409 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5410 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
5411 
5412 		rval = DFC_ARG_NULL;
5413 		goto done;
5414 	}
5415 
5416 	if (!dfc->buf2_size || !dfc->buf2) {
5417 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5418 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
5419 
5420 		rval = DFC_ARG_NULL;
5421 		goto done;
5422 	}
5423 
5424 	if (!dfc->buf3 || !dfc->buf3_size) {
5425 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5426 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
5427 
5428 		rval = DFC_ARG_NULL;
5429 		goto done;
5430 	}
5431 
5432 	if (dfc->buf3_size < sizeof (uint32_t)) {
5433 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5434 		    "%s: Buffer3 too small. %d < %d",
5435 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size,
5436 		    sizeof (uint32_t));
5437 
5438 		rval = DFC_ARG_TOOSMALL;
5439 		goto done;
5440 	}
5441 
5442 	cmd_size  = dfc->buf1_size;
5443 	cmd_buf = (uint8_t *)kmem_zalloc(cmd_size,
5444 	    KM_SLEEP);
5445 
5446 	rsp_size  = dfc->buf2_size;
5447 	rsp_buf = (uint8_t *)kmem_zalloc(rsp_size,
5448 	    KM_SLEEP);
5449 
5450 	/* Read the command buffer */
5451 	if (ddi_copyin((void *)dfc->buf1, (void *)cmd_buf,
5452 	    cmd_size, mode) != 0) {
5453 		EMLXS_MSGF(EMLXS_CONTEXT,
5454 		    &emlxs_dfc_error_msg,
5455 		    "%s: Unable to read command buffer.",
5456 		    emlxs_dfc_xlate(dfc->cmd));
5457 
5458 		rval = DFC_COPYIN_ERROR;
5459 		goto done;
5460 	}
5461 
5462 	/* Send the command */
5463 	rval = emlxs_send_menlo_cmd(hba, cmd_buf, cmd_size,
5464 	    rsp_buf, &rsp_size);
5465 
5466 	if (rval == 0) {
5467 		/* Return the response */
5468 		if (ddi_copyout((void *)rsp_buf, (void *)dfc->buf2,
5469 		    rsp_size, mode) != 0) {
5470 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5471 			    "%s: Unable to write response.",
5472 			    emlxs_dfc_xlate(dfc->cmd));
5473 
5474 			rval = DFC_COPYOUT_ERROR;
5475 			goto done;
5476 		}
5477 
5478 		/* Return the response size */
5479 		if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf3,
5480 		    dfc->buf3_size, mode) != 0) {
5481 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5482 			    "%s: Unable to write response size.",
5483 			    emlxs_dfc_xlate(dfc->cmd));
5484 
5485 			rval = DFC_COPYOUT_ERROR;
5486 			goto done;
5487 		}
5488 	}
5489 
5490 done:
5491 
5492 	if (cmd_buf) {
5493 		kmem_free(cmd_buf, dfc->buf1_size);
5494 	}
5495 
5496 	if (rsp_buf) {
5497 		kmem_free(rsp_buf, dfc->buf2_size);
5498 	}
5499 
5500 	return (rval);
5501 
5502 } /* emlxs_dfc_send_menlo() */
5503 
5504 
5505 extern int32_t
5506 emlxs_send_menlo_cmd(emlxs_hba_t *hba, uint8_t *cmd_buf, uint32_t cmd_size,
5507     uint8_t *rsp_buf, uint32_t *rsp_size)
5508 {
5509 	emlxs_port_t		*port = &PPORT;
5510 	uint8_t			*data_buf = NULL;
5511 	uint32_t		data_size = 0;
5512 	fc_packet_t		*pkt = NULL;
5513 	uint32_t		rval = 0;
5514 	menlo_set_cmd_t		set_cmd;
5515 	menlo_reset_cmd_t	reset_cmd;
5516 	uint32_t		rsp_code;
5517 	uint32_t		mm_mode = 0;
5518 	uint32_t		cmd_code;
5519 	clock_t			timeout;
5520 	MAILBOXQ		*mbq = NULL;
5521 	MAILBOX			*mb;
5522 	uint32_t		addr;
5523 	uint32_t		value;
5524 	uint32_t		mbxstatus;
5525 
5526 	cmd_code = *(uint32_t *)cmd_buf;
5527 	cmd_code = BE_SWAP32(cmd_code);
5528 
5529 	/* Look for Zephyr specific commands */
5530 	if (cmd_code & 0x80000000) {
5531 		bzero((uint8_t *)&reset_cmd, sizeof (menlo_reset_cmd_t));
5532 		bzero((uint8_t *)&set_cmd, sizeof (menlo_set_cmd_t));
5533 		bzero((uint8_t *)&rsp_code, sizeof (uint32_t));
5534 
5535 		/* Validate response buffer */
5536 		if (*rsp_size < sizeof (uint32_t)) {
5537 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5538 			    "emlxs_send_menlo_cmd: Response overrun.");
5539 			rval = DFC_RSP_BUF_OVERRUN;
5540 			goto done;
5541 		}
5542 
5543 		/* All of these responses will be 4 bytes only */
5544 		*rsp_size = sizeof (uint32_t);
5545 		rsp_code = 0;
5546 
5547 		/* Validate command buffer */
5548 		switch (cmd_code) {
5549 		case MENLO_CMD_RESET:
5550 			if (cmd_size < sizeof (menlo_reset_cmd_t)) {
5551 				EMLXS_MSGF(EMLXS_CONTEXT,
5552 				    &emlxs_dfc_error_msg,
5553 				    "emlxs_send_menlo_cmd: "
5554 				    "Invalid command size. %d < %d",
5555 				    cmd_size,
5556 				    sizeof (menlo_reset_cmd_t));
5557 				rval = DFC_ARG_INVALID;
5558 				goto done;
5559 			}
5560 			cmd_size = sizeof (menlo_reset_cmd_t);
5561 
5562 			/* Read the command buffer */
5563 			bcopy((void *)cmd_buf, (void *)&reset_cmd, cmd_size);
5564 
5565 			if (reset_cmd.firmware) {
5566 				/* MENLO_FW_GOLDEN */
5567 				value = 1;
5568 
5569 				EMLXS_MSGF(EMLXS_CONTEXT,
5570 				    &emlxs_dfc_detail_msg,
5571 				    "emlxs_send_menlo_cmd: Reset with Golden "
5572 				    "firmware requested.");
5573 
5574 			} else {
5575 				/* MENLO_FW_OPERATIONAL */
5576 				value = 0;
5577 
5578 				EMLXS_MSGF(EMLXS_CONTEXT,
5579 				    &emlxs_dfc_detail_msg,
5580 				    "emlxs_send_menlo_cmd: Reset with "
5581 				    "Operational firmware requested.");
5582 			}
5583 
5584 			addr  = 0x103007;
5585 
5586 			break;
5587 
5588 		case MENLO_CMD_SET_MODE:
5589 			if (cmd_size < sizeof (menlo_set_cmd_t)) {
5590 				EMLXS_MSGF(EMLXS_CONTEXT,
5591 				    &emlxs_dfc_error_msg,
5592 				    "emlxs_send_menlo_cmd: "
5593 				    "Invalid command size. %d < %d",
5594 				    cmd_size,
5595 				    sizeof (menlo_set_cmd_t));
5596 				rval = DFC_ARG_INVALID;
5597 				goto done;
5598 			}
5599 			cmd_size = sizeof (menlo_set_cmd_t);
5600 
5601 			/* Read the command buffer */
5602 			bcopy((void *)cmd_buf, (void *)&set_cmd, cmd_size);
5603 
5604 			if (set_cmd.value1) {
5605 				EMLXS_MSGF(EMLXS_CONTEXT,
5606 				    &emlxs_dfc_detail_msg,
5607 				    "emlxs_send_menlo_cmd: "
5608 				    "Maintenance mode enable requested.");
5609 
5610 				/* Make sure the mode flag is cleared */
5611 				if (hba->flag & FC_MENLO_MODE) {
5612 					mutex_enter(&EMLXS_PORT_LOCK);
5613 					hba->flag &= ~FC_MENLO_MODE;
5614 					mutex_exit(&EMLXS_PORT_LOCK);
5615 				}
5616 
5617 				mm_mode = 1;
5618 			} else {
5619 				EMLXS_MSGF(EMLXS_CONTEXT,
5620 				    &emlxs_dfc_detail_msg,
5621 				    "emlxs_send_menlo_cmd: "
5622 				    "Maintenance mode disable requested.");
5623 			}
5624 
5625 			addr  = 0x103107;
5626 			value = mm_mode;
5627 
5628 			break;
5629 
5630 		default:
5631 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5632 			    "emlxs_send_menlo_cmd: "
5633 			    "Invalid command. cmd=%x", cmd_code);
5634 			rval = DFC_ARG_INVALID;
5635 			goto done;
5636 		}
5637 
5638 		mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
5639 		    KM_SLEEP);
5640 
5641 		mb = (MAILBOX *) mbq;
5642 
5643 		/* Create the set_variable mailbox request */
5644 		emlxs_mb_set_var(hba, mbq, addr, value);
5645 
5646 		mbq->flag |= MBQ_PASSTHRU;
5647 
5648 		/* issue the mbox cmd to the sli */
5649 		mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
5650 
5651 		if (mbxstatus) {
5652 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5653 			    "emlxs_send_menlo_cmd: %s failed. mbxstatus=0x%x",
5654 			    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
5655 
5656 			if (mbxstatus == MBX_TIMEOUT) {
5657 				rval = DFC_TIMEOUT;
5658 			} else {
5659 				rval = DFC_IO_ERROR;
5660 			}
5661 			goto done;
5662 		}
5663 
5664 		bcopy((void *)&rsp_code, (void *)rsp_buf, *rsp_size);
5665 
5666 		/* Check if we need to wait for maintenance mode */
5667 		if (mm_mode && !(hba->flag & FC_MENLO_MODE)) {
5668 			/* Wait for link to come up in maintenance mode */
5669 			mutex_enter(&EMLXS_LINKUP_LOCK);
5670 
5671 			timeout = emlxs_timeout(hba, 30);
5672 
5673 			rval = 0;
5674 			while ((rval != -1) && !(hba->flag & FC_MENLO_MODE)) {
5675 				rval =
5676 				    cv_timedwait(&EMLXS_LINKUP_CV,
5677 				    &EMLXS_LINKUP_LOCK, timeout);
5678 			}
5679 
5680 			mutex_exit(&EMLXS_LINKUP_LOCK);
5681 
5682 			if (rval == -1) {
5683 				EMLXS_MSGF(EMLXS_CONTEXT,
5684 				    &emlxs_dfc_error_msg,
5685 				    "emlxs_send_menlo_cmd: "
5686 				    "Menlo maintenance mode error. Timeout.");
5687 
5688 				rval = DFC_TIMEOUT;
5689 				goto done;
5690 			}
5691 		}
5692 	} else {	/* Standard commands */
5693 
5694 		if (hba->state <= FC_LINK_DOWN) {
5695 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5696 			    "emlxs_send_menlo_cmd: Adapter link down.");
5697 
5698 			rval = DFC_LINKDOWN_ERROR;
5699 			goto done;
5700 		}
5701 
5702 		if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
5703 			/* Check cmd size */
5704 			/* Must be at least 12 bytes of command */
5705 			/* plus 4 bytes of data */
5706 			if (cmd_size < (12 + 4)) {
5707 				EMLXS_MSGF(EMLXS_CONTEXT,
5708 				    &emlxs_dfc_error_msg,
5709 				    "emlxs_send_menlo_cmd: "
5710 				    "Invalid command size. %d < %d",
5711 				    cmd_size,
5712 				    (12 + 4));
5713 
5714 				rval = DFC_ARG_INVALID;
5715 				goto done;
5716 			}
5717 
5718 			/* Extract data buffer from command buffer */
5719 			data_buf    = cmd_buf  + 12;
5720 			data_size   = cmd_size - 12;
5721 			cmd_size    = 12;
5722 		}
5723 
5724 		if (!(pkt = emlxs_pkt_alloc(port, cmd_size, *rsp_size, 0,
5725 		    KM_NOSLEEP))) {
5726 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5727 			    "emlxs_send_menlo_cmd: Unable to allocate packet.");
5728 
5729 			rval = DFC_SYSRES_ERROR;
5730 			goto done;
5731 		}
5732 
5733 		/* Make this a polled IO */
5734 		pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5735 		pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5736 		pkt->pkt_comp = NULL;
5737 		pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5738 		pkt->pkt_timeout = 30;
5739 
5740 		/* Build the fc header */
5741 		pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
5742 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5743 		pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
5744 		pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5745 		pkt->pkt_cmd_fhdr.f_ctl =
5746 		    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
5747 		pkt->pkt_cmd_fhdr.seq_id = 0;
5748 		pkt->pkt_cmd_fhdr.df_ctl = 0;
5749 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
5750 		pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5751 		pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5752 		pkt->pkt_cmd_fhdr.ro = 0;
5753 
5754 		/* Copy in the command buffer */
5755 		bcopy((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size);
5756 
5757 		if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5758 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5759 			    "emlxs_send_menlo_cmd: Unable to send packet.");
5760 
5761 			rval = DFC_IO_ERROR;
5762 			goto done;
5763 		}
5764 
5765 		if (pkt->pkt_state != FC_PKT_SUCCESS) {
5766 			if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5767 				EMLXS_MSGF(EMLXS_CONTEXT,
5768 				    &emlxs_dfc_error_msg,
5769 				    "emlxs_send_menlo_cmd: "
5770 				    "Pkt Transport error. Pkt Timeout.");
5771 				rval = DFC_TIMEOUT;
5772 			} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
5773 			    (pkt->pkt_reason == FC_REASON_OVERRUN)) {
5774 				EMLXS_MSGF(EMLXS_CONTEXT,
5775 				    &emlxs_dfc_error_msg,
5776 				    "emlxs_send_menlo_cmd: "
5777 				    "Pkt Transport error. Response overrun.");
5778 				rval = DFC_RSP_BUF_OVERRUN;
5779 			} else {
5780 				EMLXS_MSGF(EMLXS_CONTEXT,
5781 				    &emlxs_dfc_error_msg,
5782 				    "emlxs_send_menlo_cmd: "
5783 				    "Pkt Transport error. state=%x",
5784 				    pkt->pkt_state);
5785 				rval = DFC_IO_ERROR;
5786 			}
5787 			goto done;
5788 		}
5789 
5790 		if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
5791 			uint32_t *rsp;
5792 
5793 			/* Check response code */
5794 			rsp = (uint32_t *)pkt->pkt_resp;
5795 			rsp_code = *rsp;
5796 			rsp_code = BE_SWAP32(rsp_code);
5797 
5798 			if (rsp_code == MENLO_RSP_SUCCESS) {
5799 				/* Now transmit the data phase */
5800 
5801 				/* Save last rx_id */
5802 				uint32_t rx_id = pkt->pkt_cmd_fhdr.rx_id;
5803 
5804 				/* Free old pkt */
5805 				emlxs_pkt_free(pkt);
5806 
5807 				/* Allocate data pkt */
5808 				if (!(pkt = emlxs_pkt_alloc(port, data_size,
5809 				    *rsp_size, 0, KM_NOSLEEP))) {
5810 					EMLXS_MSGF(EMLXS_CONTEXT,
5811 					    &emlxs_dfc_error_msg,
5812 					    "emlxs_send_menlo_cmd: "
5813 					    "Unable to allocate data "
5814 					    "packet.");
5815 
5816 					rval = DFC_SYSRES_ERROR;
5817 					goto done;
5818 				}
5819 
5820 				/* Make this a polled IO */
5821 				pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5822 				pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5823 				pkt->pkt_comp = NULL;
5824 				pkt->pkt_tran_type = FC_PKT_OUTBOUND;
5825 				pkt->pkt_timeout = 30;
5826 
5827 				/* Build the fc header */
5828 				pkt->pkt_cmd_fhdr.d_id =
5829 				    LE_SWAP24_LO(EMLXS_MENLO_DID);
5830 				pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5831 				pkt->pkt_cmd_fhdr.s_id =
5832 				    LE_SWAP24_LO(port->did);
5833 				pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5834 				pkt->pkt_cmd_fhdr.f_ctl =
5835 				    F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
5836 				    F_CTL_SEQ_INITIATIVE;
5837 				pkt->pkt_cmd_fhdr.seq_id = 0;
5838 				pkt->pkt_cmd_fhdr.df_ctl = 0;
5839 				pkt->pkt_cmd_fhdr.seq_cnt = 0;
5840 				pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5841 				pkt->pkt_cmd_fhdr.rx_id = rx_id;
5842 				pkt->pkt_cmd_fhdr.ro = 0;
5843 
5844 				/* Copy in the data buffer */
5845 				bcopy((void *)data_buf, (void *)pkt->pkt_cmd,
5846 				    data_size);
5847 
5848 				if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5849 					EMLXS_MSGF(EMLXS_CONTEXT,
5850 					    &emlxs_dfc_error_msg,
5851 					    "emlxs_send_menlo_cmd: "
5852 					    "Unable to send data packet.");
5853 
5854 					rval = DFC_IO_ERROR;
5855 					goto done;
5856 				}
5857 
5858 				if (pkt->pkt_state != FC_PKT_SUCCESS) {
5859 					if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5860 						EMLXS_MSGF(EMLXS_CONTEXT,
5861 						    &emlxs_dfc_error_msg,
5862 						    "emlxs_send_menlo_cmd: "
5863 						    "Data Pkt Transport "
5864 						    "error. Pkt Timeout.");
5865 						rval = DFC_TIMEOUT;
5866 					} else if ((pkt->pkt_state ==
5867 					    FC_PKT_LOCAL_RJT) &&
5868 					    (pkt->pkt_reason ==
5869 					    FC_REASON_OVERRUN)) {
5870 						EMLXS_MSGF(EMLXS_CONTEXT,
5871 						    &emlxs_dfc_error_msg,
5872 						    "emlxs_send_menlo_cmd: "
5873 						    "Data Pkt Transport "
5874 						    "error. Response overrun.");
5875 						rval = DFC_RSP_BUF_OVERRUN;
5876 					} else {
5877 						EMLXS_MSGF(EMLXS_CONTEXT,
5878 						    &emlxs_dfc_error_msg,
5879 						    "emlxs_send_menlo_cmd: "
5880 						    "Data Pkt Transport "
5881 						    "error. state=%x",
5882 						    pkt->pkt_state);
5883 						rval = DFC_IO_ERROR;
5884 					}
5885 					goto done;
5886 				}
5887 			}
5888 		}
5889 
5890 		bcopy((void *)pkt->pkt_resp, (void *)rsp_buf, *rsp_size);
5891 		*rsp_size = *rsp_size - pkt->pkt_resp_resid;
5892 	}
5893 
5894 	rval = 0;
5895 
5896 done:
5897 
5898 	if (pkt) {
5899 		emlxs_pkt_free(pkt);
5900 	}
5901 
5902 	if (mbq) {
5903 		kmem_free(mbq, sizeof (MAILBOXQ));
5904 	}
5905 
5906 	return (rval);
5907 
5908 } /* emlxs_send_menlo_cmd() */
5909 
5910 
5911 /* ARGSUSED */
5912 extern void
5913 emlxs_fcoe_attention_thread(emlxs_hba_t *hba,
5914     void *arg1, void *arg2)
5915 {
5916 	emlxs_port_t		*port = &PPORT;
5917 	menlo_init_rsp_t	*rsp;
5918 	menlo_get_cmd_t		*cmd;
5919 	fc_packet_t		*pkt = NULL;
5920 
5921 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_get_cmd_t),
5922 	    sizeof (menlo_init_rsp_t), 0, KM_NOSLEEP))) {
5923 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5924 		    "FCoE attention: Unable to allocate packet.");
5925 
5926 		return;
5927 	}
5928 
5929 	/* Make this a polled IO */
5930 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5931 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5932 	pkt->pkt_comp = NULL;
5933 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5934 	pkt->pkt_timeout = 30;
5935 
5936 	/* Build the fc header */
5937 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
5938 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5939 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
5940 	pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5941 	pkt->pkt_cmd_fhdr.f_ctl =
5942 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
5943 	pkt->pkt_cmd_fhdr.seq_id = 0;
5944 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5945 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5946 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5947 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5948 	pkt->pkt_cmd_fhdr.ro = 0;
5949 
5950 	cmd = (menlo_get_cmd_t *)pkt->pkt_cmd;
5951 	cmd->code = MENLO_CMD_GET_INIT;
5952 	cmd->context = 0;
5953 	cmd->length = sizeof (menlo_init_rsp_t);
5954 
5955 	/* Little Endian Swap */
5956 	cmd->code = BE_SWAP32(cmd->code);
5957 	cmd->length = BE_SWAP32(cmd->length);
5958 
5959 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5960 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5961 		    "FCoE attention: Unable to send packet.");
5962 
5963 		goto done;
5964 	}
5965 
5966 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
5967 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5968 		    "FCoE attention: Pkt Transport error. state=%x",
5969 		    pkt->pkt_state);
5970 
5971 		goto done;
5972 	}
5973 
5974 	/* Check response code */
5975 	rsp = (menlo_init_rsp_t *)pkt->pkt_resp;
5976 	rsp->code = BE_SWAP32(rsp->code);
5977 
5978 	if (rsp->code != MENLO_RSP_SUCCESS) {
5979 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5980 		    "FCoE attention: FCOE Response error =%x", rsp->code);
5981 
5982 		goto done;
5983 	}
5984 
5985 	/* Little Endian Swap */
5986 	rsp->bb_credit = BE_SWAP32(rsp->bb_credit);
5987 	rsp->frame_size = BE_SWAP32(rsp->frame_size);
5988 	rsp->fw_version = BE_SWAP32(rsp->fw_version);
5989 	rsp->reset_status = BE_SWAP32(rsp->reset_status);
5990 	rsp->maint_status = BE_SWAP32(rsp->maint_status);
5991 	rsp->fw_type = BE_SWAP32(rsp->fw_type);
5992 	rsp->fru_data_valid = BE_SWAP32(rsp->fru_data_valid);
5993 
5994 	/* Log the event */
5995 	emlxs_log_fcoe_event(port, rsp);
5996 
5997 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5998 	    "MENLO_INIT: bb_credit      = 0x%x", rsp->bb_credit);
5999 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6000 	    "MENLO_INIT: frame_size     = 0x%x", rsp->frame_size);
6001 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6002 	    "MENLO_INIT: fw_version     = 0x%x", rsp->fw_version);
6003 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6004 	    "MENLO_INIT: reset_status   = 0x%x", rsp->reset_status);
6005 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6006 	    "MENLO_INIT: maint_status   = 0x%x", rsp->maint_status);
6007 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6008 	    "MENLO_INIT: fw_type        = 0x%x", rsp->fw_type);
6009 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6010 	    "MENLO_INIT: fru_data_valid = 0x%x", rsp->fru_data_valid);
6011 
6012 	/* Perform attention checks */
6013 	if (rsp->fru_data_valid == 0) {
6014 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_error_msg,
6015 		    "Invalid FRU data found on adapter. "
6016 		    "Return adapter to Emulex for repair.");
6017 	}
6018 
6019 	switch (rsp->fw_type) {
6020 	case MENLO_FW_TYPE_GOLDEN:
6021 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_warning_msg,
6022 		    "FCoE chip is running Golden firmware. "
6023 		    "Update FCoE firmware immediately.");
6024 		break;
6025 
6026 	case MENLO_FW_TYPE_DIAG:
6027 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_notice_msg,
6028 		    "FCoE chip is running Diagnostic firmware. "
6029 		    "Operational use of the adapter is suspended.");
6030 		break;
6031 	}
6032 
6033 done:
6034 
6035 	if (pkt) {
6036 		emlxs_pkt_free(pkt);
6037 	}
6038 
6039 	return;
6040 
6041 } /* emlxs_fcoe_attention_thread() */
6042 
6043 #endif /* MENLO_SUPPORT */
6044 
6045 
6046 static int32_t
6047 emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6048 {
6049 	emlxs_port_t	*port = &PPORT;
6050 	uint32_t	offset;
6051 	uint32_t	cnt;
6052 	uint8_t		*buffer;
6053 	uint8_t		*bptr;
6054 	uint32_t	i;
6055 
6056 	if (hba->bus_type != SBUS_FC) {
6057 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6058 		    "%s: Invalid bus_type. (bus_type=%x)",
6059 		    emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
6060 
6061 		return (DFC_ARG_INVALID);
6062 	}
6063 
6064 	if (!(hba->flag & FC_OFFLINE_MODE)) {
6065 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6066 		    "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
6067 
6068 		return (DFC_ONLINE_ERROR);
6069 	}
6070 
6071 	if (!dfc->buf1 || !dfc->buf1_size) {
6072 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6073 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6074 
6075 		return (DFC_ARG_NULL);
6076 	}
6077 
6078 	offset = dfc->data1;
6079 	cnt = dfc->data2;
6080 
6081 	if (offset > (64 * 1024)) {
6082 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6083 		    "%s: Offset too large. (offset=%d)",
6084 		    emlxs_dfc_xlate(dfc->cmd), offset);
6085 
6086 		return (DFC_ARG_TOOBIG);
6087 	}
6088 
6089 	if (cnt > dfc->buf1_size) {
6090 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6091 		    "%s: Count too large. (count=%d)",
6092 		    emlxs_dfc_xlate(dfc->cmd), cnt);
6093 
6094 		return (DFC_ARG_TOOBIG);
6095 	}
6096 
6097 	if ((cnt + offset) > (64 * 1024)) {
6098 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6099 		    "%s: Count+Offset too large. (count=%d offset=%d)",
6100 		    emlxs_dfc_xlate(dfc->cmd), cnt, offset);
6101 
6102 		return (DFC_ARG_TOOBIG);
6103 	}
6104 
6105 	if (cnt == 0) {
6106 		return (0);
6107 	}
6108 
6109 	if ((buffer = (uint8_t *)kmem_zalloc(cnt, KM_NOSLEEP)) == NULL) {
6110 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6111 		    "%s: Unable to allocate buffer.",
6112 		    emlxs_dfc_xlate(dfc->cmd));
6113 
6114 		return (DFC_SYSRES_ERROR);
6115 	}
6116 
6117 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer, cnt, mode) != 0) {
6118 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6119 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
6120 
6121 		kmem_free(buffer, cnt);
6122 		return (DFC_COPYIN_ERROR);
6123 	}
6124 
6125 	bptr = buffer;
6126 	for (i = 0; i < cnt; i++) {
6127 		SBUS_WRITE_FLASH_COPY(hba, offset, *bptr);
6128 		offset++;
6129 		bptr++;
6130 	}
6131 
6132 	kmem_free(buffer, cnt);
6133 
6134 #ifdef FMA_SUPPORT
6135 	/* Access handle validation */
6136 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
6137 	    != DDI_FM_OK) {
6138 		EMLXS_MSGF(EMLXS_CONTEXT,
6139 		    &emlxs_invalid_access_handle_msg, NULL);
6140 		return (DFC_DRV_ERROR);
6141 	}
6142 #endif  /* FMA_SUPPORT */
6143 
6144 	return (0);
6145 
6146 } /* emlxs_dfc_write_flash() */
6147 
6148 
6149 static int32_t
6150 emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6151 {
6152 	emlxs_port_t	*port = &PPORT;
6153 	uint32_t	offset;
6154 	uint32_t	count;
6155 	uint32_t	outsz;
6156 	uint8_t		*buffer;
6157 	uint8_t		*bptr;
6158 	uint32_t	i;
6159 
6160 	if (hba->bus_type != SBUS_FC) {
6161 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6162 		    "%s: Invalid bus_type. (bus_type=%x)",
6163 		    emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
6164 
6165 		return (DFC_ARG_INVALID);
6166 	}
6167 
6168 	if (!(hba->flag & FC_OFFLINE_MODE)) {
6169 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6170 		    "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
6171 
6172 		return (DFC_ONLINE_ERROR);
6173 	}
6174 
6175 	if (!dfc->buf1 || !dfc->buf1_size) {
6176 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6177 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6178 
6179 		return (DFC_ARG_NULL);
6180 	}
6181 
6182 	offset = dfc->data1;
6183 	count = dfc->data2;
6184 	outsz = dfc->buf1_size;
6185 
6186 	if (offset > (64 * 1024)) {
6187 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6188 		    "%s: Offset too large. (offset=%d)",
6189 		    emlxs_dfc_xlate(dfc->cmd), offset);
6190 
6191 		return (DFC_ARG_TOOBIG);
6192 	}
6193 
6194 	if ((count + offset) > (64 * 1024)) {
6195 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6196 		    "%s: Count+Offset too large. (count=%d offset=%d)",
6197 		    emlxs_dfc_xlate(dfc->cmd), count, offset);
6198 
6199 		return (DFC_ARG_TOOBIG);
6200 	}
6201 
6202 	if (count < outsz) {
6203 		outsz = count;
6204 	}
6205 
6206 	if ((buffer = (uint8_t *)kmem_zalloc(outsz, KM_NOSLEEP)) == NULL) {
6207 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6208 		    "%s: Unable to allocate buffer.",
6209 		    emlxs_dfc_xlate(dfc->cmd));
6210 
6211 		return (DFC_SYSRES_ERROR);
6212 	}
6213 
6214 	bptr = buffer;
6215 	for (i = 0; i < outsz; i++) {
6216 		*bptr++ = SBUS_READ_FLASH_COPY(hba, offset++);
6217 	}
6218 
6219 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1, outsz, mode) != 0) {
6220 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6221 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
6222 
6223 		kmem_free(buffer, outsz);
6224 		return (DFC_COPYOUT_ERROR);
6225 	}
6226 
6227 	kmem_free(buffer, outsz);
6228 
6229 #ifdef FMA_SUPPORT
6230 	/* Access handle validation */
6231 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.sbus_flash_acc_handle)
6232 	    != DDI_FM_OK) {
6233 		EMLXS_MSGF(EMLXS_CONTEXT,
6234 		    &emlxs_invalid_access_handle_msg, NULL);
6235 		return (DFC_DRV_ERROR);
6236 	}
6237 #endif  /* FMA_SUPPORT */
6238 
6239 	return (0);
6240 
6241 } /* emlxs_dfc_read_flash() */
6242 
6243 
6244 static int32_t
6245 emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6246 {
6247 	emlxs_port_t	*port = &PPORT;
6248 	uint8_t		*rsp_buf;
6249 	uint8_t		*cmd_buf;
6250 	dfc_destid_t	destid;
6251 	uint32_t	rsp_size;
6252 	uint32_t	cmd_size;
6253 	uint32_t	timeout;
6254 	fc_packet_t	*pkt = NULL;
6255 	NODELIST	*ndlp;
6256 	uint32_t	did;
6257 	uint32_t	rval = 0;
6258 	char		buffer[128];
6259 
6260 	cmd_buf = dfc->buf1;
6261 	cmd_size = dfc->buf1_size;
6262 	rsp_buf = dfc->buf2;
6263 	rsp_size = dfc->buf2_size;
6264 
6265 	timeout = 2 * hba->fc_ratov;
6266 
6267 	if (!cmd_size || !cmd_buf) {
6268 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6269 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6270 
6271 		rval = DFC_ARG_NULL;
6272 		goto done;
6273 	}
6274 
6275 	if (!rsp_buf || !rsp_size) {
6276 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6277 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
6278 
6279 		rval = DFC_ARG_NULL;
6280 		goto done;
6281 	}
6282 
6283 	if (!dfc->buf3 || !dfc->buf3_size) {
6284 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6285 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
6286 
6287 		rval = DFC_ARG_NULL;
6288 		goto done;
6289 	}
6290 
6291 	if (dfc->buf3_size < sizeof (dfc_destid_t)) {
6292 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6293 		    "%s: Buffer3 too small. (size=%d)",
6294 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
6295 
6296 		rval = DFC_ARG_TOOSMALL;
6297 		goto done;
6298 	}
6299 
6300 	if (!dfc->buf4 || !dfc->buf4_size) {
6301 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6302 		    "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
6303 
6304 		rval = DFC_ARG_NULL;
6305 		goto done;
6306 	}
6307 
6308 	if (dfc->buf4_size < sizeof (uint32_t)) {
6309 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6310 		    "%s: Buffer4 too small. (size=%d)",
6311 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
6312 
6313 		rval = DFC_ARG_TOOSMALL;
6314 		goto done;
6315 	}
6316 
6317 	if (ddi_copyin((void *)dfc->buf3, (void *)&destid,
6318 	    sizeof (dfc_destid_t), mode) != 0) {
6319 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6320 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
6321 
6322 		rval = DFC_COPYIN_ERROR;
6323 		goto done;
6324 	}
6325 
6326 	if (destid.idType == 0) {
6327 		if ((ndlp = emlxs_node_find_wwpn(port, destid.wwpn)) == NULL) {
6328 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6329 			    "%s: WWPN does not exists. %s",
6330 			    emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
6331 			    destid.wwpn));
6332 
6333 			rval = DFC_ARG_INVALID;
6334 			goto done;
6335 		}
6336 		did = ndlp->nlp_DID;
6337 	} else {
6338 		if (emlxs_node_find_did(port, destid.d_id) == NULL) {
6339 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6340 			    "%s: DID does not exist. did=%x",
6341 			    emlxs_dfc_xlate(dfc->cmd), destid.d_id);
6342 
6343 			rval = DFC_ARG_INVALID;
6344 			goto done;
6345 		}
6346 		did = destid.d_id;
6347 	}
6348 
6349 	if (did == 0) {
6350 		did = port->did;
6351 	}
6352 
6353 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
6354 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6355 		    "%s: Unable to allocate packet.",
6356 		    emlxs_dfc_xlate(dfc->cmd));
6357 
6358 		rval = DFC_SYSRES_ERROR;
6359 		goto done;
6360 	}
6361 
6362 	/* Make this a polled IO */
6363 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
6364 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
6365 	pkt->pkt_comp = NULL;
6366 
6367 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
6368 	pkt->pkt_timeout = (timeout) ? timeout : 30;
6369 
6370 	/* Build the fc header */
6371 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(did);
6372 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
6373 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
6374 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
6375 	pkt->pkt_cmd_fhdr.f_ctl =
6376 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
6377 	pkt->pkt_cmd_fhdr.seq_id = 0;
6378 	pkt->pkt_cmd_fhdr.df_ctl = 0;
6379 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
6380 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
6381 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
6382 	pkt->pkt_cmd_fhdr.ro = 0;
6383 
6384 	/* Copy in the command buffer */
6385 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd, cmd_size,
6386 	    mode) != 0) {
6387 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6388 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
6389 
6390 		rval = DFC_COPYIN_ERROR;
6391 		goto done;
6392 	}
6393 
6394 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
6395 		rval = DFC_IO_ERROR;
6396 		goto done;
6397 	}
6398 
6399 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
6400 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
6401 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6402 			    "Pkt Transport error. Pkt Timeout.");
6403 			rval = DFC_TIMEOUT;
6404 		} else {
6405 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6406 			    "Pkt Transport error. state=%x", pkt->pkt_state);
6407 			rval = DFC_IO_ERROR;
6408 		}
6409 		goto done;
6410 	}
6411 
6412 	rsp_size -= pkt->pkt_resp_resid;
6413 	if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf, rsp_size,
6414 	    mode) != 0) {
6415 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6416 		    "%s: rsp_buf ddi_copyout failed.",
6417 		    emlxs_dfc_xlate(dfc->cmd));
6418 
6419 		rval = DFC_COPYOUT_ERROR;
6420 		goto done;
6421 	}
6422 
6423 	if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf4,
6424 	    sizeof (uint32_t), mode) != 0) {
6425 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6426 		    "%s: rsp_size ddi_copyout failed.",
6427 		    emlxs_dfc_xlate(dfc->cmd));
6428 
6429 		rval = DFC_COPYOUT_ERROR;
6430 		goto done;
6431 	}
6432 
6433 	rval = 0;
6434 
6435 done:
6436 	if (pkt) {
6437 		emlxs_pkt_free(pkt);
6438 	}
6439 
6440 	return (rval);
6441 
6442 } /* emlxs_dfc_send_els() */
6443 
6444 
6445 static int32_t
6446 emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6447 {
6448 	emlxs_port_t	*port = &PPORT;
6449 	dfc_ioinfo_t	ioinfo;
6450 	uint32_t	i;
6451 
6452 	if (!dfc->buf1 || !dfc->buf1_size) {
6453 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6454 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6455 
6456 		return (DFC_ARG_NULL);
6457 	}
6458 
6459 	if (dfc->buf1_size < sizeof (dfc_ioinfo_t)) {
6460 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6461 		    "%s: Buffer1 too small. (size=%d)",
6462 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6463 
6464 		return (DFC_ARG_TOOSMALL);
6465 	}
6466 
6467 	bzero(&ioinfo, sizeof (dfc_ioinfo_t));
6468 
6469 	ioinfo.a_mboxCmd = HBASTATS.MboxIssued;
6470 	ioinfo.a_mboxCmpl = HBASTATS.MboxCompleted;
6471 	ioinfo.a_mboxErr = HBASTATS.MboxError;
6472 
6473 	for (i = 0; i < hba->chan_count; i++) {
6474 		ioinfo.a_iocbCmd += HBASTATS.IocbIssued[i];
6475 		ioinfo.a_iocbRsp += HBASTATS.IocbReceived[i];
6476 	}
6477 
6478 	ioinfo.a_adapterIntr = HBASTATS.IntrEvent[0] + HBASTATS.IntrEvent[1] +
6479 	    HBASTATS.IntrEvent[2] + HBASTATS.IntrEvent[3] +
6480 	    HBASTATS.IntrEvent[4] + HBASTATS.IntrEvent[5] +
6481 	    HBASTATS.IntrEvent[6] + HBASTATS.IntrEvent[7];
6482 
6483 	ioinfo.a_fcpCmd = HBASTATS.FcpIssued;
6484 	ioinfo.a_fcpCmpl = HBASTATS.FcpCompleted;
6485 	ioinfo.a_fcpErr = HBASTATS.FcpCompleted - HBASTATS.FcpGood;
6486 
6487 	ioinfo.a_seqXmit = HBASTATS.IpSeqIssued;
6488 	ioinfo.a_seqRcv = HBASTATS.IpSeqReceived;
6489 	ioinfo.a_seqXmitErr = HBASTATS.IpSeqCompleted - HBASTATS.IpSeqGood;
6490 
6491 	ioinfo.a_bcastXmit = HBASTATS.IpBcastIssued;
6492 	ioinfo.a_bcastRcv = HBASTATS.IpBcastReceived;
6493 
6494 	ioinfo.a_elsXmit = HBASTATS.ElsCmdIssued;
6495 	ioinfo.a_elsRcv = HBASTATS.ElsCmdReceived;
6496 	ioinfo.a_elsXmitErr = HBASTATS.ElsCmdCompleted - HBASTATS.ElsCmdGood;
6497 
6498 	ioinfo.a_RSCNRcv = HBASTATS.ElsRscnReceived;
6499 
6500 	ioinfo.a_elsBufPost = HBASTATS.ElsUbPosted;
6501 	ioinfo.a_ipBufPost = HBASTATS.IpUbPosted;
6502 
6503 	ioinfo.a_cnt1 = 0;
6504 	ioinfo.a_cnt2 = 0;
6505 	ioinfo.a_cnt3 = 0;
6506 	ioinfo.a_cnt4 = 0;
6507 
6508 	if (ddi_copyout((void *)&ioinfo, (void *)dfc->buf1,
6509 	    sizeof (dfc_ioinfo_t), mode) != 0) {
6510 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6511 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
6512 
6513 		return (DFC_COPYOUT_ERROR);
6514 	}
6515 
6516 	return (0);
6517 
6518 } /* emlxs_dfc_get_ioinfo() */
6519 
6520 
6521 static int32_t
6522 emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6523 {
6524 	emlxs_port_t	*port = &PPORT;
6525 	dfc_linkinfo_t	linkinfo;
6526 
6527 	if (!dfc->buf1 || !dfc->buf1_size) {
6528 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6529 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6530 
6531 		return (DFC_ARG_NULL);
6532 	}
6533 
6534 	if (dfc->buf1_size < sizeof (dfc_linkinfo_t)) {
6535 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6536 		    "%s: Buffer1 too small. (size=%d)",
6537 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6538 
6539 		return (DFC_ARG_TOOSMALL);
6540 	}
6541 
6542 	bzero(&linkinfo, sizeof (dfc_linkinfo_t));
6543 
6544 	linkinfo.a_linkEventTag = hba->link_event_tag;
6545 	linkinfo.a_linkUp = HBASTATS.LinkUp;
6546 	linkinfo.a_linkDown = HBASTATS.LinkDown;
6547 	linkinfo.a_linkMulti = HBASTATS.LinkMultiEvent;
6548 	linkinfo.a_DID = port->did;
6549 	linkinfo.a_topology = 0;
6550 
6551 	if (hba->state <= FC_LINK_DOWN) {
6552 		linkinfo.a_linkState = LNK_DOWN;
6553 	}
6554 #ifdef MENLO_SUPPORT
6555 	else if (hba->flag & FC_MENLO_MODE) {
6556 		linkinfo.a_linkState = LNK_DOWN;
6557 		linkinfo.a_topology  = LNK_MENLO_MAINTENANCE;
6558 
6559 	}
6560 #endif /* MENLO_SUPPORT */
6561 	else if (hba->state == FC_LINK_DOWN_PERSIST) {
6562 		linkinfo.a_linkState = LNK_DOWN_PERSIST;
6563 	} else if (hba->state < FC_READY) {
6564 		linkinfo.a_linkState = LNK_DISCOVERY;
6565 	} else {
6566 		linkinfo.a_linkState = LNK_READY;
6567 	}
6568 
6569 	if (linkinfo.a_linkState != LNK_DOWN) {
6570 		if (hba->topology == TOPOLOGY_LOOP) {
6571 			if (hba->flag & FC_FABRIC_ATTACHED) {
6572 				linkinfo.a_topology = LNK_PUBLIC_LOOP;
6573 			} else {
6574 				linkinfo.a_topology = LNK_LOOP;
6575 			}
6576 
6577 			linkinfo.a_alpa = port->did & 0xff;
6578 			linkinfo.a_alpaCnt = port->alpa_map[0];
6579 
6580 			if (linkinfo.a_alpaCnt > 127) {
6581 				linkinfo.a_alpaCnt = 127;
6582 			}
6583 
6584 			bcopy((void *)&port->alpa_map[0], linkinfo.a_alpaMap,
6585 			    linkinfo.a_alpaCnt+1);
6586 		} else {
6587 			if (hba->flag & FC_FABRIC_ATTACHED) {
6588 				linkinfo.a_topology = LNK_FABRIC;
6589 			} else {
6590 				linkinfo.a_topology = LNK_PT2PT;
6591 			}
6592 		}
6593 	}
6594 
6595 	bcopy(&hba->wwpn, linkinfo.a_wwpName, 8);
6596 	bcopy(&hba->wwnn, linkinfo.a_wwnName, 8);
6597 
6598 	if (ddi_copyout((void *)&linkinfo, (void *)dfc->buf1,
6599 	    sizeof (dfc_linkinfo_t), mode) != 0) {
6600 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6601 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
6602 
6603 		return (DFC_COPYOUT_ERROR);
6604 	}
6605 
6606 	return (0);
6607 
6608 } /* emlxs_dfc_get_linkinfo() */
6609 
6610 #ifdef SFCT_SUPPORT
6611 static int32_t
6612 emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6613 {
6614 	emlxs_port_t		*port = &PPORT;
6615 	emlxs_tgtport_stat_t	*statp = &TGTPORTSTAT;
6616 	dfc_tgtport_stat_t	dfcstat;
6617 
6618 	if (!dfc->buf1 || !dfc->buf1_size) {
6619 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6620 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6621 
6622 		return (DFC_ARG_NULL);
6623 	}
6624 
6625 	if (dfc->buf1_size < sizeof (emlxs_tgtport_stat_t)) {
6626 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6627 		    "%s: Buffer1 too small. (size=%d)",
6628 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6629 
6630 		return (DFC_ARG_TOOSMALL);
6631 	}
6632 
6633 	bzero(&dfcstat, sizeof (dfcstat));
6634 
6635 	dfcstat.Version = DFC_TGTPORT_STAT_VERSION;
6636 
6637 	dfcstat.FctRcvDropped = statp->FctRcvDropped;
6638 	dfcstat.FctOverQDepth = statp->FctOverQDepth;
6639 	dfcstat.FctOutstandingIO = statp->FctOutstandingIO;
6640 	dfcstat.FctFailedPortRegister = statp->FctFailedPortRegister;
6641 	dfcstat.FctPortRegister = statp->FctPortRegister;
6642 	dfcstat.FctPortDeregister = statp->FctPortDeregister;
6643 
6644 	dfcstat.FctAbortSent = statp->FctAbortSent;
6645 	dfcstat.FctNoBuffer = statp->FctNoBuffer;
6646 	dfcstat.FctScsiStatusErr = statp->FctScsiStatusErr;
6647 	dfcstat.FctScsiQfullErr = statp->FctScsiQfullErr;
6648 	dfcstat.FctScsiResidOver = statp->FctScsiResidOver;
6649 	dfcstat.FctScsiResidUnder = statp->FctScsiResidUnder;
6650 	dfcstat.FctScsiSenseErr = statp->FctScsiSenseErr;
6651 
6652 	dfcstat.FctEvent = statp->FctEvent;
6653 	dfcstat.FctCompleted = statp->FctCompleted;
6654 	dfcstat.FctCmplGood = statp->FctCmplGood;
6655 	dfcstat.FctCmplError = statp->FctCmplError;
6656 	dfcstat.FctStray = statp->FctStray;
6657 
6658 	bcopy(&statp->FctP2IOWcnt[0], &dfcstat.FctP2IOWcnt[0],
6659 	    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
6660 	bcopy(&statp->FctP2IORcnt[0], &dfcstat.FctP2IORcnt[0],
6661 	    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
6662 	dfcstat.FctIOCmdCnt = statp->FctIOCmdCnt;
6663 	dfcstat.FctReadBytes = statp->FctReadBytes;
6664 	dfcstat.FctWriteBytes = statp->FctWriteBytes;
6665 	dfcstat.FctCmdReceived = statp->FctCmdReceived;
6666 
6667 	if (dfc->flag) {	/* Clear counters after read */
6668 		bzero(&statp->FctP2IOWcnt[0],
6669 		    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
6670 		bzero(&statp->FctP2IORcnt[0],
6671 		    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
6672 		statp->FctIOCmdCnt = 0;
6673 		statp->FctReadBytes = 0;
6674 		statp->FctWriteBytes = 0;
6675 		statp->FctCmdReceived = 0;
6676 	}
6677 	if (hba->state <= FC_LINK_DOWN) {
6678 		dfcstat.FctLinkState = LNK_DOWN;
6679 	}
6680 #ifdef MENLO_SUPPORT
6681 	else if (hba->flag & FC_MENLO_MODE) {
6682 		dfcstat.FctLinkState = LNK_DOWN;
6683 	}
6684 #endif /* MENLO_SUPPORT */
6685 	else if (hba->state < FC_READY) {
6686 		dfcstat.FctLinkState = LNK_DISCOVERY;
6687 	} else {
6688 		dfcstat.FctLinkState = LNK_READY;
6689 	}
6690 
6691 	if (ddi_copyout((void *)&dfcstat, (void *)dfc->buf1,
6692 	    sizeof (dfc_tgtport_stat_t), mode) != 0) {
6693 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6694 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
6695 
6696 		return (DFC_COPYOUT_ERROR);
6697 	}
6698 
6699 	return (0);
6700 
6701 } /* emlxs_dfc_get_fctstat() */
6702 #endif /* SFCT_SUPPORT */
6703 
6704 static int32_t
6705 emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6706 {
6707 	emlxs_port_t	*port;
6708 	emlxs_config_t	*cfg = &CFG;
6709 	dfc_node_t	*dfc_node;
6710 	dfc_node_t	*dnp;
6711 	uint32_t	node_count;
6712 	NODELIST	*nlp;
6713 	uint32_t	size;
6714 	uint32_t	i;
6715 
6716 	port = &VPORT(dfc->data1);
6717 
6718 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
6719 	    emlxs_dfc_xlate(dfc->cmd));
6720 
6721 	if (!dfc->buf1 || !dfc->buf1_size) {
6722 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6723 		    "%s: NULL buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6724 
6725 		return (DFC_ARG_NULL);
6726 	}
6727 
6728 	if (dfc->buf1_size < (sizeof (dfc_node_t) * MAX_NODES)) {
6729 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6730 		    "%s: Buffer1 too small. (size=%d)",
6731 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6732 
6733 		return (DFC_ARG_TOOSMALL);
6734 	}
6735 
6736 	if (!dfc->buf2 || !dfc->buf2_size) {
6737 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6738 		    "%s: NULL buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
6739 
6740 		return (DFC_ARG_NULL);
6741 	}
6742 
6743 	if (dfc->buf2_size < sizeof (uint32_t)) {
6744 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6745 		    "%s: Buffer2 too small. (size=%d)",
6746 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
6747 
6748 		return (DFC_ARG_TOOSMALL);
6749 	}
6750 
6751 	node_count = port->node_count;
6752 
6753 	if (node_count == 0) {
6754 		return (0);
6755 	}
6756 
6757 	if (node_count > MAX_NODES) {
6758 		node_count = MAX_NODES;
6759 	}
6760 
6761 	size = node_count * sizeof (dfc_node_t);
6762 
6763 	if (!(dfc_node = (dfc_node_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6764 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6765 		    "%s: Unable to allocate dfc_node.",
6766 		    emlxs_dfc_xlate(dfc->cmd));
6767 
6768 		return (DFC_SYSRES_ERROR);
6769 	}
6770 
6771 	dnp = dfc_node;
6772 
6773 	rw_enter(&port->node_rwlock, RW_READER);
6774 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
6775 		nlp = port->node_table[i];
6776 		while (nlp != NULL) {
6777 			dnp->port_id = nlp->nlp_DID;
6778 			dnp->rpi = nlp->nlp_Rpi;
6779 			dnp->xri = nlp->nlp_Xri;
6780 
6781 			bcopy((char *)&nlp->sparm, (char *)&dnp->sparm,
6782 			    sizeof (dnp->sparm));
6783 
6784 			if (nlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE) {
6785 				dnp->flags |= PORT_FLAG_FCP_TARGET;
6786 			}
6787 			if (nlp->nlp_fcp_info & NLP_FCP_INI_DEVICE) {
6788 				dnp->flags |= PORT_FLAG_FCP_INI;
6789 
6790 			}
6791 			if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
6792 				dnp->flags |= PORT_FLAG_FCP2;
6793 			}
6794 			if (cfg[CFG_NETWORK_ON].current && nlp->nlp_Xri) {
6795 				dnp->flags |= PORT_FLAG_IP;
6796 			}
6797 			if (nlp->nlp_fcp_info & NLP_EMLX_VPORT) {
6798 				dnp->flags |= PORT_FLAG_VPORT;
6799 			}
6800 
6801 			dnp++;
6802 			nlp = (NODELIST *) nlp->nlp_list_next;
6803 		}
6804 	}
6805 	rw_exit(&port->node_rwlock);
6806 
6807 	if (ddi_copyout((void *)dfc_node, (void *)dfc->buf1, size, mode) != 0) {
6808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6809 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
6810 
6811 		kmem_free(dfc_node, size);
6812 		return (DFC_COPYOUT_ERROR);
6813 	}
6814 
6815 	if (ddi_copyout((void *)&node_count, (void *)dfc->buf2,
6816 	    sizeof (uint32_t), mode) != 0) {
6817 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6818 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
6819 
6820 		kmem_free(dfc_node, size);
6821 		return (DFC_COPYOUT_ERROR);
6822 	}
6823 
6824 	kmem_free(dfc_node, size);
6825 
6826 	return (0);
6827 
6828 } /* emlxs_dfc_get_nodeinfo() */
6829 
6830 
6831 static int32_t
6832 emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6833 {
6834 	emlxs_port_t	*port = &PPORT;
6835 	uint32_t	offset;
6836 	uint32_t	size;
6837 	uint32_t	max_size;
6838 	uint8_t		*buffer;
6839 	uint8_t		*slim;
6840 
6841 	offset = dfc->data1;
6842 	size = dfc->data2;
6843 
6844 	if (!dfc->buf1 || !dfc->buf1_size) {
6845 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6846 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6847 
6848 		return (DFC_ARG_NULL);
6849 	}
6850 
6851 	if (size > dfc->buf1_size) {
6852 		size = dfc->buf1_size;
6853 	}
6854 
6855 	if (offset % 4) {
6856 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6857 		    "%s: Offset misaligned. (offset=%d)",
6858 		    emlxs_dfc_xlate(dfc->cmd), offset);
6859 
6860 		return (DFC_ARG_MISALIGNED);
6861 	}
6862 
6863 	if (size % 4) {
6864 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6865 		    "%s: Size misaligned. (size=%d)",
6866 		    emlxs_dfc_xlate(dfc->cmd), size);
6867 
6868 		return (DFC_ARG_MISALIGNED);
6869 	}
6870 
6871 	if (hba->flag & FC_SLIM2_MODE) {
6872 		max_size = SLI2_SLIM2_SIZE;
6873 	} else {
6874 		max_size = 4096;
6875 	}
6876 
6877 	if (offset >= max_size) {
6878 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6879 		    "%s: Offset too large. (offset=%d)",
6880 		    emlxs_dfc_xlate(dfc->cmd), offset);
6881 
6882 		return (DFC_ARG_TOOBIG);
6883 	}
6884 
6885 	if ((size + offset) > max_size) {
6886 		size = (max_size - offset);
6887 	}
6888 
6889 	if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6890 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6891 		    "%s: Unable to allocate buffer.",
6892 		    emlxs_dfc_xlate(dfc->cmd));
6893 
6894 		return (DFC_SYSRES_ERROR);
6895 	}
6896 
6897 	if (hba->flag & FC_SLIM2_MODE) {
6898 		slim = (uint8_t *)hba->sli.sli3.slim2.virt + offset;
6899 		BE_SWAP32_BCOPY((uint8_t *)slim, (uint8_t *)buffer, size);
6900 	} else {
6901 		slim = (uint8_t *)hba->sli.sli3.slim_addr + offset;
6902 		READ_SLIM_COPY(hba, (uint32_t *)buffer, (uint32_t *)slim,
6903 		    (size / 4));
6904 	}
6905 
6906 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1, size, mode) != 0) {
6907 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6908 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
6909 
6910 		kmem_free(buffer, size);
6911 		return (DFC_COPYOUT_ERROR);
6912 	}
6913 
6914 	kmem_free(buffer, size);
6915 
6916 #ifdef FMA_SUPPORT
6917 	/* Access handle validation */
6918 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
6919 	    != DDI_FM_OK) {
6920 		EMLXS_MSGF(EMLXS_CONTEXT,
6921 		    &emlxs_invalid_access_handle_msg, NULL);
6922 		return (DFC_DRV_ERROR);
6923 	}
6924 #endif  /* FMA_SUPPORT */
6925 
6926 	return (0);
6927 
6928 } /* emlxs_dfc_read_mem() */
6929 
6930 
6931 static int32_t
6932 emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6933 {
6934 	emlxs_port_t	*port = &PPORT;
6935 	uint32_t	offset;
6936 	uint32_t	size;
6937 	uint32_t	max_size;
6938 	uint8_t		*buffer;
6939 	uint8_t		*slim;
6940 
6941 	offset = dfc->data1;
6942 	size = dfc->data2;
6943 
6944 	if (!dfc->buf1 || !dfc->buf1_size) {
6945 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6946 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
6947 
6948 		return (DFC_ARG_NULL);
6949 	}
6950 
6951 	if (size > dfc->buf1_size) {
6952 		size = dfc->buf1_size;
6953 	}
6954 
6955 	if (offset % 4) {
6956 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6957 		    "%s: Offset misaligned. (offset=%d)",
6958 		    emlxs_dfc_xlate(dfc->cmd), offset);
6959 
6960 		return (DFC_ARG_MISALIGNED);
6961 	}
6962 
6963 	if (size % 4) {
6964 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6965 		    "%s: Size misaligned. (szie=%d)",
6966 		    emlxs_dfc_xlate(dfc->cmd), size);
6967 
6968 		return (DFC_ARG_MISALIGNED);
6969 	}
6970 
6971 	if (hba->flag & FC_SLIM2_MODE) {
6972 		max_size = SLI2_SLIM2_SIZE;
6973 	} else {
6974 		max_size = 4096;
6975 	}
6976 
6977 	if (offset >= max_size) {
6978 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6979 		    "%s: Offset too large. (offset=%d)",
6980 		    emlxs_dfc_xlate(dfc->cmd), offset);
6981 
6982 		return (DFC_ARG_TOOBIG);
6983 	}
6984 
6985 	if ((size + offset) > max_size) {
6986 		size = (max_size - offset);
6987 	}
6988 
6989 	if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6990 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6991 		    "%s: Unable to allocate buffer.",
6992 		    emlxs_dfc_xlate(dfc->cmd));
6993 
6994 		return (DFC_SYSRES_ERROR);
6995 	}
6996 
6997 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer, size, mode) != 0) {
6998 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6999 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
7000 
7001 		kmem_free(buffer, size);
7002 		return (DFC_COPYIN_ERROR);
7003 	}
7004 
7005 	if (hba->flag & FC_SLIM2_MODE) {
7006 		slim = (uint8_t *)hba->sli.sli3.slim2.virt + offset;
7007 		BE_SWAP32_BCOPY((uint8_t *)buffer, (uint8_t *)slim, size);
7008 	} else {
7009 		slim = (uint8_t *)hba->sli.sli3.slim_addr + offset;
7010 		WRITE_SLIM_COPY(hba, (uint32_t *)buffer, (uint32_t *)slim,
7011 		    (size / 4));
7012 	}
7013 
7014 	kmem_free(buffer, size);
7015 
7016 #ifdef FMA_SUPPORT
7017 	/* Access handle validation */
7018 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.slim_acc_handle)
7019 	    != DDI_FM_OK) {
7020 		EMLXS_MSGF(EMLXS_CONTEXT,
7021 		    &emlxs_invalid_access_handle_msg, NULL);
7022 		return (DFC_DRV_ERROR);
7023 	}
7024 #endif  /* FMA_SUPPORT */
7025 
7026 	return (0);
7027 
7028 } /* emlxs_dfc_write_mem() */
7029 
7030 
7031 /* ARGSUSED */
7032 static int32_t
7033 emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7034 {
7035 	emlxs_port_t	*port = &PPORT;
7036 	uint32_t	offset;
7037 	uint32_t	value;
7038 
7039 	offset = dfc->data1;
7040 	value = dfc->data2;
7041 
7042 	if (hba->model_info.flags & EMLXS_FCOE_SUPPORTED) {
7043 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7044 		    "%s: FCoE not  supported.", emlxs_dfc_xlate(dfc->cmd));
7045 
7046 		return (DFC_FCOE_NOTSUPPORTED);
7047 	}
7048 
7049 	if (!(hba->flag & FC_OFFLINE_MODE)) {
7050 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7051 		    "%s: Adapter not offline.", emlxs_dfc_xlate(dfc->cmd));
7052 
7053 		return (DFC_ONLINE_ERROR);
7054 	}
7055 
7056 	if (offset % 4) {
7057 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7058 		    "%s: Offset misaligned. (offset=%d)",
7059 		    emlxs_dfc_xlate(dfc->cmd), offset);
7060 
7061 		return (DFC_ARG_MISALIGNED);
7062 	}
7063 
7064 	if (offset > 255) {
7065 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7066 		    "%s: Offset too large. (offset=%d)",
7067 		    emlxs_dfc_xlate(dfc->cmd), offset);
7068 
7069 		return (DFC_ARG_TOOBIG);
7070 	}
7071 
7072 	WRITE_CSR_REG(hba, (hba->sli.sli3.csr_addr + offset), value);
7073 
7074 #ifdef FMA_SUPPORT
7075 	/* Access handle validation */
7076 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7077 	    != DDI_FM_OK) {
7078 		EMLXS_MSGF(EMLXS_CONTEXT,
7079 		    &emlxs_invalid_access_handle_msg, NULL);
7080 		return (DFC_DRV_ERROR);
7081 	}
7082 #endif  /* FMA_SUPPORT */
7083 
7084 	return (0);
7085 
7086 } /* emlxs_dfc_write_ctlreg() */
7087 
7088 
7089 static int32_t
7090 emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7091 {
7092 	emlxs_port_t	*port = &PPORT;
7093 	uint32_t	offset;
7094 	uint32_t	value;
7095 
7096 	offset = dfc->data1;
7097 
7098 	if (hba->model_info.flags & EMLXS_FCOE_SUPPORTED) {
7099 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7100 		    "%s: FCoE not  supported.", emlxs_dfc_xlate(dfc->cmd));
7101 
7102 		return (DFC_FCOE_NOTSUPPORTED);
7103 	}
7104 
7105 	if (offset % 4) {
7106 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7107 		    "%s: Offset misaligned. (offset=%d)",
7108 		    emlxs_dfc_xlate(dfc->cmd), offset);
7109 
7110 		return (DFC_ARG_MISALIGNED);
7111 	}
7112 
7113 	if (offset > 255) {
7114 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7115 		    "%s: Offset too large. (offset=%d)",
7116 		    emlxs_dfc_xlate(dfc->cmd), offset);
7117 
7118 		return (DFC_ARG_TOOBIG);
7119 	}
7120 
7121 	if (!dfc->buf1 || !dfc->buf1_size) {
7122 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7123 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
7124 
7125 		return (DFC_ARG_NULL);
7126 	}
7127 
7128 	if (dfc->buf1_size < sizeof (uint32_t)) {
7129 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7130 		    "%s: Buffer1 too small. (size=%d)",
7131 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7132 
7133 		return (DFC_ARG_TOOSMALL);
7134 	}
7135 
7136 	value = READ_CSR_REG(hba, (hba->sli.sli3.csr_addr + offset));
7137 
7138 	if (ddi_copyout((void *)&value, (void *)dfc->buf1, sizeof (uint32_t),
7139 	    mode) != 0) {
7140 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7141 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
7142 
7143 		return (DFC_COPYOUT_ERROR);
7144 	}
7145 
7146 #ifdef FMA_SUPPORT
7147 	/* Access handle validation */
7148 	if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7149 	    != DDI_FM_OK) {
7150 		EMLXS_MSGF(EMLXS_CONTEXT,
7151 		    &emlxs_invalid_access_handle_msg, NULL);
7152 		return (DFC_DRV_ERROR);
7153 	}
7154 #endif  /* FMA_SUPPORT */
7155 
7156 	return (0);
7157 
7158 } /* emlxs_dfc_read_ctlreg() */
7159 
7160 
7161 static int32_t
7162 emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7163 {
7164 	emlxs_port_t		*port = &PPORT;
7165 	uint32_t		event;
7166 	uint32_t		enable;
7167 	uint32_t		pid;
7168 	uint32_t		count;
7169 	uint32_t		i;
7170 	emlxs_dfc_event_t	*dfc_event;
7171 
7172 	event = dfc->data1;
7173 	pid = dfc->data2;
7174 	enable = dfc->flag;
7175 
7176 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7177 	    "%s: %s. pid=%d enable=%d", emlxs_dfc_xlate(dfc->cmd),
7178 	    emlxs_dfc_event_xlate(event), pid, enable);
7179 
7180 	switch (event) {
7181 	case FC_REG_LINK_EVENT:
7182 	case FC_REG_RSCN_EVENT:
7183 	case FC_REG_CT_EVENT:
7184 	case FC_REG_DUMP_EVENT:
7185 	case FC_REG_TEMP_EVENT:
7186 	case FC_REG_VPORTRSCN_EVENT:
7187 	case FC_REG_FCOE_EVENT:
7188 		break;
7189 
7190 	case FC_REG_MULTIPULSE_EVENT:
7191 	default:
7192 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7193 		    "%s: %s. Invalid event. pid=%d enable=%d",
7194 		    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7195 		    pid, enable);
7196 
7197 		return (DFC_ARG_INVALID);
7198 	}
7199 
7200 	if (enable) {
7201 		if (dfc->buf1_size < sizeof (uint32_t)) {
7202 			dfc->buf1 = NULL;
7203 		} else if (!dfc->buf1) {
7204 			dfc->buf1_size = 0;
7205 		}
7206 
7207 		/* Make sure this pid/event is not already registered */
7208 		dfc_event = NULL;
7209 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
7210 			dfc_event = &hba->dfc_event[i];
7211 
7212 			if (dfc_event->pid == pid &&
7213 			    dfc_event->event == event) {
7214 				break;
7215 			}
7216 		}
7217 
7218 		if (i == MAX_DFC_EVENTS) {
7219 			/* Find next available event object */
7220 			for (i = 0; i < MAX_DFC_EVENTS; i++) {
7221 				dfc_event = &hba->dfc_event[i];
7222 
7223 				if (!dfc_event->pid && !dfc_event->event) {
7224 					break;
7225 				}
7226 			}
7227 
7228 			/* Return if all event objects are busy */
7229 			if (i == MAX_DFC_EVENTS) {
7230 				EMLXS_MSGF(EMLXS_CONTEXT,
7231 				    &emlxs_dfc_error_msg,
7232 				    "%s: %s. Too many events registered. "
7233 				    "pid=%d enable=%d",
7234 				    emlxs_dfc_xlate(dfc->cmd),
7235 				    emlxs_dfc_event_xlate(event), pid,
7236 				    enable);
7237 
7238 				return (DFC_DRVRES_ERROR);
7239 			}
7240 		}
7241 
7242 		/* Initialize */
7243 		dfc_event->pid = pid;
7244 		dfc_event->event = event;
7245 		dfc_event->last_id = (uint32_t)-1;
7246 		dfc_event->dataout = NULL;
7247 		dfc_event->size = 0;
7248 		dfc_event->mode = 0;
7249 
7250 		(void) emlxs_get_dfc_event(port, dfc_event, 0);
7251 
7252 		if (dfc->buf1) {
7253 			if (ddi_copyout((void *)&dfc_event->last_id,
7254 			    dfc->buf1, sizeof (uint32_t), mode) != 0) {
7255 				EMLXS_MSGF(EMLXS_CONTEXT,
7256 				    &emlxs_dfc_error_msg,
7257 				    "%s: ddi_copyout failed.",
7258 				    emlxs_dfc_xlate(dfc->cmd));
7259 
7260 				return (DFC_COPYOUT_ERROR);
7261 			}
7262 		}
7263 
7264 		/*
7265 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7266 		 * "%s: %s. Enabled. pid=%d id=%d", emlxs_dfc_xlate(dfc->cmd),
7267 		 * emlxs_dfc_event_xlate(event), pid, dfc_event->last_id);
7268 		 */
7269 
7270 		hba->event_mask |= event;
7271 
7272 	} else {	/* Disable */
7273 
7274 		/* Find the event entry */
7275 		dfc_event = NULL;
7276 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
7277 			dfc_event = &hba->dfc_event[i];
7278 
7279 			if (dfc_event->pid == pid &&
7280 			    dfc_event->event == event) {
7281 				break;
7282 			}
7283 		}
7284 
7285 		if (i == MAX_DFC_EVENTS) {
7286 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7287 			    "%s: %s. Event not registered. pid=%d enable=%d",
7288 			    emlxs_dfc_xlate(dfc->cmd),
7289 			    emlxs_dfc_event_xlate(event), pid, enable);
7290 
7291 			return (DFC_ARG_INVALID);
7292 		}
7293 
7294 		/* Kill the event thread if it is sleeping */
7295 		(void) emlxs_kill_dfc_event(port, dfc_event);
7296 
7297 		/* Count the number of pids still registered for this event */
7298 		count = 0;
7299 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
7300 			dfc_event = &hba->dfc_event[i];
7301 
7302 			if (dfc_event->event == event) {
7303 				count++;
7304 			}
7305 		}
7306 
7307 		/* If no more pids need this event, */
7308 		/* then disable logging for this event */
7309 		if (count == 0) {
7310 			hba->event_mask &= ~event;
7311 		}
7312 	}
7313 
7314 	return (0);
7315 
7316 } /* emlxs_dfc_set_event() */
7317 
7318 
7319 static int32_t
7320 emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7321 {
7322 	emlxs_port_t	*port = &PPORT;
7323 	uint32_t	size;
7324 	int32_t		rval = 0;
7325 	HBA_EVENTINFO 	*event_buffer = NULL;
7326 	uint32_t	event_count = 0;
7327 	uint32_t	missed = 0;
7328 
7329 	if (!dfc->buf1 || !dfc->buf1_size) {
7330 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7331 		    "%s: Null buffer1 buffer.", emlxs_dfc_xlate(dfc->cmd));
7332 
7333 		return (DFC_ARG_NULL);
7334 	}
7335 
7336 	event_count = dfc->buf1_size / sizeof (HBA_EVENTINFO);
7337 
7338 	if (!event_count) {
7339 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7340 		    "%s: Buffer1 too small. (size=%d)",
7341 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7342 
7343 		return (DFC_ARG_TOOSMALL);
7344 	}
7345 
7346 	if (!dfc->buf2 || !dfc->buf2_size) {
7347 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7348 		    "%s: Null buffer2 buffer.", emlxs_dfc_xlate(dfc->cmd));
7349 
7350 		return (DFC_ARG_NULL);
7351 	}
7352 
7353 	if (dfc->buf2_size < sizeof (uint32_t)) {
7354 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7355 		    "%s: Buffer2 too small. (size=%d)",
7356 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
7357 
7358 		return (DFC_ARG_TOOSMALL);
7359 	}
7360 
7361 	if (!dfc->buf3 || !dfc->buf3_size) {
7362 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7363 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
7364 
7365 		return (DFC_ARG_NULL);
7366 	}
7367 
7368 	if (dfc->buf3_size < sizeof (uint32_t)) {
7369 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7370 		    "%s: Buffer3 too small. (size=%d)",
7371 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
7372 
7373 		return (DFC_ARG_TOOSMALL);
7374 	}
7375 
7376 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s called. max=%d",
7377 	    emlxs_dfc_xlate(dfc->cmd), event_count);
7378 
7379 	size = (event_count * sizeof (HBA_EVENTINFO));
7380 	event_buffer = (HBA_EVENTINFO *)kmem_zalloc(size, KM_SLEEP);
7381 
7382 	if (emlxs_get_dfc_eventinfo(port, event_buffer, &event_count,
7383 	    &missed) != 0) {
7384 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7385 		    "%s: emlxs_get_dfc_eventinfo failed.",
7386 		    emlxs_dfc_xlate(dfc->cmd));
7387 
7388 		rval = DFC_DRV_ERROR;
7389 		goto done;
7390 	}
7391 
7392 	if (event_count) {
7393 		if (ddi_copyout((void *)event_buffer, dfc->buf1,
7394 		    (event_count * sizeof (HBA_EVENTINFO)), mode) != 0) {
7395 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7396 			    "%s: ddi_copyout failed.",
7397 			    emlxs_dfc_xlate(dfc->cmd));
7398 
7399 			rval = DFC_COPYOUT_ERROR;
7400 			goto done;
7401 		}
7402 	}
7403 
7404 	if (ddi_copyout((void *)&event_count, dfc->buf2, sizeof (uint32_t),
7405 	    mode) != 0) {
7406 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7407 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
7408 
7409 		rval = DFC_COPYOUT_ERROR;
7410 		goto done;
7411 	}
7412 
7413 	if (ddi_copyout((void *)&missed, dfc->buf3, sizeof (uint32_t),
7414 	    mode) != 0) {
7415 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7416 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
7417 
7418 		rval = DFC_COPYOUT_ERROR;
7419 		goto done;
7420 	}
7421 
7422 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7423 	    "%s: events=%d missed=%d new=%d last_id=%d",
7424 	    emlxs_dfc_xlate(dfc->cmd), event_count, hba->hba_event.missed,
7425 	    hba->hba_event.new, hba->hba_event.last_id);
7426 
7427 done:
7428 
7429 	if (event_buffer) {
7430 		kmem_free(event_buffer, size);
7431 	}
7432 
7433 	return (rval);
7434 
7435 } /* emlxs_dfc_get_eventinfo() */
7436 
7437 
7438 static int32_t
7439 emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7440 {
7441 	emlxs_port_t		*port = &PPORT;
7442 	uint32_t		event;
7443 	uint32_t		pid;
7444 	uint32_t		sleep;
7445 	uint32_t		i;
7446 	int32_t			rval = DFC_SUCCESS;
7447 	emlxs_dfc_event_t	*dfc_event;
7448 
7449 	event = dfc->data1;
7450 	pid = dfc->data2;
7451 
7452 	if (!dfc->buf1_size) {
7453 		dfc->buf1 = NULL;
7454 	} else if (!dfc->buf1) {
7455 		dfc->buf1_size = 0;
7456 	}
7457 
7458 	if (dfc->buf2_size < sizeof (uint32_t)) {
7459 		dfc->buf2 = NULL;
7460 	} else if (!dfc->buf2) {
7461 		dfc->buf2_size = 0;
7462 	}
7463 
7464 	if (dfc->buf3_size < sizeof (uint32_t)) {
7465 		dfc->buf3 = NULL;
7466 	} else if (!dfc->buf3) {
7467 		dfc->buf3_size = 0;
7468 	}
7469 
7470 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7471 	    "%s: %s. pid=%d size=%d,%p rcv_size=%d,%p id=%d",
7472 	    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), pid,
7473 	    dfc->buf1_size, dfc->buf1, dfc->buf2_size, dfc->buf2, dfc->data3);
7474 
7475 	/* Find the event entry */
7476 	dfc_event = NULL;
7477 	for (i = 0; i < MAX_DFC_EVENTS; i++) {
7478 		dfc_event = &hba->dfc_event[i];
7479 
7480 		if (dfc_event->pid == pid && dfc_event->event == event) {
7481 			break;
7482 		}
7483 	}
7484 
7485 	if (i == MAX_DFC_EVENTS) {
7486 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7487 		    "%s: %s. Event not registered. pid=%d",
7488 		    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7489 		    pid);
7490 
7491 		return (DFC_ARG_INVALID);
7492 	}
7493 
7494 	if (!(hba->event_mask & dfc_event->event)) {
7495 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7496 		    "%s: %s. Event not registered. pid=%d",
7497 		    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7498 		    pid);
7499 
7500 		return (DFC_ARG_INVALID);
7501 	}
7502 
7503 	/* Initialize event buffer pointers */
7504 	dfc_event->dataout = dfc->buf1;
7505 	dfc_event->size = dfc->buf1_size;
7506 	dfc_event->last_id = dfc->data3;
7507 	dfc_event->mode = mode;
7508 
7509 	sleep = (dfc->flag & 0x01) ? 1 : 0;
7510 
7511 	if ((rval = emlxs_get_dfc_event(port, dfc_event, sleep))) {
7512 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7513 		    "%s: %s. Exiting. pid=%d rsize=%d id=%d rval=%d",
7514 		    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
7515 		    pid, dfc_event->size, dfc_event->last_id, rval);
7516 
7517 		return (rval);
7518 	}
7519 
7520 	if (dfc->buf2) {
7521 		if (ddi_copyout((void *)&dfc_event->size, dfc->buf2,
7522 		    sizeof (uint32_t), mode) != 0) {
7523 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7524 			    "%s: ddi_copyout failed.",
7525 			    emlxs_dfc_xlate(dfc->cmd));
7526 
7527 			return (DFC_COPYOUT_ERROR);
7528 		}
7529 	}
7530 
7531 	if (dfc->buf3) {
7532 		if (ddi_copyout((void *)&dfc_event->last_id, dfc->buf3,
7533 		    sizeof (uint32_t), mode) != 0) {
7534 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7535 			    "%s: ddi_copyout failed.",
7536 			    emlxs_dfc_xlate(dfc->cmd));
7537 
7538 			return (DFC_COPYOUT_ERROR);
7539 		}
7540 	}
7541 
7542 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7543 	    "%s: %s. Completed. pid=%d rsize=%d id=%d",
7544 	    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event), pid,
7545 	    dfc_event->size, dfc_event->last_id);
7546 
7547 	return (rval);
7548 
7549 } /* emlxs_dfc_get_event() */
7550 
7551 
7552 extern uint32_t
7553 emlxs_get_dump_region(emlxs_hba_t *hba, uint32_t region,
7554     uint8_t *buffer, uint32_t *psize)
7555 {
7556 	emlxs_port_t	*port = &PPORT;
7557 	uint32_t	size;
7558 	uint32_t	size_only;
7559 	uint32_t	rval = 0;
7560 	uint8_t		*memptr;
7561 	uint32_t	*wptr;
7562 
7563 	if (!buffer || !(*psize)) {
7564 		size_only = 1;
7565 		size = 0xffffffff;
7566 	} else {
7567 		size_only = 0;
7568 		size = *psize;
7569 	}
7570 
7571 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
7572 		if (region != 7) {
7573 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7574 			    "emlxs_get_dump_region: Invalid sli4 region. "
7575 			    "(id=%d)", region);
7576 
7577 			rval = DFC_ARG_INVALID;
7578 			goto done;
7579 		}
7580 	}
7581 
7582 	switch (region) {
7583 	case 0:	/* SLI Registers */
7584 
7585 		if (size < (4 * sizeof (uint32_t))) {
7586 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7587 			    "emlxs_get_dump_region: Buffer too small. "
7588 			    "(SLI Registers: size=%d)", size);
7589 
7590 			rval = DFC_ARG_TOOSMALL;
7591 			goto done;
7592 		}
7593 
7594 		size = (4 * sizeof (uint32_t));
7595 
7596 		if (size_only) {
7597 			break;
7598 		}
7599 
7600 		wptr = (uint32_t *)buffer;
7601 		wptr[0] = READ_CSR_REG(hba, FC_HA_REG(hba));
7602 		wptr[1] = READ_CSR_REG(hba, FC_CA_REG(hba));
7603 		wptr[2] = READ_CSR_REG(hba, FC_HS_REG(hba));
7604 		wptr[3] = READ_CSR_REG(hba, FC_HC_REG(hba));
7605 
7606 #ifdef FMA_SUPPORT
7607 		/* Access handle validation */
7608 		if (emlxs_fm_check_acc_handle(hba, hba->sli.sli3.csr_acc_handle)
7609 		    != DDI_FM_OK) {
7610 			EMLXS_MSGF(EMLXS_CONTEXT,
7611 			    &emlxs_invalid_access_handle_msg, NULL);
7612 			rval = DFC_DRV_ERROR;
7613 		}
7614 #endif  /* FMA_SUPPORT */
7615 
7616 		break;
7617 
7618 	case 1:	/* SLIM */
7619 
7620 		if (hba->flag & FC_SLIM2_MODE) {
7621 			size = MIN(SLI2_SLIM2_SIZE, size);
7622 		} else {
7623 			size = MIN(4096, size);
7624 		}
7625 
7626 		if (size_only) {
7627 			break;
7628 		}
7629 
7630 		if (hba->flag & FC_SLIM2_MODE) {
7631 			memptr = (uint8_t *)hba->sli.sli3.slim2.virt;
7632 			BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer,
7633 			    size);
7634 		} else {
7635 			memptr = (uint8_t *)hba->sli.sli3.slim_addr;
7636 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
7637 			    (uint32_t *)memptr, (size / 4));
7638 #ifdef FMA_SUPPORT
7639 			/* Access handle validation */
7640 			if (emlxs_fm_check_acc_handle(hba,
7641 			    hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
7642 				EMLXS_MSGF(EMLXS_CONTEXT,
7643 				    &emlxs_invalid_access_handle_msg, NULL);
7644 				rval = DFC_DRV_ERROR;
7645 			}
7646 #endif  /* FMA_SUPPORT */
7647 		}
7648 
7649 		break;
7650 
7651 	case 2:	/* Port Control Block */
7652 
7653 		if (size < sizeof (PCB)) {
7654 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7655 			    "emlxs_get_dump_region: Buffer too small. "
7656 			    "(PCB: size=%d)", size);
7657 
7658 			rval = DFC_ARG_TOOSMALL;
7659 			goto done;
7660 		}
7661 
7662 		size = sizeof (PCB);
7663 
7664 		if (size_only) {
7665 			break;
7666 		}
7667 
7668 		memptr = (uint8_t *)&(((SLIM2 *)hba->sli.sli3.slim2.virt)->pcb);
7669 		BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
7670 		break;
7671 
7672 	case 3:	/* MailBox */
7673 
7674 		if (size < MAILBOX_CMD_BSIZE) {
7675 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7676 			    "emlxs_get_dump_region: Buffer too small. "
7677 			    "(Mailbox: size=%d)", size);
7678 
7679 			rval = DFC_ARG_TOOSMALL;
7680 			goto done;
7681 		}
7682 
7683 		size = MAILBOX_CMD_BSIZE;
7684 
7685 		if (size_only) {
7686 			break;
7687 		}
7688 
7689 		if (hba->flag & FC_SLIM2_MODE) {
7690 			memptr = (uint8_t *)hba->sli.sli3.slim2.virt;
7691 			BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer,
7692 			    size);
7693 		} else {
7694 			memptr = (uint8_t *)hba->sli.sli3.slim_addr;
7695 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
7696 			    (uint32_t *)memptr, (size / 4));
7697 #ifdef FMA_SUPPORT
7698 			/* Access handle validation */
7699 			if (emlxs_fm_check_acc_handle(hba,
7700 			    hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
7701 				EMLXS_MSGF(EMLXS_CONTEXT,
7702 				    &emlxs_invalid_access_handle_msg, NULL);
7703 				rval = DFC_DRV_ERROR;
7704 			}
7705 #endif  /* FMA_SUPPORT */
7706 		}
7707 
7708 		break;
7709 
7710 	case 4:	/* Host Put/Get pointer array */
7711 
7712 		if (size < MAX_RINGS * sizeof (HGP)) {
7713 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7714 			    "emlxs_get_dump_region: Buffer too small. "
7715 			    "(HGP: size=%d)", size);
7716 
7717 			rval = DFC_ARG_TOOSMALL;
7718 			goto done;
7719 		}
7720 
7721 		size = MAX_RINGS * sizeof (HGP);
7722 
7723 		if (size_only) {
7724 			break;
7725 		}
7726 
7727 		{
7728 			memptr = (uint8_t *)hba->sli.sli3.slim_addr +
7729 			    hba->sli.sli3.hgp_ring_offset;
7730 
7731 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
7732 			    (uint32_t *)memptr, (size / 4));
7733 #ifdef FMA_SUPPORT
7734 			/* Access handle validation */
7735 			if (emlxs_fm_check_acc_handle(hba,
7736 			    hba->sli.sli3.slim_acc_handle) != DDI_FM_OK) {
7737 				EMLXS_MSGF(EMLXS_CONTEXT,
7738 				    &emlxs_invalid_access_handle_msg, NULL);
7739 				rval = DFC_DRV_ERROR;
7740 			}
7741 #endif  /* FMA_SUPPORT */
7742 		}
7743 
7744 		break;
7745 
7746 	case 5:	/* Port  Get/Put pointer array */
7747 
7748 		if (size < MAX_RINGS * sizeof (PGP)) {
7749 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7750 			    "emlxs_get_dump_region: Buffer too small. "
7751 			    "(PGP: size=%d)", size);
7752 
7753 			rval = DFC_ARG_TOOSMALL;
7754 			goto done;
7755 		}
7756 
7757 		size = MAX_RINGS * sizeof (PGP);
7758 
7759 		if (size_only) {
7760 			break;
7761 		}
7762 
7763 		memptr = (uint8_t *)
7764 		    ((SLIM2 *)hba->sli.sli3.slim2.virt)->mbx.us.s2.port;
7765 		BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
7766 		break;
7767 
7768 	case 6:	/* Command/Response Ring */
7769 
7770 		if (size < SLI_IOCB_MAX_SIZE) {
7771 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7772 			    "emlxs_get_dump_region: Buffer too small. "
7773 			    "(Rings: size=%d)", size);
7774 
7775 			rval = DFC_ARG_TOOSMALL;
7776 			goto done;
7777 		}
7778 
7779 		size = SLI_IOCB_MAX_SIZE;
7780 
7781 		if (size_only) {
7782 			break;
7783 		}
7784 
7785 		memptr = (uint8_t *)((SLIM2 *)hba->sli.sli3.slim2.virt)->IOCBs;
7786 		BE_SWAP32_BCOPY((uint8_t *)memptr, (uint8_t *)buffer, size);
7787 		break;
7788 
7789 	case 7:	/* All driver specific structures */
7790 
7791 		if (size < sizeof (emlxs_hba_t)) {
7792 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7793 			    "emlxs_get_dump_region: Buffer too small. "
7794 			    "(Driver: size=%d)", size);
7795 
7796 			rval = DFC_ARG_TOOSMALL;
7797 			goto done;
7798 		}
7799 
7800 		size = sizeof (emlxs_hba_t);
7801 
7802 		if (size_only) {
7803 			break;
7804 		}
7805 
7806 		memptr = (uint8_t *)hba;
7807 		bcopy((void *)memptr, (void *)buffer, size);
7808 
7809 		break;
7810 
7811 	default:
7812 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7813 		    "emlxs_get_dump_region: Invalid region. (id=%d)", region);
7814 
7815 		rval = DFC_ARG_INVALID;
7816 	}
7817 
7818 done:
7819 
7820 	*psize = size;
7821 
7822 	return (rval);
7823 
7824 } /* emlxs_get_dump_region() */
7825 
7826 
7827 
7828 static int32_t
7829 emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7830 {
7831 	emlxs_port_t	*port = &PPORT;
7832 	uint32_t	size;
7833 	uint32_t	size_only = 0;
7834 	uint32_t	rval = 0;
7835 	uint8_t		*buffer = NULL;
7836 
7837 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7838 	    "%s: region=%d size=%d",
7839 	    emlxs_dfc_xlate(dfc->cmd), dfc->data1, dfc->buf1_size);
7840 
7841 	if (!dfc->buf1 || !dfc->buf1_size) {
7842 		size_only = 1;
7843 	}
7844 
7845 	if (!dfc->buf2 || !dfc->buf2_size) {
7846 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7847 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
7848 
7849 		return (DFC_ARG_NULL);
7850 	}
7851 
7852 	if (dfc->buf2_size < sizeof (uint32_t)) {
7853 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7854 		    "%s: Buffer2 too small. (size=%d)",
7855 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
7856 
7857 		return (DFC_ARG_TOOSMALL);
7858 	}
7859 
7860 	/* First get region size only */
7861 	size = 0;
7862 	rval = emlxs_get_dump_region(hba, dfc->data1, NULL, &size);
7863 
7864 	if (rval != 0) {
7865 		goto done;
7866 	}
7867 
7868 	if (!size_only) {
7869 		if (dfc->buf1_size < size) {
7870 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7871 			    "%s: Buffer1 too small. (size: %d < %d)",
7872 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size, size);
7873 
7874 			rval = DFC_ARG_TOOSMALL;
7875 			goto done;
7876 		}
7877 
7878 		buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP);
7879 
7880 		/* Get the region data */
7881 		rval = emlxs_get_dump_region(hba, dfc->data1, buffer, &size);
7882 
7883 		if (rval != 0) {
7884 			goto done;
7885 		}
7886 
7887 		/* Return the region data */
7888 		if (ddi_copyout((void *)buffer, (void *) dfc->buf1,
7889 		    size, mode) != 0) {
7890 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7891 			    "%s: ddi_copyout failed.",
7892 			    emlxs_dfc_xlate(dfc->cmd));
7893 
7894 			rval = DFC_COPYOUT_ERROR;
7895 			goto done;
7896 		}
7897 	}
7898 
7899 	/* Return the region size */
7900 	if (ddi_copyout((void *) &size, (void *) dfc->buf2,
7901 	    sizeof (uint32_t), mode) != 0) {
7902 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7903 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
7904 
7905 		rval = DFC_COPYOUT_ERROR;
7906 		goto done;
7907 	}
7908 
7909 done:
7910 
7911 	if (buffer) {
7912 		kmem_free(buffer, size);
7913 	}
7914 
7915 	return (rval);
7916 
7917 } /* emlxs_dfc_get_dump_region() */
7918 
7919 
7920 
7921 #ifdef MENLO_SUPPORT
7922 static int32_t
7923 emlxs_dfc_menlo_port_offset(emlxs_hba_t *hba)
7924 {
7925 	uint32_t	cnt;
7926 	char		pathname[256];
7927 
7928 	(void) ddi_pathname(hba->dip, pathname);
7929 	cnt = strlen(pathname);
7930 	if ((cnt < 4) || (strcmp(&pathname[cnt-3], "0,1") != 0))
7931 		return (0);
7932 	return (1);
7933 }
7934 
7935 static int32_t
7936 emlxs_dfc_set_menlo_loopback(emlxs_hba_t *hba)
7937 {
7938 	emlxs_port_t *port = &PPORT;
7939 	MAILBOXQ *mbq = NULL;
7940 	MAILBOX *mb = NULL;
7941 	fc_packet_t *pkt = NULL;
7942 	uint32_t mbxstatus;
7943 	uint32_t i;
7944 	uint32_t offset;
7945 	uint32_t rval = 0;
7946 	menlo_cmd_t *cmd;
7947 
7948 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
7949 	    KM_SLEEP);
7950 
7951 	mb = (MAILBOX *)mbq;
7952 
7953 	/* SET MENLO maint mode */
7954 	/* Create the set_variable mailbox request */
7955 	emlxs_mb_set_var(hba, mbq, 0x103107, 1);
7956 
7957 	mbq->flag |= MBQ_PASSTHRU;
7958 
7959 	/* issue the mbox cmd to the sli */
7960 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
7961 
7962 	if (mbxstatus) {
7963 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7964 		    "%s: %s failed. mbxstatus=0x%x",
7965 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
7966 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
7967 
7968 		rval = DFC_IO_ERROR;
7969 		if (mbxstatus == MBX_TIMEOUT)
7970 			rval = DFC_TIMEOUT;
7971 		goto done;
7972 	}
7973 
7974 
7975 	/* Wait 30 sec for maint mode */
7976 	i = 0;
7977 	do {
7978 		if (i++ > 300) {
7979 			break;
7980 		}
7981 
7982 		delay(drv_usectohz(100000));
7983 
7984 	} while (!(hba->flag & FC_MENLO_MODE));
7985 
7986 	if (!(hba->flag & FC_MENLO_MODE)) {
7987 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7988 		    "%s: Unable to enter maint mode.",
7989 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
7990 
7991 		rval = DFC_DRV_ERROR;
7992 		goto done;
7993 	}
7994 
7995 	offset = emlxs_dfc_menlo_port_offset(hba);
7996 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7997 	    "%s: Entered maint mode. Port offset: %d",
7998 	    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE), offset);
7999 
8000 
8001 	/* Issue Menlo loopback command */
8002 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_cmd_t),
8003 	    sizeof (uint32_t), 0, KM_NOSLEEP))) {
8004 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8005 		    "%s: Unable to allocate packet.",
8006 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8007 
8008 		rval = DFC_SYSRES_ERROR;
8009 		goto done;
8010 	}
8011 
8012 	/* Make this a polled IO */
8013 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
8014 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8015 	pkt->pkt_comp = NULL;
8016 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
8017 	pkt->pkt_timeout = 30;
8018 
8019 	/* Build the fc header */
8020 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
8021 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
8022 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
8023 	pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
8024 	pkt->pkt_cmd_fhdr.f_ctl =
8025 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
8026 	pkt->pkt_cmd_fhdr.seq_id = 0;
8027 	pkt->pkt_cmd_fhdr.df_ctl = 0;
8028 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
8029 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
8030 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
8031 	pkt->pkt_cmd_fhdr.ro = 0;
8032 
8033 	cmd = (menlo_cmd_t *)pkt->pkt_cmd;
8034 	cmd->code = BE_SWAP32(MENLO_CMD_LOOPBACK);
8035 	cmd->lb.context = BE_SWAP32(offset);
8036 	cmd->lb.type = BE_SWAP32(MENLO_LOOPBACK_ENABLE);
8037 
8038 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
8039 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8040 		    "%s: Unable to send packet.",
8041 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8042 
8043 		rval = DFC_IO_ERROR;
8044 		goto done;
8045 	}
8046 
8047 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
8048 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8049 			EMLXS_MSGF(EMLXS_CONTEXT,
8050 			    &emlxs_dfc_error_msg,
8051 			    "%s: Pkt Transport error. Pkt Timeout.",
8052 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8053 			rval = DFC_TIMEOUT;
8054 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
8055 		    (pkt->pkt_reason == FC_REASON_OVERRUN)) {
8056 			EMLXS_MSGF(EMLXS_CONTEXT,
8057 			    &emlxs_dfc_error_msg,
8058 			    "%s: Pkt Transport error. Rsp overrun.",
8059 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8060 			rval = DFC_RSP_BUF_OVERRUN;
8061 		} else {
8062 			EMLXS_MSGF(EMLXS_CONTEXT,
8063 			    &emlxs_dfc_error_msg,
8064 			    "%s: Pkt Transport error. state=%x",
8065 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8066 			    pkt->pkt_state);
8067 			rval = DFC_IO_ERROR;
8068 		}
8069 		goto done;
8070 	}
8071 
8072 
8073 	/* CLEAR MENLO maint mode */
8074 	/* Create the set_variable mailbox request */
8075 	emlxs_mb_set_var(hba, mbq, 0x103107, 0);
8076 
8077 	mbq->flag |= MBQ_PASSTHRU;
8078 
8079 	/* issue the mbox cmd to the sli */
8080 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8081 
8082 	if (mbxstatus) {
8083 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8084 		    "%s: %s failed. mbxstatus=0x%x",
8085 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8086 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
8087 
8088 		rval = DFC_IO_ERROR;
8089 		if (mbxstatus == MBX_TIMEOUT)
8090 			rval = DFC_TIMEOUT;
8091 	}
8092 
8093 	delay(drv_usectohz(1000000));
8094 	i = 0;
8095 	while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) {
8096 		delay(drv_usectohz(100000));
8097 		i++;
8098 
8099 		if (i == 300) {
8100 			rval = DFC_TIMEOUT;
8101 
8102 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8103 			    "%s: Linkup timeout.",
8104 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8105 
8106 			goto done;
8107 		}
8108 	}
8109 
8110 done:
8111 	/* Free allocated mbox memory */
8112 	if (mbq) {
8113 		kmem_free(mbq, sizeof (MAILBOXQ));
8114 	}
8115 	if (pkt) {
8116 		emlxs_pkt_free(pkt);
8117 	}
8118 	return (rval);
8119 }
8120 
8121 static int32_t
8122 emlxs_dfc_set_menlo_fte(emlxs_hba_t *hba)
8123 {
8124 	emlxs_port_t *port = &PPORT;
8125 	fc_packet_t *pkt = NULL;
8126 	uint32_t rval = 0;
8127 	menlo_cmd_t *cmd;
8128 
8129 
8130 	/* Issue Menlo loopback command */
8131 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_cmd_t),
8132 	    sizeof (uint32_t), 0, KM_NOSLEEP))) {
8133 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8134 		    "%s: Unable to allocate packet.",
8135 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8136 
8137 		rval = DFC_SYSRES_ERROR;
8138 		goto done;
8139 	}
8140 
8141 	/* Make this a polled IO */
8142 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
8143 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8144 	pkt->pkt_comp = NULL;
8145 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
8146 	pkt->pkt_timeout = 30;
8147 
8148 	/* Build the fc header */
8149 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(EMLXS_MENLO_DID);
8150 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
8151 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
8152 	pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
8153 	pkt->pkt_cmd_fhdr.f_ctl =
8154 	    F_CTL_FIRST_SEQ | F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
8155 	pkt->pkt_cmd_fhdr.seq_id = 0;
8156 	pkt->pkt_cmd_fhdr.df_ctl = 0;
8157 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
8158 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
8159 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
8160 	pkt->pkt_cmd_fhdr.ro = 0;
8161 
8162 	cmd = (menlo_cmd_t *)pkt->pkt_cmd;
8163 	cmd->code = BE_SWAP32(MENLO_CMD_FTE_INSERT);
8164 	cmd->fte_insert.fcid = BE_SWAP32(0);
8165 	bcopy((caddr_t)&port->wwpn, (caddr_t)cmd->fte_insert.wwpn, 8);
8166 
8167 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
8168 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8169 		    "%s: Unable to send packet.",
8170 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8171 
8172 		rval = DFC_IO_ERROR;
8173 		goto done;
8174 	}
8175 
8176 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
8177 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8178 			EMLXS_MSGF(EMLXS_CONTEXT,
8179 			    &emlxs_dfc_error_msg,
8180 			    "%s: Pkt Transport error. Pkt Timeout.",
8181 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8182 			rval = DFC_TIMEOUT;
8183 		} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
8184 		    (pkt->pkt_reason == FC_REASON_OVERRUN)) {
8185 			EMLXS_MSGF(EMLXS_CONTEXT,
8186 			    &emlxs_dfc_error_msg,
8187 			    "%s: Pkt Transport error. Rsp overrun.",
8188 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE));
8189 			rval = DFC_RSP_BUF_OVERRUN;
8190 		} else {
8191 			EMLXS_MSGF(EMLXS_CONTEXT,
8192 			    &emlxs_dfc_error_msg,
8193 			    "%s: Pkt Transport error. state=%x",
8194 			    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8195 			    pkt->pkt_state);
8196 			rval = DFC_IO_ERROR;
8197 		}
8198 		goto done;
8199 	}
8200 
8201 
8202 done:
8203 	if (pkt) {
8204 		emlxs_pkt_free(pkt);
8205 	}
8206 	return (rval);
8207 }
8208 
8209 static int32_t
8210 emlxs_dfc_reset_menlo(emlxs_hba_t *hba)
8211 {
8212 	emlxs_port_t *port = &PPORT;
8213 	MAILBOXQ *mbq = NULL;
8214 	MAILBOX *mb = NULL;
8215 	uint32_t mbxstatus;
8216 	uint32_t rval = 0;
8217 
8218 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
8219 	    KM_SLEEP);
8220 
8221 	mb = (MAILBOX *)mbq;
8222 
8223 	/* RESET MENLO */
8224 	/* Create the set_variable mailbox request */
8225 	emlxs_mb_set_var(hba, mbq, 0x103007, 0);
8226 
8227 	mbq->flag |= MBQ_PASSTHRU;
8228 
8229 	/* issue the mbox cmd to the sli */
8230 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8231 
8232 	if (mbxstatus) {
8233 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8234 		    "%s: %s failed. mbxstatus=0x%x",
8235 		    emlxs_dfc_xlate(EMLXS_LOOPBACK_MODE),
8236 		    emlxs_mb_cmd_xlate(mb->mbxCommand), mbxstatus);
8237 
8238 		rval = DFC_IO_ERROR;
8239 		if (mbxstatus == MBX_TIMEOUT)
8240 			rval = DFC_TIMEOUT;
8241 		goto done;
8242 	}
8243 done:
8244 	/* Free allocated mbox memory */
8245 	if (mbq) {
8246 		kmem_free(mbq, sizeof (MAILBOXQ));
8247 	}
8248 	return (rval);
8249 }
8250 
8251 #endif /* MENLO_SUPPORT */
8252 
8253 /* ARGSUSED */
8254 static int32_t
8255 emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8256 {
8257 	emlxs_port_t	*port = &PPORT;
8258 	emlxs_config_t	*cfg = &CFG;
8259 	MAILBOXQ	*mbq = NULL;
8260 	MAILBOX		*mb = NULL;
8261 	uint32_t	rval = DFC_SUCCESS;
8262 	uint32_t	i;
8263 	uint32_t	timeout;
8264 	uint32_t	topology;
8265 	uint32_t	speed;
8266 	uint32_t	new_mode;
8267 	NODELIST	*ndlp;
8268 
8269 	if (hba->model_info.flags & EMLXS_FCOE_SUPPORTED) {
8270 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8271 		    "%s: FCoE not supported.", emlxs_dfc_xlate(dfc->cmd));
8272 
8273 		return (DFC_FCOE_NOTSUPPORTED);
8274 	}
8275 
8276 	/* Reinitialize the link */
8277 	switch (dfc->flag) {
8278 	case 0:	/* Disable */
8279 
8280 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8281 		    "%s: Disabling Loopback.", emlxs_dfc_xlate(dfc->cmd));
8282 
8283 		if (!(hba->flag & FC_LOOPBACK_MODE)) {
8284 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8285 			    "%s: Loopback already disabled.",
8286 			    emlxs_dfc_xlate(dfc->cmd));
8287 
8288 			return (rval);
8289 		}
8290 		goto resetdone;
8291 
8292 	case 1:	/* Internal loopback */
8293 		new_mode = FC_ILB_MODE;
8294 		topology = FLAGS_LOCAL_LB;
8295 		speed = 0;
8296 
8297 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8298 		    "%s: Enabling ILB.", emlxs_dfc_xlate(dfc->cmd));
8299 
8300 		/* Check if mode already set */
8301 		if ((hba->flag & FC_ILB_MODE)) {
8302 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8303 			    "%s: ILB mode already enabled.",
8304 			    emlxs_dfc_xlate(dfc->cmd));
8305 
8306 			return (rval);
8307 		}
8308 
8309 		break;
8310 
8311 	case 2:	/* External loopback */
8312 		new_mode = FC_ELB_MODE;
8313 		topology = FLAGS_TOPOLOGY_MODE_LOOP;
8314 		speed = cfg[CFG_LINK_SPEED].current;
8315 
8316 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8317 		    "%s: Enabling ELB.", emlxs_dfc_xlate(dfc->cmd));
8318 
8319 		/* Check if mode already set */
8320 		if ((hba->flag & FC_ELB_MODE)) {
8321 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8322 			    "%s: ELB mode already enabled.",
8323 			    emlxs_dfc_xlate(dfc->cmd));
8324 
8325 			return (rval);
8326 		}
8327 
8328 		break;
8329 
8330 	default:
8331 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8332 		    "%s: Invalid loopback mode. (mode=%x)",
8333 		    emlxs_dfc_xlate(dfc->cmd), dfc->flag);
8334 
8335 		return (DFC_ARG_INVALID);
8336 	}
8337 
8338 	/* Make sure adapter is online */
8339 	if (emlxs_online(hba)) {
8340 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8341 		    "%s: Unable to bring adapter online.",
8342 		    emlxs_dfc_xlate(dfc->cmd));
8343 
8344 		return (DFC_OFFLINE_ERROR);
8345 	}
8346 
8347 #ifdef MENLO_SUPPORT
8348 	if (hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) {
8349 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8350 		    "%s: Menlo support detected: mode:x%x",
8351 		    emlxs_dfc_xlate(dfc->cmd), new_mode);
8352 
8353 		if (new_mode == FC_ILB_MODE) {
8354 			rval = emlxs_dfc_set_menlo_loopback(hba);
8355 			if (rval)
8356 				goto done;
8357 		}
8358 	}
8359 #endif /* MENLO_SUPPORT */
8360 
8361 	mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ),
8362 	    KM_SLEEP);
8363 
8364 	mb = (MAILBOX *) mbq;
8365 
8366 	/* Take the link down */
8367 	emlxs_mb_down_link(hba, mbq);
8368 
8369 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8370 
8371 	if (rval == MBX_TIMEOUT) {
8372 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8373 		    "%s: Mailbox timed out. cmd=%x",
8374 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
8375 
8376 		rval = DFC_TIMEOUT;
8377 		goto done;
8378 	}
8379 
8380 	if (rval) {
8381 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8382 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
8383 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
8384 
8385 		rval = DFC_IO_ERROR;
8386 		goto done;
8387 	}
8388 
8389 	/* Reinitialize the link */
8390 	emlxs_mb_init_link(hba, mbq, topology, speed);
8391 
8392 	/* Set the loopback mode and timer */
8393 	mutex_enter(&EMLXS_PORT_LOCK);
8394 	hba->flag |= new_mode;
8395 	hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
8396 	mutex_exit(&EMLXS_PORT_LOCK);
8397 
8398 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
8399 
8400 	if (rval == MBX_TIMEOUT) {
8401 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8402 		    "%s: Mailbox timed out. cmd=%x",
8403 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
8404 
8405 		rval = DFC_TIMEOUT;
8406 		goto done;
8407 	}
8408 
8409 	if (rval) {
8410 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8411 		    "%s: %s failed. status=%x", emlxs_dfc_xlate(dfc->cmd),
8412 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
8413 
8414 		rval = DFC_IO_ERROR;
8415 		goto done;
8416 	}
8417 
8418 	/*
8419 	 * Wait for adapter to come online.
8420 	 * Need *2 since we wait 1/2 sec in while loop.
8421 	 */
8422 	timeout = dfc->data1;
8423 	if (!timeout) {
8424 		timeout = 60 * 2;
8425 	} else {
8426 		timeout = timeout * 2;
8427 	}
8428 
8429 	i = 0;
8430 	while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) {
8431 		delay(drv_usectohz(500000));
8432 		i++;
8433 
8434 		if (i == timeout) {
8435 			rval = DFC_TIMEOUT;
8436 
8437 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8438 			    "%s: Linkup timeout.", emlxs_dfc_xlate(dfc->cmd));
8439 
8440 			goto done;
8441 		}
8442 	}
8443 
8444 	/* Create host node */
8445 	if (emlxs_mb_reg_did(port, port->did, (SERV_PARM *)&hba->sparam,
8446 	    NULL, NULL, NULL)) {
8447 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8448 		    "%s: Unable to register host node.",
8449 		    emlxs_dfc_xlate(dfc->cmd));
8450 
8451 		rval = DFC_DRV_ERROR;
8452 		goto done;
8453 	}
8454 
8455 	i = 0;
8456 	do {
8457 		if (i++ > 300) {
8458 			break;
8459 		}
8460 
8461 		delay(drv_usectohz(100000));
8462 
8463 	} while (!(ndlp = emlxs_node_find_did(port, port->did)));
8464 
8465 	if (!ndlp) {
8466 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8467 		    "%s: Unable to create host node.",
8468 		    emlxs_dfc_xlate(dfc->cmd));
8469 
8470 		rval = DFC_DRV_ERROR;
8471 		goto done;
8472 	}
8473 
8474 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8475 	    "%s: Node created. node=%p", emlxs_dfc_xlate(dfc->cmd), ndlp);
8476 
8477 #ifdef MENLO_SUPPORT
8478 	if (hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) {
8479 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8480 		    "%s: Menlo support detected: mode:x%x",
8481 		    emlxs_dfc_xlate(dfc->cmd), new_mode);
8482 
8483 		rval = emlxs_dfc_set_menlo_fte(hba);
8484 		if (rval)
8485 			goto done;
8486 	}
8487 #endif /* MENLO_SUPPORT */
8488 
8489 	/* Create host XRI */
8490 	(void) emlxs_create_xri(port, &hba->chan[hba->channel_ct], ndlp);
8491 
8492 	i = 0;
8493 	do {
8494 		if (i++ > 300) {
8495 			break;
8496 		}
8497 
8498 		delay(drv_usectohz(100000));
8499 
8500 	} while (!ndlp->nlp_Xri);
8501 
8502 	if (!ndlp->nlp_Xri) {
8503 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8504 		    "%s: Unable to create XRI.", emlxs_dfc_xlate(dfc->cmd));
8505 
8506 		rval = DFC_DRV_ERROR;
8507 		goto done;
8508 	}
8509 
8510 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8511 	    "%s: XRI created. xri=%x", emlxs_dfc_xlate(dfc->cmd),
8512 	    ndlp->nlp_Xri);
8513 done:
8514 	/* Free allocated mbox memory */
8515 	if (mbq) {
8516 		kmem_free(mbq, sizeof (MAILBOXQ));
8517 	}
8518 
8519 	if (rval) {
8520 resetdone:
8521 		/* Reset the adapter */
8522 #ifdef MENLO_SUPPORT
8523 		if (hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) {
8524 
8525 			rval = emlxs_dfc_reset_menlo(hba);
8526 
8527 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8528 			    "%s: Menlo reset: rval:x%x",
8529 			    emlxs_dfc_xlate(dfc->cmd), rval);
8530 	}
8531 #endif /* MENLO_SUPPORT */
8532 
8533 		/* Reset link whether we are bound to ULP or not */
8534 		(void) emlxs_reset_link(hba, 1, 1);
8535 	}
8536 
8537 	return (rval);
8538 } /* emlxs_dfc_loopback_mode() */
8539 
8540 
8541 static int32_t
8542 emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8543 {
8544 	emlxs_port_t	*port = &PPORT;
8545 	uint32_t	rval = 0;
8546 	NODELIST	*ndlp;
8547 	clock_t		timeout;
8548 	fc_packet_t	*pkt = NULL;
8549 	SLI_CT_REQUEST	*CtCmd;
8550 	uint16_t	CtRsp;
8551 
8552 	if (hba->model_info.flags & EMLXS_FCOE_SUPPORTED) {
8553 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8554 		    "%s: FCoE not  supported.", emlxs_dfc_xlate(dfc->cmd));
8555 
8556 		return (DFC_FCOE_NOTSUPPORTED);
8557 	}
8558 
8559 	mutex_enter(&EMLXS_PORT_LOCK);
8560 	if (!(hba->flag & FC_LOOPBACK_MODE)) {
8561 		mutex_exit(&EMLXS_PORT_LOCK);
8562 
8563 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8564 		    "%s: Adapter not in loopback mode.",
8565 		    emlxs_dfc_xlate(dfc->cmd));
8566 
8567 		rval = DFC_DRV_ERROR;
8568 		goto done;
8569 	}
8570 	hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
8571 	mutex_exit(&EMLXS_PORT_LOCK);
8572 
8573 	if (!(hba->flag & FC_ONLINE_MODE)) {
8574 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8575 		    "%s: Adapter offline.", emlxs_dfc_xlate(dfc->cmd));
8576 
8577 		rval = DFC_OFFLINE_ERROR;
8578 		goto done;
8579 	}
8580 
8581 	if (hba->state < FC_LINK_UP) {
8582 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8583 		    "%s: Link not up.", emlxs_dfc_xlate(dfc->cmd));
8584 
8585 		rval = DFC_OFFLINE_ERROR;
8586 		goto done;
8587 	}
8588 
8589 	if (!dfc->buf1 || !dfc->buf1_size) {
8590 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8591 		    "%s: NULL buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
8592 
8593 		rval = DFC_ARG_NULL;
8594 		goto done;
8595 	}
8596 
8597 	if (!dfc->buf2 || !dfc->buf2_size) {
8598 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8599 		    "%s: NULL buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
8600 
8601 		rval = DFC_ARG_NULL;
8602 		goto done;
8603 	}
8604 
8605 	if (dfc->buf1_size > MAX_CT_PAYLOAD) {
8606 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8607 		    "%s: Buffer1 too large. (size=%d)",
8608 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8609 
8610 		rval = DFC_ARG_TOOBIG;
8611 		goto done;
8612 	}
8613 
8614 	/* Check if we have a node for ourselves */
8615 	ndlp = emlxs_node_find_did(port, port->did);
8616 
8617 	if (!ndlp) {
8618 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8619 		    "%s: Host node not found.", emlxs_dfc_xlate(dfc->cmd));
8620 
8621 		rval = DFC_ARG_INVALID;
8622 		goto done;
8623 	}
8624 
8625 	if (!ndlp->nlp_Xri) {
8626 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8627 		    "%s: Host XRI not found.", emlxs_dfc_xlate(dfc->cmd));
8628 
8629 		rval = DFC_DRV_ERROR;
8630 		goto done;
8631 	}
8632 
8633 	pkt = emlxs_pkt_alloc(port, dfc->buf1_size + 16,
8634 	    dfc->buf2_size + 16, 0, KM_SLEEP);
8635 
8636 	if (pkt == NULL) {
8637 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8638 		    "%s: Unable to allocate pkt.", emlxs_dfc_xlate(dfc->cmd));
8639 		rval = DFC_SYSRES_ERROR;
8640 		goto done;
8641 	}
8642 
8643 	CtCmd = (SLI_CT_REQUEST*)pkt->pkt_cmd;
8644 	CtRsp = SLI_CT_LOOPBACK;
8645 	CtCmd->CommandResponse.bits.CmdRsp = LE_SWAP16(CtRsp);
8646 
8647 	if (ddi_copyin((void *)dfc->buf1, (void *)&CtCmd->un.data,
8648 	    dfc->buf1_size, mode) != 0) {
8649 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8650 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
8651 
8652 		rval = DFC_COPYIN_ERROR;
8653 		goto done;
8654 	}
8655 
8656 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
8657 	pkt->pkt_timeout = 2 * hba->fc_ratov;
8658 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8659 	pkt->pkt_comp = NULL;
8660 
8661 	pkt->pkt_cmd_fhdr.d_id = port->did;
8662 	pkt->pkt_cmd_fhdr.r_ctl = FC_SOL_CTL;
8663 	pkt->pkt_cmd_fhdr.s_id = port->did;
8664 	pkt->pkt_cmd_fhdr.type = FC_CT_TYPE;
8665 	pkt->pkt_cmd_fhdr.f_ctl = 0;
8666 	pkt->pkt_cmd_fhdr.seq_id = 0;
8667 	pkt->pkt_cmd_fhdr.df_ctl = 0;
8668 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
8669 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
8670 	pkt->pkt_cmd_fhdr.rx_id = ndlp->nlp_Xri;
8671 	pkt->pkt_cmd_fhdr.ro = 0;
8672 
8673 	mutex_enter(&EMLXS_PKT_LOCK);
8674 	timeout = emlxs_timeout(hba, (pkt->pkt_timeout + 15));
8675 
8676 	if (hba->loopback_pkt) {
8677 		rval = 0;
8678 		while ((rval != -1) && hba->loopback_pkt) {
8679 			rval =
8680 			    cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK,
8681 			    timeout);
8682 		}
8683 
8684 		if (rval == -1) {
8685 			mutex_exit(&EMLXS_PKT_LOCK);
8686 
8687 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8688 			    "Loopback busy timeout.");
8689 			rval = DFC_TIMEOUT;
8690 			goto done;
8691 		}
8692 	}
8693 	hba->loopback_pkt = (void *) pkt;
8694 	mutex_exit(&EMLXS_PKT_LOCK);
8695 
8696 	/* Send polled command */
8697 	if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
8698 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8699 		    "Pkt Transport error. ret=%x state=%x", rval,
8700 		    pkt->pkt_state);
8701 
8702 		rval = DFC_IO_ERROR;
8703 		goto done;
8704 	}
8705 
8706 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
8707 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8708 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8709 			    "Pkt Transport error. Pkt Timeout.");
8710 			rval = DFC_TIMEOUT;
8711 		} else {
8712 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8713 			    "Pkt Transport error. state=%x", pkt->pkt_state);
8714 			rval = DFC_IO_ERROR;
8715 		}
8716 		goto done;
8717 	}
8718 
8719 	/* Wait for sequence completion */
8720 	mutex_enter(&EMLXS_PKT_LOCK);
8721 	rval = 0;
8722 	while ((rval != -1) && !(pkt->pkt_tran_flags & FC_TRAN_COMPLETED)) {
8723 		rval = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout);
8724 	}
8725 	mutex_exit(&EMLXS_PKT_LOCK);
8726 
8727 	if (rval == -1) {
8728 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8729 		    "Loopback sequence timeout.");
8730 
8731 		rval = DFC_TIMEOUT;
8732 		goto done;
8733 	}
8734 
8735 	CtCmd = (SLI_CT_REQUEST*)pkt->pkt_resp;
8736 
8737 	if (ddi_copyout((void *)&CtCmd->un.data, (void *)dfc->buf2,
8738 	    dfc->buf2_size, mode) != 0) {
8739 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8740 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
8741 
8742 		rval = DFC_COPYOUT_ERROR;
8743 		goto done;
8744 	}
8745 
8746 	rval = 0;
8747 
8748 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "%s: Test completed.",
8749 	    emlxs_dfc_xlate(dfc->cmd));
8750 
8751 done:
8752 
8753 	if (rval) {
8754 		mutex_enter(&EMLXS_PKT_LOCK);
8755 		if (pkt && (hba->loopback_pkt == pkt)) {
8756 			hba->loopback_pkt = NULL;
8757 		}
8758 		mutex_exit(&EMLXS_PKT_LOCK);
8759 
8760 		/* Reset the adapter */
8761 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
8762 	}
8763 
8764 	if (pkt) {
8765 		emlxs_pkt_free(pkt);
8766 	}
8767 
8768 	return (rval);
8769 
8770 } /* emlxs_dfc_loopback_test() */
8771 
8772 
8773 extern int32_t
8774 emlxs_dfc_handle_event(emlxs_hba_t *hba, CHANNEL *cp, IOCBQ *iocbq)
8775 {
8776 	emlxs_port_t	*port = &PPORT;
8777 	IOCB		*cmd;
8778 	emlxs_buf_t	*sbp;
8779 
8780 	cmd = &iocbq->iocb;
8781 
8782 	HBASTATS.CtEvent++;
8783 
8784 	sbp = (emlxs_buf_t *)iocbq->sbp;
8785 
8786 	if (!sbp) {
8787 		HBASTATS.CtStray++;
8788 
8789 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8790 		    "Stray interrupt. cmd=0x%x iotag=0x%x status=0x%x "
8791 		    "perr=0x%x", (uint32_t)cmd->ULPCOMMAND,
8792 		    (uint32_t)cmd->ULPIOTAG, cmd->ULPSTATUS,
8793 		    cmd->un.ulpWord[4]);
8794 
8795 		return (DFC_ARG_INVALID);
8796 	}
8797 
8798 	if (cp->channelno != hba->channel_ct) {
8799 		HBASTATS.CtStray++;
8800 
8801 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8802 		    "CT Event: Invalid IO Channel:%d iocbq=%p", cp->channelno,
8803 		    iocbq);
8804 
8805 		return (DFC_ARG_INVALID);
8806 	}
8807 
8808 	switch (cmd->ULPCOMMAND) {
8809 	case CMD_XMIT_SEQUENCE_CR:
8810 	case CMD_XMIT_SEQUENCE64_CR:
8811 	case CMD_XMIT_SEQUENCE_CX:
8812 	case CMD_XMIT_SEQUENCE64_CX:
8813 
8814 		HBASTATS.CtCmdCompleted++;
8815 
8816 		if (cmd->ULPSTATUS == 0) {
8817 			HBASTATS.CtCmdGood++;
8818 
8819 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8820 			    "XMIT_SEQUENCE comp: status=0x%x",
8821 			    cmd->ULPSTATUS);
8822 		} else {
8823 			HBASTATS.CtCmdError++;
8824 
8825 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8826 			    "XMIT_SEQUENCE comp: status=0x%x [%08x,%08x]",
8827 			    cmd->ULPSTATUS, cmd->un.ulpWord[4],
8828 			    cmd->un.ulpWord[5]);
8829 		}
8830 
8831 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
8832 		    cmd->un.grsp.perr.statLocalError, 1);
8833 
8834 		break;
8835 
8836 	default:
8837 
8838 		HBASTATS.CtStray++;
8839 
8840 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8841 		    "Invalid iocb: cmd=0x%x", cmd->ULPCOMMAND);
8842 
8843 		emlxs_pkt_complete(sbp, cmd->ULPSTATUS,
8844 		    cmd->un.grsp.perr.statLocalError, 1);
8845 
8846 		break;
8847 
8848 	}	/* switch(cmd->ULPCOMMAND) */
8849 
8850 	return (0);
8851 
8852 } /* emlxs_dfc_handle_event() */
8853 
8854 
8855 /* ARGSUSED */
8856 extern int
8857 emlxs_dfc_handle_unsol_req(emlxs_port_t *port, CHANNEL *cp, IOCBQ *iocbq,
8858     MATCHMAP *mp, uint32_t size)
8859 {
8860 	emlxs_hba_t	*hba = HBA;
8861 	IOCB		*iocb;
8862 	uint8_t		*bp;
8863 	fc_packet_t	*pkt;
8864 
8865 	iocb = &iocbq->iocb;
8866 	bp = (uint8_t *)mp->virt;
8867 
8868 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8869 	    "CT Receive: cmd=%x status=0x%x ",
8870 	    iocb->ULPCOMMAND, iocb->ULPSTATUS);
8871 
8872 	/*
8873 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
8874 	 * "CT Receive: payload=%p size=%d [%02x,%02x, %02x, %02x]", bp,
8875 	 * size, bp[0], bp[1], bp[2],bp[3]);
8876 	 */
8877 
8878 	/* Return payload */
8879 	mutex_enter(&EMLXS_PKT_LOCK);
8880 	if (hba->loopback_pkt) {
8881 		pkt = (fc_packet_t *)hba->loopback_pkt;
8882 		hba->loopback_pkt = NULL;
8883 
8884 		size = MIN(size, pkt->pkt_rsplen);
8885 		bcopy(bp, pkt->pkt_resp, size);
8886 		pkt->pkt_tran_flags |= FC_TRAN_COMPLETED;
8887 
8888 		cv_broadcast(&EMLXS_PKT_CV);
8889 	}
8890 	mutex_exit(&EMLXS_PKT_LOCK);
8891 
8892 	return (0);
8893 
8894 } /* emlxs_dfc_handle_unsol_req() */
8895 
8896 
8897 #ifdef DHCHAP_SUPPORT
8898 
8899 static int32_t
8900 emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8901 {
8902 	emlxs_port_t	*port = &PPORT;
8903 	uint8_t		lwwpn[8];
8904 	uint8_t		rwwpn[8];
8905 	int32_t		rval = 0;
8906 
8907 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
8908 	    emlxs_dfc_xlate(dfc->cmd));
8909 
8910 	if (!dfc->buf1 || !dfc->buf1_size) {
8911 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8912 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
8913 
8914 		return (DFC_ARG_NULL);
8915 	}
8916 
8917 	if (dfc->buf1_size < 8) {
8918 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8919 		    "%s: Buffer1 too small. (size=%d)",
8920 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8921 
8922 		return (DFC_ARG_TOOSMALL);
8923 	}
8924 
8925 	if (!dfc->buf2 || !dfc->buf2_size) {
8926 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8927 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
8928 
8929 		return (DFC_ARG_NULL);
8930 	}
8931 
8932 	if (dfc->buf2_size < 8) {
8933 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8934 		    "%s: Buffer2 too small. (size=%d)",
8935 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8936 
8937 		return (DFC_ARG_TOOSMALL);
8938 	}
8939 
8940 	/* Read the lwwpn */
8941 	if (ddi_copyin((void *)dfc->buf1, (void *)&lwwpn, 8, mode) != 0) {
8942 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8943 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
8944 
8945 		return (DFC_COPYIN_ERROR);
8946 	}
8947 
8948 	/* Read the rwwpn */
8949 	if (ddi_copyin((void *)dfc->buf2, (void *)&rwwpn, 8, mode) != 0) {
8950 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8951 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
8952 
8953 		return (DFC_COPYIN_ERROR);
8954 	}
8955 
8956 	/* Initiate authentication here */
8957 	rval = emlxs_dhc_init_auth(hba, lwwpn, rwwpn);
8958 
8959 	return (rval);
8960 
8961 } /* emlxs_dfc_init_auth() */
8962 
8963 
8964 static int32_t
8965 emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8966 {
8967 	emlxs_port_t		*port = &PPORT;
8968 	dfc_fcsp_config_t	fcsp_config;
8969 	uint32_t		rval = DFC_SUCCESS;
8970 
8971 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
8972 	    emlxs_dfc_xlate(dfc->cmd));
8973 
8974 	if (!dfc->buf1 || !dfc->buf1_size) {
8975 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8976 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
8977 
8978 		return (DFC_ARG_NULL);
8979 	}
8980 
8981 	if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
8982 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8983 		    "%s: Buffer1 too small. (size=%d)",
8984 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8985 
8986 		return (DFC_ARG_TOOSMALL);
8987 	}
8988 
8989 	/* Read the fcsp_config */
8990 	if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_config,
8991 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
8992 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8993 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
8994 
8995 		return (DFC_COPYIN_ERROR);
8996 	}
8997 
8998 	if ((rval = emlxs_dhc_get_auth_cfg(hba, &fcsp_config)) != 0) {
8999 		return (rval);
9000 	}
9001 
9002 	if (ddi_copyout((void *)&fcsp_config, (void *)dfc->buf1,
9003 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
9004 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9005 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
9006 
9007 		return (DFC_COPYOUT_ERROR);
9008 	}
9009 
9010 	return (0);
9011 
9012 } /* emlxs_dfc_get_auth_cfg() */
9013 
9014 
9015 
9016 static int32_t
9017 emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9018 {
9019 	emlxs_port_t		*port = &PPORT;
9020 	dfc_fcsp_config_t	fcsp_config;
9021 	dfc_password_t		dfc_pwd;
9022 	uint32_t		rval = DFC_SUCCESS;
9023 
9024 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
9025 	    emlxs_dfc_xlate(dfc->cmd));
9026 
9027 	if (!dfc->buf1 || !dfc->buf1_size) {
9028 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9029 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9030 
9031 		return (DFC_ARG_NULL);
9032 	}
9033 
9034 	if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
9035 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9036 		    "%s: Buffer1 too small. (size=%d)",
9037 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9038 
9039 		return (DFC_ARG_TOOSMALL);
9040 	}
9041 
9042 	if (!dfc->buf2 || !dfc->buf2_size) {
9043 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9044 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
9045 
9046 		return (DFC_ARG_NULL);
9047 	}
9048 
9049 	if (dfc->buf2_size < sizeof (dfc_password_t)) {
9050 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9051 		    "%s: Buffer2 too small. (size=%d)",
9052 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9053 
9054 		return (DFC_ARG_TOOSMALL);
9055 	}
9056 
9057 	/* Read the fcsp_config */
9058 	if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_config,
9059 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
9060 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9061 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
9062 
9063 		return (DFC_COPYIN_ERROR);
9064 	}
9065 
9066 	/* Read the password */
9067 	if (ddi_copyin((void *)dfc->buf2, (void *)&dfc_pwd,
9068 	    sizeof (dfc_password_t), mode) != 0) {
9069 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9070 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
9071 
9072 		return (DFC_COPYIN_ERROR);
9073 	}
9074 
9075 	switch (dfc->flag) {
9076 	case EMLXS_AUTH_CFG_ADD:
9077 		rval = emlxs_dhc_add_auth_cfg(hba, &fcsp_config, &dfc_pwd);
9078 		break;
9079 
9080 	case EMLXS_AUTH_CFG_DELETE:
9081 		rval = emlxs_dhc_delete_auth_cfg(hba, &fcsp_config, &dfc_pwd);
9082 		break;
9083 	}
9084 
9085 	if (rval) {
9086 		return (rval);
9087 	}
9088 
9089 	if (ddi_copyout((void *)&fcsp_config, (void *)dfc->buf1,
9090 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
9091 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9092 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
9093 
9094 		return (DFC_COPYOUT_ERROR);
9095 	}
9096 
9097 	return (0);
9098 
9099 } /* emlxs_dfc_set_auth_cfg() */
9100 
9101 
9102 
9103 static int32_t
9104 emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9105 {
9106 	emlxs_port_t		*port = &PPORT;
9107 	dfc_auth_password_t	dfc_pwd;
9108 	uint32_t		rval = DFC_SUCCESS;
9109 
9110 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
9111 	    emlxs_dfc_xlate(dfc->cmd));
9112 
9113 	if (!dfc->buf1 || !dfc->buf1_size) {
9114 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9115 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9116 
9117 		return (DFC_ARG_NULL);
9118 	}
9119 
9120 	if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
9121 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9122 		    "%s: Buffer1 too small. (size=%d)",
9123 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9124 
9125 		return (DFC_ARG_TOOSMALL);
9126 	}
9127 
9128 
9129 	/* Read the auth password */
9130 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_pwd,
9131 	    sizeof (dfc_auth_password_t), mode) != 0) {
9132 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9133 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
9134 
9135 		return (DFC_COPYIN_ERROR);
9136 	}
9137 
9138 	if ((rval = emlxs_dhc_get_auth_key(hba, &dfc_pwd)) != 0) {
9139 		return (rval);
9140 	}
9141 
9142 	if (ddi_copyout((void *)&dfc_pwd, (void *)dfc->buf1,
9143 	    sizeof (dfc_auth_password_t), mode) != 0) {
9144 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9145 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
9146 
9147 		return (DFC_COPYOUT_ERROR);
9148 	}
9149 
9150 	return (0);
9151 
9152 } /* emlxs_dfc_get_auth_pwd() */
9153 
9154 
9155 static int32_t
9156 emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9157 {
9158 	emlxs_port_t		*port = &PPORT;
9159 	dfc_auth_password_t	dfc_pwd;
9160 	uint32_t		rval = DFC_SUCCESS;
9161 
9162 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
9163 	    emlxs_dfc_xlate(dfc->cmd));
9164 
9165 	if (!dfc->buf1 || !dfc->buf1_size) {
9166 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9167 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9168 
9169 		return (DFC_ARG_NULL);
9170 	}
9171 
9172 	if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
9173 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9174 		    "%s: Buffer1 too small. (size=%d)",
9175 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9176 
9177 		return (DFC_ARG_TOOSMALL);
9178 	}
9179 
9180 	/* Read the auth password */
9181 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_pwd,
9182 	    sizeof (dfc_auth_password_t), mode) != 0) {
9183 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9184 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
9185 
9186 		return (DFC_COPYIN_ERROR);
9187 	}
9188 
9189 	if ((rval = emlxs_dhc_set_auth_key(hba, &dfc_pwd))) {
9190 		return (rval);
9191 	}
9192 
9193 	if (ddi_copyout((void *)&dfc_pwd, (void *)dfc->buf1,
9194 	    sizeof (dfc_auth_password_t), mode) != 0) {
9195 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9196 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
9197 
9198 		return (DFC_COPYOUT_ERROR);
9199 	}
9200 
9201 	return (0);
9202 
9203 } /* emlxs_dfc_set_auth_pwd() */
9204 
9205 
9206 static int32_t
9207 emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9208 {
9209 	emlxs_port_t		*port = &PPORT;
9210 	dfc_auth_status_t	fcsp_status;
9211 	uint32_t		rval = DFC_SUCCESS;
9212 
9213 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
9214 	    emlxs_dfc_xlate(dfc->cmd));
9215 
9216 	if (!dfc->buf1 || !dfc->buf1_size) {
9217 		EMLXS_MSGF(EMLXS_CONTEXT,
9218 		    &emlxs_dfc_error_msg, "%s: Null buffer1 found.",
9219 		    emlxs_dfc_xlate(dfc->cmd));
9220 
9221 		return (DFC_ARG_NULL);
9222 	}
9223 
9224 	if (dfc->buf1_size < sizeof (dfc_auth_status_t)) {
9225 		EMLXS_MSGF(EMLXS_CONTEXT,
9226 		    &emlxs_dfc_error_msg, "%s: Buffer too small. (size=%d)",
9227 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
9228 
9229 		return (DFC_ARG_TOOSMALL);
9230 	}
9231 
9232 	/* Read the fcsp_config */
9233 	if (ddi_copyin((void *) dfc->buf1, (void *) &fcsp_status,
9234 	    sizeof (dfc_auth_status_t), mode) != 0) {
9235 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9236 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
9237 
9238 		return (DFC_COPYIN_ERROR);
9239 	}
9240 
9241 	if ((rval = emlxs_dhc_get_auth_status(hba, &fcsp_status)) != 0) {
9242 		return (rval);
9243 	}
9244 
9245 	if (ddi_copyout((void *) &fcsp_status, (void *) dfc->buf1,
9246 	    sizeof (dfc_auth_status_t), mode) != 0) {
9247 		EMLXS_MSGF(EMLXS_CONTEXT,
9248 		    &emlxs_dfc_error_msg, "%s: ddi_copyout failed.",
9249 		    emlxs_dfc_xlate(dfc->cmd));
9250 
9251 		return (DFC_COPYOUT_ERROR);
9252 	}
9253 
9254 	return (0);
9255 
9256 } /* emlxs_dfc_get_auth_status() */
9257 
9258 
9259 static int32_t
9260 emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9261 {
9262 	emlxs_port_t		*port = &PPORT;
9263 	dfc_fcsp_config_t	*fcsp_cfg;
9264 	uint32_t		count;
9265 	uint32_t		size;
9266 	uint32_t		rval = DFC_SUCCESS;
9267 
9268 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
9269 	    emlxs_dfc_xlate(dfc->cmd));
9270 
9271 	/* Lock cfg table while we do this */
9272 	/* This prevents the table from changing while we get a copy */
9273 	mutex_enter(&hba->auth_lock);
9274 
9275 	if (!dfc->buf2 || !dfc->buf2_size) {
9276 		EMLXS_MSGF(EMLXS_CONTEXT,
9277 		    &emlxs_dfc_error_msg, "%s: Null buffer2 found.",
9278 		    emlxs_dfc_xlate(dfc->cmd));
9279 
9280 		mutex_exit(&hba->auth_lock);
9281 		return (DFC_ARG_NULL);
9282 	}
9283 
9284 	if (dfc->buf2_size < sizeof (uint32_t)) {
9285 		EMLXS_MSGF(EMLXS_CONTEXT,
9286 		    &emlxs_dfc_error_msg, "%s: Buffer2 too small. (size=%d)",
9287 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
9288 
9289 		mutex_exit(&hba->auth_lock);
9290 		return (DFC_ARG_TOOSMALL);
9291 	}
9292 
9293 	if (ddi_copyout((void *)&hba->auth_cfg_count, (void *)dfc->buf2,
9294 	    sizeof (uint32_t), mode) != 0) {
9295 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9296 		    "%s: ddi_copyout failed for table count. count=%d",
9297 		    emlxs_dfc_xlate(dfc->cmd), hba->auth_cfg_count);
9298 
9299 		mutex_exit(&hba->auth_lock);
9300 		return (DFC_COPYOUT_ERROR);
9301 	}
9302 
9303 	if (!dfc->buf1 || !dfc->buf1_size) {
9304 		mutex_exit(&hba->auth_lock);
9305 		return (DFC_SUCCESS);
9306 	}
9307 
9308 	/* Check table size */
9309 	count = dfc->buf1_size / sizeof (dfc_fcsp_config_t);
9310 	if (count < hba->auth_cfg_count) {
9311 		EMLXS_MSGF(EMLXS_CONTEXT,
9312 		    &emlxs_dfc_error_msg, "%s: Buffer1 too small. (%d < %d)",
9313 		    emlxs_dfc_xlate(dfc->cmd), count, hba->auth_cfg_count);
9314 
9315 		mutex_exit(&hba->auth_lock);
9316 		return (DFC_ARG_TOOSMALL);
9317 	}
9318 
9319 	size = hba->auth_cfg_count * sizeof (dfc_fcsp_config_t);
9320 
9321 	mutex_exit(&hba->auth_lock);
9322 
9323 	fcsp_cfg = (dfc_fcsp_config_t *)kmem_zalloc(size, KM_SLEEP);
9324 
9325 	mutex_enter(&hba->auth_lock);
9326 
9327 	if ((rval = emlxs_dhc_get_auth_cfg_table(hba, fcsp_cfg)) != 0) {
9328 		mutex_exit(&hba->auth_lock);
9329 		kmem_free(fcsp_cfg, size);
9330 		return (rval);
9331 	}
9332 
9333 	mutex_exit(&hba->auth_lock);
9334 
9335 	if (ddi_copyout((void *)fcsp_cfg, (void *)dfc->buf1, size, mode) != 0) {
9336 		EMLXS_MSGF(EMLXS_CONTEXT,
9337 		    &emlxs_dfc_error_msg, "%s: ddi_copyout failed.",
9338 		    emlxs_dfc_xlate(dfc->cmd));
9339 
9340 		kmem_free(fcsp_cfg, size);
9341 		return (DFC_COPYOUT_ERROR);
9342 	}
9343 
9344 	kmem_free(fcsp_cfg, size);
9345 	return (0);
9346 
9347 } /* emlxs_dfc_get_auth_cfg_table() */
9348 
9349 
9350 static int32_t
9351 emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9352 {
9353 	emlxs_port_t		*port = &PPORT;
9354 	dfc_auth_password_t	*auth_pwd;
9355 	uint32_t		count;
9356 	uint32_t		size;
9357 	uint32_t		rval = DFC_SUCCESS;
9358 
9359 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg, "%s requested.",
9360 	    emlxs_dfc_xlate(dfc->cmd));
9361 
9362 	/* Lock cfg table while we do this */
9363 	/* This prevents the table from changing while we get a copy */
9364 	mutex_enter(&hba->auth_lock);
9365 
9366 	if (!dfc->buf2 || !dfc->buf2_size) {
9367 		EMLXS_MSGF(EMLXS_CONTEXT,
9368 		    &emlxs_dfc_error_msg, "%s: Null buffer2 found.",
9369 		    emlxs_dfc_xlate(dfc->cmd));
9370 
9371 		mutex_exit(&hba->auth_lock);
9372 		return (DFC_ARG_NULL);
9373 	}
9374 
9375 	if (dfc->buf2_size < sizeof (uint32_t)) {
9376 		EMLXS_MSGF(EMLXS_CONTEXT,
9377 		    &emlxs_dfc_error_msg, "%s: Buffer2 too small. (size=%d)",
9378 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
9379 
9380 		mutex_exit(&hba->auth_lock);
9381 		return (DFC_ARG_TOOSMALL);
9382 	}
9383 
9384 	if (ddi_copyout((void *)&hba->auth_key_count, (void *)dfc->buf2,
9385 	    sizeof (uint32_t), mode) != 0) {
9386 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9387 		    "%s: ddi_copyout failed for table count. count=%d",
9388 		    emlxs_dfc_xlate(dfc->cmd), hba->auth_key_count);
9389 
9390 		mutex_exit(&hba->auth_lock);
9391 		return (DFC_COPYOUT_ERROR);
9392 	}
9393 
9394 	if (!dfc->buf1 || !dfc->buf1_size) {
9395 		mutex_exit(&hba->auth_lock);
9396 		return (DFC_SUCCESS);
9397 	}
9398 
9399 	/* Check table size */
9400 	count = dfc->buf1_size / sizeof (dfc_auth_password_t);
9401 	if (count < hba->auth_key_count) {
9402 		EMLXS_MSGF(EMLXS_CONTEXT,
9403 		    &emlxs_dfc_error_msg, "%s: Buffer1 too small. (%d < %d)",
9404 		    emlxs_dfc_xlate(dfc->cmd), count, hba->auth_key_count);
9405 
9406 		mutex_exit(&hba->auth_lock);
9407 		return (DFC_ARG_TOOSMALL);
9408 	}
9409 
9410 	size = hba->auth_key_count * sizeof (dfc_auth_password_t);
9411 
9412 	mutex_exit(&hba->auth_lock);
9413 
9414 	auth_pwd = (dfc_auth_password_t *)kmem_zalloc(size, KM_SLEEP);
9415 
9416 	mutex_enter(&hba->auth_lock);
9417 
9418 	if ((rval = emlxs_dhc_get_auth_key_table(hba, auth_pwd)) != 0) {
9419 		mutex_exit(&hba->auth_lock);
9420 		kmem_free(auth_pwd, size);
9421 		return (rval);
9422 	}
9423 
9424 	mutex_exit(&hba->auth_lock);
9425 
9426 	if (ddi_copyout((void *)auth_pwd, (void *)dfc->buf1, size, mode) != 0) {
9427 		EMLXS_MSGF(EMLXS_CONTEXT,
9428 		    &emlxs_dfc_error_msg, "%s: ddi_copyout failed.",
9429 		    emlxs_dfc_xlate(dfc->cmd));
9430 
9431 		kmem_free(auth_pwd, size);
9432 		return (DFC_COPYOUT_ERROR);
9433 	}
9434 
9435 	kmem_free(auth_pwd, size);
9436 	return (0);
9437 
9438 } /* emlxs_dfc_get_auth_key_table() */
9439 
9440 
9441 
9442 #endif	/* DHCHAP_SUPPORT */
9443 
9444 #ifdef SAN_DIAG_SUPPORT
9445 static int32_t
9446 emlxs_dfc_sd_set_bucket(dfc_t *dfc, int32_t mode)
9447 {
9448 	uint32_t	type, search_type;
9449 	uint16_t	state;
9450 	int32_t		rval = DFC_SD_OK;
9451 
9452 	type = dfc->data1;
9453 	search_type = dfc->data2;
9454 
9455 	mutex_enter(&sd_bucket_mutex);
9456 	state = sd_bucket.state;
9457 	mutex_exit(&sd_bucket_mutex);
9458 
9459 	if (state == SD_COLLECTING)
9460 		rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9461 	else if ((search_type < SD_SEARCH_LINEAR) ||
9462 	    (search_type > SD_SEARCH_POWER_2))
9463 		rval = DFC_SD_ERROR_INVALID_ARG;
9464 	else if (type != SD_SCSI_IO_LATENCY_TYPE)
9465 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9466 	else {
9467 		(void) ddi_copyin(dfc->buf3, (void *) &sd_bucket,
9468 		    sizeof (sd_bucket_info_t), mode);
9469 		mutex_enter(&sd_bucket_mutex);
9470 		sd_bucket.state = SD_STOPPED;
9471 		mutex_exit(&sd_bucket_mutex);
9472 	}
9473 
9474 set_bucket_exit:
9475 	return (rval);
9476 }
9477 
9478 
9479 static int32_t
9480 emlxs_dfc_sd_destroy_bucket(dfc_t *dfc)
9481 {
9482 	uint32_t	type;
9483 	int32_t 	rval = DFC_SD_OK;
9484 
9485 	type = dfc->data1;
9486 
9487 	mutex_enter(&sd_bucket_mutex);
9488 
9489 	if (sd_bucket.search_type == 0)
9490 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9491 	else if (sd_bucket.state == SD_COLLECTING)
9492 		rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9493 	else if (type != SD_SCSI_IO_LATENCY_TYPE)
9494 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9495 	else
9496 		bzero((uint8_t *)&sd_bucket, sizeof (sd_bucket_info_t));
9497 
9498 destroy_bucket_exit:
9499 	mutex_exit(&sd_bucket_mutex);
9500 	return (rval);
9501 }
9502 
9503 
9504 static int32_t
9505 emlxs_dfc_sd_get_bucket(dfc_t *dfc, int32_t mode)
9506 {
9507 	uint32_t	type;
9508 	int32_t		rval = DFC_SD_OK;
9509 
9510 	type = dfc->data1;
9511 
9512 	if (sd_bucket.search_type == 0)
9513 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9514 	else if (type != SD_SCSI_IO_LATENCY_TYPE)
9515 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9516 	else
9517 		(void) ddi_copyout(&sd_bucket, dfc->buf3,
9518 		    sizeof (sd_bucket_info_t), mode);
9519 
9520 	return (rval);
9521 }
9522 
9523 
9524 static int32_t
9525 emlxs_dfc_sd_start_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9526 {
9527 	emlxs_port_t	*vport;
9528 	NODELIST	*nlp;
9529 	uint8_t		wwpn[8];
9530 	int32_t		rval = DFC_SD_OK;
9531 	int		i;
9532 
9533 	if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9534 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9535 		goto start_collect_exit;
9536 	}
9537 
9538 	if (sd_bucket.search_type == 0) {
9539 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9540 		goto start_collect_exit;
9541 	}
9542 
9543 	/* Read the wwn object */
9544 	(void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode);
9545 
9546 	/* Make sure WWPN is unique */
9547 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9548 
9549 	if (!vport) {
9550 		rval = DFC_SD_ERROR_INVALID_PORT;
9551 		goto start_collect_exit;
9552 	}
9553 
9554 	/* traverse list of nodes for this vport and reset counter */
9555 	rw_enter(&vport->node_rwlock, RW_READER);
9556 	if (vport->sd_io_latency_state == SD_COLLECTING) {
9557 		rval = DFC_SD_ERROR_DATA_COLLECTION_ACTIVE;
9558 		rw_exit(&vport->node_rwlock);
9559 		goto start_collect_exit;
9560 	}
9561 
9562 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9563 		nlp = vport->node_table[i];
9564 		while (nlp != NULL) {
9565 			bzero((void *)&nlp->sd_dev_bucket[0],
9566 			    sizeof (struct SD_time_stats_v0) *
9567 			    SD_IO_LATENCY_MAX_BUCKETS);
9568 
9569 			nlp = nlp->nlp_list_next;
9570 		}
9571 	}
9572 
9573 	vport->sd_io_latency_state = SD_COLLECTING;
9574 	rw_exit(&vport->node_rwlock);
9575 
9576 	mutex_enter(&sd_bucket_mutex);
9577 	sd_bucket.state = SD_COLLECTING;
9578 	mutex_exit(&sd_bucket_mutex);
9579 
9580 start_collect_exit:
9581 	return (rval);
9582 }
9583 
9584 
9585 static int32_t
9586 emlxs_dfc_sd_stop_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9587 {
9588 	emlxs_port_t	*vport;
9589 	emlxs_hba_t	*temp_hba;
9590 	uint8_t		wwpn[8];
9591 	int32_t		rval = DFC_SD_OK;
9592 	int		i, j;
9593 
9594 	if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9595 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9596 		goto stop_collect_exit;
9597 	}
9598 
9599 	if (sd_bucket.search_type == 0) {
9600 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9601 		goto stop_collect_exit;
9602 	}
9603 
9604 	/* Read the wwn object */
9605 	(void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode);
9606 
9607 	/* Make sure WWPN is unique */
9608 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9609 
9610 	if (!vport) {
9611 		rval = DFC_SD_ERROR_INVALID_PORT;
9612 		goto stop_collect_exit;
9613 	}
9614 
9615 	rw_enter(&vport->node_rwlock, RW_READER);
9616 	if (vport->sd_io_latency_state != SD_COLLECTING) {
9617 		rval = DFC_SD_ERROR_DATA_COLLECTION_NOT_ACTIVE;
9618 		rw_exit(&vport->node_rwlock);
9619 		goto stop_collect_exit;
9620 	}
9621 	vport->sd_io_latency_state = SD_STOPPED;
9622 	rw_exit(&vport->node_rwlock);
9623 
9624 	/* see if any other port is collecting io latency */
9625 	for (i = 0; i < emlxs_device.hba_count; i++) {
9626 		temp_hba = emlxs_device.hba[i];
9627 		for (j = 0; j < temp_hba->num_of_ports; j++) {
9628 			vport = &temp_hba->port[j];
9629 			if (vport->sd_io_latency_state == SD_COLLECTING)
9630 				goto stop_collect_exit;
9631 		}
9632 	}
9633 
9634 	/*
9635 	 * if we get here, that means no one else is collecting
9636 	 * io latency data.
9637 	 */
9638 	mutex_enter(&sd_bucket_mutex);
9639 	sd_bucket.state = SD_STOPPED;
9640 	mutex_exit(&sd_bucket_mutex);
9641 
9642 stop_collect_exit:
9643 	return (rval);
9644 }
9645 
9646 
9647 static int32_t
9648 emlxs_dfc_sd_reset_collection(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9649 {
9650 	emlxs_port_t   *vport;
9651 	NODELIST	*nlp;
9652 	uint8_t		wwpn[8];
9653 	int32_t 	rval = DFC_SD_OK;
9654 	int		i;
9655 
9656 	if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9657 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9658 		goto reset_collect_exit;
9659 	}
9660 
9661 	if (sd_bucket.search_type == 0) {
9662 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9663 		goto reset_collect_exit;
9664 	}
9665 
9666 	/* Read the wwn object */
9667 	(void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode);
9668 
9669 	/* Make sure WWPN is unique */
9670 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9671 
9672 	if (!vport) {
9673 		rval = DFC_SD_ERROR_INVALID_PORT;
9674 		goto reset_collect_exit;
9675 	}
9676 
9677 	/* traverse list of nodes for this vport and reset counter */
9678 	rw_enter(&vport->node_rwlock, RW_READER);
9679 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9680 		nlp = vport->node_table[i];
9681 		while (nlp != NULL) {
9682 			bzero((void *)&nlp->sd_dev_bucket[0],
9683 			    sizeof (struct SD_time_stats_v0) *
9684 			    SD_IO_LATENCY_MAX_BUCKETS);
9685 
9686 			nlp = nlp->nlp_list_next;
9687 		}
9688 	}
9689 	rw_exit(&vport->node_rwlock);
9690 
9691 reset_collect_exit:
9692 	return (rval);
9693 }
9694 
9695 
9696 static int32_t
9697 emlxs_dfc_sd_get_data(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9698 {
9699 	emlxs_port_t   *vport;
9700 	uint8_t		wwpn[8];
9701 	int		i, skip_bytes;
9702 	uint16_t	count;
9703 	uint32_t	bufsize, size_needed;
9704 	NODELIST	*nlp;
9705 	int32_t 	rval = DFC_SD_OK;
9706 
9707 	if (dfc->data1 != SD_SCSI_IO_LATENCY_TYPE) {
9708 		rval = DFC_SD_ERROR_NOT_SUPPORTED;
9709 		goto get_data_exit;
9710 	}
9711 
9712 	if (sd_bucket.search_type == 0) {
9713 		rval = DFC_SD_ERROR_BUCKET_NOT_SET;
9714 		goto get_data_exit;
9715 	}
9716 
9717 	/* Read the wwn object */
9718 	(void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode);
9719 
9720 	/* Make sure WWPN is unique */
9721 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9722 
9723 	if (!vport) {
9724 		rval = DFC_SD_ERROR_INVALID_PORT;
9725 		goto get_data_exit;
9726 	}
9727 
9728 	bufsize = dfc->buf4_size;
9729 
9730 	/*
9731 	 * count # of targets to see if buffer is big enough
9732 	 */
9733 	count = 0;
9734 	rw_enter(&vport->node_rwlock, RW_READER);
9735 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9736 		nlp = vport->node_table[i];
9737 		while (nlp != NULL) {
9738 			count++;
9739 			nlp = nlp->nlp_list_next;
9740 		}
9741 	}
9742 	rw_exit(&vport->node_rwlock);
9743 
9744 	size_needed = count * (sizeof (HBA_WWN) +
9745 	    sizeof (struct SD_time_stats_v0) * SD_IO_LATENCY_MAX_BUCKETS);
9746 
9747 	if (bufsize < size_needed) {
9748 		rval = DFC_SD_ERROR_MORE_DATA_AVAIL;
9749 		goto update_count;	/* not enough space, return */
9750 	}
9751 
9752 	/*
9753 	 * return data collected, reset counter.
9754 	 */
9755 	count = 0;
9756 	skip_bytes = 0;
9757 	rw_enter(&vport->node_rwlock, RW_READER);
9758 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
9759 		nlp = vport->node_table[i];
9760 		while (nlp != NULL) {
9761 			/* copy port name */
9762 			(void) ddi_copyout((void *)&nlp->nlp_portname,
9763 			    (void *)((char *)dfc->buf4 + skip_bytes),
9764 			    sizeof (HBA_WWN), mode);
9765 			skip_bytes += sizeof (HBA_WWN);
9766 
9767 			/* copy bucket data */
9768 			(void) ddi_copyout((void *)&nlp->sd_dev_bucket[0],
9769 			    (void *)((char *)dfc->buf4 + skip_bytes),
9770 			    sizeof (struct SD_time_stats_v0) *
9771 			    SD_IO_LATENCY_MAX_BUCKETS, mode);
9772 			skip_bytes += sizeof (struct SD_time_stats_v0) *
9773 			    SD_IO_LATENCY_MAX_BUCKETS;
9774 
9775 			bzero((void *)&nlp->sd_dev_bucket[0],
9776 			    sizeof (struct SD_time_stats_v0) *
9777 			    SD_IO_LATENCY_MAX_BUCKETS);
9778 
9779 			count++;
9780 			bufsize -= sizeof (struct SD_IO_Latency_Response);
9781 
9782 			nlp = nlp->nlp_list_next;
9783 		}
9784 	}
9785 	rw_exit(&vport->node_rwlock);
9786 
9787 update_count:
9788 	(void) ddi_copyout((void *)&count, (void *)dfc->buf2,
9789 	    sizeof (uint16_t), mode);
9790 
9791 get_data_exit:
9792 	return (rval);
9793 }
9794 
9795 
9796 static int32_t
9797 emlxs_dfc_sd_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9798 {
9799 	emlxs_port_t		*vport;
9800 	uint8_t			wwpn[8];
9801 	uint32_t		event, pid, enable;
9802 	int32_t 		rval = DFC_SD_OK;
9803 	int			i, count;
9804 	emlxs_dfc_event_t	*dfc_event;
9805 
9806 	/*
9807 	 * The value of "event" has been shifted left based on
9808 	 * the category that the application gave to libdfc.
9809 	 *
9810 	 * This is so the old Event handling code won't mistakenly
9811 	 * grab an SD Event.
9812 	 */
9813 	event = dfc->data1;
9814 	pid = dfc->data3;
9815 	enable = dfc->flag;
9816 
9817 	/* Read the wwn object */
9818 	(void) ddi_copyin((void *)dfc->buf3, (void *)wwpn, 8, mode);
9819 
9820 	/* Make sure WWPN is unique */
9821 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9822 
9823 	if (!vport) {
9824 		rval = DFC_SD_ERROR_INVALID_PORT;
9825 		goto set_sd_event_exit;
9826 	}
9827 
9828 	if (enable) {
9829 		/* Find next available event object */
9830 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
9831 			dfc_event = &vport->sd_events[i];
9832 
9833 			if (!dfc_event->pid && !dfc_event->event)
9834 				break;
9835 		}
9836 
9837 		/* Return if all event objects are busy */
9838 		if (i == MAX_DFC_EVENTS) {
9839 			rval = DFC_SD_ERROR_OUT_OF_HANDLES;
9840 			goto set_sd_event_exit;
9841 		}
9842 
9843 		/* Initialize */
9844 		/* TODO: Should we add SUBCAT in dfc_event ??? */
9845 		dfc_event->pid = pid;
9846 		dfc_event->event = event;
9847 		dfc_event->last_id = (uint32_t)-1;
9848 		dfc_event->dataout = NULL;
9849 		dfc_event->size = 0;
9850 		dfc_event->mode = 0;
9851 
9852 		(void) emlxs_get_sd_event(vport, dfc_event, 0);
9853 
9854 		if (dfc->buf1)
9855 			(void) ddi_copyout((void *) &dfc_event->last_id,
9856 			    dfc->buf1, sizeof (uint32_t), mode);
9857 
9858 		vport->sd_event_mask |= event;
9859 	} else { /* Disable */
9860 		/* find event entry */
9861 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
9862 			dfc_event = &vport->sd_events[i];
9863 
9864 			if (dfc_event->pid  == pid && dfc_event->event == event)
9865 				break;
9866 		}
9867 
9868 		/* Return if not found */
9869 		if (i == MAX_DFC_EVENTS) {
9870 			rval = DFC_SD_ERROR_INVALID_ARG;
9871 			goto set_sd_event_exit;
9872 		}
9873 
9874 		/* Kill the event thread if it is sleeping */
9875 		(void) emlxs_kill_dfc_event(vport, dfc_event);
9876 
9877 		/* Count the number of pids still registered for this event */
9878 		count = 0;
9879 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
9880 			dfc_event = &vport->sd_events[i];
9881 
9882 			if (dfc_event->event == event)
9883 				count++;
9884 		}
9885 
9886 		/*
9887 		 * If no more pids need this event,
9888 		 * then disable logging for this event
9889 		 */
9890 		if (count == 0)
9891 			vport->sd_event_mask &= ~event;
9892 	}
9893 
9894 set_sd_event_exit:
9895 	return (rval);
9896 } /* emlxs_dfc_sd_set_event */
9897 
9898 
9899 static int32_t
9900 emlxs_dfc_sd_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9901 {
9902 	emlxs_port_t   *vport;
9903 	uint8_t		wwpn[8];
9904 	uint32_t	event, pid, sleep, i;
9905 	int32_t		rval = DFC_SD_OK;
9906 	emlxs_dfc_event_t *dfc_event;
9907 
9908 	event = dfc->data1;
9909 	pid = dfc->data2;
9910 
9911 	/* Read the wwn object */
9912 	(void) ddi_copyin((void *)dfc->buf4, (void *)wwpn, 8, mode);
9913 
9914 	/* Make sure WWPN is unique */
9915 	vport = emlxs_vport_find_wwpn(hba, wwpn);
9916 
9917 	if (!vport) {
9918 		rval = DFC_SD_ERROR_INVALID_PORT;
9919 		goto get_sd_event_exit;
9920 	}
9921 
9922 	/* Find the event entry */
9923 	dfc_event = NULL;
9924 	for (i = 0; i < MAX_DFC_EVENTS; i++) {
9925 		dfc_event = &vport->sd_events[i];
9926 
9927 		if (dfc_event->pid == pid && dfc_event->event == event)
9928 			break;
9929 	}
9930 
9931 	if (i == MAX_DFC_EVENTS) {
9932 		rval = DFC_SD_ERROR_GENERIC;
9933 		goto get_sd_event_exit;
9934 	}
9935 
9936 	if (!(vport->sd_event_mask & dfc_event->event)) {
9937 		rval = DFC_SD_ERROR_GENERIC;
9938 		goto get_sd_event_exit;
9939 	}
9940 
9941 	/* Initialize event buffer pointers */
9942 	dfc_event->dataout = dfc->buf1;
9943 	dfc_event->size = dfc->buf1_size;
9944 	dfc_event->last_id = dfc->data3;
9945 	dfc_event->mode = mode;
9946 
9947 	sleep = (dfc->flag & 0x01) ? 1 : 0;
9948 
9949 	if (emlxs_get_sd_event(vport, dfc_event, sleep))
9950 		return (DFC_SD_ERROR_GENERIC);
9951 
9952 	/*
9953 	 * update rcv_size.
9954 	 */
9955 	if (dfc->buf2)
9956 		(void) ddi_copyout((void *) &dfc_event->size, dfc->buf2,
9957 		    sizeof (uint32_t), mode);
9958 
9959 	/*
9960 	 * update index
9961 	 */
9962 	if (dfc->buf3)
9963 		(void) ddi_copyout((void *) &dfc_event->last_id, dfc->buf3,
9964 		    sizeof (uint32_t), mode);
9965 
9966 get_sd_event_exit:
9967 	return (rval);
9968 } /* emlxs_dfc_sd_get_event */
9969 #endif
9970 
9971 static int32_t
9972 emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
9973 {
9974 	emlxs_port_t			*port = &PPORT;
9975 	fc_packet_t			*pkt = NULL;
9976 	NODELIST			*ndlp;
9977 	FCP_CMND			*fcp_cmd;
9978 	FCP_RSP				*fcp_rsp;
9979 	void				*ptr;
9980 	char				buffer[64];
9981 	dfc_send_scsi_fcp_cmd_info_t	cmdinfo;
9982 	uint32_t			rval = 0;
9983 
9984 	/* cmd info */
9985 	if (!dfc->buf1 ||
9986 	    (dfc->buf1_size != sizeof (dfc_send_scsi_fcp_cmd_info_t))) {
9987 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9988 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
9989 
9990 		rval = DFC_ARG_NULL;
9991 		goto done;
9992 	}
9993 
9994 	/* reqBuffer info */
9995 	if (!dfc->buf2 || (dfc->buf2_size != sizeof (FCP_CMND))) {
9996 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
9997 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
9998 
9999 		rval = DFC_ARG_NULL;
10000 		goto done;
10001 	}
10002 
10003 	/* rspBuffer info, could be 0 for SCSI commands like TUR */
10004 	if (!dfc->buf3 && dfc->buf3_size) {
10005 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10006 		    "%s: Null buffer3 found.", emlxs_dfc_xlate(dfc->cmd));
10007 
10008 		rval = DFC_ARG_NULL;
10009 		goto done;
10010 	}
10011 
10012 	/* senseBuffer info */
10013 	if (!dfc->buf4 || !dfc->buf4_size) {
10014 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10015 		    "%s: Null buffer4 found.", emlxs_dfc_xlate(dfc->cmd));
10016 
10017 		rval = DFC_ARG_NULL;
10018 		goto done;
10019 	}
10020 
10021 	if (ddi_copyin((void *) dfc->buf1, (void *) &cmdinfo,
10022 	    sizeof (dfc_send_scsi_fcp_cmd_info_t), mode) != 0) {
10023 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10024 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
10025 
10026 		rval = DFC_COPYIN_ERROR;
10027 		goto done;
10028 	}
10029 
10030 	if (cmdinfo.ver == DFC_SEND_SCSI_FCP_V2) {
10031 		port =
10032 		    emlxs_vport_find_wwpn(hba, (uint8_t *)&cmdinfo.src_wwn);
10033 		if (port == NULL) {
10034 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10035 			    "%s: WWPN does not exists. %s",
10036 			    emlxs_dfc_xlate(dfc->cmd), emlxs_wwn_xlate(buffer,
10037 			    (uint8_t *)&cmdinfo.src_wwn));
10038 
10039 			rval = DFC_ARG_INVALID;
10040 			goto done;
10041 		}
10042 	}
10043 
10044 	if ((ndlp = emlxs_node_find_wwpn(port,
10045 	    (uint8_t *)&cmdinfo.dst_wwn)) == NULL) {
10046 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10047 		    "%s: WWPN does not exists. %s", emlxs_dfc_xlate(dfc->cmd),
10048 		    emlxs_wwn_xlate(buffer, (uint8_t *)&cmdinfo.dst_wwn));
10049 
10050 		rval = DFC_ARG_INVALID;
10051 		goto done;
10052 	}
10053 
10054 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (FCP_CMND), sizeof (FCP_RSP),
10055 	    dfc->buf3_size, KM_NOSLEEP))) {
10056 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10057 		    "%s: Unable to allocate packet.",
10058 		    emlxs_dfc_xlate(dfc->cmd));
10059 
10060 		rval = DFC_SYSRES_ERROR;
10061 		goto done;
10062 	}
10063 	fcp_cmd = (FCP_CMND *) pkt->pkt_cmd;
10064 	/* Copy in the command buffer */
10065 	if (ddi_copyin((void *)dfc->buf2, (void *)fcp_cmd, sizeof (FCP_CMND),
10066 	    mode) != 0) {
10067 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10068 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
10069 
10070 		rval = DFC_COPYIN_ERROR;
10071 		goto done;
10072 	}
10073 
10074 	/* Make this a polled IO */
10075 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
10076 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
10077 	pkt->pkt_comp = NULL;
10078 
10079 	/* Build the fc header */
10080 	pkt->pkt_cmd_fhdr.d_id = LE_SWAP24_LO(ndlp->nlp_DID);
10081 	pkt->pkt_cmd_fhdr.r_ctl = FC_FCP_CMND;
10082 	pkt->pkt_cmd_fhdr.s_id = LE_SWAP24_LO(port->did);
10083 	pkt->pkt_cmd_fhdr.type = FC_FCP_DATA;
10084 	pkt->pkt_cmd_fhdr.seq_id = 0;
10085 	pkt->pkt_cmd_fhdr.df_ctl = 0;
10086 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
10087 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
10088 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
10089 	pkt->pkt_cmd_fhdr.ro = 0;
10090 
10091 	pkt->pkt_timeout = 30;
10092 
10093 	if ((fcp_cmd->fcpCntl3 == WRITE_DATA) && dfc->buf3_size) {
10094 		pkt->pkt_tran_type = FC_PKT_FCP_WRITE;
10095 		if (ddi_copyin((void *)dfc->buf3, (void *)pkt->pkt_data,
10096 		    dfc->buf3_size, mode) != 0) {
10097 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10098 			    "%s: ddi_copyin failed.",
10099 			    emlxs_dfc_xlate(dfc->cmd));
10100 
10101 			rval = DFC_COPYIN_ERROR;
10102 			goto done;
10103 		}
10104 	} else {
10105 		pkt->pkt_tran_type = FC_PKT_FCP_READ;
10106 	}
10107 
10108 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
10109 		rval = DFC_IO_ERROR;
10110 		goto done;
10111 	}
10112 
10113 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
10114 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
10115 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10116 			    "Pkt Transport error. Pkt Timeout.");
10117 			rval = DFC_TIMEOUT;
10118 		} else {
10119 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10120 			    "Pkt Transport error. state=%x", pkt->pkt_state);
10121 			rval = DFC_IO_ERROR;
10122 		}
10123 		goto done;
10124 	}
10125 
10126 	if (pkt->pkt_data_resid) {
10127 		if (pkt->pkt_data_resid < dfc->buf3_size)
10128 			dfc->buf3_size -= pkt->pkt_data_resid;
10129 		else
10130 			dfc->buf3_size = 0;
10131 	}
10132 
10133 	SCSI_RSP_CNT(cmdinfo) = dfc->buf3_size;
10134 
10135 	fcp_rsp = (FCP_RSP *) pkt->pkt_resp;
10136 	/*
10137 	 * This is sense count for flag = 0.
10138 	 * It is fcp response size for flag = 1.
10139 	 */
10140 	if (dfc->flag) {
10141 		SCSI_SNS_CNT(cmdinfo) = 24 + LE_SWAP32(fcp_rsp->rspSnsLen) +
10142 		    LE_SWAP32(fcp_rsp->rspRspLen);
10143 		ptr = (void *)fcp_rsp;
10144 	} else {
10145 		SCSI_SNS_CNT(cmdinfo) = LE_SWAP32(fcp_rsp->rspSnsLen);
10146 		ptr = (void *)&fcp_rsp->rspSnsInfo[0];
10147 	}
10148 
10149 	if (ddi_copyout((void *) &cmdinfo, (void *) dfc->buf1,
10150 	    sizeof (dfc_send_scsi_fcp_cmd_info_t), mode) != 0) {
10151 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10152 		    "%s: rsp_buf ddi_copyout failed.",
10153 		    emlxs_dfc_xlate(dfc->cmd));
10154 
10155 		rval = DFC_COPYOUT_ERROR;
10156 		goto done;
10157 	}
10158 
10159 	if (SCSI_SNS_CNT(cmdinfo)) {
10160 		if (ddi_copyout(ptr, (void *)dfc->buf4, SCSI_SNS_CNT(cmdinfo),
10161 		    mode) != 0) {
10162 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10163 			    "%s: rsp_size ddi_copyout failed.",
10164 			    emlxs_dfc_xlate(dfc->cmd));
10165 
10166 			rval = DFC_COPYOUT_ERROR;
10167 			goto done;
10168 		}
10169 	}
10170 
10171 	if (SCSI_RSP_CNT(cmdinfo)) {
10172 		if (ddi_copyout((void *)pkt->pkt_data, (void *)dfc->buf3,
10173 		    SCSI_RSP_CNT(cmdinfo), mode) != 0) {
10174 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10175 			    "%s: rsp_size ddi_copyout failed.",
10176 			    emlxs_dfc_xlate(dfc->cmd));
10177 
10178 			rval = DFC_COPYOUT_ERROR;
10179 			goto done;
10180 		}
10181 	}
10182 
10183 
10184 	rval = 0;
10185 
10186 done:
10187 	if (pkt) {
10188 		emlxs_pkt_free(pkt);
10189 	}
10190 
10191 	return (rval);
10192 
10193 } /* emlxs_dfc_send_scsi_fcp() */
10194 
10195 
10196 static int32_t
10197 emlxs_dfc_get_persist_linkdown(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10198 {
10199 	emlxs_port_t		*port = &PPORT;
10200 	emlxs_config_t		*cfg = &CFG;
10201 	uint16_t		linkdown = 0;
10202 	uint32_t		rval = 0;
10203 
10204 	if (hba->model_info.flags & EMLXS_FCOE_SUPPORTED) {
10205 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10206 		    "%s: FCoE not  supported.", emlxs_dfc_xlate(dfc->cmd));
10207 
10208 		return (DFC_FCOE_NOTSUPPORTED);
10209 	}
10210 
10211 	if (!dfc->buf1 || !dfc->buf1_size) {
10212 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10213 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10214 
10215 		return (DFC_ARG_NULL);
10216 	}
10217 
10218 	linkdown = (uint16_t)cfg[CFG_PERSIST_LINKDOWN].current;
10219 	if (ddi_copyout((void *)&linkdown, dfc->buf1, dfc->buf1_size,
10220 	    mode) != 0) {
10221 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10222 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
10223 
10224 		return (DFC_COPYOUT_ERROR);
10225 	}
10226 
10227 	return (rval);
10228 
10229 } /* emlxs_dfc_get_persist_linkdown() */
10230 
10231 
10232 /*ARGSUSED*/
10233 static int32_t
10234 emlxs_dfc_set_persist_linkdown(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10235 {
10236 	emlxs_port_t		*port = &PPORT;
10237 	emlxs_config_t		*cfg = &CFG;
10238 	uint32_t		rval = 0;
10239 
10240 	if (hba->model_info.flags & EMLXS_FCOE_SUPPORTED) {
10241 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10242 		    "%s: FCoE not  supported.", emlxs_dfc_xlate(dfc->cmd));
10243 
10244 		return (DFC_FCOE_NOTSUPPORTED);
10245 	}
10246 
10247 	if (dfc->data1) {
10248 		cfg[CFG_PERSIST_LINKDOWN].current = 1;
10249 	} else {
10250 		cfg[CFG_PERSIST_LINKDOWN].current = 0;
10251 	}
10252 
10253 	return (rval);
10254 
10255 } /* emlxs_dfc_set_persist_linkdown() */
10256 
10257 
10258 static int32_t
10259 emlxs_dfc_get_fcflist(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10260 {
10261 	emlxs_port_t		*port = &PPORT;
10262 	DFC_FCoEFCFInfo_t	*fcflistentry;
10263 	DFC_FCoEFCFList_t	*fcflist;
10264 	FCFIobj_t		*fp;
10265 	uint32_t		size;
10266 	uint32_t		i;
10267 	uint32_t		count = 0;
10268 	uint32_t		rval = 0;
10269 
10270 	if (!dfc->buf1 || !dfc->buf1_size) {
10271 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10272 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10273 
10274 		return (DFC_ARG_NULL);
10275 	}
10276 
10277 	if (dfc->buf1_size < sizeof (DFC_FCoEFCFList_t)) {
10278 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10279 		    "%s: Buffer1 too small. (size=%d)",
10280 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10281 
10282 		return (DFC_ARG_TOOSMALL);
10283 	}
10284 
10285 	if (! (hba->model_info.flags & EMLXS_FCOE_SUPPORTED)) {
10286 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10287 		    "%s: FCoE not  supported.", emlxs_dfc_xlate(dfc->cmd));
10288 
10289 		return (DFC_FCOE_NOTSUPPORTED);
10290 	}
10291 
10292 	size = sizeof (DFC_FCoEFCFList_t) +
10293 	    hba->sli.sli4.FCFICount * sizeof (DFC_FCoEFCFInfo_t);
10294 	fcflist = (DFC_FCoEFCFList_t *)kmem_zalloc(size, KM_SLEEP);
10295 
10296 	if (ddi_copyin(dfc->buf1, (void *)fcflist,
10297 	    sizeof (DFC_FCoEFCFList_t), mode) != 0) {
10298 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10299 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
10300 
10301 		rval = DFC_COPYIN_ERROR;
10302 		goto done;
10303 	}
10304 
10305 	fcflistentry = fcflist->entries;
10306 	mutex_enter(&hba->sli.sli4.id_lock);
10307 	fp = hba->sli.sli4.FCFIp;
10308 	for (i = 0; i < hba->sli.sli4.FCFICount; i ++) {
10309 		if ((fp->state == RESOURCE_ALLOCATED) &&
10310 		    (fp->fcf_rec.fcf_valid)) {
10311 			fcflistentry->Priority = fp->fcf_rec.fip_priority;
10312 			if (fp->fcf_rec.fcf_available)
10313 				fcflistentry->State = FCF_AVAILABLE_STATE;
10314 			fcflistentry->LKA_Period = fp->fcf_rec.fka_adv_period;
10315 
10316 			bcopy((void *)fp->fcf_rec.vlan_bitmap,
10317 			    (void *)fcflistentry->VLanBitMap, 512);
10318 			bcopy((void *)fp->fcf_rec.fc_map,
10319 			    (void *)fcflistentry->FC_Map, 3);
10320 			bcopy((void *)fp->fcf_rec.fabric_name_identifier,
10321 			    (void *)fcflistentry->FabricName, 8);
10322 			bcopy((void *)fp->fcf_rec.switch_name_identifier,
10323 			    (void *)fcflistentry->SwitchName, 8);
10324 			bcopy((void *)&fp->fcf_rec.fcf_mac_address_hi,
10325 			    (void *)fcflistentry->Mac, 6);
10326 
10327 			count ++;
10328 			fcflistentry ++;
10329 		}
10330 		fp ++;
10331 	}
10332 	mutex_exit(&hba->sli.sli4.id_lock);
10333 
10334 	if (count > fcflist->numberOfEntries)
10335 		rval = DFC_ARG_TOOSMALL;
10336 
10337 	i = sizeof (DFC_FCoEFCFList_t) +
10338 	    (fcflist->numberOfEntries - 1) * sizeof (DFC_FCoEFCFInfo_t);
10339 	fcflist->numberOfEntries = count;
10340 
10341 	if (ddi_copyout((void *) fcflist, dfc->buf1,
10342 	    i, mode) != 0) {
10343 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10344 		    "%s: ddi_copyout failed.", emlxs_dfc_xlate(dfc->cmd));
10345 
10346 		rval = DFC_COPYOUT_ERROR;
10347 		goto done;
10348 	}
10349 
10350 done:
10351 	kmem_free(fcflist, size);
10352 	return (rval);
10353 
10354 } /* emlxs_dfc_get_fcflist() */
10355 
10356 
10357 static int32_t
10358 emlxs_dfc_send_mbox4(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10359 {
10360 	emlxs_port_t	*port = &PPORT;
10361 	MAILBOX4	*mb4 = NULL;
10362 	MAILBOXQ	*mbq = NULL;
10363 	MBUF_INFO	bufinfo;
10364 	uint32_t	offset;
10365 	int32_t		mbxstatus = 0;
10366 	uint32_t	rval = 0;
10367 
10368 	if (!dfc->buf1 || !dfc->buf1_size) {
10369 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10370 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10371 
10372 		return (DFC_ARG_NULL);
10373 	}
10374 
10375 	if (!dfc->buf2 || !dfc->buf2_size) {
10376 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10377 		    "%s: Null buffer2 found.", emlxs_dfc_xlate(dfc->cmd));
10378 
10379 		return (DFC_ARG_NULL);
10380 	}
10381 
10382 	if ((dfc->buf1_size != sizeof (MAILBOX4)) &&
10383 	    (dfc->buf2_size != sizeof (MAILBOX4))) {
10384 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10385 		    "%s: Invalid buffer size. (size=%d)",
10386 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
10387 
10388 		return (DFC_ARG_INVALID);
10389 	}
10390 
10391 	if (dfc->buf3_size && !dfc->buf3) {
10392 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10393 		    "%s: NULL buffer3 found.",
10394 		    emlxs_dfc_xlate(dfc->cmd));
10395 
10396 		return (DFC_ARG_INVALID);
10397 	}
10398 
10399 	if (! (hba->model_info.flags & EMLXS_FCOE_SUPPORTED)) {
10400 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10401 		    "%s: FCoE not  supported.", emlxs_dfc_xlate(dfc->cmd));
10402 
10403 		return (DFC_FCOE_NOTSUPPORTED);
10404 	}
10405 
10406 	bzero(&bufinfo, sizeof (MBUF_INFO));
10407 	if (dfc->buf3_size) {
10408 		bufinfo.size = dfc->buf3_size;
10409 		bufinfo.flags = FC_MBUF_DMA | FC_MBUF_SNGLSG | FC_MBUF_DMA32;
10410 		bufinfo.align = ddi_ptob(hba->dip, 1L);
10411 		(void) emlxs_mem_alloc(hba, &bufinfo);
10412 
10413 		if (bufinfo.virt == NULL) {
10414 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10415 			    "%s: Unable to allocate buffer.",
10416 			    emlxs_dfc_xlate(dfc->cmd));
10417 
10418 			rval = DFC_SYSRES_ERROR;
10419 			goto done;
10420 		}
10421 
10422 		if (ddi_copyin((void *)dfc->buf3, (void *)bufinfo.virt,
10423 		    dfc->buf3_size, mode) != 0) {
10424 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10425 			    "%s: ddi_copyin failed", emlxs_dfc_xlate(dfc->cmd));
10426 
10427 			rval = DFC_COPYIN_ERROR;
10428 			goto done;
10429 		}
10430 	}
10431 
10432 	mbq =
10433 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10434 
10435 	mb4 = (MAILBOX4 *) mbq;
10436 
10437 	bzero((void *)mb4, sizeof (MAILBOX4));
10438 
10439 	if (ddi_copyin((void *)dfc->buf1, (void *)mb4, dfc->buf1_size,
10440 	    mode) != 0) {
10441 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10442 		    "%s: ddi_copyin failed.", emlxs_dfc_xlate(dfc->cmd));
10443 
10444 		rval = DFC_COPYIN_ERROR;
10445 		goto done;
10446 	}
10447 
10448 	if (dfc->buf3_size) {
10449 		offset = dfc->data3;
10450 		mb4->un.varWords[offset-1] = PADDR_LO(bufinfo.phys);
10451 		mb4->un.varWords[offset] = PADDR_HI(bufinfo.phys);
10452 	}
10453 
10454 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
10455 	    "%s: %s sent.  (%x %x %x %x)", emlxs_dfc_xlate(dfc->cmd),
10456 	    emlxs_mb_cmd_xlate(mb4->mbxCommand), mb4->un.varWords[0],
10457 	    mb4->un.varWords[1], mb4->un.varWords[2], mb4->un.varWords[3]);
10458 
10459 	/* issue the mbox cmd to the sli */
10460 	mbxstatus = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10461 
10462 	if (mbxstatus) {
10463 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10464 		    "%s: %s failed. mbxstatus=0x%x",
10465 		    emlxs_dfc_xlate(dfc->cmd),
10466 		    emlxs_mb_cmd_xlate(mb4->mbxCommand), mbxstatus);
10467 	}
10468 
10469 	if (ddi_copyout((void *)mb4, (void *)dfc->buf2, dfc->buf2_size,
10470 	    mode) != 0) {
10471 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10472 		    "%s: ddi_copyout failed. cmd=%x",
10473 		    emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10474 
10475 		rval = DFC_COPYOUT_ERROR;
10476 		goto done;
10477 	}
10478 
10479 	if (dfc->buf3_size) {
10480 		if (ddi_copyout((void *)bufinfo.virt, (void *)dfc->buf3,
10481 		    dfc->buf3_size, mode) != 0) {
10482 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10483 			    "%s: ddi_copyout failed. cmd=%x",
10484 			    emlxs_dfc_xlate(dfc->cmd), mb4->mbxCommand);
10485 
10486 			rval = DFC_COPYIN_ERROR;
10487 			goto done;
10488 		}
10489 	}
10490 done:
10491 	/* Free allocated memory */
10492 	if (bufinfo.virt) {
10493 		emlxs_mem_free(hba, &bufinfo);
10494 	}
10495 
10496 	if (mbq) {
10497 		kmem_free(mbq, sizeof (MAILBOXQ));
10498 	}
10499 
10500 	return (rval);
10501 } /* emlxs_dfc_send_mbox4() */
10502 
10503 
10504 static int
10505 emlxs_dfc_rd_be_fcf(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10506 {
10507 	emlxs_port_t	*port = &PPORT;
10508 	MATCHMAP	*mp;
10509 	MAILBOX4	*mb  = NULL;
10510 	MAILBOXQ	*mbq = NULL;
10511 	IOCTL_FCOE_READ_FCF_TABLE *fcf;
10512 	mbox_req_hdr_t  *hdr_req;
10513 	FCF_RECORD_t *fcfrec;
10514 	int32_t		rc = 0;
10515 	uint32_t	rval = 0;
10516 	uint16_t	index;
10517 
10518 	if (!dfc->buf1 || !dfc->buf1_size) {
10519 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10520 		    "%s: Null buffer1 found.", emlxs_dfc_xlate(dfc->cmd));
10521 
10522 		return (DFC_ARG_NULL);
10523 	}
10524 
10525 	mbq =
10526 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10527 
10528 	index = dfc->data1;
10529 	mb = (MAILBOX4 *)mbq;
10530 
10531 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
10532 
10533 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
10534 		rval = DFC_SYSRES_ERROR;
10535 		goto done;
10536 	}
10537 	/*
10538 	 * Save address for completion
10539 	 * Signifies a non-embedded command
10540 	 */
10541 	mb->un.varSLIConfig.be.embedded = 0;
10542 	mbq->nonembed = (uint8_t *)mp;
10543 	mbq->mbox_cmpl = NULL;
10544 
10545 	mb->mbxCommand = MBX_SLI_CONFIG;
10546 	mb->mbxOwner = OWN_HOST;
10547 
10548 	hdr_req = (mbox_req_hdr_t *)mp->virt;
10549 	hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
10550 	hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE;
10551 	hdr_req->timeout = 0;
10552 	hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE);
10553 	fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1);
10554 	fcf->params.request.fcf_index = index;
10555 
10556 	rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10557 	if (rc == MBX_SUCCESS) {
10558 		fcfrec = &fcf->params.response.fcf_entry[0];
10559 		if (ddi_copyout((void *)fcfrec, (void *)dfc->buf1,
10560 		    dfc->buf1_size, mode) != 0) {
10561 			rval = DFC_COPYOUT_ERROR;
10562 		}
10563 		if (ddi_copyout(
10564 		    (void *)&fcf->params.response.next_valid_fcf_index,
10565 		    (void *)dfc->buf2, dfc->buf2_size, mode) != 0) {
10566 			rval = DFC_COPYOUT_ERROR;
10567 		}
10568 	} else {
10569 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10570 		    "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
10571 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rc);
10572 		rval = DFC_COPYOUT_ERROR;
10573 	}
10574 done:
10575 	if (mp)
10576 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mp);
10577 	if (mbq)
10578 		kmem_free(mbq, sizeof (MAILBOXQ));
10579 
10580 	return (rval);
10581 }
10582 
10583 
10584 /*ARGSUSED*/
10585 static int
10586 emlxs_dfc_set_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10587 {
10588 	emlxs_port_t				*port = &PPORT;
10589 	MAILBOXQ				*mbq = NULL;
10590 	MAILBOX4				*mb;
10591 	IOCTL_COMMON_QUERY_FIRMWARE_CONFIG	*fw_config;
10592 	IOCTL_DCBX_SET_DCBX_MODE		*dcbx_mode;
10593 	uint32_t				port_num;
10594 	uint32_t				rval = 0;
10595 
10596 	mbq =
10597 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10598 
10599 	mb = (MAILBOX4 *)mbq;
10600 
10601 	/*
10602 	 * Signifies an embedded command
10603 	 */
10604 	mb->un.varSLIConfig.be.embedded = 1;
10605 	mbq->mbox_cmpl = NULL;
10606 
10607 	mb->mbxCommand = MBX_SLI_CONFIG;
10608 	mb->mbxOwner = OWN_HOST;
10609 	mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
10610 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
10611 	    IOCTL_SUBSYSTEM_COMMON;
10612 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
10613 	    COMMON_OPCODE_QUERY_FIRMWARE_CONFIG;
10614 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
10615 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
10616 	    sizeof (IOCTL_COMMON_QUERY_FIRMWARE_CONFIG);
10617 
10618 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10619 	if (rval != MBX_SUCCESS) {
10620 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10621 		    "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
10622 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
10623 
10624 		rval = DFC_DRV_ERROR;
10625 		goto done;
10626 	}
10627 
10628 	fw_config =
10629 	    (IOCTL_COMMON_QUERY_FIRMWARE_CONFIG *)&mb->un.varSLIConfig.payload;
10630 	port_num = fw_config->params.response.PhysicalPort;
10631 
10632 	bzero((void *)mb, sizeof (MAILBOX4));
10633 	mb->un.varSLIConfig.be.embedded = 1;
10634 	mbq->mbox_cmpl = NULL;
10635 
10636 	mb->mbxCommand = MBX_SLI_CONFIG;
10637 	mb->mbxOwner = OWN_HOST;
10638 	mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
10639 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
10640 	    IOCTL_SUBSYSTEM_DCBX;
10641 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
10642 	    DCBX_OPCODE_SET_DCBX_MODE;
10643 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
10644 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
10645 	    sizeof (IOCTL_DCBX_SET_DCBX_MODE);
10646 	dcbx_mode = (IOCTL_DCBX_SET_DCBX_MODE *)&mb->un.varSLIConfig.payload;
10647 	dcbx_mode->params.request.port_num = port_num;
10648 	dcbx_mode->params.request.dcbx_mode = dfc->data1;
10649 
10650 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
10651 	    "%s requested on port %d.", emlxs_dfc_xlate(dfc->cmd), port_num);
10652 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10653 	if (rval != MBX_SUCCESS) {
10654 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10655 		    "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
10656 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
10657 
10658 		rval = DFC_DRV_ERROR;
10659 	}
10660 
10661 done:
10662 	if (mbq)
10663 		kmem_free(mbq, sizeof (MAILBOXQ));
10664 
10665 	return (rval);
10666 }
10667 
10668 
10669 static int
10670 emlxs_dfc_get_be_dcbx(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
10671 {
10672 	emlxs_port_t				*port = &PPORT;
10673 	MAILBOXQ				*mbq = NULL;
10674 	MAILBOX4				*mb;
10675 	IOCTL_COMMON_QUERY_FIRMWARE_CONFIG	*fw_config;
10676 	IOCTL_DCBX_GET_DCBX_MODE		*dcbx_mode;
10677 	uint32_t				port_num;
10678 	uint32_t				rval = 0;
10679 
10680 	mbq =
10681 	    (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP);
10682 
10683 	mb = (MAILBOX4 *)mbq;
10684 
10685 	/*
10686 	 * Signifies an embedded command
10687 	 */
10688 	mb->un.varSLIConfig.be.embedded = 1;
10689 	mbq->mbox_cmpl = NULL;
10690 
10691 	mb->mbxCommand = MBX_SLI_CONFIG;
10692 	mb->mbxOwner = OWN_HOST;
10693 	mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
10694 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
10695 	    IOCTL_SUBSYSTEM_COMMON;
10696 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
10697 	    COMMON_OPCODE_QUERY_FIRMWARE_CONFIG;
10698 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
10699 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
10700 	    sizeof (IOCTL_COMMON_QUERY_FIRMWARE_CONFIG);
10701 
10702 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10703 	if (rval != MBX_SUCCESS) {
10704 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10705 		    "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
10706 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
10707 
10708 		rval = DFC_DRV_ERROR;
10709 		goto done;
10710 	}
10711 
10712 	fw_config =
10713 	    (IOCTL_COMMON_QUERY_FIRMWARE_CONFIG *)&mb->un.varSLIConfig.payload;
10714 	port_num = fw_config->params.response.PhysicalPort;
10715 
10716 	bzero((void *)mb, sizeof (MAILBOX4));
10717 	mb->un.varSLIConfig.be.embedded = 1;
10718 	mbq->mbox_cmpl = NULL;
10719 
10720 	mb->mbxCommand = MBX_SLI_CONFIG;
10721 	mb->mbxOwner = OWN_HOST;
10722 	mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
10723 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
10724 	    IOCTL_SUBSYSTEM_DCBX;
10725 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
10726 	    DCBX_OPCODE_GET_DCBX_MODE;
10727 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
10728 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
10729 	    sizeof (IOCTL_DCBX_SET_DCBX_MODE);
10730 	dcbx_mode = (IOCTL_DCBX_GET_DCBX_MODE *)&mb->un.varSLIConfig.payload;
10731 	dcbx_mode->params.request.port_num = port_num;
10732 
10733 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
10734 	    "%s requested on port %d.", emlxs_dfc_xlate(dfc->cmd), port_num);
10735 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
10736 	if (rval != MBX_SUCCESS) {
10737 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
10738 		    "%s: %s failed. mbxstatus=0x%x", emlxs_dfc_xlate(dfc->cmd),
10739 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
10740 
10741 		rval = DFC_DRV_ERROR;
10742 		goto done;
10743 	}
10744 
10745 	if (ddi_copyout((void *)&dcbx_mode->params.response.dcbx_mode,
10746 	    (void *)dfc->buf1, dfc->buf1_size, mode) != 0) {
10747 		rval = DFC_COPYOUT_ERROR;
10748 	}
10749 
10750 done:
10751 	if (mbq)
10752 		kmem_free(mbq, sizeof (MAILBOXQ));
10753 
10754 	return (rval);
10755 }
10756