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 2008 Emulex.  All rights reserved.
24  * Use is subject to License terms.
25  */
26 
27 
28 #include "emlxs.h"
29 
30 #define	PRIV_LILP_POSIT(port_dev)	port_dev->dev_did.priv_lilp_posit
31 #define	HARD_ADDR(port_dev)		port_dev->dev_hard_addr.hard_addr
32 #define	HBA_10GBIT	HBA_PORTSPEED_10GBIT
33 
34 #ifdef DFC_SUPPORT
35 
36 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
37 EMLXS_MSG_DEF(EMLXS_DFC_C);
38 
39 static int32_t emlxs_dfc_get_rev(emlxs_hba_t *hba,
40 	dfc_t *dfc, int32_t mode);
41 static int32_t emlxs_dfc_get_hbainfo(emlxs_hba_t *hba,
42 	dfc_t *dfc, int32_t mode);
43 static int32_t emlxs_dfc_get_hbastats(emlxs_hba_t *hba,
44 	dfc_t *dfc, int32_t mode);
45 static int32_t emlxs_dfc_get_drvstats(emlxs_hba_t *hba,
46 	dfc_t *dfc, int32_t mode);
47 static int32_t emlxs_dfc_set_diag(emlxs_hba_t *hba,
48 	dfc_t *dfc, int32_t mode);
49 static int32_t emlxs_dfc_send_mbox(emlxs_hba_t *hba,
50 	dfc_t *dfc, int32_t mode);
51 static int32_t emlxs_dfc_read_pci(emlxs_hba_t *hba,
52 	dfc_t *dfc, int32_t mode);
53 static int32_t emlxs_dfc_write_pci(emlxs_hba_t *hba,
54 	dfc_t *dfc, int32_t mode);
55 static int32_t emlxs_dfc_get_cfg(emlxs_hba_t *hba,
56 	dfc_t *dfc, int32_t mode);
57 static int32_t emlxs_dfc_set_cfg(emlxs_hba_t *hba,
58 	dfc_t *dfc, int32_t mode);
59 static int32_t emlxs_dfc_send_menlo(emlxs_hba_t *hba,
60 	dfc_t *dfc, int32_t mode);
61 static int32_t emlxs_dfc_send_ct(emlxs_hba_t *hba,
62 	dfc_t *dfc, int32_t mode);
63 static int32_t emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba,
64 	dfc_t *dfc, int32_t mode);
65 static int32_t emlxs_dfc_write_flash(emlxs_hba_t *hba,
66 	dfc_t *dfc, int32_t mode);
67 static int32_t emlxs_dfc_read_flash(emlxs_hba_t *hba,
68 	dfc_t *dfc, int32_t mode);
69 static int32_t emlxs_dfc_send_els(emlxs_hba_t *hba,
70 	dfc_t *dfc, int32_t mode);
71 static int32_t emlxs_dfc_loopback_test(emlxs_hba_t *hba,
72 	dfc_t *dfc, int32_t mode);
73 static int32_t emlxs_dfc_get_dump_region(emlxs_hba_t *hba,
74 	dfc_t *dfc, int32_t mode);
75 static int32_t emlxs_dfc_loopback_mode(emlxs_hba_t *hba,
76 	dfc_t *dfc, int32_t mode);
77 static int32_t emlxs_dfc_get_ioinfo(emlxs_hba_t *hba,
78 	dfc_t *dfc, int32_t mode);
79 static int32_t emlxs_dfc_get_linkinfo(emlxs_hba_t *hba,
80 	dfc_t *dfc, int32_t mode);
81 static int32_t emlxs_dfc_read_mem(emlxs_hba_t *hba,
82 	dfc_t *dfc, int32_t mode);
83 static int32_t emlxs_dfc_write_mem(emlxs_hba_t *hba,
84 	dfc_t *dfc, int32_t mode);
85 static int32_t emlxs_dfc_write_ctlreg(emlxs_hba_t *hba,
86 	dfc_t *dfc, int32_t mode);
87 static int32_t emlxs_dfc_read_ctlreg(emlxs_hba_t *hba,
88 	dfc_t *dfc, int32_t mode);
89 static int32_t emlxs_dfc_get_event(emlxs_hba_t *hba,
90 	dfc_t *dfc, int32_t mode);
91 static int32_t emlxs_dfc_set_event(emlxs_hba_t *hba,
92 	dfc_t *dfc, int32_t mode);
93 static int32_t emlxs_dfc_get_eventinfo(emlxs_hba_t *hba,
94 	dfc_t *dfc, int32_t mode);
95 static int32_t emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba,
96 	dfc_t *dfc, int32_t mode);
97 
98 #ifdef SFCT_SUPPORT
99 static int32_t emlxs_dfc_get_fctstat(emlxs_hba_t *hba,
100 	dfc_t *dfc, int32_t mode);
101 #endif	/* SFCT_SUPPORT */
102 #ifdef NPIV_SUPPORT
103 static int32_t emlxs_dfc_create_vport(emlxs_hba_t *hba,
104 	dfc_t *dfc, int32_t mode);
105 static int32_t emlxs_dfc_destroy_vport(emlxs_hba_t *hba,
106 	dfc_t *dfc, int32_t mode);
107 static int32_t emlxs_dfc_get_vportinfo(emlxs_hba_t *hba,
108 	dfc_t *dfc, int32_t mode);
109 static int32_t emlxs_dfc_npiv_resource(emlxs_hba_t *hba,
110 	dfc_t *dfc, int32_t mode);
111 static int32_t emlxs_dfc_npiv_test(emlxs_hba_t *hba,
112 	dfc_t *dfc, int32_t mode);
113 static emlxs_port_t *emlxs_vport_find_wwpn(emlxs_hba_t *hba,
114 	uint8_t *wwpn);
115 #endif	/* NPIV_SUPPORT */
116 
117 #ifdef DHCHAP_SUPPORT
118 static int32_t emlxs_dfc_init_auth(emlxs_hba_t *hba,
119 	dfc_t *dfc, int32_t mode);
120 static int32_t emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba,
121 	dfc_t *dfc, int32_t mode);
122 static int32_t emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba,
123 	dfc_t *dfc, int32_t mode);
124 static int32_t emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba,
125 	dfc_t *dfc, int32_t mode);
126 static int32_t emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba,
127 	dfc_t *dfc, int32_t mode);
128 static int32_t emlxs_dfc_get_auth_status(emlxs_hba_t *hba,
129 	dfc_t *dfc, int32_t mode);
130 static int32_t emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba,
131 	dfc_t *dfc, int32_t mode);
132 static int32_t emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba,
133 	dfc_t *dfc, int32_t mode);
134 #endif	/* DHCHAP_SUPPORT */
135 
136 static int32_t emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba,
137 	dfc_t *dfc, int32_t mode);
138 #ifdef FCIO_SUPPORT
139 static int32_t emlxs_fcio_manage(emlxs_hba_t *hba,
140 	dfc_t *dfc, int32_t mode);
141 #endif	/* FCIO_SUPPORT */
142 
143 
144 uint32_t emlxs_loopback_tmo = 60;
145 
146 emlxs_table_t emlxs_dfc_table[] =
147 {
148 	{EMLXS_GET_HBAINFO, "GET_HBAINFO"},
149 	{EMLXS_GET_REV, "GET_REV"},
150 	{EMLXS_SET_DIAG, "SET_DIAG"},
151 	{EMLXS_SEND_MBOX, "SEND_MBOX"},
152 	{EMLXS_READ_PCI, "READ_PCI"},
153 	{EMLXS_WRITE_PCI, "WRITE_PCI"},
154 	{EMLXS_GET_CFG, "GET_CFG"},
155 	{EMLXS_SET_CFG, "SET_CFG"},
156 	{EMLXS_SEND_CT, "SEND_CT"},
157 	{EMLXS_SEND_CT_RSP, "SEND_CT_RSP"},
158 	{EMLXS_SEND_MENLO, "SEND_MENLO"},
159 	{EMLXS_WRITE_FLASH, "WRITE_FLASH"},
160 	{EMLXS_READ_FLASH, "READ_FLASH"},
161 	{EMLXS_SEND_ELS, "SEND_ELS"},
162 	{EMLXS_LOOPBACK_TEST, "LOOPBACK_TEST"},
163 	{EMLXS_GET_DUMPREGION, "GET_DUMPREGION"},
164 	{EMLXS_LOOPBACK_MODE, "LOOPBACK_MODE"},
165 	{EMLXS_GET_IOINFO, "GET_IOINFO"},
166 	{EMLXS_GET_LINKINFO, "GET_LINKINFO"},
167 	{EMLXS_GET_NODEINFO, "GET_NODEINFO"},
168 	{EMLXS_READ_MEM, "READ_MEM"},
169 	{EMLXS_WRITE_MEM, "WRITE_MEM"},
170 	{EMLXS_WRITE_CTLREG, "WRITE_CTLREG"},
171 	{EMLXS_READ_CTLREG, "READ_CTLREG"},
172 	{EMLXS_SEND_SCSI, "SEND_SCSI"},
173 	{EMLXS_GET_EVENT, "GET_EVENT"},
174 	{EMLXS_SET_EVENT, "SET_EVENT"},
175 	{EMLXS_GET_EVENTINFO, "GET_EVENTINFO"},
176 	{EMLXS_GET_HBASTATS, "GET_HBASTATS"},
177 	{EMLXS_GET_DRVSTATS, "GET_DRVSTATS"},
178 	{EMLXS_CREATE_VPORT, "CREATE_VPORT"},
179 	{EMLXS_DESTROY_VPORT, "DESTROY_VPORT"},
180 	{EMLXS_GET_VPORTINFO, "GET_VPORTINFO"},
181 	{EMLXS_NPIV_RESOURCE, "NPIV_RESOURCE"},
182 	{EMLXS_NPIV_TEST, "NPIV_TEST"},
183 	{EMLXS_INIT_AUTH, "INIT_AUTH"},
184 	{EMLXS_GET_AUTH_CFG, "GET_AUTH_CFG"},
185 	{EMLXS_SET_AUTH_CFG, "SET_AUTH_CFG"},
186 	{EMLXS_GET_AUTH_PASSWORD, "GET_AUTH_PASSWORD"},
187 	{EMLXS_SET_AUTH_PASSWORD, "SET_AUTH_PASSWORD"},
188 	{EMLXS_GET_AUTH_STATUS, "GET_AUTH_STATUS"},
189 	{EMLXS_GET_AUTH_CFG_TABLE, "GET_AUTH_CFG_TABLE"},
190 	{EMLXS_GET_AUTH_KEY_TABLE, "GET_AUTH_KEY_TABLE"},
191 	{EMLXS_FCIO_CMD, "FCIO_CMD"},
192 	{EMLXS_GET_FCTSTAT, "GET_FCTSTAT"},
193 
194 };	/* emlxs_dfc_table */
195 
196 
197 emlxs_table_t emlxs_dfc_event_table[] =
198 {
199 	{FC_REG_LINK_EVENT, "LINK_EVENT"},
200 	{FC_REG_RSCN_EVENT, "RSCN_EVENT"},
201 	{FC_REG_CT_EVENT, "CT_EVENT"},
202 	{FC_REG_DUMP_EVENT, "DUMP_EVENT"},
203 	{FC_REG_TEMP_EVENT, "TEMP_EVENT"},
204 	{FC_REG_FCOE_EVENT, "FCOE_EVENT"},
205 
206 };	/* emlxs_dfc_event_table */
207 
208 
209 extern char *
210 emlxs_dfc_xlate(uint16_t cmd)
211 {
212 	static char buffer[32];
213 	uint32_t i;
214 	uint32_t count;
215 
216 	count = sizeof (emlxs_dfc_table) / sizeof (emlxs_table_t);
217 	for (i = 0; i < count; i++) {
218 		if (cmd == emlxs_dfc_table[i].code) {
219 			return (emlxs_dfc_table[i].string);
220 		}
221 	}
222 
223 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
224 	return (buffer);
225 
226 } /* emlxs_dfc_xlate() */
227 
228 
229 extern char *
230 emlxs_dfc_event_xlate(uint32_t event)
231 {
232 	static char buffer[32];
233 	uint32_t i;
234 	uint32_t count;
235 
236 	count = sizeof (emlxs_dfc_event_table) / sizeof (emlxs_table_t);
237 	for (i = 0; i < count; i++) {
238 		if (event == emlxs_dfc_event_table[i].code) {
239 			return (emlxs_dfc_event_table[i].string);
240 		}
241 	}
242 
243 	(void) sprintf(buffer, "Event=0x%x", event);
244 	return (buffer);
245 
246 } /* emlxs_dfc_event_xlate() */
247 
248 
249 
250 extern int32_t
251 emlxs_dfc_manage(emlxs_hba_t *hba, void *arg, int32_t mode)
252 {
253 	emlxs_port_t *port = &PPORT;
254 	int rval = 0;
255 	dfc_t *dfc;
256 
257 	if (!(dfc = (dfc_t *)kmem_zalloc(sizeof (dfc_t), KM_SLEEP))) {
258 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
259 		    "%s: Unable to allocate dfc buffer.",
260 		    emlxs_dfc_xlate(dfc->cmd));
261 
262 		return (DFC_SYSRES_ERROR);
263 	}
264 #ifdef	_MULTI_DATAMODEL
265 	switch (ddi_model_convert_from(mode & FMODELS)) {
266 	case DDI_MODEL_ILP32:
267 		{
268 			dfc32_t dfc32;
269 
270 			if (ddi_copyin((void *)arg, (void *)&dfc32,
271 			    sizeof (dfc32_t), mode)) {
272 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
273 				    "%s: ddi_copyin failed.",
274 				    emlxs_dfc_xlate(dfc->cmd));
275 
276 				rval = DFC_COPYIN_ERROR;
277 				break;
278 			}
279 			dfc->cmd = dfc32.cmd;
280 			dfc->flag = dfc32.flag;
281 			dfc->buf1 = (void *)(unsigned long)dfc32.buf1;
282 			dfc->buf1_size = dfc32.buf1_size;
283 			dfc->data1 = dfc32.data1;
284 			dfc->buf2 = (void *)(unsigned long)dfc32.buf2;
285 			dfc->buf2_size = dfc32.buf2_size;
286 			dfc->data2 = dfc32.data2;
287 			dfc->buf3 = (void *)(unsigned long)dfc32.buf3;
288 			dfc->buf3_size = dfc32.buf3_size;
289 			dfc->data3 = dfc32.data3;
290 			dfc->buf4 = (void *)(unsigned long)dfc32.buf4;
291 			dfc->buf4_size = dfc32.buf4_size;
292 			dfc->data4 = dfc32.data4;
293 
294 			break;
295 		}
296 
297 	case DDI_MODEL_NONE:
298 		if (ddi_copyin((void *)arg, (void *)dfc,
299 		    sizeof (dfc_t), mode)) {
300 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
301 			    "%s: ddi_copyin failed.",
302 			    emlxs_dfc_xlate(dfc->cmd));
303 
304 			rval = DFC_COPYIN_ERROR;
305 		}
306 		break;
307 	}
308 #else	/* _MULTI_DATAMODEL */
309 	if (ddi_copyin((void *) arg, (void *) dfc, sizeof (dfc_t), mode)) {
310 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
311 		    "%s: ddi_copyin failed.",
312 		    emlxs_dfc_xlate(dfc->cmd));
313 
314 		rval = DFC_COPYIN_ERROR;
315 	}
316 #endif	/* _MULTI_DATAMODEL */
317 
318 
319 	switch (dfc->cmd) {
320 	case EMLXS_GET_HBAINFO:
321 		{
322 
323 			rval = emlxs_dfc_get_hbainfo(hba, dfc, mode);
324 
325 			break;
326 		}
327 
328 	case EMLXS_GET_HBASTATS:
329 		{
330 
331 			rval = emlxs_dfc_get_hbastats(hba, dfc, mode);
332 
333 			break;
334 		}
335 
336 	case EMLXS_GET_DRVSTATS:
337 		{
338 
339 			rval = emlxs_dfc_get_drvstats(hba, dfc, mode);
340 
341 			break;
342 		}
343 
344 	case EMLXS_GET_NODEINFO:
345 		{
346 
347 			rval = emlxs_dfc_get_nodeinfo(hba, dfc, mode);
348 
349 			break;
350 		}
351 
352 	case EMLXS_SET_DIAG:
353 		{
354 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
355 			    "%s requested.",
356 			    emlxs_dfc_xlate(dfc->cmd));
357 
358 			rval = emlxs_dfc_set_diag(hba, dfc, mode);
359 
360 			break;
361 		}
362 
363 	case EMLXS_SEND_MBOX:
364 		{
365 			rval = emlxs_dfc_send_mbox(hba, dfc, mode);
366 
367 			break;
368 		}
369 
370 	case EMLXS_READ_PCI:
371 		{
372 			rval = emlxs_dfc_read_pci(hba, dfc, mode);
373 
374 			break;
375 		}
376 
377 	case EMLXS_WRITE_PCI:
378 		{
379 			rval = emlxs_dfc_write_pci(hba, dfc, mode);
380 
381 			break;
382 		}
383 
384 	case EMLXS_GET_CFG:
385 		{
386 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
387 			    "%s requested.",
388 			    emlxs_dfc_xlate(dfc->cmd));
389 
390 			rval = emlxs_dfc_get_cfg(hba, dfc, mode);
391 
392 			break;
393 		}
394 
395 	case EMLXS_SET_CFG:
396 		{
397 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
398 			    "%s requested.",
399 			    emlxs_dfc_xlate(dfc->cmd));
400 
401 			rval = emlxs_dfc_set_cfg(hba, dfc, mode);
402 
403 			break;
404 		}
405 
406 	case EMLXS_SEND_CT:
407 		{
408 			rval = emlxs_dfc_send_ct(hba, dfc, mode);
409 
410 			break;
411 		}
412 
413 	case EMLXS_SEND_CT_RSP:
414 		{
415 			rval = emlxs_dfc_send_ct_rsp(hba, dfc, mode);
416 
417 			break;
418 		}
419 
420 #ifdef MENLO_SUPPORT
421 	case EMLXS_SEND_MENLO:
422 		{
423 			rval = emlxs_dfc_send_menlo(hba, dfc, mode);
424 
425 			break;
426 		}
427 #endif	/* MENLO_SUPPORT */
428 
429 	case EMLXS_WRITE_FLASH:
430 		{
431 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
432 			    "%s requested.",
433 			    emlxs_dfc_xlate(dfc->cmd));
434 
435 			rval = emlxs_dfc_write_flash(hba, dfc, mode);
436 
437 			break;
438 		}
439 
440 	case EMLXS_READ_FLASH:
441 		{
442 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
443 			    "%s requested.",
444 			    emlxs_dfc_xlate(dfc->cmd));
445 
446 			rval = emlxs_dfc_read_flash(hba, dfc, mode);
447 
448 			break;
449 		}
450 
451 	case EMLXS_SEND_ELS:
452 		{
453 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
454 			    "%s requested.",
455 			    emlxs_dfc_xlate(dfc->cmd));
456 
457 			rval = emlxs_dfc_send_els(hba, dfc, mode);
458 
459 			break;
460 		}
461 
462 	case EMLXS_LOOPBACK_TEST:
463 		{
464 			rval = emlxs_dfc_loopback_test(hba, dfc, mode);
465 
466 			break;
467 		}
468 
469 	case EMLXS_GET_DUMPREGION:
470 		{
471 
472 			rval = emlxs_dfc_get_dump_region(hba, dfc, mode);
473 
474 			break;
475 		}
476 
477 	case EMLXS_LOOPBACK_MODE:
478 		{
479 			rval = emlxs_dfc_loopback_mode(hba, dfc, mode);
480 
481 			break;
482 		}
483 
484 	case EMLXS_GET_IOINFO:
485 		{
486 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
487 			    "%s requested.",
488 			    emlxs_dfc_xlate(dfc->cmd));
489 
490 			rval = emlxs_dfc_get_ioinfo(hba, dfc, mode);
491 
492 			break;
493 		}
494 
495 	case EMLXS_GET_LINKINFO:
496 		{
497 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
498 			    "%s requested.",
499 			    emlxs_dfc_xlate(dfc->cmd));
500 
501 			rval = emlxs_dfc_get_linkinfo(hba, dfc, mode);
502 
503 			break;
504 		}
505 
506 #ifdef SFCT_SUPPORT
507 	case EMLXS_GET_FCTSTAT:
508 		{
509 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
510 			    "%s requested.",
511 			    emlxs_dfc_xlate(dfc->cmd));
512 
513 			rval = emlxs_dfc_get_fctstat(hba, dfc, mode);
514 
515 			break;
516 		}
517 #endif	/* SFCT_SUPPORT */
518 
519 	case EMLXS_READ_MEM:
520 		{
521 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
522 			    "%s requested.",
523 			    emlxs_dfc_xlate(dfc->cmd));
524 
525 			rval = emlxs_dfc_read_mem(hba, dfc, mode);
526 
527 			break;
528 		}
529 
530 	case EMLXS_WRITE_MEM:
531 		{
532 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
533 			    "%s requested.",
534 			    emlxs_dfc_xlate(dfc->cmd));
535 
536 			rval = emlxs_dfc_write_mem(hba, dfc, mode);
537 
538 			break;
539 		}
540 
541 	case EMLXS_WRITE_CTLREG:
542 		{
543 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
544 			    "%s requested.",
545 			    emlxs_dfc_xlate(dfc->cmd));
546 
547 			rval = emlxs_dfc_write_ctlreg(hba, dfc, mode);
548 
549 			break;
550 		}
551 
552 	case EMLXS_READ_CTLREG:
553 		{
554 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
555 			    "%s requested.",
556 			    emlxs_dfc_xlate(dfc->cmd));
557 
558 			rval = emlxs_dfc_read_ctlreg(hba, dfc, mode);
559 
560 			break;
561 		}
562 
563 
564 	case EMLXS_GET_EVENTINFO:
565 		{
566 			rval = emlxs_dfc_get_eventinfo(hba, dfc, mode);
567 
568 			break;
569 		}
570 
571 	case EMLXS_GET_EVENT:
572 		{
573 			rval = emlxs_dfc_get_event(hba, dfc, mode);
574 
575 			break;
576 		}
577 
578 	case EMLXS_SET_EVENT:
579 		{
580 			rval = emlxs_dfc_set_event(hba, dfc, mode);
581 
582 			break;
583 		}
584 
585 	case EMLXS_GET_REV:
586 		{
587 			rval = emlxs_dfc_get_rev(hba, dfc, mode);
588 
589 			break;
590 		}
591 
592 	case EMLXS_SEND_SCSI:
593 		{
594 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
595 			    "%s requested.",
596 			    emlxs_dfc_xlate(dfc->cmd));
597 
598 			rval = emlxs_dfc_send_scsi_fcp(hba, dfc, mode);
599 			break;
600 		}
601 
602 #ifdef NPIV_SUPPORT
603 	case EMLXS_CREATE_VPORT:
604 		{
605 
606 			rval = emlxs_dfc_create_vport(hba, dfc, mode);
607 
608 			break;
609 		}
610 
611 	case EMLXS_DESTROY_VPORT:
612 		{
613 
614 			rval = emlxs_dfc_destroy_vport(hba, dfc, mode);
615 
616 			break;
617 		}
618 
619 	case EMLXS_GET_VPORTINFO:
620 		{
621 
622 			rval = emlxs_dfc_get_vportinfo(hba, dfc, mode);
623 
624 			break;
625 		}
626 
627 	case EMLXS_NPIV_RESOURCE:
628 		{
629 			rval = emlxs_dfc_npiv_resource(hba, dfc, mode);
630 
631 			break;
632 		}
633 
634 	case EMLXS_NPIV_TEST:
635 		{
636 			rval = emlxs_dfc_npiv_test(hba, dfc, mode);
637 
638 			break;
639 		}
640 #endif	/* NPIV_SUPPORT */
641 
642 #ifdef DHCHAP_SUPPORT
643 	case EMLXS_INIT_AUTH:
644 		{
645 			rval = emlxs_dfc_init_auth(hba, dfc, mode);
646 
647 			break;
648 		}
649 
650 	case EMLXS_GET_AUTH_CFG:
651 		{
652 			rval = emlxs_dfc_get_auth_cfg(hba, dfc, mode);
653 
654 			break;
655 		}
656 
657 	case EMLXS_SET_AUTH_CFG:
658 		{
659 			rval = emlxs_dfc_set_auth_cfg(hba, dfc, mode);
660 
661 			break;
662 		}
663 
664 	case EMLXS_GET_AUTH_PASSWORD:
665 		{
666 			rval = emlxs_dfc_get_auth_pwd(hba, dfc, mode);
667 
668 			break;
669 		}
670 
671 	case EMLXS_SET_AUTH_PASSWORD:
672 		{
673 			rval = emlxs_dfc_set_auth_pwd(hba, dfc, mode);
674 
675 			break;
676 		}
677 
678 	case EMLXS_GET_AUTH_STATUS:
679 		{
680 			rval = emlxs_dfc_get_auth_status(hba, dfc, mode);
681 
682 			break;
683 		}
684 
685 	case EMLXS_GET_AUTH_CFG_TABLE:
686 		{
687 			rval = emlxs_dfc_get_auth_cfg_table(hba, dfc, mode);
688 			break;
689 		}
690 
691 	case EMLXS_GET_AUTH_KEY_TABLE:
692 		{
693 			rval = emlxs_dfc_get_auth_key_table(hba, dfc, mode);
694 			break;
695 		}
696 
697 #endif	/* DHCHAP_SUPPORT */
698 
699 #ifdef FCIO_SUPPORT
700 	case EMLXS_FCIO_CMD:
701 		rval = emlxs_fcio_manage(hba, dfc, mode);
702 		break;
703 #endif	/* FCIO_SUPPORT */
704 
705 	default:
706 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
707 		    "Unknown command received. (0x%x)",
708 		    dfc->cmd);
709 		rval = DFC_ARG_INVALID;
710 
711 	}	/* switch() */
712 
713 	kmem_free(dfc, sizeof (dfc_t));
714 	return (rval);
715 
716 } /* emlxs_dfc_manage() */
717 
718 
719 #ifdef FCIO_SUPPORT
720 
721 emlxs_table_t emlxs_fcio_table[] =
722 {
723 	{FCIO_GET_NUM_DEVS, "GET_NUM_DEVS"},
724 	{FCIO_GET_DEV_LIST, "GET_DEV_LIST"},
725 	{FCIO_GET_SYM_PNAME, "GET_SYM_PNAME"},
726 	{FCIO_GET_SYM_NNAME, "GET_SYM_NNAME"},
727 	{FCIO_SET_SYM_PNAME, "SET_SYM_PNAME"},
728 	{FCIO_SET_SYM_NNAME, "SET_SYM_NNAME"},
729 	{FCIO_GET_LOGI_PARAMS, "GET_LOGI_PARAMS"},
730 	{FCIO_DEV_LOGIN, "DEV_LOGIN"},
731 	{FCIO_DEV_LOGOUT, "DEV_LOGOUT"},
732 	{FCIO_GET_STATE, "GET_STATE"},
733 	{FCIO_DEV_REMOVE, "DEV_REMOVE"},
734 	{FCIO_GET_FCODE_REV, "GET_FCODE_REV"},
735 	{FCIO_GET_FW_REV, "GET_FW_REV"},
736 	{FCIO_GET_DUMP_SIZE, "GET_DUMP_SIZE"},
737 	{FCIO_FORCE_DUMP, "FORCE_DUMP"},
738 	{FCIO_GET_DUMP, "GET_DUMP"},
739 	{FCIO_GET_TOPOLOGY, "GET_TOPOLOGY"},
740 	{FCIO_RESET_LINK, "RESET_LINK"},
741 	{FCIO_RESET_HARD, "RESET_HARD"},
742 	{FCIO_RESET_HARD_CORE, "RESET_HARD_CORE"},
743 	{FCIO_DIAG, "DIAG"},
744 	{FCIO_NS, "NS"},
745 	{FCIO_DOWNLOAD_FW, "DOWNLOAD_FW"},
746 	{FCIO_GET_HOST_PARAMS, "GET_HOST_PARAMS"},
747 	{FCIO_LINK_STATUS, "LINK_STATUS"},
748 	{FCIO_DOWNLOAD_FCODE, "DOWNLOAD_FCODE"},
749 	{FCIO_GET_NODE_ID, "GET_NODE_ID"},
750 	{FCIO_SET_NODE_ID, "SET_NODE_ID"},
751 	{FCIO_SEND_NODE_ID, "SEND_NODE_ID"},
752 	{FCIO_GET_ADAPTER_ATTRIBUTES, "GET_ADAPTER_ATTRIBUTES"},
753 	{FCIO_GET_OTHER_ADAPTER_PORTS, "GET_OTHER_ADAPTER_PORTS"},
754 	{FCIO_GET_ADAPTER_PORT_ATTRIBUTES, "GET_ADAPTER_PORT_ATTRIBUTES"},
755 	{FCIO_GET_DISCOVERED_PORT_ATTRIBUTES, "GET_DISCOVERED_PORT_ATTRIBUTES"},
756 	{FCIO_GET_PORT_ATTRIBUTES, "GET_PORT_ATTRIBUTES"},
757 	{FCIO_GET_ADAPTER_PORT_STATS, "GET_ADAPTER_PORT_STATS"},
758 
759 };	/* emlxs_fcio_table */
760 
761 
762 extern char *
763 emlxs_fcio_xlate(uint16_t cmd)
764 {
765 	static char buffer[32];
766 	uint32_t i;
767 	uint32_t count;
768 
769 	count = sizeof (emlxs_fcio_table) / sizeof (emlxs_table_t);
770 	for (i = 0; i < count; i++) {
771 		if (cmd == emlxs_fcio_table[i].code) {
772 			return (emlxs_fcio_table[i].string);
773 		}
774 	}
775 
776 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
777 	return (buffer);
778 
779 } /* emlxs_fcio_xlate() */
780 
781 
782 static int32_t
783 emlxs_fcio_manage(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
784 {
785 	emlxs_port_t *port = &PPORT;
786 	emlxs_config_t *cfg = &CFG;
787 	int rval = 0;
788 	fcio_t local_fcio;
789 	fcio_t *fcio = &local_fcio;
790 	emlxs_vpd_t *vpd = &VPD;
791 	fc_hba_port_attributes_t *port_attrs;
792 	emlxs_node_t *ndlp;
793 	uint8_t *wwpn;
794 
795 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
796 	    "%s: %s: requested.",
797 	    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1));
798 
799 	if (!dfc->buf4 || !dfc->buf4_size) {
800 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
801 		    "%s: %s: Null buffer4 found.",
802 		    emlxs_dfc_xlate(dfc->cmd),
803 		    emlxs_fcio_xlate(dfc->data1));
804 
805 		return (EFAULT);
806 	}
807 	if (dfc->buf4_size < sizeof (uint32_t)) {
808 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
809 		    "%s: %s: Buffer4 too small. (size=%d)",
810 		    emlxs_dfc_xlate(dfc->cmd), emlxs_fcio_xlate(dfc->data1),
811 		    dfc->buf4_size);
812 
813 		return (EFAULT);
814 	}
815 	/* Map DFC to FCIO */
816 	bzero(fcio, sizeof (fcio_t));
817 	fcio->fcio_flags = dfc->flag;
818 	fcio->fcio_cmd = dfc->data1;
819 	fcio->fcio_cmd_flags = dfc->data2;
820 	fcio->fcio_xfer = dfc->data3;
821 	fcio->fcio_errno = FC_FAILURE;	/* dfc->buf4 on return */
822 
823 	if (dfc->buf1_size && dfc->buf1) {
824 		fcio->fcio_ilen = dfc->buf1_size;
825 		fcio->fcio_ibuf = kmem_zalloc(dfc->buf1_size, KM_SLEEP);
826 
827 		if (!fcio->fcio_ibuf) {
828 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
829 			    "%s: %s: Unable to allocate ibuf. (size=%d)",
830 			    emlxs_dfc_xlate(dfc->cmd),
831 			    emlxs_fcio_xlate(dfc->data1),
832 			    fcio->fcio_ilen);
833 
834 			rval = EFAULT;
835 			goto done;
836 		}
837 		if (ddi_copyin(dfc->buf1, fcio->fcio_ibuf,
838 		    fcio->fcio_ilen, mode)) {
839 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
840 			    "%s: %s: ddi_copyin failed. (size=%d)",
841 			    emlxs_dfc_xlate(dfc->cmd),
842 			    emlxs_fcio_xlate(dfc->data1),
843 			    fcio->fcio_ilen);
844 
845 			rval = EFAULT;
846 			goto done;
847 		}
848 	}
849 	if (dfc->buf2_size && dfc->buf2) {
850 		fcio->fcio_olen = dfc->buf2_size;
851 		fcio->fcio_obuf = kmem_zalloc(dfc->buf2_size, KM_SLEEP);
852 
853 		if (!fcio->fcio_obuf) {
854 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
855 			    "%s: %s: Unable to allocate obuf. (size=%d)",
856 			    emlxs_dfc_xlate(dfc->cmd),
857 			    emlxs_fcio_xlate(dfc->data1),
858 			    fcio->fcio_olen);
859 
860 			rval = EFAULT;
861 			goto done;
862 		}
863 		if (ddi_copyin(dfc->buf2, fcio->fcio_obuf,
864 		    fcio->fcio_olen, mode)) {
865 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
866 			    "%s: %s: ddi_copyin failed. (size=%d)",
867 			    emlxs_dfc_xlate(dfc->cmd),
868 			    emlxs_fcio_xlate(dfc->data1),
869 			    fcio->fcio_olen);
870 
871 			rval = EFAULT;
872 			goto done;
873 		}
874 	}
875 	if (dfc->buf3_size && dfc->buf3) {
876 		fcio->fcio_alen = dfc->buf3_size;
877 		fcio->fcio_abuf = kmem_zalloc(dfc->buf3_size, KM_SLEEP);
878 
879 		if (!fcio->fcio_abuf) {
880 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
881 			    "%s: %s: Unable to allocate abuf. (size=%d)",
882 			    emlxs_dfc_xlate(dfc->cmd),
883 			    emlxs_fcio_xlate(dfc->data1),
884 			    fcio->fcio_alen);
885 
886 			rval = EFAULT;
887 			goto done;
888 		}
889 		if (ddi_copyin(dfc->buf3, fcio->fcio_abuf,
890 		    fcio->fcio_alen, mode)) {
891 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
892 			    "%s: %s: ddi_copyin failed. (size=%d)",
893 			    emlxs_dfc_xlate(dfc->cmd),
894 			    emlxs_fcio_xlate(dfc->data1),
895 			    fcio->fcio_alen);
896 
897 			rval = EFAULT;
898 			goto done;
899 		}
900 	}
901 	/* FCIO command */
902 	switch (fcio->fcio_cmd) {
903 	case FCIO_DIAG:
904 		{
905 			fc_fca_pm_t pm;
906 			/* uint32_t ret; */
907 
908 			bzero((caddr_t)&pm, sizeof (fc_fca_pm_t));
909 
910 			pm.pm_cmd_len = fcio->fcio_ilen;
911 			pm.pm_cmd_buf = fcio->fcio_ibuf;
912 			pm.pm_data_len = fcio->fcio_alen;
913 			pm.pm_data_buf = fcio->fcio_abuf;
914 			pm.pm_stat_len = fcio->fcio_olen;
915 			pm.pm_stat_buf = fcio->fcio_obuf;
916 			pm.pm_cmd_code = FC_PORT_DIAG;
917 			pm.pm_cmd_flags = fcio->fcio_cmd_flags;
918 
919 			rval = emlxs_port_manage(port, &pm);
920 
921 			if (rval != FC_SUCCESS) {
922 				fcio->fcio_errno = rval;
923 
924 				if (rval == FC_INVALID_REQUEST) {
925 					rval = ENOTTY;
926 				} else {
927 					rval = EIO;
928 				}
929 			}
930 			break;
931 		}
932 
933 	case FCIO_GET_HOST_PARAMS:
934 		{
935 			fc_port_dev_t *port_dev;
936 			uint32_t i;
937 
938 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
939 			    fcio->fcio_olen != sizeof (fc_port_dev_t)) {
940 				rval = EINVAL;
941 				break;
942 			}
943 			port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
944 			port_dev->dev_did.port_id = port->did;
945 			port_dev->dev_hard_addr.hard_addr =
946 			    cfg[CFG_ASSIGN_ALPA].current;
947 			port_dev->dev_state = port->ulp_statec;
948 			bcopy((caddr_t)&port->wwpn,
949 			    (caddr_t)&port_dev->dev_pwwn, 8);
950 			bcopy((caddr_t)&port->wwnn,
951 			    (caddr_t)&port_dev->dev_nwwn, 8);
952 
953 			if (hba->topology == TOPOLOGY_LOOP) {
954 				for (i = 0; i < port->alpa_map[0]; i++) {
955 					if (port->alpa_map[i+1] == port->did) {
956 						PRIV_LILP_POSIT(port_dev) =
957 						    (uint8_t)(i & 0xff);
958 						break;
959 					}
960 				}
961 			}
962 			port_dev->dev_type[0] = SWAP_DATA32(0x00000120);
963 			port_dev->dev_type[1] = SWAP_DATA32(0x00000001);
964 
965 			break;
966 		}
967 
968 	case FCIO_RESET_LINK:
969 		{
970 			uint8_t null_wwn[8];
971 
972 			if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
973 			    fcio->fcio_ilen != 8) {
974 				rval = EINVAL;
975 				break;
976 			}
977 			bzero(null_wwn, 8);
978 
979 			if (bcmp((uint8_t *)fcio->fcio_ibuf,
980 			    null_wwn, 8) == 0) {
981 				rval = emlxs_reset(port, FC_FCA_LINK_RESET);
982 
983 				if (rval != FC_SUCCESS) {
984 					fcio->fcio_errno = rval;
985 					rval = EIO;
986 				}
987 			} else {
988 				rval = ENOTSUP;
989 			}
990 			break;
991 		}
992 
993 	case FCIO_RESET_HARD:
994 	case FCIO_RESET_HARD_CORE:
995 		{
996 			rval = emlxs_reset(port, FC_FCA_RESET);
997 
998 			if (rval != FC_SUCCESS) {
999 				fcio->fcio_errno = rval;
1000 				rval = EIO;
1001 			}
1002 			break;
1003 		}
1004 
1005 	case FCIO_DOWNLOAD_FW:
1006 		{
1007 			fc_fca_pm_t pm;
1008 
1009 			if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1010 			    fcio->fcio_ilen <= 0) {
1011 				rval = EINVAL;
1012 				break;
1013 			}
1014 			bzero((caddr_t)&pm, sizeof (pm));
1015 
1016 			pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1017 			pm.pm_cmd_code = FC_PORT_DOWNLOAD_FW;
1018 			pm.pm_data_len = fcio->fcio_ilen;
1019 			pm.pm_data_buf = fcio->fcio_ibuf;
1020 
1021 			rval = emlxs_port_manage(port, &pm);
1022 
1023 			if (rval != FC_SUCCESS) {
1024 				fcio->fcio_errno = rval;
1025 				rval = EIO;
1026 			}
1027 			break;
1028 		}
1029 
1030 	case FCIO_GET_FW_REV:
1031 		{
1032 			fc_fca_pm_t pm;
1033 
1034 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1035 			    fcio->fcio_olen < FC_FW_REV_SIZE) {
1036 				rval = EINVAL;
1037 				break;
1038 			}
1039 			bzero((caddr_t)&pm, sizeof (pm));
1040 
1041 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1042 			pm.pm_cmd_code = FC_PORT_GET_FW_REV;
1043 			pm.pm_data_len = fcio->fcio_olen;
1044 			pm.pm_data_buf = fcio->fcio_obuf;
1045 
1046 			rval = emlxs_port_manage(port, &pm);
1047 
1048 			if (rval != FC_SUCCESS) {
1049 				fcio->fcio_errno = rval;
1050 				rval = EIO;
1051 			}
1052 			break;
1053 		}
1054 
1055 	case FCIO_GET_FCODE_REV:
1056 		{
1057 			fc_fca_pm_t pm;
1058 
1059 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1060 			    fcio->fcio_olen < FC_FCODE_REV_SIZE) {
1061 				rval = EINVAL;
1062 				break;
1063 			}
1064 			bzero((caddr_t)&pm, sizeof (pm));
1065 
1066 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1067 			pm.pm_cmd_code = FC_PORT_GET_FCODE_REV;
1068 			pm.pm_data_len = fcio->fcio_olen;
1069 			pm.pm_data_buf = fcio->fcio_obuf;
1070 
1071 			rval = emlxs_port_manage(port, &pm);
1072 
1073 			if (rval != FC_SUCCESS) {
1074 				fcio->fcio_errno = rval;
1075 				rval = EIO;
1076 			}
1077 			break;
1078 		}
1079 
1080 	case FCIO_DOWNLOAD_FCODE:
1081 		{
1082 			fc_fca_pm_t pm;
1083 
1084 			if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1085 			    fcio->fcio_ilen <= 0) {
1086 				rval = EINVAL;
1087 				break;
1088 			}
1089 			bzero((caddr_t)&pm, sizeof (pm));
1090 
1091 			pm.pm_cmd_flags = FC_FCA_PM_WRITE;
1092 			pm.pm_cmd_code = FC_PORT_DOWNLOAD_FCODE;
1093 			pm.pm_data_len = fcio->fcio_ilen;
1094 			pm.pm_data_buf = fcio->fcio_ibuf;
1095 
1096 			rval = emlxs_port_manage(port, &pm);
1097 
1098 			if (rval != FC_SUCCESS) {
1099 				fcio->fcio_errno = rval;
1100 				rval = EIO;
1101 			}
1102 			break;
1103 		}
1104 
1105 	case FCIO_GET_ADAPTER_ATTRIBUTES:
1106 		{
1107 			fc_hba_adapter_attributes_t *hba_attrs;
1108 
1109 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1110 			    fcio->fcio_olen <
1111 			    sizeof (fc_hba_adapter_attributes_t)) {
1112 				rval = EINVAL;
1113 				break;
1114 			}
1115 			hba_attrs =
1116 			    (fc_hba_adapter_attributes_t *)fcio->fcio_obuf;
1117 
1118 			hba_attrs->version = FC_HBA_ADAPTER_ATTRIBUTES_VERSION;
1119 			(void) strncpy(hba_attrs->Manufacturer,
1120 			    "Emulex", sizeof (hba_attrs->Manufacturer));
1121 			(void) strncpy(hba_attrs->SerialNumber, vpd->serial_num,
1122 			    sizeof (hba_attrs->SerialNumber));
1123 			(void) strncpy(hba_attrs->Model, hba->model_info.model,
1124 			    sizeof (hba_attrs->Model));
1125 			(void) strncpy(hba_attrs->ModelDescription,
1126 			    hba->model_info.model_desc,
1127 			    sizeof (hba_attrs->ModelDescription));
1128 			bcopy((caddr_t)&port->wwnn,
1129 			    (caddr_t)&hba_attrs->NodeWWN, 8);
1130 			(void) strncpy((caddr_t)hba_attrs->NodeSymbolicName,
1131 			    (caddr_t)port->snn,
1132 			    sizeof (hba_attrs->NodeSymbolicName));
1133 			(void) sprintf(hba_attrs->HardwareVersion, "%x",
1134 			    vpd->biuRev);
1135 			(void) sprintf(hba_attrs->DriverVersion, "%s (%s)",
1136 			    emlxs_version, emlxs_revision);
1137 			(void) strncpy(hba_attrs->OptionROMVersion,
1138 			    vpd->fcode_version,
1139 			    sizeof (hba_attrs->OptionROMVersion));
1140 			(void) sprintf(hba_attrs->FirmwareVersion, "%s (%s)",
1141 			    vpd->fw_version, vpd->fw_label);
1142 			(void) strncpy(hba_attrs->DriverName, DRIVER_NAME,
1143 			    sizeof (hba_attrs->DriverName));
1144 			hba_attrs->VendorSpecificID =
1145 			    ((hba->model_info.device_id << 16) |
1146 			    PCI_VENDOR_ID_EMULEX);
1147 			hba_attrs->NumberOfPorts = hba->num_of_ports;
1148 
1149 			break;
1150 		}
1151 
1152 	case FCIO_GET_ADAPTER_PORT_ATTRIBUTES:
1153 		{
1154 			fc_hba_port_attributes_t *port_attrs;
1155 			uint32_t value1;
1156 			uint32_t value2;
1157 
1158 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1159 			    fcio->fcio_olen <
1160 			    sizeof (fc_hba_port_attributes_t)) {
1161 				rval = EINVAL;
1162 				break;
1163 			}
1164 			port_attrs =
1165 			    (fc_hba_port_attributes_t *)fcio->fcio_obuf;
1166 
1167 			port_attrs->version = FC_HBA_PORT_ATTRIBUTES_VERSION;
1168 			port_attrs->lastChange = 0;
1169 			port_attrs->fp_minor = 0;
1170 			bcopy((caddr_t)&port->wwnn,
1171 			    (caddr_t)&port_attrs->NodeWWN, 8);
1172 			bcopy((caddr_t)&port->wwpn,
1173 			    (caddr_t)&port_attrs->PortWWN, 8);
1174 
1175 			if (hba->state <= FC_LINK_DOWN) {
1176 				/* port_attrs->PortFcId   */
1177 				/* port_attrs->PortType   */
1178 				/* port_attrs->PortSpeed  */
1179 				/* port_attrs->FabricName */
1180 				port_attrs->PortState =
1181 				    FC_HBA_PORTSTATE_OFFLINE;
1182 			} else {
1183 				port_attrs->PortFcId = port->did;
1184 				port_attrs->PortState =
1185 				    FC_HBA_PORTSTATE_ONLINE;
1186 
1187 				if (hba->topology == TOPOLOGY_LOOP) {
1188 					port_attrs->PortType =
1189 					    FC_HBA_PORTTYPE_LPORT;
1190 				} else {
1191 					port_attrs->PortType =
1192 					    FC_HBA_PORTTYPE_NPORT;
1193 				}
1194 
1195 				ndlp = emlxs_node_find_did(port, Fabric_DID);
1196 
1197 				if (ndlp) {
1198 					bcopy(&ndlp->nlp_portname, (caddr_t)
1199 					    &port_attrs->FabricName,
1200 					    sizeof (port_attrs->FabricName));
1201 				}
1202 				switch (hba->linkspeed) {
1203 				case 0:
1204 					port_attrs->PortSpeed =
1205 					    HBA_PORTSPEED_1GBIT;
1206 					break;
1207 				case LA_1GHZ_LINK:
1208 					port_attrs->PortSpeed =
1209 					    HBA_PORTSPEED_1GBIT;
1210 					break;
1211 				case LA_2GHZ_LINK:
1212 					port_attrs->PortSpeed =
1213 					    HBA_PORTSPEED_2GBIT;
1214 					break;
1215 				case LA_4GHZ_LINK:
1216 					port_attrs->PortSpeed =
1217 					    HBA_PORTSPEED_4GBIT;
1218 					break;
1219 				case LA_8GHZ_LINK:
1220 					port_attrs->PortSpeed =
1221 					    HBA_PORTSPEED_8GBIT;
1222 					break;
1223 				case LA_10GHZ_LINK:
1224 					port_attrs->PortSpeed =
1225 					    HBA_PORTSPEED_10GBIT;
1226 					break;
1227 				default:
1228 					port_attrs->PortSpeed =
1229 					    HBA_PORTSPEED_UNKNOWN;
1230 
1231 				}
1232 			}
1233 
1234 			port_attrs->PortSupportedClassofService =
1235 			    SWAP_DATA32(FC_NS_CLASS3);
1236 			(void) strncpy((caddr_t)port_attrs->PortSymbolicName,
1237 			    (caddr_t)port->spn,
1238 			    sizeof (port_attrs->PortSymbolicName));
1239 
1240 			/* Set the hba speed limit */
1241 			if (vpd->link_speed & LMT_10GB_CAPABLE) {
1242 				port_attrs->PortSupportedSpeed |=
1243 				    FC_HBA_PORTSPEED_10GBIT;
1244 			}
1245 			if (vpd->link_speed & LMT_8GB_CAPABLE) {
1246 				port_attrs->PortSupportedSpeed |=
1247 				    FC_HBA_PORTSPEED_8GBIT;
1248 			}
1249 			if (vpd->link_speed & LMT_4GB_CAPABLE) {
1250 				port_attrs->PortSupportedSpeed |=
1251 				    FC_HBA_PORTSPEED_4GBIT;
1252 			}
1253 			if (vpd->link_speed & LMT_2GB_CAPABLE) {
1254 				port_attrs->PortSupportedSpeed |=
1255 				    FC_HBA_PORTSPEED_2GBIT;
1256 			}
1257 			if (vpd->link_speed & LMT_1GB_CAPABLE) {
1258 				port_attrs->PortSupportedSpeed |=
1259 				    FC_HBA_PORTSPEED_1GBIT;
1260 			}
1261 			value1 = 0x00000120;
1262 			value2 = 0x00000001;
1263 
1264 			bcopy((caddr_t)&value1,
1265 			    (caddr_t)&port_attrs->PortSupportedFc4Types[0],
1266 			    4);
1267 			bcopy((caddr_t)&value2,
1268 			    (caddr_t)&port_attrs->PortSupportedFc4Types[4],
1269 			    4);
1270 
1271 			bcopy((caddr_t)&value1,
1272 			    (caddr_t)&port_attrs->PortActiveFc4Types[0], 4);
1273 			bcopy((caddr_t)&value2,
1274 			    (caddr_t)&port_attrs->PortActiveFc4Types[4], 4);
1275 
1276 			port_attrs->PortMaxFrameSize = FF_FRAME_SIZE;
1277 			port_attrs->NumberofDiscoveredPorts =
1278 			    emlxs_nport_count(port);
1279 
1280 			break;
1281 		}
1282 
1283 	case FCIO_GET_NODE_ID:
1284 		{
1285 			fc_fca_pm_t pm;
1286 
1287 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1288 			    fcio->fcio_olen < sizeof (fc_rnid_t)) {
1289 				rval = EINVAL;
1290 				break;
1291 			}
1292 			bzero((caddr_t)&pm, sizeof (pm));
1293 
1294 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1295 			pm.pm_cmd_code = FC_PORT_GET_NODE_ID;
1296 			pm.pm_data_len = fcio->fcio_olen;
1297 			pm.pm_data_buf = fcio->fcio_obuf;
1298 
1299 			rval = emlxs_port_manage(port, &pm);
1300 
1301 			if (rval != FC_SUCCESS) {
1302 				fcio->fcio_errno = rval;
1303 				rval = EIO;
1304 			}
1305 			break;
1306 		}
1307 
1308 	case FCIO_SET_NODE_ID:
1309 		{
1310 			fc_fca_pm_t pm;
1311 
1312 			if (fcio->fcio_xfer != FCIO_XFER_WRITE ||
1313 			    fcio->fcio_ilen < sizeof (fc_rnid_t)) {
1314 				rval = EINVAL;
1315 				break;
1316 			}
1317 			bzero((caddr_t)&pm, sizeof (pm));
1318 
1319 			pm.pm_cmd_flags = FC_FCA_PM_READ;
1320 			pm.pm_cmd_code = FC_PORT_SET_NODE_ID;
1321 			pm.pm_data_len = fcio->fcio_ilen;
1322 			pm.pm_data_buf = fcio->fcio_ibuf;
1323 
1324 			rval = emlxs_port_manage(port, &pm);
1325 
1326 			if (rval != FC_SUCCESS) {
1327 				fcio->fcio_errno = rval;
1328 				rval = EIO;
1329 			}
1330 			break;
1331 		}
1332 
1333 	case FCIO_GET_NUM_DEVS:
1334 		{
1335 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1336 			    fcio->fcio_olen < sizeof (uint32_t)) {
1337 				rval = EINVAL;
1338 				break;
1339 			}
1340 			*(uint32_t *)fcio->fcio_obuf = emlxs_nport_count(port);
1341 
1342 			break;
1343 		}
1344 
1345 	case FCIO_GET_DEV_LIST:
1346 		{
1347 			fc_port_dev_t *port_dev;
1348 			uint32_t max_count;
1349 			uint32_t i;
1350 			uint32_t j;
1351 			emlxs_node_t *nlp;
1352 			uint32_t nport_count;
1353 			caddr_t np;
1354 			caddr_t wp;
1355 
1356 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1357 			    fcio->fcio_alen < sizeof (uint32_t)) {
1358 				rval = EINVAL;
1359 				break;
1360 			}
1361 			port_dev = (fc_port_dev_t *)fcio->fcio_obuf;
1362 			max_count = fcio->fcio_olen / sizeof (fc_port_dev_t);
1363 
1364 			rw_enter(&port->node_rwlock, RW_READER);
1365 
1366 			nport_count = emlxs_nport_count(port);
1367 			*(uint32_t *)fcio->fcio_abuf = nport_count;
1368 
1369 			if (nport_count == 0) {
1370 				rw_exit(&port->node_rwlock);
1371 
1372 				fcio->fcio_errno = FC_NO_MAP;
1373 				rval = EIO;
1374 				break;
1375 			}
1376 			if (nport_count > max_count) {
1377 				rw_exit(&port->node_rwlock);
1378 
1379 				fcio->fcio_errno = FC_TOOMANY;
1380 				rval = EIO;
1381 				break;
1382 			}
1383 
1384 #define	TOP_LOOP()	for (j = 1; j < port->alpa_map[0]; j++) { \
1385 				if (nlp->nlp_DID == port->alpa_map[j]) { \
1386 					PRIV_LILP_POSIT(port_dev) = j - 1; \
1387 					break; \
1388 				} \
1389 			}
1390 
1391 
1392 			for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
1393 				nlp = port->node_table[i];
1394 				while (nlp != NULL) {
1395 					if ((nlp->nlp_DID & 0xFFF000) !=
1396 					    0xFFF000) {
1397 						port_dev->dev_dtype = 0;
1398 						port_dev->dev_type[0] =
1399 						    SWAP_LONG(0x00000100);
1400 						port_dev->dev_state =
1401 						    PORT_DEVICE_LOGGED_IN;
1402 						port_dev->dev_did.port_id =
1403 						    nlp->nlp_DID;
1404 						PRIV_LILP_POSIT(port_dev) = 0;
1405 						HARD_ADDR(port_dev) = 0;
1406 
1407 						if (hba->topology ==
1408 						    TOPOLOGY_LOOP) {
1409 
1410 	for (j = 1; j < port->alpa_map[0]; j++) {
1411 		if (nlp->nlp_DID == port->alpa_map[j]) {
1412 			PRIV_LILP_POSIT(port_dev) = j - 1;
1413 			break;
1414 		}
1415 	}
1416 							HARD_ADDR(port_dev) =
1417 							    nlp->nlp_DID;
1418 
1419 						}
1420 
1421 						np = (caddr_t)
1422 						    &nlp->nlp_portname;
1423 						wp = (caddr_t)
1424 						    &port_dev->dev_pwwn;
1425 						bcopy(np, wp, 8);
1426 
1427 						np = (caddr_t)
1428 						    &nlp->nlp_nodename;
1429 						wp = (caddr_t)
1430 						    &port_dev->dev_nwwn;
1431 						bcopy(np, wp, 8);
1432 						port_dev++;
1433 					}
1434 					nlp = (NODELIST *) nlp->nlp_list_next;
1435 				}
1436 			}
1437 			rw_exit(&port->node_rwlock);
1438 
1439 			break;
1440 		}
1441 
1442 	case FCIO_GET_LOGI_PARAMS:
1443 		{
1444 			uint8_t null_wwn[8];
1445 
1446 			if (fcio->fcio_ilen != sizeof (la_wwn_t) ||
1447 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0 ||
1448 			    (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0) {
1449 				rval = EINVAL;
1450 				break;
1451 			}
1452 			bzero(null_wwn, 8);
1453 			wwpn = (uint8_t *)fcio->fcio_ibuf;
1454 
1455 			if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1456 			    (bcmp((caddr_t)wwpn,
1457 			    (caddr_t)&port->wwpn, 8) == 0)) {
1458 				bcopy((caddr_t)&port->sparam,
1459 				    (caddr_t)fcio->fcio_obuf, fcio->fcio_olen);
1460 			} else {
1461 				ndlp = emlxs_node_find_wwpn(port, wwpn);
1462 
1463 				if (ndlp) {
1464 					bcopy((caddr_t)&ndlp->sparm,
1465 					    (caddr_t)fcio->fcio_obuf,
1466 					    fcio->fcio_olen);
1467 				} else {
1468 					rval = ENXIO;
1469 				}
1470 			}
1471 
1472 			break;
1473 		}
1474 
1475 	case FCIO_GET_STATE:
1476 		{
1477 			uint8_t null_wwn[8];
1478 			uint32_t *statep;
1479 
1480 			if (fcio->fcio_ilen != 8 ||
1481 			    fcio->fcio_olen != 4 ||
1482 			    (fcio->fcio_xfer & FCIO_XFER_WRITE) == 0 ||
1483 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1484 				rval = EINVAL;
1485 				break;
1486 			}
1487 			bzero(null_wwn, 8);
1488 			wwpn = (uint8_t *)fcio->fcio_ibuf;
1489 			statep = (uint32_t *)fcio->fcio_obuf;
1490 
1491 			if ((bcmp((caddr_t)wwpn, (caddr_t)null_wwn, 8) == 0) ||
1492 			    (bcmp((caddr_t)wwpn,
1493 			    (caddr_t)&port->wwpn, 8) == 0)) {
1494 				*statep = PORT_DEVICE_VALID;
1495 			} else {
1496 				ndlp = emlxs_node_find_wwpn(port, wwpn);
1497 
1498 				if (ndlp) {
1499 					*statep = PORT_DEVICE_VALID;
1500 				} else {
1501 					*statep = PORT_DEVICE_INVALID;
1502 				}
1503 			}
1504 
1505 			break;
1506 		}
1507 
1508 	case FCIO_GET_TOPOLOGY:
1509 		{
1510 			uint32_t *tp;
1511 
1512 			if (fcio->fcio_olen != 4 ||
1513 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1514 				rval = EINVAL;
1515 				break;
1516 			}
1517 			tp = (uint32_t *)fcio->fcio_obuf;
1518 
1519 			if (hba->state <= FC_LINK_DOWN) {
1520 				*tp = FC_TOP_UNKNOWN;
1521 			} else {
1522 				ndlp = emlxs_node_find_did(port, Fabric_DID);
1523 
1524 				if (hba->topology == TOPOLOGY_LOOP) {
1525 					if (ndlp) {
1526 						*tp = FC_TOP_PUBLIC_LOOP;
1527 					} else {
1528 						*tp = FC_TOP_PRIVATE_LOOP;
1529 					}
1530 				} else {
1531 					if (ndlp) {
1532 						*tp = FC_TOP_FABRIC;
1533 					} else {
1534 						*tp = FC_TOP_PT_PT;
1535 					}
1536 				}
1537 			}
1538 
1539 			break;
1540 		}
1541 
1542 	case FCIO_LINK_STATUS:
1543 		{
1544 			fc_portid_t *portid;
1545 			fc_rls_acc_t *rls;
1546 			fc_fca_pm_t pm;
1547 
1548 			if (fcio->fcio_ilen != sizeof (fc_portid_t) ||
1549 			    fcio->fcio_olen != sizeof (fc_rls_acc_t) ||
1550 			    fcio->fcio_xfer != FCIO_XFER_RW) {
1551 				rval = EINVAL;
1552 				break;
1553 			}
1554 			if ((fcio->fcio_cmd_flags !=
1555 			    FCIO_CFLAGS_RLS_DEST_FPORT) &&
1556 			    (fcio->fcio_cmd_flags !=
1557 			    FCIO_CFLAGS_RLS_DEST_NPORT)) {
1558 				rval = EINVAL;
1559 				break;
1560 			}
1561 			portid = (fc_portid_t *)fcio->fcio_ibuf;
1562 			rls = (fc_rls_acc_t *)fcio->fcio_obuf;
1563 
1564 			if (portid->port_id == 0 ||
1565 			    portid->port_id == port->did) {
1566 				bzero((caddr_t)&pm, sizeof (pm));
1567 
1568 				pm.pm_cmd_flags = FC_FCA_PM_READ;
1569 				pm.pm_cmd_code = FC_PORT_RLS;
1570 				pm.pm_data_len = sizeof (fc_rls_acc_t);
1571 				pm.pm_data_buf = (caddr_t)rls;
1572 
1573 				rval = emlxs_port_manage(port, &pm);
1574 
1575 				if (rval != FC_SUCCESS) {
1576 					fcio->fcio_errno = rval;
1577 					rval = EIO;
1578 				}
1579 			} else {
1580 				rval = ENOTSUP;
1581 			}
1582 			break;
1583 		}
1584 
1585 	case FCIO_GET_OTHER_ADAPTER_PORTS:
1586 		{
1587 			uint32_t index;
1588 			char *path;
1589 
1590 			if (fcio->fcio_olen < MAXPATHLEN ||
1591 			    fcio->fcio_ilen != sizeof (uint32_t)) {
1592 				rval = EINVAL;
1593 				break;
1594 			}
1595 			index = *(uint32_t *)fcio->fcio_ibuf;
1596 			path = (char *)fcio->fcio_obuf;
1597 
1598 			if (index > hba->vpi_max - 1) {
1599 				fcio->fcio_errno = FC_BADPORT;
1600 				rval = EFAULT;
1601 				break;
1602 			}
1603 			(void) ddi_pathname(hba->dip, path);
1604 
1605 			break;
1606 		}
1607 
1608 	case FCIO_GET_DISCOVERED_PORT_ATTRIBUTES:
1609 		{
1610 			uint32_t index;
1611 
1612 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1613 			    fcio->fcio_ilen < sizeof (uint32_t) ||
1614 			    fcio->fcio_olen <
1615 			    sizeof (fc_hba_port_attributes_t)) {
1616 				rval = EINVAL;
1617 				break;
1618 			}
1619 			index = *(uint32_t *)fcio->fcio_ibuf;
1620 			ndlp = emlxs_node_find_index(port, index, 1);
1621 
1622 			if (!ndlp) {
1623 				fcio->fcio_errno = FC_OUTOFBOUNDS;
1624 				rval = EINVAL;
1625 				break;
1626 			}
1627 			goto get_node_attrs;
1628 		}
1629 
1630 		/* Same as FCIO_GET_DISCOVERED_PORT_ATTRIBUTES */
1631 		/* except WWPN is used instead of index */
1632 	case FCIO_GET_PORT_ATTRIBUTES:
1633 		{
1634 			emlxs_node_t *ndlp2;
1635 			/* uint32_t value1; */
1636 
1637 			if (fcio->fcio_xfer != FCIO_XFER_READ ||
1638 			    fcio->fcio_ilen < 8 ||
1639 			    fcio->fcio_olen <
1640 			    sizeof (fc_hba_port_attributes_t)) {
1641 				rval = EINVAL;
1642 				break;
1643 			}
1644 			wwpn = (uint8_t *)fcio->fcio_ibuf;
1645 			ndlp = emlxs_node_find_wwpn(port, wwpn);
1646 
1647 			if (!ndlp) {
1648 				fcio->fcio_errno = FC_NOMAP;
1649 				rval = EINVAL;
1650 				break;
1651 			}
1652 			/* Filter fabric ports */
1653 			if ((ndlp->nlp_DID & 0xFFF000) == 0xFFF000) {
1654 				fcio->fcio_errno = FC_NOMAP;
1655 				rval = EINVAL;
1656 				break;
1657 			}
1658 	get_node_attrs:
1659 
1660 			port_attrs =
1661 			    (fc_hba_port_attributes_t *)fcio->fcio_obuf;
1662 
1663 			port_attrs->version = FC_HBA_PORT_ATTRIBUTES_VERSION;
1664 			/* port_attrs->lastChange */
1665 			/* port_attrs->fp_minor   */
1666 			bcopy((caddr_t)&ndlp->nlp_nodename,
1667 			    (caddr_t)&port_attrs->NodeWWN, 8);
1668 			bcopy((caddr_t)&ndlp->nlp_portname,
1669 			    (caddr_t)&port_attrs->PortWWN, 8);
1670 
1671 			port_attrs->PortSpeed = HBA_PORTSPEED_UNKNOWN;
1672 			port_attrs->PortType = FC_HBA_PORTTYPE_UNKNOWN;
1673 			port_attrs->PortState = FC_HBA_PORTSTATE_OFFLINE;
1674 
1675 			if (hba->state > FC_LINK_UP) {
1676 				ndlp2 = emlxs_node_find_did(port, Fabric_DID);
1677 
1678 				port_attrs->PortFcId = ndlp->nlp_DID;
1679 				port_attrs->PortState = FC_HBA_PORTSTATE_ONLINE;
1680 
1681 				/* no switch */
1682 				if (!ndlp2) {
1683 					if (hba->topology == TOPOLOGY_LOOP) {
1684 						port_attrs->PortType =
1685 						    FC_HBA_PORTTYPE_LPORT;
1686 					} else {
1687 						port_attrs->PortType =
1688 						    FC_HBA_PORTTYPE_PTP;
1689 					}
1690 
1691 					/* We share a common speed */
1692 					switch (hba->linkspeed) {
1693 					case 0:
1694 						port_attrs->PortSpeed =
1695 						    HBA_PORTSPEED_1GBIT;
1696 						break;
1697 					case LA_1GHZ_LINK:
1698 						port_attrs->PortSpeed =
1699 						    HBA_PORTSPEED_1GBIT;
1700 						break;
1701 					case LA_2GHZ_LINK:
1702 						port_attrs->PortSpeed =
1703 						    HBA_PORTSPEED_2GBIT;
1704 						break;
1705 					case LA_4GHZ_LINK:
1706 						port_attrs->PortSpeed =
1707 						    HBA_PORTSPEED_4GBIT;
1708 						break;
1709 					case LA_8GHZ_LINK:
1710 						port_attrs->PortSpeed =
1711 						    HBA_PORTSPEED_8GBIT;
1712 						break;
1713 					case LA_10GHZ_LINK:
1714 						port_attrs->PortSpeed =
1715 						    HBA_PORTSPEED_10GBIT;
1716 						break;
1717 					}
1718 				}
1719 				/* public loop */
1720 				else if (hba->topology == TOPOLOGY_LOOP) {
1721 					/* Check for common area and domain */
1722 					if ((ndlp->nlp_DID & 0xFFFF00) ==
1723 					    (port->did & 0xFFFF00)) {
1724 						port_attrs->PortType =
1725 						    FC_HBA_PORTTYPE_NLPORT;
1726 
1727 						/* We share a common speed */
1728 						switch (hba->linkspeed) {
1729 						case 0:
1730 							port_attrs->PortSpeed =
1731 							    HBA_PORTSPEED_1GBIT;
1732 							break;
1733 						case LA_1GHZ_LINK:
1734 							port_attrs->PortSpeed =
1735 							    HBA_PORTSPEED_1GBIT;
1736 							break;
1737 						case LA_2GHZ_LINK:
1738 							port_attrs->PortSpeed =
1739 							    HBA_PORTSPEED_2GBIT;
1740 							break;
1741 						case LA_4GHZ_LINK:
1742 							port_attrs->PortSpeed =
1743 							    HBA_PORTSPEED_4GBIT;
1744 							break;
1745 						case LA_8GHZ_LINK:
1746 							port_attrs->PortSpeed =
1747 							    HBA_PORTSPEED_8GBIT;
1748 							break;
1749 						case LA_10GHZ_LINK:
1750 							port_attrs->PortSpeed =
1751 							    HBA_10GBIT;
1752 							break;
1753 						}
1754 					}
1755 				}
1756 			}
1757 			port_attrs->PortSupportedClassofService =
1758 			    SWAP_DATA32(FC_NS_CLASS3);
1759 			/* port_attrs->PortSymbolicName		*/
1760 			/* port_attrs->PortSupportedSpeed	*/
1761 			/* port_attrs->PortSupportedFc4Types	*/
1762 			/* port_attrs->PortActiveFc4Types	*/
1763 			/* port_attrs->PortMaxFrameSize		*/
1764 			/* port_attrs->NumberofDiscoveredPorts	*/
1765 
1766 			break;
1767 		}
1768 
1769 	case FCIO_GET_SYM_PNAME:
1770 		{
1771 			if (fcio->fcio_olen < (strlen(port->spn) + 1) ||
1772 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1773 				rval = EINVAL;
1774 				break;
1775 			}
1776 			(void) strcpy((caddr_t)fcio->fcio_obuf,
1777 			    (caddr_t)port->spn);
1778 
1779 			break;
1780 		}
1781 
1782 	case FCIO_GET_SYM_NNAME:
1783 		{
1784 			if (fcio->fcio_olen < (strlen(port->snn) + 1) ||
1785 			    (fcio->fcio_xfer & FCIO_XFER_READ) == 0) {
1786 				rval = EINVAL;
1787 				break;
1788 			}
1789 			(void) strcpy((caddr_t)fcio->fcio_obuf,
1790 			    (caddr_t)port->snn);
1791 
1792 			break;
1793 		}
1794 
1795 	case FCIO_SET_SYM_PNAME:
1796 	case FCIO_SET_SYM_NNAME:
1797 	case FCIO_DEV_LOGIN:
1798 	case FCIO_DEV_LOGOUT:
1799 	case FCIO_DEV_REMOVE:
1800 	case FCIO_GET_DUMP_SIZE:
1801 	case FCIO_FORCE_DUMP:
1802 	case FCIO_GET_DUMP:
1803 	case FCIO_NS:
1804 	case FCIO_SEND_NODE_ID:
1805 	case FCIO_GET_ADAPTER_PORT_STATS:
1806 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
1807 		    "%s: Unsupported FCIO command.",
1808 		    emlxs_fcio_xlate(fcio->fcio_cmd));
1809 		rval = ENOTSUP;
1810 		break;
1811 
1812 	default:
1813 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
1814 		    "Unknown FCIO command. (0x%x)",
1815 		    fcio->fcio_cmd);
1816 		rval = EFAULT;
1817 
1818 	}	/* switch() */
1819 
1820 done:
1821 
1822 	if (rval == 0) {
1823 		fcio->fcio_errno = 0;
1824 	}
1825 	if (fcio->fcio_ibuf) {
1826 		if (ddi_copyout(fcio->fcio_ibuf, dfc->buf1,
1827 		    fcio->fcio_ilen, mode)) {
1828 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1829 			    "%s: %s: ddi_copyout failed. (size=%d)",
1830 			    emlxs_dfc_xlate(dfc->cmd),
1831 			    emlxs_fcio_xlate(dfc->data1),
1832 			    fcio->fcio_ilen);
1833 
1834 			rval = EFAULT;
1835 		}
1836 		kmem_free(fcio->fcio_ibuf, fcio->fcio_ilen);
1837 	}
1838 	if (fcio->fcio_obuf) {
1839 		if (ddi_copyout(fcio->fcio_obuf, dfc->buf2,
1840 		    fcio->fcio_olen, mode)) {
1841 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1842 			    "%s: %s: ddi_copyout failed. (size=%d)",
1843 			    emlxs_dfc_xlate(dfc->cmd),
1844 			    emlxs_fcio_xlate(dfc->data1),
1845 			    fcio->fcio_olen);
1846 
1847 			rval = EFAULT;
1848 		}
1849 		kmem_free(fcio->fcio_obuf, fcio->fcio_olen);
1850 	}
1851 	if (fcio->fcio_abuf) {
1852 		if (ddi_copyout(fcio->fcio_abuf, dfc->buf3,
1853 		    fcio->fcio_alen, mode)) {
1854 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1855 			    "%s: %s: ddi_copyout failed. (size=%d)",
1856 			    emlxs_dfc_xlate(dfc->cmd),
1857 			    emlxs_fcio_xlate(dfc->data1),
1858 			    fcio->fcio_alen);
1859 
1860 			rval = EFAULT;
1861 		}
1862 		kmem_free(fcio->fcio_abuf, fcio->fcio_alen);
1863 	}
1864 	if (ddi_copyout((void *)&fcio->fcio_errno, (void *)dfc->buf4,
1865 	    dfc->buf4_size, mode) != 0) {
1866 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1867 		    "%s: %s: ddi_copyout failed. (size=%d)",
1868 		    emlxs_dfc_xlate(dfc->cmd),
1869 		    emlxs_fcio_xlate(dfc->data1),
1870 		    dfc->buf4_size);
1871 
1872 		rval = EFAULT;
1873 	}
1874 	return (rval);
1875 
1876 } /* emlxs_fcio_manage() */
1877 
1878 #endif	/* FCIO_SUPPORT */
1879 
1880 
1881 
1882 #ifdef NPIV_SUPPORT
1883 
1884 static int32_t
1885 emlxs_dfc_create_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
1886 {
1887 	emlxs_port_t *port = &PPORT;
1888 	emlxs_config_t *cfg = &CFG;
1889 	emlxs_port_t *vport;
1890 	dfc_vportinfo_t dfc_vport;
1891 	uint32_t vpi;
1892 	uint32_t options;
1893 	char name[256];
1894 	uint8_t wwn[8];
1895 
1896 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
1897 	    "%s requested.",
1898 	    emlxs_dfc_xlate(dfc->cmd));
1899 
1900 	options = dfc->data1;
1901 
1902 	if (!dfc->buf1 || !dfc->buf1_size) {
1903 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1904 		    "%s: Null buffer1 found.",
1905 		    emlxs_dfc_xlate(dfc->cmd));
1906 
1907 		return (DFC_ARG_NULL);
1908 	}
1909 	if (dfc->buf1_size < sizeof (dfc_vportinfo_t)) {
1910 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1911 		    "%s: Buffer1 too small. (size=%d)",
1912 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
1913 
1914 		return (DFC_ARG_TOOSMALL);
1915 	}
1916 	/* Read the dfc_vport object */
1917 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_vport,
1918 	    sizeof (dfc_vportinfo_t), mode) != 0) {
1919 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1920 		    "%s: ddi_copyin failed.",
1921 		    emlxs_dfc_xlate(dfc->cmd));
1922 
1923 		return (DFC_COPYIN_ERROR);
1924 	}
1925 	if (!(options & VPORT_OPT_AUTORETRY)) {
1926 		if (!(hba->flag & FC_NPIV_ENABLED)) {
1927 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1928 			    "%s: NPIV currently not enabled.",
1929 			    emlxs_dfc_xlate(dfc->cmd));
1930 
1931 			return (DFC_NPIV_DISABLED);
1932 		}
1933 		if (!(hba->flag & FC_NPIV_SUPPORTED)) {
1934 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1935 			    "%s: NPIV currently not supported.",
1936 			    emlxs_dfc_xlate(dfc->cmd));
1937 
1938 			return (DFC_NPIV_UNSUPPORTED);
1939 		}
1940 	}
1941 	/*
1942 	 * Only the same WWNN and WWPN can be re-created
1943 	 */
1944 	bzero(wwn, 8);
1945 	if (bcmp(wwn, dfc_vport.wwpn, 8) || bcmp(wwn, dfc_vport.wwnn, 0)) {
1946 		for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
1947 			vport = &VPORT(vpi);
1948 
1949 			if ((bcmp((caddr_t)&vport->wwnn,
1950 			    (caddr_t)dfc_vport.wwnn, 8) == 0) &&
1951 			    (bcmp((caddr_t)&vport->wwpn,
1952 			    (caddr_t)dfc_vport.wwpn, 8) == 0)) {
1953 				if (!(vport->flag & EMLXS_PORT_CONFIG) &&
1954 				    (vport->flag & EMLXS_PORT_BOUND)) {
1955 					dfc_vport.vpi = vpi;
1956 					break;
1957 				} else {
1958 					EMLXS_MSGF(EMLXS_CONTEXT,
1959 					    &emlxs_dfc_error_msg,
1960 					    "%s: VPI already in use.",
1961 					    emlxs_dfc_xlate(dfc->cmd));
1962 
1963 					return (DFC_ARG_INVALID);
1964 				}
1965 			}
1966 		}
1967 	}	/* else auto assign */
1968 	/* Acquire a VPI */
1969 	if (dfc_vport.vpi == 0) {
1970 		/* Auto Assign VPI */
1971 		for (vpi = 1; vpi <= hba->vpi_max; vpi++) {
1972 			vport = &VPORT(vpi);
1973 
1974 			if (!(vport->flag & EMLXS_PORT_CONFIG)) {
1975 				break;
1976 			}
1977 		}
1978 
1979 		if (vpi > hba->vpi_max) {
1980 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1981 			    "%s: Out of resources.",
1982 			    emlxs_dfc_xlate(dfc->cmd));
1983 
1984 			return (DFC_DRVRES_ERROR);
1985 		}
1986 		dfc_vport.vpi = vpi;
1987 	}
1988 	/* Establish a WWPN */
1989 	bzero(wwn, 8);
1990 	if (bcmp(wwn, dfc_vport.wwpn, 8) == 0) {
1991 		/* Generate new WWPN */
1992 		bcopy((caddr_t)&hba->wwpn, (caddr_t)dfc_vport.wwpn, 8);
1993 		dfc_vport.wwpn[0] = 0x20;
1994 		dfc_vport.wwpn[1] = vpi;
1995 	} else {	/* use one provided */
1996 		/* Make sure WWPN is unique */
1997 		if (emlxs_vport_find_wwpn(hba, dfc_vport.wwpn)) {
1998 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
1999 			    "%s: WWPN already exists. vpi=%d",
2000 			    emlxs_dfc_xlate(dfc->cmd), vpi);
2001 
2002 			return (DFC_ARG_INVALID);
2003 		}
2004 	}
2005 
2006 	/* Establish a WWNN */
2007 	bzero(wwn, 8);
2008 	if (bcmp(wwn, dfc_vport.wwnn, 8) == 0) {
2009 		/* Generate new WWNN */
2010 		bcopy((caddr_t)&hba->wwnn, (caddr_t)dfc_vport.wwnn, 8);
2011 		dfc_vport.wwnn[0] = 0x28;
2012 		dfc_vport.wwnn[1] = vpi;
2013 	}
2014 	/* else use WWNN provided */
2015 
2016 	/* Generate the symbolic node name */
2017 	if (dfc_vport.snn[0]) {
2018 		(void) strcpy(name, dfc_vport.snn);
2019 		(void) sprintf(dfc_vport.snn, "%s %s", hba->snn, name);
2020 	} else {
2021 		(void) strcpy(dfc_vport.snn, hba->snn);
2022 	}
2023 
2024 	/* Generate the symbolic port name */
2025 	if (dfc_vport.spn[0]) {
2026 		(void) strcpy(name, dfc_vport.spn);
2027 		(void) sprintf(dfc_vport.spn, "%s VPort-%d VName-%s",
2028 		    hba->spn, vpi, name);
2029 	} else {
2030 		(void) sprintf(dfc_vport.spn, "%s VPort-%d", hba->spn, vpi);
2031 	}
2032 
2033 	dfc_vport.port_id = 0;
2034 	dfc_vport.ulp_statec = FC_STATE_OFFLINE;
2035 	dfc_vport.flags = VPORT_CONFIG;
2036 
2037 	/* Set the highest configured vpi */
2038 	if (dfc_vport.vpi >= hba->vpi_high) {
2039 		hba->vpi_high = dfc_vport.vpi;
2040 	}
2041 	/* Configure the port object */
2042 	bcopy((caddr_t)dfc_vport.wwnn, (caddr_t)&vport->wwnn, 8);
2043 	bcopy((caddr_t)dfc_vport.wwpn, (caddr_t)&vport->wwpn, 8);
2044 	(void) strncpy((caddr_t)vport->snn, (caddr_t)dfc_vport.snn, 256);
2045 	(void) strncpy((caddr_t)vport->spn, (caddr_t)dfc_vport.spn, 256);
2046 	vport->flag |= (EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
2047 
2048 	/* Adjust restricted flags */
2049 	vport->options &= ~EMLXS_OPT_RESTRICT_MASK;
2050 	vport->flag &= ~EMLXS_PORT_RESTRICTED;
2051 	if (options & VPORT_OPT_RESTRICT) {
2052 		vport->options |= EMLXS_OPT_RESTRICT;
2053 		vport->flag |= EMLXS_PORT_RESTRICTED;
2054 		dfc_vport.flags |= VPORT_RESTRICTED;
2055 	} else if (options & VPORT_OPT_UNRESTRICT) {
2056 		vport->options |= EMLXS_OPT_UNRESTRICT;
2057 	} else if (cfg[CFG_VPORT_RESTRICTED].current) {
2058 		vport->flag |= EMLXS_PORT_RESTRICTED;
2059 		dfc_vport.flags |= VPORT_RESTRICTED;
2060 	}
2061 #ifdef SFCT_SUPPORT
2062 	if (vport->tgt_mode) {
2063 		emlxs_fct_bind_port(vport);
2064 	}
2065 #endif	/* SFCT_SUPPORT */
2066 
2067 	if (ddi_copyout((void *)&dfc_vport, (void *)dfc->buf1,
2068 	    sizeof (dfc_vportinfo_t), mode) != 0) {
2069 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2070 		    "%s: ddi_copyout failed.",
2071 		    emlxs_dfc_xlate(dfc->cmd));
2072 
2073 		return (DFC_COPYOUT_ERROR);
2074 	}
2075 	if (vport->flag & EMLXS_PORT_BOUND) {
2076 		/*
2077 		 * The same WWNN, WWPN and VPI has been re-created. Bring up
2078 		 * the vport now!
2079 		 */
2080 		emlxs_port_online(vport);
2081 	}
2082 	return (0);
2083 
2084 } /* emlxs_dfc_create_vport() */
2085 
2086 
2087 static int32_t
2088 emlxs_dfc_destroy_vport(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2089 {
2090 	emlxs_port_t *port = &PPORT;
2091 	emlxs_port_t *vport;
2092 	uint8_t wwpn[8];
2093 	fc_packet_t *pkt = NULL;
2094 	uint32_t rval = 0;
2095 	ELS_PKT *els;
2096 	char buffer[256];
2097 
2098 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2099 	    "%s requested.",
2100 	    emlxs_dfc_xlate(dfc->cmd));
2101 
2102 	if (!dfc->buf1 || !dfc->buf1_size) {
2103 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2104 		    "%s: Null buffer1 found.",
2105 		    emlxs_dfc_xlate(dfc->cmd));
2106 
2107 		rval = DFC_ARG_NULL;
2108 		goto done;
2109 	}
2110 	if (dfc->buf1_size < 8) {
2111 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2112 		    "%s: Buffer1 too small. (size=%d)",
2113 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2114 
2115 		rval = DFC_ARG_TOOSMALL;
2116 		goto done;
2117 	}
2118 	/* Read the wwn object */
2119 	if (ddi_copyin((void *)dfc->buf1, (void *)wwpn, 8, mode) != 0) {
2120 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2121 		    "%s: ddi_copyin failed.",
2122 		    emlxs_dfc_xlate(dfc->cmd));
2123 
2124 		rval = DFC_COPYIN_ERROR;
2125 		goto done;
2126 	}
2127 	/* Make sure WWPN is unique */
2128 	vport = emlxs_vport_find_wwpn(hba, wwpn);
2129 
2130 	if (!vport) {
2131 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2132 		    "%s: WWPN does not exists. %s",
2133 		    emlxs_dfc_xlate(dfc->cmd),
2134 		    emlxs_wwn_xlate(buffer, wwpn));
2135 
2136 		rval = DFC_ARG_INVALID;
2137 		goto done;
2138 	}
2139 	if (vport->did) {
2140 		/* Fabric Logout */
2141 		if (!(pkt = emlxs_pkt_alloc(vport,
2142 		    sizeof (uint32_t) + sizeof (LOGO),
2143 		    sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
2144 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2145 			    "%s: Unable to allocate packet.",
2146 			    emlxs_dfc_xlate(dfc->cmd));
2147 
2148 			rval = DFC_SYSRES_ERROR;
2149 			goto done;
2150 		}
2151 		/* Make this a polled IO */
2152 		pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
2153 		pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
2154 		pkt->pkt_comp = NULL;
2155 
2156 		pkt->pkt_tran_type = FC_PKT_EXCHANGE;
2157 		pkt->pkt_timeout = 60;
2158 
2159 		/* Build the fc header */
2160 		pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(Fabric_DID);
2161 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
2162 		pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(vport->did);
2163 		pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2164 		pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
2165 		    F_CTL_SEQ_INITIATIVE;
2166 		pkt->pkt_cmd_fhdr.seq_id = 0;
2167 		pkt->pkt_cmd_fhdr.df_ctl = 0;
2168 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
2169 		pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
2170 		pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
2171 		pkt->pkt_cmd_fhdr.ro = 0;
2172 
2173 		/* Build the command */
2174 		els = (ELS_PKT *) pkt->pkt_cmd;
2175 		els->elsCode = 0x05;	/* LOGO */
2176 		els->un.logo.un.nPortId32 = SWAP_DATA32(vport->did);
2177 		bcopy(&vport->wwpn, &els->un.logo.portName, 8);
2178 
2179 		/*
2180 		 * Just send LOGO. Don't worry about result. This is just a
2181 		 * courtesy anyway.
2182 		 */
2183 		(void) emlxs_pkt_send(pkt, 1);
2184 
2185 
2186 		/* Take the port offline */
2187 		(void) emlxs_port_offline(vport, 0xffffffff);
2188 	}
2189 	vport->flag &= ~(EMLXS_PORT_CONFIG | EMLXS_PORT_ENABLE);
2190 
2191 	rval = 0;
2192 
2193 done:
2194 
2195 	if (pkt) {
2196 		emlxs_pkt_free(pkt);
2197 	}
2198 	return (rval);
2199 
2200 } /* emlxs_dfc_destroy_vport() */
2201 
2202 
2203 static int32_t
2204 emlxs_dfc_get_vportinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2205 {
2206 	emlxs_port_t *port = &PPORT;
2207 	emlxs_port_t *vport;
2208 	dfc_vportinfo_t *dfc_vport;
2209 	dfc_vportinfo_t *dfc_vport_list = NULL;
2210 	uint32_t i;
2211 	/* uint32_t j; */
2212 	uint32_t size;
2213 	uint32_t max_count;
2214 	uint32_t rval = DFC_SUCCESS;
2215 
2216 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2217 	    "%s requested.",
2218 	    emlxs_dfc_xlate(dfc->cmd));
2219 
2220 	if (!dfc->buf1 || !dfc->buf1_size) {
2221 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2222 		    "%s: Null buffer1 found.",
2223 		    emlxs_dfc_xlate(dfc->cmd));
2224 
2225 		return (DFC_ARG_NULL);
2226 	}
2227 	size = (sizeof (dfc_vportinfo_t) * MAX_VPORTS);
2228 
2229 	if (!(dfc_vport_list = (dfc_vportinfo_t *)
2230 	    kmem_zalloc(size, KM_NOSLEEP))) {
2231 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2232 		    "%s: Unable to allocate memory.",
2233 		    emlxs_dfc_xlate(dfc->cmd));
2234 
2235 		return (DFC_SYSRES_ERROR);
2236 	}
2237 	max_count = 0;
2238 	for (i = 0; i <= hba->vpi_max; i++) {
2239 		vport = &VPORT(i);
2240 		dfc_vport = &dfc_vport_list[i];
2241 
2242 		if (!(vport->flag & EMLXS_PORT_CONFIG)) {
2243 			continue;
2244 		}
2245 		bcopy(vport->snn, dfc_vport->snn, 256);
2246 		bcopy(vport->spn, dfc_vport->spn, 256);
2247 		bcopy(&vport->wwpn, dfc_vport->wwpn, 8);
2248 		bcopy(&vport->wwnn, dfc_vport->wwnn, 8);
2249 		dfc_vport->port_id = vport->did;
2250 		dfc_vport->vpi = vport->vpi;
2251 		dfc_vport->ulp_statec = vport->ulp_statec;
2252 		dfc_vport->flags = VPORT_CONFIG;
2253 
2254 		if (vport->flag & EMLXS_PORT_ENABLE) {
2255 			dfc_vport->flags |= VPORT_ENABLED;
2256 		}
2257 		if (vport->flag & EMLXS_PORT_BOUND) {
2258 			dfc_vport->flags |= VPORT_BOUND;
2259 		}
2260 		if (vport->flag & EMLXS_PORT_IP_UP) {
2261 			dfc_vport->flags |= VPORT_IP;
2262 		}
2263 		if (vport->flag & EMLXS_PORT_RESTRICTED) {
2264 			dfc_vport->flags |= VPORT_RESTRICTED;
2265 		}
2266 		max_count++;
2267 	}
2268 
2269 	max_count *= sizeof (dfc_vportinfo_t);
2270 
2271 	if (max_count > dfc->buf1_size) {
2272 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2273 		    "%s: Buffer1 too small. (%d > %d)",
2274 		    emlxs_dfc_xlate(dfc->cmd), max_count,
2275 		    dfc->buf1_size);
2276 
2277 		rval = DFC_ARG_TOOSMALL;
2278 		goto done;
2279 	}
2280 	if (ddi_copyout((void *)dfc_vport_list, (void *)dfc->buf1,
2281 	    dfc->buf1_size, mode) != 0) {
2282 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2283 		    "%s: ddi_copyout failed.",
2284 		    emlxs_dfc_xlate(dfc->cmd));
2285 
2286 		rval = DFC_COPYOUT_ERROR;
2287 		goto done;
2288 	}
2289 done:
2290 
2291 	if (dfc_vport_list) {
2292 		kmem_free(dfc_vport_list, size);
2293 	}
2294 	return (rval);
2295 
2296 } /* emlxs_dfc_get_vportinfo() */
2297 
2298 
2299 static emlxs_port_t *
2300 emlxs_vport_find_wwpn(emlxs_hba_t *hba, uint8_t *wwpn)
2301 {
2302 	emlxs_port_t *port;
2303 	NODELIST *nlp;
2304 	int i, j;
2305 
2306 	for (i = 0; i <= hba->vpi_max; i++) {
2307 		port = &VPORT(i);
2308 
2309 		if (!(port->flag & EMLXS_PORT_CONFIG)) {
2310 			continue;
2311 		}
2312 		/* Check Local N-port */
2313 		if (bcmp(&port->wwpn, wwpn, 8) == 0) {
2314 			return (port);
2315 		}
2316 		/* Check Remote N-port */
2317 		rw_enter(&port->node_rwlock, RW_READER);
2318 		for (j = 0; j < EMLXS_NUM_HASH_QUES; j++) {
2319 			nlp = port->node_table[j];
2320 			while (nlp != NULL) {
2321 				/* Check Local N-port */
2322 				if (bcmp(&nlp->nlp_portname, wwpn, 8) == 0) {
2323 					rw_exit(&port->node_rwlock);
2324 					return (port);
2325 				}
2326 				nlp = nlp->nlp_list_next;
2327 			}
2328 		}
2329 
2330 		rw_exit(&port->node_rwlock);
2331 	}
2332 
2333 	return (0);
2334 
2335 } /* emlxs_vport_find_wwpn() */
2336 
2337 
2338 static int32_t
2339 emlxs_dfc_npiv_resource(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2340 {
2341 	emlxs_port_t *port = &PPORT;
2342 	dfc_vport_resource_t vres;
2343 	MAILBOXQ *mbq = NULL;
2344 	MAILBOX *mb;
2345 	uint32_t rval = DFC_SUCCESS;
2346 
2347 	if (!dfc->buf1 || !dfc->buf1_size) {
2348 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2349 		    "%s: Null buffer1 found.",
2350 		    emlxs_dfc_xlate(dfc->cmd));
2351 
2352 		return (DFC_ARG_NULL);
2353 	}
2354 	if (dfc->buf1_size < sizeof (dfc_vport_resource_t)) {
2355 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2356 		    "%s: Buffer1 too small. (size=%d)",
2357 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2358 
2359 		return (DFC_ARG_TOOSMALL);
2360 	}
2361 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
2362 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2363 		    "%s: Unable to allocate mailbox buffer.",
2364 		    emlxs_dfc_xlate(dfc->cmd));
2365 
2366 		return (DFC_SYSRES_ERROR);
2367 	}
2368 	mb = (MAILBOX *)mbq;
2369 
2370 	emlxs_mb_read_config(hba, mb);
2371 
2372 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
2373 
2374 	if (rval == MBX_TIMEOUT) {
2375 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2376 		    "%s: Mailbox timed out. cmd=%x",
2377 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
2378 
2379 		rval = DFC_TIMEOUT;
2380 		goto done;
2381 	}
2382 	if (rval) {
2383 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2384 		    "%s: %s failed. status=%x",
2385 		    emlxs_dfc_xlate(dfc->cmd),
2386 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
2387 
2388 		rval = DFC_IO_ERROR;
2389 		goto done;
2390 	}
2391 	bzero(&vres, sizeof (dfc_vport_resource_t));
2392 	vres.vpi_max = mb->un.varRdConfig.max_vpi;
2393 	vres.vpi_inuse = (mb->un.varRdConfig.max_vpi <=
2394 	    mb->un.varRdConfig.avail_vpi) ? 0 :
2395 	    mb->un.varRdConfig.max_vpi -
2396 	    mb->un.varRdConfig.avail_vpi;
2397 
2398 	vres.rpi_max = mb->un.varRdConfig.max_rpi;
2399 	vres.rpi_inuse = (mb->un.varRdConfig.max_rpi <=
2400 	    mb->un.varRdConfig.avail_rpi) ? 0 :
2401 	    mb->un.varRdConfig.max_rpi -
2402 	    mb->un.varRdConfig.avail_rpi;
2403 
2404 	if (ddi_copyout((void *)&vres, (void *)dfc->buf1,
2405 	    sizeof (dfc_vport_resource_t), mode) != 0) {
2406 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2407 		    "%s: ddi_copyout failed.",
2408 		    emlxs_dfc_xlate(dfc->cmd));
2409 
2410 		rval = DFC_COPYOUT_ERROR;
2411 	}
2412 done:
2413 
2414 	/* Free allocated mbox memory */
2415 	if (mbq) {
2416 		kmem_free(mbq, sizeof (MAILBOXQ));
2417 	}
2418 	return (rval);
2419 
2420 } /* emlxs_dfc_npiv_resource() */
2421 
2422 
2423 static int32_t
2424 emlxs_dfc_npiv_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2425 {
2426 	emlxs_port_t *port = &PPORT;
2427 	emlxs_port_t *vport = &VPORT(hba->vpi_max);
2428 	emlxs_config_t *cfg = &CFG;
2429 	fc_packet_t *pkt = NULL;
2430 	fc_packet_t *pkt1 = NULL;
2431 	ELS_PKT *els;
2432 	/* SERV_PARM *sp; */
2433 	LS_RJT *lsrjt;
2434 	uint32_t checklist = 0;
2435 	uint32_t rval = DFC_SUCCESS;
2436 	uint8_t wwn[8];
2437 	emlxs_vpd_t *vpd = &VPD;
2438 	int i;
2439 
2440 	if (!dfc->buf1 || !dfc->buf1_size) {
2441 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2442 		    "%s: Null buffer1 found.",
2443 		    emlxs_dfc_xlate(dfc->cmd));
2444 
2445 		return (DFC_ARG_NULL);
2446 	}
2447 	if (dfc->buf1_size < sizeof (uint32_t)) {
2448 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2449 		    "%s: Buffer1 too small. (size=%d)",
2450 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2451 
2452 		return (DFC_ARG_TOOSMALL);
2453 	}
2454 	if (cfg[CFG_NPIV_ENABLE].current) {
2455 		checklist |= CL_NPIV_PARM_ENABLE;
2456 	}
2457 	if (hba->sli_mode >= 3) {
2458 		checklist |= CL_SLI3_ENABLE;
2459 	}
2460 	if (vpd->feaLevelHigh >= 0x09) {
2461 		checklist |= CL_HBA_SUPPORT_NPIV;
2462 	}
2463 	if (hba->num_of_ports <= hba->vpi_max) {
2464 		checklist |= CL_HBA_HAS_RESOURCES;
2465 	}
2466 	if (hba->state < FC_LINK_UP) {
2467 		goto done;
2468 	}
2469 	checklist |= CL_HBA_LINKUP;
2470 
2471 	if (hba->topology == TOPOLOGY_LOOP) {
2472 		goto done;
2473 	}
2474 	if (!(hba->flag & FC_FABRIC_ATTACHED)) {
2475 		goto done;
2476 	}
2477 	checklist |= CL_P2P_TOPOLOGY;
2478 
2479 	if (!(hba->flag & FC_NPIV_SUPPORTED)) {
2480 		goto done;
2481 	}
2482 	checklist |= CL_FABRIC_SUPPORTS_NPIV;
2483 
2484 	/* Does fabric have resources? */
2485 
2486 	/* Check if we have resources */
2487 	if (!(checklist & CL_HBA_HAS_RESOURCES)) {
2488 		/*
2489 		 * If we're out of resources then it doesn't matter if fabric
2490 		 * has resources
2491 		 */
2492 		goto done;
2493 	} else {
2494 		/* Now check if fabric have resources */
2495 		for (i = 1; i <= hba->vpi_max; i++) {
2496 			vport = &VPORT(i);
2497 			if (vport->did) {
2498 				checklist |= CL_FABRIC_HAS_RESOURCES;
2499 				goto done;
2500 			}
2501 		}
2502 	}
2503 
2504 	vport->vpi = hba->vpi_max;
2505 	vport->hba = hba;
2506 
2507 	if (!(pkt = emlxs_pkt_alloc(vport,
2508 	    sizeof (uint32_t) + sizeof (SERV_PARM),
2509 	    sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
2510 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2511 		    "Unable to allocate packet.");
2512 		goto done;
2513 	}
2514 	/* Build (FDISC) the fc header */
2515 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(Fabric_DID);
2516 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_EXTENDED_SVC | R_CTL_UNSOL_CONTROL;
2517 	pkt->pkt_cmd_fhdr.s_id = 0;
2518 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2519 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_SEQ_INITIATIVE;
2520 	pkt->pkt_cmd_fhdr.seq_id = 0;
2521 	pkt->pkt_cmd_fhdr.df_ctl = 0;
2522 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
2523 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
2524 	pkt->pkt_cmd_fhdr.rx_id = 0xffff;
2525 	pkt->pkt_cmd_fhdr.ro = 0;
2526 
2527 	/* Build the command (FDISC) */
2528 	els = (ELS_PKT *)pkt->pkt_cmd;
2529 	els->elsCode = 0x04;	/* FLOGI - This will be changed automatically */
2530 				/* by the drive (See emlxs_send_els()) */
2531 
2532 	els->un.logi.cmn.fcphHigh = 0x09;
2533 	els->un.logi.cmn.fcphLow = 0x08;
2534 	els->un.logi.cmn.bbCreditMsb = 0xff;
2535 	els->un.logi.cmn.bbCreditlsb = 0xff;
2536 	els->un.logi.cmn.reqMultipleNPort = 1;
2537 	els->un.logi.cmn.bbRcvSizeMsb = 0x08;
2538 	els->un.logi.cmn.bbRcvSizeLsb = 0x00;
2539 	els->un.logi.cmn.w2.nPort.totalConcurrSeq = 0xff;
2540 	els->un.logi.cmn.w2.nPort.roByCategoryMsb = 0xff;
2541 	els->un.logi.cmn.w2.nPort.roByCategoryLsb = 0xff;
2542 	els->un.logi.cmn.e_d_tov = 0x7d0;
2543 
2544 	bcopy((caddr_t)&hba->wwnn, (caddr_t)wwn, 8);
2545 	wwn[0] = 0x28;
2546 	wwn[1] = hba->vpi_max;
2547 	bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.nodeName, 8);
2548 
2549 	bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
2550 	wwn[0] = 0x20;
2551 	wwn[1] = hba->vpi_max;
2552 	bcopy((caddr_t)wwn, (caddr_t)&els->un.logi.portName, 8);
2553 
2554 	els->un.logi.cls1.openSeqPerXchgMsb = 0x00;
2555 	els->un.logi.cls1.openSeqPerXchgLsb = 0x01;
2556 
2557 	els->un.logi.cls2.classValid = 1;
2558 	els->un.logi.cls2.rcvDataSizeMsb = 0x08;
2559 	els->un.logi.cls2.rcvDataSizeLsb = 0x00;
2560 	els->un.logi.cls2.concurrentSeqMsb = 0x00;
2561 	els->un.logi.cls2.concurrentSeqLsb = 0xff;
2562 	els->un.logi.cls2.EeCreditSeqMsb = 0x00;
2563 	els->un.logi.cls2.EeCreditSeqLsb = 0x0c;
2564 	els->un.logi.cls2.openSeqPerXchgMsb = 0x00;
2565 	els->un.logi.cls2.openSeqPerXchgLsb = 0x01;
2566 
2567 	els->un.logi.cls3.classValid = 1;
2568 	els->un.logi.cls3.rcvDataSizeMsb = 0x08;
2569 	els->un.logi.cls3.rcvDataSizeLsb = 0x00;
2570 	els->un.logi.cls3.concurrentSeqMsb = 0x00;
2571 	els->un.logi.cls3.concurrentSeqLsb = 0xff;
2572 	els->un.logi.cls3.openSeqPerXchgMsb = 0x00;
2573 	els->un.logi.cls3.openSeqPerXchgLsb = 0x01;
2574 
2575 	bcopy((void *)&els->un.logi, (void *)&vport->sparam,
2576 	    sizeof (SERV_PARM));
2577 
2578 	/* Make this a polled IO */
2579 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
2580 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
2581 	pkt->pkt_comp = NULL;
2582 
2583 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
2584 	pkt->pkt_timeout = 60;
2585 
2586 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
2587 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2588 		    "%s: Unable to send packet.",
2589 		    emlxs_dfc_xlate(dfc->cmd));
2590 
2591 		goto done;
2592 	}
2593 	if (pkt->pkt_state == FC_PKT_SUCCESS) {
2594 		if (!(pkt1 = emlxs_pkt_alloc(vport,
2595 		    sizeof (uint32_t) + sizeof (LOGO),
2596 		    sizeof (FCP_RSP), 0, KM_NOSLEEP))) {
2597 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2598 			    "Unable to allocate LOGO packet.");
2599 			goto free_resc;
2600 		}
2601 		/* Make this a polled IO */
2602 		pkt1->pkt_tran_flags &= ~FC_TRAN_INTR;
2603 		pkt1->pkt_tran_flags |= FC_TRAN_NO_INTR;
2604 		pkt1->pkt_comp = NULL;
2605 
2606 		pkt1->pkt_tran_type = FC_PKT_EXCHANGE;
2607 		pkt1->pkt_timeout = 60;
2608 
2609 		/* Build (LOGO) the fc header */
2610 		pkt1->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(Fabric_DID);
2611 		pkt1->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
2612 		pkt1->pkt_cmd_fhdr.s_id =
2613 		    SWAP_DATA24_LO(pkt->pkt_resp_fhdr.d_id);
2614 		pkt1->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
2615 		pkt1->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
2616 		    F_CTL_SEQ_INITIATIVE;
2617 		pkt1->pkt_cmd_fhdr.seq_id = 0;
2618 		pkt1->pkt_cmd_fhdr.df_ctl = 0;
2619 		pkt1->pkt_cmd_fhdr.seq_cnt = 0;
2620 		pkt1->pkt_cmd_fhdr.ox_id = 0xFFFF;
2621 		pkt1->pkt_cmd_fhdr.rx_id = 0xFFFF;
2622 		pkt1->pkt_cmd_fhdr.ro = 0;
2623 
2624 		/* Build the command (LOGO) */
2625 		els = (ELS_PKT *)pkt1->pkt_cmd;
2626 		els->elsCode = 0x05;	/* LOGO */
2627 		els->un.logo.un.nPortId32 =
2628 		    SWAP_DATA32(pkt->pkt_resp_fhdr.d_id);
2629 		bcopy((caddr_t)&hba->wwpn, (caddr_t)wwn, 8);
2630 		wwn[0] = 0x20;
2631 		wwn[1] = hba->vpi_max;
2632 		bcopy(wwn, &els->un.logo.portName, 8);
2633 
2634 		if (emlxs_pkt_send(pkt1, 1) != FC_SUCCESS) {
2635 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2636 			    "%s: Unable to send packet.",
2637 			    emlxs_dfc_xlate(dfc->cmd));
2638 
2639 			goto free_resc;
2640 		}
2641 		if (pkt1->pkt_state != FC_PKT_SUCCESS) {
2642 			if (pkt1->pkt_state == FC_PKT_TIMEOUT) {
2643 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2644 				    "%s: Pkt Transport error. Pkt Timeout.",
2645 				    emlxs_dfc_xlate(dfc->cmd));
2646 			} else {
2647 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2648 				    "%s: Pkt Transport error. state=%x",
2649 				    emlxs_dfc_xlate(dfc->cmd),
2650 				    pkt1->pkt_state);
2651 			}
2652 			goto free_resc;
2653 		}
2654 		checklist |= CL_FABRIC_HAS_RESOURCES;
2655 	} else if (pkt->pkt_state == FC_PKT_LS_RJT) {
2656 		lsrjt = (LS_RJT *) pkt->pkt_resp;
2657 		if (lsrjt->un.b.lsRjtRsnCodeExp != LSEXP_OUT_OF_RESOURCE) {
2658 			checklist |= CL_FABRIC_HAS_RESOURCES;
2659 		}
2660 	}
2661 	/*
2662 	 * Free up default RPIs and VPI
2663 	 */
2664 free_resc:
2665 	(void) emlxs_mb_unreg_rpi(vport, 0xffff, 0, 0, 0);
2666 	(void) emlxs_mb_unreg_vpi(vport);
2667 
2668 done:
2669 	if (ddi_copyout((void *)&checklist, (void *)dfc->buf1,
2670 	    sizeof (uint32_t), mode) != 0) {
2671 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2672 		    "%s: ddi_copyout failed.",
2673 		    emlxs_dfc_xlate(dfc->cmd));
2674 		rval = DFC_COPYOUT_ERROR;
2675 	}
2676 	if (pkt) {
2677 		/* Free the pkt */
2678 		emlxs_pkt_free(pkt);
2679 	}
2680 	if (pkt1) {
2681 		/* Free the pkt */
2682 		emlxs_pkt_free(pkt1);
2683 	}
2684 	return (rval);
2685 
2686 } /* emlxs_dfc_npiv_test() */
2687 
2688 #endif	/* NPIV_SUPPORT */
2689 
2690 
2691 
2692 static int32_t
2693 emlxs_dfc_get_rev(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2694 {
2695 	emlxs_port_t *port = &PPORT;
2696 	uint32_t rev;
2697 
2698 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2699 	    "%s requested.",
2700 	    emlxs_dfc_xlate(dfc->cmd));
2701 
2702 	if (!dfc->buf1 || !dfc->buf1_size) {
2703 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2704 		    "%s: Null buffer1 found.",
2705 		    emlxs_dfc_xlate(dfc->cmd));
2706 
2707 		return (DFC_ARG_NULL);
2708 	}
2709 	if (dfc->buf1_size < sizeof (uint32_t)) {
2710 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2711 		    "%s: Buffer1 too small. (size=%d)",
2712 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2713 
2714 		return (DFC_ARG_TOOSMALL);
2715 	}
2716 	rev = DFC_REV;
2717 
2718 	if (ddi_copyout((void *)&rev, (void *)dfc->buf1,
2719 	    sizeof (uint32_t), mode) != 0) {
2720 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2721 		    "%s: ddi_copyout failed.",
2722 		    emlxs_dfc_xlate(dfc->cmd));
2723 
2724 		return (DFC_COPYOUT_ERROR);
2725 	}
2726 	return (0);
2727 
2728 } /* emlxs_dfc_get_rev() */
2729 
2730 
2731 static int32_t
2732 emlxs_dfc_get_hbainfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
2733 {
2734 	emlxs_port_t *port = &PPORT;
2735 	emlxs_vpd_t *vpd = &VPD;
2736 	emlxs_config_t *cfg = &CFG;
2737 	dfc_hbainfo_t hbainfo;
2738 	NODELIST *ndlp;
2739 	char pathname[256];
2740 
2741 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
2742 	    "%s requested.",
2743 	    emlxs_dfc_xlate(dfc->cmd));
2744 
2745 	if (!dfc->buf1 || !dfc->buf1_size) {
2746 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2747 		    "%s: Null buffer1 found.",
2748 		    emlxs_dfc_xlate(dfc->cmd));
2749 
2750 		return (DFC_ARG_NULL);
2751 	}
2752 	if (dfc->buf1_size < sizeof (dfc_hbainfo_t)) {
2753 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2754 		    "%s: Buffer1 too small. (size = %d)",
2755 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
2756 
2757 		return (DFC_ARG_TOOSMALL);
2758 	}
2759 	bzero((void *)&hbainfo, sizeof (dfc_hbainfo_t));
2760 
2761 	(void) strncpy(hbainfo.vpd_serial_num, vpd->serial_num,
2762 	    sizeof (hbainfo.vpd_serial_num));
2763 	(void) strncpy(hbainfo.vpd_part_num, vpd->part_num,
2764 	    sizeof (hbainfo.vpd_part_num));
2765 	(void) strncpy(hbainfo.vpd_port_num, vpd->port_num,
2766 	    sizeof (hbainfo.vpd_port_num));
2767 	(void) strncpy(hbainfo.vpd_eng_change, vpd->eng_change,
2768 	    sizeof (hbainfo.vpd_eng_change));
2769 	(void) strncpy(hbainfo.vpd_manufacturer, vpd->manufacturer,
2770 	    sizeof (hbainfo.vpd_manufacturer));
2771 	(void) strncpy(hbainfo.vpd_model, vpd->model,
2772 	    sizeof (hbainfo.vpd_model));
2773 	(void) strncpy(hbainfo.vpd_model_desc, vpd->model_desc,
2774 	    sizeof (hbainfo.vpd_model_desc));
2775 	(void) strncpy(hbainfo.vpd_prog_types, vpd->prog_types,
2776 	    sizeof (hbainfo.vpd_prog_types));
2777 	(void) strncpy(hbainfo.vpd_id, vpd->id, sizeof (hbainfo.vpd_id));
2778 
2779 	hbainfo.device_id = hba->model_info.device_id;
2780 	hbainfo.vendor_id = ddi_get32(hba->pci_acc_handle,
2781 	    (uint32_t *)(hba->pci_addr + PCI_VENDOR_ID_REGISTER)) & 0xffff;
2782 
2783 	hbainfo.ports = hba->num_of_ports;
2784 	hbainfo.port_index = vpd->port_index;
2785 
2786 	bcopy(&hba->wwnn, hbainfo.wwnn, sizeof (hbainfo.wwnn));
2787 	(void) strncpy(hbainfo.snn, port->snn, sizeof (hbainfo.snn));
2788 
2789 	bcopy(&hba->wwpn, hbainfo.wwpn, sizeof (hbainfo.wwpn));
2790 	(void) strncpy(hbainfo.spn, port->spn, sizeof (hbainfo.spn));
2791 
2792 	hbainfo.biuRev = vpd->biuRev;
2793 	hbainfo.smRev = vpd->smRev;
2794 	hbainfo.smFwRev = vpd->smFwRev;
2795 	hbainfo.endecRev = vpd->endecRev;
2796 	hbainfo.rBit = vpd->rBit;
2797 	hbainfo.fcphHigh = vpd->fcphHigh;
2798 	hbainfo.fcphLow = vpd->fcphLow;
2799 	hbainfo.feaLevelHigh = vpd->feaLevelHigh;
2800 	hbainfo.feaLevelLow = vpd->feaLevelLow;
2801 
2802 	hbainfo.kern_rev = vpd->postKernRev;
2803 	(void) strncpy(hbainfo.kern_name, vpd->postKernName,
2804 	    sizeof (hbainfo.kern_name));
2805 
2806 	hbainfo.stub_rev = vpd->opFwRev;
2807 	(void) strncpy(hbainfo.stub_name, vpd->opFwName,
2808 	    sizeof (hbainfo.stub_name));
2809 
2810 	hbainfo.sli1_rev = vpd->sli1FwRev;
2811 	(void) strncpy(hbainfo.sli1_name, vpd->sli1FwName,
2812 	    sizeof (hbainfo.sli1_name));
2813 
2814 	hbainfo.sli2_rev = vpd->sli2FwRev;
2815 	(void) strncpy(hbainfo.sli2_name, vpd->sli2FwName,
2816 	    sizeof (hbainfo.sli2_name));
2817 
2818 	hbainfo.sli3_rev = vpd->sli3FwRev;
2819 	(void) strncpy(hbainfo.sli3_name, vpd->sli3FwName,
2820 	    sizeof (hbainfo.sli3_name));
2821 
2822 	hbainfo.sli4_rev = vpd->sli4FwRev;
2823 	(void) strncpy(hbainfo.sli4_name, vpd->sli4FwName,
2824 	    sizeof (hbainfo.sli4_name));
2825 
2826 	hbainfo.sli_mode = hba->sli_mode;
2827 	hbainfo.vpi_max = hba->vpi_max;
2828 	hbainfo.vpi_high = hba->vpi_high;
2829 	hbainfo.flags = 0;
2830 
2831 	/* Set support flags */
2832 	hbainfo.flags = HBA_FLAG_DYN_WWN;
2833 
2834 #ifdef NPIV_SUPPORT
2835 	hbainfo.flags |= HBA_FLAG_NPIV;
2836 #endif	/* NPIV_SUPPORT */
2837 
2838 #ifdef DHCHAP_SUPPORT
2839 	hbainfo.flags |= HBA_FLAG_DHCHAP;
2840 
2841 	if (cfg[CFG_AUTH_E2E].current) {
2842 		hbainfo.flags |= HBA_FLAG_E2E_AUTH;
2843 	}
2844 #endif	/* DHCHAP_SUPPORT */
2845 
2846 	(void) strncpy(hbainfo.fcode_version, vpd->fcode_version,
2847 	    sizeof (hbainfo.fcode_version));
2848 	(void) strncpy(hbainfo.boot_version, vpd->boot_version,
2849 	    sizeof (hbainfo.boot_version));
2850 	(void) strncpy(hbainfo.fw_version, vpd->fw_version,
2851 	    sizeof (hbainfo.fw_version));
2852 	(void) strncpy(hbainfo.drv_label, emlxs_label,
2853 	    sizeof (hbainfo.drv_label));
2854 	(void) strncpy(hbainfo.drv_module, emlxs_name,
2855 	    sizeof (hbainfo.drv_module));
2856 	(void) strncpy(hbainfo.drv_name, DRIVER_NAME,
2857 	    sizeof (hbainfo.drv_name));
2858 	(void) strncpy(hbainfo.drv_version, emlxs_version,
2859 	    sizeof (hbainfo.drv_version));
2860 	(void) strncpy(hbainfo.drv_revision, emlxs_revision,
2861 	    sizeof (hbainfo.drv_revision));
2862 	(void) strncpy(hbainfo.hostname, (char *)utsname.nodename,
2863 	    sizeof (hbainfo.hostname));
2864 
2865 	(void) ddi_pathname(hba->dip, pathname);
2866 	(void) sprintf(hbainfo.os_devname, "/devices%s", pathname);
2867 
2868 	if (hba->flag & (FC_OFFLINE_MODE | FC_OFFLINING_MODE)) {
2869 		hbainfo.flags |= HBA_FLAG_OFFLINE;
2870 	}
2871 	hbainfo.drv_instance = hba->ddiinst;
2872 	hbainfo.port_id = port->did;
2873 	hbainfo.port_type = HBA_PORTTYPE_UNKNOWN;
2874 
2875 #ifdef MENLO_SUPPORT
2876 	if (hba->flag & FC_MENLO_MODE) {
2877 		hbainfo.topology = LNK_MENLO_MAINTENANCE;
2878 	} else
2879 #endif	/* MENLO_SUPPORT */
2880 
2881 	if (hba->state >= FC_LINK_UP) {
2882 		ndlp = emlxs_node_find_did(port, Fabric_DID);
2883 
2884 		if (hba->topology == TOPOLOGY_LOOP) {
2885 			if (ndlp) {
2886 				hbainfo.port_type = HBA_PORTTYPE_NLPORT;
2887 				hbainfo.topology = LNK_PUBLIC_LOOP;
2888 			} else {
2889 				hbainfo.port_type = HBA_PORTTYPE_LPORT;
2890 				hbainfo.topology = LNK_LOOP;
2891 			}
2892 
2893 			hbainfo.alpa_count = port->alpa_map[0];
2894 			bcopy((void *)&port->alpa_map[1], hbainfo.alpa_map,
2895 			    hbainfo.alpa_count);
2896 		} else {
2897 			if (ndlp) {
2898 				hbainfo.port_type = HBA_PORTTYPE_NPORT;
2899 				hbainfo.topology = LNK_FABRIC;
2900 			} else {
2901 				hbainfo.port_type = HBA_PORTTYPE_PTP;
2902 				hbainfo.topology = LNK_PT2PT;
2903 			}
2904 		}
2905 
2906 		if (ndlp) {
2907 			bcopy(&ndlp->nlp_nodename, hbainfo.fabric_wwnn,
2908 			    sizeof (hbainfo.fabric_wwnn));
2909 			bcopy(&ndlp->nlp_portname, hbainfo.fabric_wwpn,
2910 			    sizeof (hbainfo.fabric_wwpn));
2911 		}
2912 		if (hba->linkspeed == LA_2GHZ_LINK) {
2913 			hbainfo.port_speed = HBA_PORTSPEED_2GBIT;
2914 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
2915 			hbainfo.port_speed = HBA_PORTSPEED_4GBIT;
2916 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
2917 			hbainfo.port_speed = HBA_PORTSPEED_8GBIT;
2918 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
2919 			hbainfo.port_speed = HBA_PORTSPEED_10GBIT;
2920 		} else {
2921 			hbainfo.port_speed = HBA_PORTSPEED_1GBIT;
2922 		}
2923 
2924 		hbainfo.node_count = port->node_count;
2925 	}
2926 	hbainfo.hard_alpa = cfg[CFG_ASSIGN_ALPA].current;
2927 	hbainfo.supported_cos = SWAP_DATA32((FC_NS_CLASS3 | FC_NS_CLASS2));
2928 
2929 	hbainfo.supported_types[0] = SWAP_DATA32(0x00000120);
2930 	hbainfo.supported_types[1] = SWAP_DATA32(0x00000001);
2931 
2932 	hbainfo.active_types[0] = SWAP_DATA32(0x00000120);
2933 	hbainfo.active_types[1] = SWAP_DATA32(0x00000001);
2934 
2935 	if (!cfg[CFG_NETWORK_ON].current) {
2936 		hbainfo.active_types[0] &= ~(SWAP_DATA32(0x00000020));
2937 	}
2938 	if (vpd->link_speed & LMT_10GB_CAPABLE) {
2939 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_10GBIT;
2940 	}
2941 	if (vpd->link_speed & LMT_8GB_CAPABLE) {
2942 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_8GBIT;
2943 	}
2944 	if (vpd->link_speed & LMT_4GB_CAPABLE) {
2945 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_4GBIT;
2946 	}
2947 	if (vpd->link_speed & LMT_2GB_CAPABLE) {
2948 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_2GBIT;
2949 	}
2950 	if (vpd->link_speed & LMT_1GB_CAPABLE) {
2951 		hbainfo.supported_speeds |= FC_HBA_PORTSPEED_1GBIT;
2952 	}
2953 	hbainfo.max_frame_size = FF_FRAME_SIZE;
2954 
2955 	if (hba->bus_type == SBUS_FC) {
2956 		hbainfo.flags |= HBA_FLAG_SBUS;
2957 	}
2958 	if (hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE)) {
2959 		hbainfo.flags |= HBA_FLAG_OFFLINE;
2960 		hbainfo.port_state = HBA_PORTSTATE_UNKNOWN;
2961 	} else if (hba->flag & FC_ONLINE_MODE) {
2962 		if (hba->flag & FC_LOOPBACK_MODE) {
2963 			hbainfo.port_state = HBA_PORTSTATE_LOOPBACK;
2964 		} else if (hba->state <= FC_LINK_DOWN) {
2965 			hbainfo.port_state = HBA_PORTSTATE_LINKDOWN;
2966 		}
2967 #ifdef MENLO_SUPPORT
2968 		else if (hba->flag & FC_MENLO_MODE) {
2969 			hbainfo.port_state = HBA_PORTSTATE_LINKDOWN;
2970 		}
2971 #endif	/* MENLO_SUPPORT */
2972 		else {
2973 			hbainfo.port_state = HBA_PORTSTATE_ONLINE;
2974 		}
2975 	} else {
2976 		hbainfo.flags |= HBA_FLAG_OFFLINE;
2977 
2978 		if (hba->state == FC_ERROR) {
2979 			hbainfo.port_state = HBA_PORTSTATE_ERROR;
2980 		} else {
2981 			hbainfo.port_state = HBA_PORTSTATE_OFFLINE;
2982 		}
2983 	}
2984 
2985 	if (ddi_copyout((void *)&hbainfo, (void *)dfc->buf1,
2986 	    sizeof (dfc_hbainfo_t), mode) != 0) {
2987 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
2988 		    "%s: ddi_copyout failed.",
2989 		    emlxs_dfc_xlate(dfc->cmd));
2990 
2991 		return (DFC_COPYOUT_ERROR);
2992 	}
2993 	return (0);
2994 
2995 } /* emlxs_dfc_get_hbainfo() */
2996 
2997 
2998 
2999 static int32_t
3000 emlxs_dfc_get_hbastats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3001 {
3002 	emlxs_port_t *port = &PPORT;
3003 	dfc_hbastats_t stats;
3004 	MAILBOX *mb = NULL;
3005 	MAILBOXQ *mbq = NULL;
3006 	uint32_t rval = 0;
3007 
3008 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
3009 	    "%s requested.",
3010 	    emlxs_dfc_xlate(dfc->cmd));
3011 
3012 	if (!dfc->buf1 || !dfc->buf1_size) {
3013 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3014 		    "%s: Null buffer1 found.",
3015 		    emlxs_dfc_xlate(dfc->cmd));
3016 
3017 		return (DFC_ARG_NULL);
3018 	}
3019 	if (dfc->buf1_size < sizeof (dfc_hbastats_t)) {
3020 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3021 		    "%s: Buffer1 too small. (size=%d)",
3022 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3023 
3024 		return (DFC_ARG_TOOSMALL);
3025 	}
3026 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
3027 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3028 		    "%s: Unable to allocate mailbox buffer.",
3029 		    emlxs_dfc_xlate(dfc->cmd));
3030 
3031 		return (DFC_SYSRES_ERROR);
3032 	}
3033 	mb = (MAILBOX *) mbq;
3034 
3035 	emlxs_mb_read_status(hba, mb);
3036 
3037 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
3038 
3039 	if (rval == MBX_TIMEOUT) {
3040 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3041 		    "%s: Mailbox timed out. cmd=%x",
3042 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3043 
3044 		rval = DFC_TIMEOUT;
3045 		goto done;
3046 	}
3047 	if (rval) {
3048 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3049 		    "%s: %s failed. status=%x",
3050 		    emlxs_dfc_xlate(dfc->cmd),
3051 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
3052 		    rval);
3053 
3054 		rval = DFC_IO_ERROR;
3055 		goto done;
3056 	}
3057 	bzero((void *)&stats, sizeof (dfc_hbastats_t));
3058 
3059 	stats.tx_frame_cnt = mb->un.varRdStatus.xmitFrameCnt;
3060 	stats.rx_frame_cnt = mb->un.varRdStatus.rcvFrameCnt;
3061 	stats.tx_kbyte_cnt = mb->un.varRdStatus.xmitByteCnt;
3062 	stats.rx_kbyte_cnt = mb->un.varRdStatus.rcvByteCnt;
3063 	stats.tx_seq_cnt = mb->un.varRdStatus.xmitSeqCnt;
3064 	stats.rx_seq_cnt = mb->un.varRdStatus.rcvSeqCnt;
3065 	stats.orig_exch_cnt = mb->un.varRdStatus.totalOrigExchanges;
3066 	stats.resp_exch_cnt = mb->un.varRdStatus.totalRespExchanges;
3067 	stats.pbsy_cnt = mb->un.varRdStatus.rcvPbsyCnt;
3068 	stats.fbsy_cnt = mb->un.varRdStatus.rcvFbsyCnt;
3069 
3070 	emlxs_mb_read_lnk_stat(hba, mb);
3071 
3072 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
3073 
3074 	if (rval == MBX_TIMEOUT) {
3075 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3076 		    "%s: Mailbox timed out. cmd=%x",
3077 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3078 
3079 		rval = DFC_TIMEOUT;
3080 		goto done;
3081 	}
3082 	if (rval) {
3083 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3084 		    "%s: %s failed. status=%x",
3085 		    emlxs_dfc_xlate(dfc->cmd),
3086 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
3087 		    rval);
3088 
3089 		rval = DFC_IO_ERROR;
3090 		goto done;
3091 	}
3092 	stats.link_failure_cnt = mb->un.varRdLnk.linkFailureCnt;
3093 	stats.loss_sync_cnt = mb->un.varRdLnk.lossSyncCnt;
3094 	stats.loss_signal_cnt = mb->un.varRdLnk.lossSignalCnt;
3095 	stats.seq_error_cnt = mb->un.varRdLnk.primSeqErrCnt;
3096 	stats.inval_tx_word_cnt = mb->un.varRdLnk.invalidXmitWord;
3097 	stats.crc_error_cnt = mb->un.varRdLnk.crcCnt;
3098 	stats.seq_timeout_cnt = mb->un.varRdLnk.primSeqTimeout;
3099 	stats.elastic_overrun_cnt = mb->un.varRdLnk.elasticOverrun;
3100 	stats.arb_timeout_cnt = mb->un.varRdLnk.arbTimeout;
3101 	stats.rx_buf_credit = mb->un.varRdLnk.rxBufCredit;
3102 	stats.rx_buf_cnt = mb->un.varRdLnk.rxBufCreditCur;
3103 	stats.tx_buf_credit = mb->un.varRdLnk.txBufCredit;
3104 	stats.tx_buf_cnt = mb->un.varRdLnk.txBufCreditCur;
3105 	stats.EOFa_cnt = mb->un.varRdLnk.EOFaCnt;
3106 	stats.EOFdti_cnt = mb->un.varRdLnk.EOFdtiCnt;
3107 	stats.EOFni_cnt = mb->un.varRdLnk.EOFniCnt;
3108 	stats.SOFf_cnt = mb->un.varRdLnk.SOFfCnt;
3109 	stats.link_event_tag = hba->link_event_tag;
3110 	stats.last_reset_time = hba->timer_tics - hba->stats.ResetTime;
3111 	stats.port_type = HBA_PORTTYPE_UNKNOWN;
3112 
3113 #ifdef MENLO_SUPPORT
3114 	if (hba->flag & FC_MENLO_MODE) {
3115 		stats.topology = LNK_MENLO_MAINTENANCE;
3116 	} else
3117 #endif	/* MENLO_SUPPORT */
3118 
3119 	if (hba->state >= FC_LINK_UP) {
3120 		if (hba->topology == TOPOLOGY_LOOP) {
3121 			if (hba->flag & FC_FABRIC_ATTACHED) {
3122 				stats.port_type = HBA_PORTTYPE_NLPORT;
3123 				stats.topology = LNK_PUBLIC_LOOP;
3124 			} else {
3125 				stats.port_type = HBA_PORTTYPE_LPORT;
3126 				stats.topology = LNK_LOOP;
3127 			}
3128 		} else {
3129 			if (hba->flag & FC_FABRIC_ATTACHED) {
3130 				stats.port_type = HBA_PORTTYPE_NPORT;
3131 				stats.topology = LNK_FABRIC;
3132 			} else {
3133 				stats.port_type = HBA_PORTTYPE_PTP;
3134 				stats.topology = LNK_PT2PT;
3135 			}
3136 		}
3137 
3138 		if (hba->linkspeed == LA_2GHZ_LINK) {
3139 			stats.link_speed = HBA_PORTSPEED_2GBIT;
3140 		} else if (hba->linkspeed == LA_4GHZ_LINK) {
3141 			stats.link_speed = HBA_PORTSPEED_4GBIT;
3142 		} else if (hba->linkspeed == LA_8GHZ_LINK) {
3143 			stats.link_speed = HBA_PORTSPEED_8GBIT;
3144 		} else if (hba->linkspeed == LA_10GHZ_LINK) {
3145 			stats.link_speed = HBA_PORTSPEED_10GBIT;
3146 		} else {
3147 			stats.link_speed = HBA_PORTSPEED_1GBIT;
3148 		}
3149 	}
3150 	if (ddi_copyout((void *)&stats, (void *)dfc->buf1,
3151 	    sizeof (dfc_hbastats_t), mode) != 0) {
3152 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3153 		    "%s: ddi_copyout failed.",
3154 		    emlxs_dfc_xlate(dfc->cmd));
3155 
3156 		return (DFC_COPYOUT_ERROR);
3157 	}
3158 done:
3159 
3160 	/* Free allocated mbox memory */
3161 	if (mbq) {
3162 		kmem_free(mbq, sizeof (MAILBOXQ));
3163 	}
3164 	return (rval);
3165 
3166 } /* emlxs_dfc_get_hbastats() */
3167 
3168 
3169 
3170 static int32_t
3171 emlxs_dfc_get_drvstats(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3172 {
3173 	emlxs_port_t *port = &PPORT;
3174 	dfc_drvstats_t stats;
3175 	uint32_t rval = 0;
3176 
3177 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
3178 	    "%s requested.",
3179 	    emlxs_dfc_xlate(dfc->cmd));
3180 
3181 	if (!dfc->buf1 || !dfc->buf1_size) {
3182 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3183 		    "%s: Null buffer1 found.",
3184 		    emlxs_dfc_xlate(dfc->cmd));
3185 
3186 		return (DFC_ARG_NULL);
3187 	}
3188 	bzero((void *)&stats, sizeof (dfc_drvstats_t));
3189 
3190 	stats.LinkUp = hba->stats.LinkUp;
3191 	stats.LinkDown = hba->stats.LinkDown;
3192 	stats.LinkEvent = hba->stats.LinkEvent;
3193 	stats.LinkMultiEvent = hba->stats.LinkMultiEvent;
3194 
3195 	stats.MboxIssued = hba->stats.MboxIssued;
3196 	stats.MboxCompleted = hba->stats.MboxCompleted;
3197 	stats.MboxGood = hba->stats.MboxGood;
3198 	stats.MboxError = hba->stats.MboxError;
3199 	stats.MboxBusy = hba->stats.MboxBusy;
3200 	stats.MboxInvalid = hba->stats.MboxInvalid;
3201 
3202 	stats.IocbIssued[0] = hba->stats.IocbIssued[0];
3203 	stats.IocbIssued[1] = hba->stats.IocbIssued[1];
3204 	stats.IocbIssued[2] = hba->stats.IocbIssued[2];
3205 	stats.IocbIssued[3] = hba->stats.IocbIssued[3];
3206 	stats.IocbReceived[0] = hba->stats.IocbReceived[0];
3207 	stats.IocbReceived[1] = hba->stats.IocbReceived[1];
3208 	stats.IocbReceived[2] = hba->stats.IocbReceived[2];
3209 	stats.IocbReceived[3] = hba->stats.IocbReceived[3];
3210 	stats.IocbTxPut[0] = hba->stats.IocbTxPut[0];
3211 	stats.IocbTxPut[1] = hba->stats.IocbTxPut[1];
3212 	stats.IocbTxPut[2] = hba->stats.IocbTxPut[2];
3213 	stats.IocbTxPut[3] = hba->stats.IocbTxPut[3];
3214 	stats.IocbTxGet[0] = hba->stats.IocbTxGet[0];
3215 	stats.IocbTxGet[1] = hba->stats.IocbTxGet[1];
3216 	stats.IocbTxGet[2] = hba->stats.IocbTxGet[2];
3217 	stats.IocbTxGet[3] = hba->stats.IocbTxGet[3];
3218 	stats.IocbRingFull[0] = hba->stats.IocbRingFull[0];
3219 	stats.IocbRingFull[1] = hba->stats.IocbRingFull[1];
3220 	stats.IocbRingFull[2] = hba->stats.IocbRingFull[2];
3221 	stats.IocbRingFull[3] = hba->stats.IocbRingFull[3];
3222 
3223 	stats.IntrEvent[0] = hba->stats.IntrEvent[0];
3224 	stats.IntrEvent[1] = hba->stats.IntrEvent[1];
3225 	stats.IntrEvent[2] = hba->stats.IntrEvent[2];
3226 	stats.IntrEvent[3] = hba->stats.IntrEvent[3];
3227 	stats.IntrEvent[4] = hba->stats.IntrEvent[4];
3228 	stats.IntrEvent[5] = hba->stats.IntrEvent[5];
3229 	stats.IntrEvent[6] = hba->stats.IntrEvent[6];
3230 	stats.IntrEvent[7] = hba->stats.IntrEvent[7];
3231 
3232 	stats.FcpIssued = hba->stats.FcpIssued;
3233 	stats.FcpCompleted = hba->stats.FcpCompleted;
3234 	stats.FcpGood = hba->stats.FcpGood;
3235 	stats.FcpError = hba->stats.FcpError;
3236 
3237 	stats.FcpEvent = hba->stats.FcpEvent;
3238 	stats.FcpStray = hba->stats.FcpStray;
3239 
3240 	stats.ElsEvent = hba->stats.ElsEvent;
3241 	stats.ElsStray = hba->stats.ElsStray;
3242 
3243 	stats.ElsCmdIssued = hba->stats.ElsCmdIssued;
3244 	stats.ElsCmdCompleted = hba->stats.ElsCmdCompleted;
3245 	stats.ElsCmdGood = hba->stats.ElsCmdGood;
3246 	stats.ElsCmdError = hba->stats.ElsCmdError;
3247 
3248 	stats.ElsRspIssued = hba->stats.ElsRspIssued;
3249 	stats.ElsRspCompleted = hba->stats.ElsRspCompleted;
3250 
3251 	stats.ElsRcvEvent = hba->stats.ElsRcvEvent;
3252 	stats.ElsRcvError = hba->stats.ElsRcvError;
3253 	stats.ElsRcvDropped = hba->stats.ElsRcvDropped;
3254 	stats.ElsCmdReceived = hba->stats.ElsCmdReceived;
3255 	stats.ElsRscnReceived = hba->stats.ElsRscnReceived;
3256 	stats.ElsPlogiReceived = hba->stats.ElsPlogiReceived;
3257 	stats.ElsPrliReceived = hba->stats.ElsPrliReceived;
3258 	stats.ElsPrloReceived = hba->stats.ElsPrloReceived;
3259 	stats.ElsLogoReceived = hba->stats.ElsLogoReceived;
3260 	stats.ElsAdiscReceived = hba->stats.ElsAdiscReceived;
3261 	stats.ElsGenReceived = hba->stats.ElsGenReceived;
3262 
3263 	stats.CtEvent = hba->stats.CtEvent;
3264 	stats.CtStray = hba->stats.CtStray;
3265 
3266 	stats.CtCmdIssued = hba->stats.CtCmdIssued;
3267 	stats.CtCmdCompleted = hba->stats.CtCmdCompleted;
3268 	stats.CtCmdGood = hba->stats.CtCmdGood;
3269 	stats.CtCmdError = hba->stats.CtCmdError;
3270 
3271 	stats.CtRspIssued = hba->stats.CtRspIssued;
3272 	stats.CtRspCompleted = hba->stats.CtRspCompleted;
3273 
3274 	stats.CtRcvEvent = hba->stats.CtRcvEvent;
3275 	stats.CtRcvError = hba->stats.CtRcvError;
3276 	stats.CtRcvDropped = hba->stats.CtRcvDropped;
3277 	stats.CtCmdReceived = hba->stats.CtCmdReceived;
3278 
3279 	stats.IpEvent = hba->stats.IpEvent;
3280 	stats.IpStray = hba->stats.IpStray;
3281 
3282 	stats.IpSeqIssued = hba->stats.IpSeqIssued;
3283 	stats.IpSeqCompleted = hba->stats.IpSeqCompleted;
3284 	stats.IpSeqGood = hba->stats.IpSeqGood;
3285 	stats.IpSeqError = hba->stats.IpSeqError;
3286 
3287 	stats.IpBcastIssued = hba->stats.IpBcastIssued;
3288 	stats.IpBcastCompleted = hba->stats.IpBcastCompleted;
3289 	stats.IpBcastGood = hba->stats.IpBcastGood;
3290 	stats.IpBcastError = hba->stats.IpBcastError;
3291 
3292 	stats.IpRcvEvent = hba->stats.IpRcvEvent;
3293 	stats.IpDropped = hba->stats.IpDropped;
3294 	stats.IpSeqReceived = hba->stats.IpSeqReceived;
3295 	stats.IpBcastReceived = hba->stats.IpBcastReceived;
3296 
3297 	stats.IpUbPosted = hba->stats.IpUbPosted;
3298 	stats.ElsUbPosted = hba->stats.ElsUbPosted;
3299 	stats.CtUbPosted = hba->stats.CtUbPosted;
3300 
3301 #if (DFC_REV >= 2)
3302 	stats.IocbThrottled = hba->stats.IocbThrottled;
3303 	stats.ElsAuthReceived = hba->stats.ElsAuthReceived;
3304 #endif
3305 
3306 	if (ddi_copyout((void *)&stats, (void *)dfc->buf1,
3307 	    dfc->buf1_size, mode) != 0) {
3308 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3309 		    "%s: ddi_copyout failed.",
3310 		    emlxs_dfc_xlate(dfc->cmd));
3311 
3312 		return (DFC_COPYOUT_ERROR);
3313 	}
3314 	return (rval);
3315 
3316 } /* emlxs_dfc_get_drvstats() */
3317 
3318 
3319 static int32_t
3320 emlxs_dfc_set_diag(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3321 {
3322 	emlxs_port_t *port = &PPORT;
3323 	int32_t rval = 0;
3324 	uint32_t flag;
3325 	uint32_t i;
3326 
3327 	if (!dfc->buf1 || !dfc->buf1_size) {
3328 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3329 		    "%s: Null buffer1 found.",
3330 		    emlxs_dfc_xlate(dfc->cmd));
3331 
3332 		return (DFC_ARG_NULL);
3333 	}
3334 	if (dfc->buf1_size < sizeof (uint32_t)) {
3335 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3336 		    "%s: Buffer1 too small. (size=%d)",
3337 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3338 
3339 		return (DFC_ARG_TOOSMALL);
3340 	}
3341 	flag = (uint32_t)dfc->flag;
3342 
3343 	mutex_enter(&EMLXS_PORT_LOCK);
3344 
3345 	/* Wait if adapter is in transition */
3346 	i = 0;
3347 	while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
3348 		if (i++ > 30) {
3349 			break;
3350 		}
3351 		mutex_exit(&EMLXS_PORT_LOCK);
3352 		delay(drv_usectohz(1000000));
3353 		mutex_enter(&EMLXS_PORT_LOCK);
3354 	}
3355 
3356 	switch (flag) {
3357 	case DDI_SHOW:
3358 		break;
3359 
3360 	case DDI_ONDI:
3361 		if (hba->flag & FC_OFFLINE_MODE) {
3362 			mutex_exit(&EMLXS_PORT_LOCK);
3363 			(void) emlxs_online(hba);
3364 			mutex_enter(&EMLXS_PORT_LOCK);
3365 		}
3366 		break;
3367 
3368 
3369 		/* Killed + Restart state */
3370 	case DDI_OFFDI:
3371 		if (hba->flag & FC_ONLINE_MODE) {
3372 			mutex_exit(&EMLXS_PORT_LOCK);
3373 
3374 			(void) emlxs_offline(hba);
3375 
3376 			/* Reset with restart */
3377 			(void) emlxs_hba_reset(hba, 1, 1);
3378 
3379 			mutex_enter(&EMLXS_PORT_LOCK);
3380 		} else if (hba->state < FC_INIT_START) {
3381 			mutex_exit(&EMLXS_PORT_LOCK);
3382 
3383 			/* Reset with restart */
3384 			(void) emlxs_hba_reset(hba, 1, 1);
3385 
3386 			mutex_enter(&EMLXS_PORT_LOCK);
3387 		}
3388 		break;
3389 
3390 		/* Killed + Reset state */
3391 	case DDI_WARMDI:
3392 		if (hba->flag & FC_ONLINE_MODE) {
3393 			mutex_exit(&EMLXS_PORT_LOCK);
3394 
3395 			(void) emlxs_offline(hba);
3396 
3397 			/* Reset with no restart */
3398 			(void) emlxs_hba_reset(hba, 0, 0);
3399 
3400 			mutex_enter(&EMLXS_PORT_LOCK);
3401 		} else if (hba->state != FC_WARM_START) {
3402 			mutex_exit(&EMLXS_PORT_LOCK);
3403 
3404 			/* Reset with no restart */
3405 			(void) emlxs_hba_reset(hba, 0, 0);
3406 
3407 			mutex_enter(&EMLXS_PORT_LOCK);
3408 		}
3409 		break;
3410 
3411 		/* Killed */
3412 	case DDI_DIAGDI:
3413 		if (hba->flag & FC_ONLINE_MODE) {
3414 			mutex_exit(&EMLXS_PORT_LOCK);
3415 
3416 			(void) emlxs_offline(hba);
3417 
3418 			mutex_enter(&EMLXS_PORT_LOCK);
3419 		} else if (hba->state != FC_KILLED) {
3420 			mutex_exit(&EMLXS_PORT_LOCK);
3421 
3422 			(void) emlxs_interlock(hba);
3423 
3424 			mutex_enter(&EMLXS_PORT_LOCK);
3425 		}
3426 		break;
3427 
3428 	default:
3429 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3430 		    "%s: Invalid flag. flag=%x",
3431 		    emlxs_dfc_xlate(dfc->cmd), flag);
3432 
3433 		rval = DFC_ARG_INVALID;
3434 	}
3435 
3436 	/* Wait if adapter is in transition */
3437 	i = 0;
3438 	while ((hba->flag & (FC_ONLINING_MODE | FC_OFFLINING_MODE))) {
3439 		if (i++ > 30) {
3440 			break;
3441 		}
3442 		mutex_exit(&EMLXS_PORT_LOCK);
3443 		delay(drv_usectohz(1000000));
3444 		mutex_enter(&EMLXS_PORT_LOCK);
3445 	}
3446 
3447 	/* Return current state */
3448 	if (hba->flag & FC_ONLINE_MODE) {
3449 		flag = DDI_ONDI;
3450 	} else if (hba->state == FC_KILLED) {
3451 		flag = DDI_DIAGDI;
3452 	} else if (hba->state == FC_WARM_START) {
3453 		flag = DDI_WARMDI;
3454 	} else {
3455 		flag = DDI_OFFDI;
3456 	}
3457 
3458 	mutex_exit(&EMLXS_PORT_LOCK);
3459 
3460 	if (ddi_copyout((void *)&flag, (void *)dfc->buf1,
3461 	    sizeof (uint32_t), mode) != 0) {
3462 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3463 		    "%s: ddi_copyout failed.",
3464 		    emlxs_dfc_xlate(dfc->cmd));
3465 
3466 		return (DFC_COPYOUT_ERROR);
3467 	}
3468 	return (rval);
3469 
3470 } /* emlxs_dfc_set_diag() */
3471 
3472 
3473 
3474 static int32_t
3475 emlxs_dfc_send_mbox(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
3476 {
3477 	emlxs_port_t *port = &PPORT;
3478 	MAILBOX *mb = NULL;
3479 	MAILBOXQ *mbq = NULL;
3480 	uint32_t size = 0;
3481 	MATCHMAP *rx_mp = NULL;
3482 	MATCHMAP *tx_mp = NULL;
3483 	uintptr_t lptr;
3484 	int32_t rval = 0;
3485 	int32_t mbxstatus = 0;
3486 	NODELIST *ndlp;
3487 	uint32_t did;
3488 	uint32_t extsize = 0;
3489 	uint8_t *extbuf = NULL;
3490 
3491 	if (!dfc->buf1 || !dfc->buf1_size) {
3492 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3493 		    "%s: Null buffer1 found.",
3494 		    emlxs_dfc_xlate(dfc->cmd));
3495 
3496 		return (DFC_ARG_NULL);
3497 	}
3498 	if (!dfc->buf2 || !dfc->buf2_size) {
3499 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3500 		    "%s: Null buffer2 found.",
3501 		    emlxs_dfc_xlate(dfc->cmd));
3502 
3503 		return (DFC_ARG_NULL);
3504 	}
3505 	if (dfc->buf1_size > MAILBOX_CMD_BSIZE) {
3506 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3507 		    "%s: Buffer1 too large. (size=%d)",
3508 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
3509 
3510 		return (DFC_ARG_TOOBIG);
3511 	}
3512 #ifdef MBOX_EXT_SUPPORT
3513 	if (dfc->buf3_size || dfc->buf4_size) {
3514 		if (dfc->buf3_size && !dfc->buf3) {
3515 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3516 			    "%s: Null buffer3 found.",
3517 			    emlxs_dfc_xlate(dfc->cmd));
3518 
3519 			return (DFC_ARG_NULL);
3520 		}
3521 		if (dfc->buf3_size > MBOX_EXTENSION_SIZE) {
3522 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3523 			    "%s: buffer3 too large. (size=%d)",
3524 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
3525 
3526 			return (DFC_ARG_TOOBIG);
3527 		}
3528 		if (dfc->buf4_size && !dfc->buf4) {
3529 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3530 			    "%s: Null buffer4 found.",
3531 			    emlxs_dfc_xlate(dfc->cmd));
3532 
3533 			return (DFC_ARG_NULL);
3534 		}
3535 		if (dfc->buf4_size > MBOX_EXTENSION_SIZE) {
3536 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3537 			    "%s: buffer4 too large. (size=%d)",
3538 			    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
3539 
3540 			return (DFC_ARG_TOOBIG);
3541 		}
3542 		extsize = (dfc->buf3_size > dfc->buf4_size)
3543 		    ? dfc->buf3_size : dfc->buf4_size;
3544 		if ((extbuf = (uint8_t *)
3545 		    kmem_zalloc(extsize, KM_SLEEP)) == 0) {
3546 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3547 			    "%s: Unable to allocate mailbox"
3548 			    " extension buffer.",
3549 			    emlxs_dfc_xlate(dfc->cmd));
3550 
3551 			return (DFC_SYSRES_ERROR);
3552 		}
3553 		if (dfc->buf3_size) {
3554 			if (ddi_copyin((void *)dfc->buf3, (void *)extbuf,
3555 			    dfc->buf3_size, mode) != 0) {
3556 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3557 				    "%s: ddi_copyin mbox extension"
3558 				    " data failed.",
3559 				    emlxs_dfc_xlate(dfc->cmd));
3560 
3561 				rval = DFC_COPYIN_ERROR;
3562 				goto done;
3563 			}
3564 		}
3565 	}
3566 #endif	/* MBOX_EXT_SUPPORT */
3567 
3568 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
3569 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3570 		    "%s: Unable to allocate mailbox buffer.",
3571 		    emlxs_dfc_xlate(dfc->cmd));
3572 
3573 		rval = DFC_SYSRES_ERROR;
3574 		goto done;
3575 	}
3576 	mb = (MAILBOX *) mbq;
3577 
3578 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
3579 
3580 	if (ddi_copyin((void *)dfc->buf1, (void *)mb,
3581 	    dfc->buf1_size, mode) != 0) {
3582 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3583 		    "%s: ddi_copyin failed.",
3584 		    emlxs_dfc_xlate(dfc->cmd));
3585 
3586 		rval = DFC_COPYIN_ERROR;
3587 		goto done;
3588 	}
3589 #ifdef _LP64
3590 	if ((mb->mbxCommand == MBX_READ_SPARM) ||
3591 	    (mb->mbxCommand == MBX_READ_RPI) ||
3592 	    (mb->mbxCommand == MBX_REG_LOGIN) ||
3593 	    (mb->mbxCommand == MBX_READ_LA) ||
3594 	    (mb->mbxCommand == MBX_RUN_BIU_DIAG)) {
3595 
3596 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3597 		    "%s: Invalid mailbox command."
3598 		    " Must use 64bit version. cmd = %x",
3599 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3600 
3601 		/* Must use 64 bit versions of these mbox cmds */
3602 		rval = DFC_ARG_INVALID;
3603 		goto done;
3604 	}
3605 #endif
3606 
3607 	lptr = 0;
3608 	size = 0;
3609 	switch (mb->mbxCommand) {
3610 		/* Offline only */
3611 	case MBX_CONFIG_LINK:	/* 0x07 */
3612 	case MBX_PART_SLIM:	/* 0x08 */
3613 	case MBX_CONFIG_RING:	/* 0x09 */
3614 	case MBX_DUMP_CONTEXT:	/* 0x18 */
3615 	case MBX_RUN_DIAGS:	/* 0x19 */
3616 	case MBX_RESTART:	/* 0x1A */
3617 	case MBX_SET_MASK:	/* 0x20 */
3618 	case MBX_FLASH_WR_ULA:	/* 0x98 */
3619 		if (!(hba->flag & FC_OFFLINE_MODE)) {
3620 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3621 			    "%s: Adapter not offline. cmd=%x",
3622 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3623 
3624 			rval = DFC_ONLINE_ERROR;
3625 			goto done;
3626 		}
3627 		break;
3628 
3629 		/* Online / Offline */
3630 	case MBX_UNREG_LOGIN:	/* 0x14 */
3631 		ndlp = emlxs_node_find_rpi(port, mb->un.varUnregLogin.rpi);
3632 
3633 		if (ndlp) {
3634 			did = ndlp->nlp_DID;
3635 
3636 			/* remove it */
3637 			emlxs_node_rm(port, ndlp);
3638 
3639 			/*
3640 			 * If we just unregistered the host node then clear
3641 			 * the host DID
3642 			 */
3643 			if (did == port->did) {
3644 				port->did = 0;
3645 			}
3646 		} else {
3647 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3648 			    "%s: Node not found. cmd=%x rpi=%x",
3649 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand,
3650 			    mb->un.varUnregLogin.rpi);
3651 
3652 			/* Node does not exist */
3653 			rval = DFC_ARG_INVALID;
3654 			goto done;
3655 		}
3656 
3657 		/* Send it */
3658 		break;
3659 
3660 	case MBX_UNREG_D_ID:	/* 0x23 */
3661 
3662 		did = mb->un.varRegLogin.did;
3663 
3664 		if (did == 0) {
3665 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3666 			    "%s: Node not found. cmd=%x did=%x",
3667 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
3668 
3669 			rval = DFC_ARG_INVALID;
3670 			goto done;
3671 		}
3672 		if (did == 0xffffffff) {
3673 			emlxs_node_destroy_all(port);
3674 			break;
3675 		}
3676 		/* Check for base node */
3677 		if (did == Bcast_DID) {
3678 			/* just flush base node */
3679 			(void) emlxs_tx_node_flush(port, &port->node_base,
3680 			    0, 0, 0);
3681 			(void) emlxs_chipq_node_flush(port, 0, &port->node_base,
3682 			    0);
3683 
3684 			/* Return now */
3685 			rval = 0;
3686 			goto done;
3687 		}
3688 		/* Make sure the node does already exist */
3689 		ndlp = emlxs_node_find_did(port, did);
3690 
3691 		if (ndlp) {
3692 			/* remove it */
3693 			emlxs_node_rm(port, ndlp);
3694 
3695 			/*
3696 			 * If we just unregistered the host node then clear
3697 			 * the host DID
3698 			 */
3699 			if (did == port->did) {
3700 				port->did = 0;
3701 			}
3702 		} else {
3703 
3704 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3705 			    "%s: Node not found. cmd=%x did=%x",
3706 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
3707 
3708 			/* Node does not exist */
3709 			rval = DFC_ARG_INVALID;
3710 			goto done;
3711 		}
3712 
3713 		/* Send it */
3714 		break;
3715 
3716 		/* Online / Offline - with DMA */
3717 	case MBX_READ_EVENT_LOG:	/* 0x38 */
3718 		lptr = (uintptr_t)getPaddr(mb->un.varRdEvtLog.un.sp64.addrHigh,
3719 		    mb->un.varRdEvtLog.un.sp64.addrLow);
3720 		size = (int)mb->un.varRdEvtLog.un.sp64.tus.f.bdeSize;
3721 
3722 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3723 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3724 			    "%s: Invalid BDE. cmd=%x",
3725 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3726 
3727 			rval = DFC_ARG_INVALID;
3728 			goto done;
3729 		}
3730 		/* Allocate receive buffer */
3731 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3732 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3733 			    "%s: Unable to allocate receive buffer. cmd=%x",
3734 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3735 
3736 			rval = DFC_DRVRES_ERROR;
3737 			goto done;
3738 		}
3739 		mb->un.varRdEvtLog.un.sp64.addrHigh =
3740 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3741 		mb->un.varRdEvtLog.un.sp64.addrLow =
3742 		    (uint32_t)putPaddrLow(rx_mp->phys);
3743 		mb->un.varRdEvtLog.un.sp64.tus.f.bdeFlags = 0;
3744 
3745 		break;
3746 
3747 	case MBX_READ_SPARM:	/* 0x0D */
3748 	case MBX_READ_SPARM64:	/* 0x8D */
3749 		lptr = (uintptr_t)getPaddr(mb->un.varRdSparm.un.sp64.addrHigh,
3750 		    mb->un.varRdSparm.un.sp64.addrLow);
3751 		size = (int)mb->un.varRdSparm.un.sp64.tus.f.bdeSize;
3752 
3753 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3754 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3755 			    "%s: Invalid BDE. cmd=%x",
3756 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3757 
3758 			rval = DFC_ARG_INVALID;
3759 			goto done;
3760 		}
3761 		/* Allocate receive buffer */
3762 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3763 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3764 			    "%s: Unable to allocate receive buffer. cmd=%x",
3765 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3766 
3767 			rval = DFC_DRVRES_ERROR;
3768 			goto done;
3769 		}
3770 		mb->un.varRdSparm.un.sp64.addrHigh =
3771 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3772 		mb->un.varRdSparm.un.sp64.addrLow =
3773 		    (uint32_t)putPaddrLow(rx_mp->phys);
3774 		mb->un.varRdSparm.un.sp64.tus.f.bdeFlags = 0;
3775 
3776 		break;
3777 
3778 	case MBX_READ_RPI:	/* 0x0F */
3779 	case MBX_READ_RPI64:	/* 0x8F */
3780 		lptr = (uintptr_t)getPaddr(mb->un.varRdRPI.un.sp64.addrHigh,
3781 		    mb->un.varRdRPI.un.sp64.addrLow);
3782 		size = (int)mb->un.varRdRPI.un.sp64.tus.f.bdeSize;
3783 
3784 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3785 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3786 			    "%s: Invalid BDE. cmd=%x",
3787 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3788 
3789 			rval = DFC_ARG_INVALID;
3790 			goto done;
3791 		}
3792 		/* Allocate receive buffer */
3793 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3794 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3795 			    "%s: Unable to allocate receive buffer. cmd=%x",
3796 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3797 
3798 			rval = DFC_DRVRES_ERROR;
3799 			goto done;
3800 		}
3801 		mb->un.varRdRPI.un.sp64.addrHigh =
3802 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3803 		mb->un.varRdRPI.un.sp64.addrLow =
3804 		    (uint32_t)putPaddrLow(rx_mp->phys);
3805 		mb->un.varRdRPI.un.sp64.tus.f.bdeFlags = 0;
3806 
3807 		break;
3808 
3809 	case MBX_RUN_BIU_DIAG:	/* 0x04 */
3810 	case MBX_RUN_BIU_DIAG64:	/* 0x84 */
3811 		lptr = (uintptr_t)
3812 		    getPaddr(mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh,
3813 		    mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow);
3814 		size = (int)mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize;
3815 
3816 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3817 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3818 			    "%s: Invalid xmit BDE. cmd=%x",
3819 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3820 
3821 			rval = DFC_ARG_INVALID;
3822 			goto done;
3823 		}
3824 		/* Allocate xmit buffer */
3825 		if ((tx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3826 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3827 			    "%s: Unable to allocate xmit buffer. cmd=%x",
3828 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3829 
3830 			rval = DFC_DRVRES_ERROR;
3831 			goto done;
3832 		}
3833 		/* Initialize the xmit buffer */
3834 		if (ddi_copyin((void *)lptr, (void *)tx_mp->virt,
3835 		    size, mode) != 0) {
3836 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3837 			    "%s: ddi_copyin failed. cmd=%x",
3838 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3839 
3840 			rval = DFC_COPYIN_ERROR;
3841 			goto done;
3842 		}
3843 		emlxs_mpdata_sync(tx_mp->dma_handle, 0,
3844 		    size, DDI_DMA_SYNC_FORDEV);
3845 
3846 		mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh =
3847 		    (uint32_t)putPaddrHigh(tx_mp->phys);
3848 		mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow =
3849 		    (uint32_t)putPaddrLow(tx_mp->phys);
3850 		mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeFlags = 0;
3851 
3852 		/* Initialize the receive buffer */
3853 		lptr = (uintptr_t)
3854 		    getPaddr(mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh,
3855 		    mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow);
3856 		size = (int)mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize;
3857 
3858 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3859 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3860 			    "%s: Invalid rcv BDE. cmd=%x",
3861 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3862 
3863 			rval = DFC_ARG_INVALID;
3864 			goto done;
3865 		}
3866 		/* Allocate receive buffer */
3867 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3868 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3869 			    "%s: Unable to allocate receive buffer. cmd=%x",
3870 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3871 
3872 			rval = DFC_DRVRES_ERROR;
3873 			goto done;
3874 		}
3875 		mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh =
3876 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3877 		mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow =
3878 		    (uint32_t)putPaddrLow(rx_mp->phys);
3879 		mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeFlags = 0;
3880 
3881 		break;
3882 
3883 	case MBX_REG_LOGIN:	/* 0x13 */
3884 	case MBX_REG_LOGIN64:	/* 0x93 */
3885 
3886 		did = mb->un.varRegLogin.did;
3887 
3888 		/* Check for invalid node ids to register */
3889 		if (did == 0 || (did & 0xff000000)) {
3890 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3891 			    "%s: Invalid node id. cmd=%x did=%x",
3892 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand, did);
3893 
3894 			rval = DFC_ARG_INVALID;
3895 			goto done;
3896 		}
3897 		/* Check if the node limit has been reached */
3898 		if (port->node_count >= hba->max_nodes) {
3899 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3900 			    "%s: Too many nodes. cmd=%x",
3901 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3902 
3903 			rval = DFC_HBARES_ERROR;
3904 			goto done;
3905 		}
3906 		lptr = (uintptr_t)getPaddr(mb->un.varRegLogin.un.sp64.addrHigh,
3907 		    mb->un.varRegLogin.un.sp64.addrLow);
3908 		size = (int)mb->un.varRegLogin.un.sp64.tus.f.bdeSize;
3909 
3910 		if (!lptr || (size > MEM_BUF_SIZE)) {
3911 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3912 			    "%s: Invalid BDE. cmd=%x",
3913 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3914 
3915 			rval = DFC_ARG_INVALID;
3916 			goto done;
3917 		}
3918 		/* Allocate xmit buffer */
3919 		if ((tx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3920 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3921 			    "%s: Unable to allocate xmit buffer. cmd=%x",
3922 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3923 
3924 			rval = DFC_DRVRES_ERROR;
3925 			goto done;
3926 		}
3927 		/* Initialize the xmit buffer */
3928 		if (ddi_copyin((void *)lptr, (void *)tx_mp->virt,
3929 		    size, mode) != 0) {
3930 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3931 			    "%s: Unable to allocate xmit buffer. cmd=%x",
3932 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3933 
3934 			rval = DFC_COPYIN_ERROR;
3935 			goto done;
3936 		}
3937 		emlxs_mpdata_sync(tx_mp->dma_handle, 0,
3938 		    size, DDI_DMA_SYNC_FORDEV);
3939 
3940 		mb->un.varRegLogin.un.sp64.addrHigh =
3941 		    (uint32_t)putPaddrHigh(tx_mp->phys);
3942 		mb->un.varRegLogin.un.sp64.addrLow =
3943 		    (uint32_t)putPaddrLow(tx_mp->phys);
3944 		mb->un.varRegLogin.un.sp64.tus.f.bdeFlags = 0;
3945 
3946 		break;
3947 
3948 	case MBX_READ_LA:	/* 0x15 */
3949 	case MBX_READ_LA64:	/* 0x95 */
3950 		lptr = (uintptr_t)
3951 		    getPaddr(mb->un.varReadLA.un.lilpBde64.addrHigh,
3952 		    mb->un.varReadLA.un.lilpBde64.addrLow);
3953 		size = (int)mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize;
3954 
3955 		if (!lptr || !size || (size > MEM_BUF_SIZE)) {
3956 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3957 			    "%s: Invalid BDE. cmd=%x",
3958 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3959 
3960 			rval = DFC_ARG_INVALID;
3961 			goto done;
3962 		}
3963 		/* Allocate receive buffer */
3964 		if ((rx_mp = (MATCHMAP *)emlxs_mem_buf_alloc(hba)) == 0) {
3965 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3966 			    "%s: Unable to allocate receive buffer. cmd=%x",
3967 			    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3968 
3969 			rval = DFC_DRVRES_ERROR;
3970 			goto done;
3971 		}
3972 		mb->un.varReadLA.un.lilpBde64.addrHigh =
3973 		    (uint32_t)putPaddrHigh(rx_mp->phys);
3974 		mb->un.varReadLA.un.lilpBde64.addrLow =
3975 		    (uint32_t)putPaddrLow(rx_mp->phys);
3976 		mb->un.varReadLA.un.lilpBde64.tus.f.bdeFlags = 0;
3977 
3978 		break;
3979 
3980 
3981 		/* Do not allow these commands */
3982 	case MBX_CONFIG_PORT:	/* 0x88 */
3983 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
3984 		    "%s: Command not allowed. cmd=%x",
3985 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
3986 
3987 		rval = DFC_ARG_INVALID;
3988 		goto done;
3989 
3990 
3991 		/* Online / Offline */
3992 	default:
3993 		break;
3994 
3995 	}	/* switch() */
3996 
3997 	mb->mbxOwner = OWN_HOST;
3998 
3999 	/* Set or don't set the PASSTHRU bit. */
4000 	/* Setting will prevent the driver from processing it as its own */
4001 	switch (mb->mbxCommand) {
4002 	case MBX_REG_LOGIN:	/* 0x13 */
4003 	case MBX_REG_LOGIN64:	/* 0x93 */
4004 		break;
4005 
4006 	default:
4007 		mbq->flag |= MBQ_PASSTHRU;
4008 	}
4009 
4010 #ifdef MBOX_EXT_SUPPORT
4011 	if (extbuf) {
4012 		mbq->extbuf = extbuf;
4013 		mbq->extsize = extsize;
4014 	}
4015 #endif	/* MBOX_EXT_SUPPORT */
4016 
4017 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4018 	    "%s: %s sent.  (%x %x %x %x)",
4019 	    emlxs_dfc_xlate(dfc->cmd),
4020 	    emlxs_mb_cmd_xlate(mb->mbxCommand),
4021 	    mb->un.varWords[0],
4022 	    mb->un.varWords[1],
4023 	    mb->un.varWords[2],
4024 	    mb->un.varWords[3]);
4025 
4026 	/* issue the mbox cmd to the sli */
4027 	mbxstatus = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
4028 
4029 	if (mbxstatus) {
4030 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4031 		    "%s: %s failed. mbxstatus=0x%x",
4032 		    emlxs_dfc_xlate(dfc->cmd),
4033 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
4034 		    mbxstatus);
4035 
4036 	}
4037 	if (ddi_copyout((void *)mb, (void *)dfc->buf2,
4038 	    dfc->buf2_size, mode) != 0) {
4039 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4040 		    "%s: ddi_copyout failed. cmd=%x",
4041 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
4042 
4043 		rval = DFC_COPYOUT_ERROR;
4044 		goto done;
4045 	}
4046 	if (rx_mp) {
4047 		emlxs_mpdata_sync(rx_mp->dma_handle, 0, size,
4048 		    DDI_DMA_SYNC_FORKERNEL);
4049 
4050 		if (ddi_copyout((void *)rx_mp->virt, (void *)lptr,
4051 		    size, mode) != 0) {
4052 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4053 			    "%s: ddi_copyout failed for receive buffer."
4054 			    " cmd = %x",
4055 			    emlxs_dfc_xlate(dfc->cmd),
4056 			    mb->mbxCommand);
4057 
4058 			rval = DFC_COPYOUT_ERROR;
4059 			goto done;
4060 		}
4061 	}
4062 #ifdef MBOX_EXT_SUPPORT
4063 	/* Any data needs to copy to mbox extension area */
4064 	if (dfc->buf4_size) {
4065 		if (ddi_copyout((void *)extbuf, (void *)dfc->buf4,
4066 		    dfc->buf4_size, mode) != 0) {
4067 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4068 			    "%s: ddi_copyout failed for mbox"
4069 			    " extension data.",
4070 			    emlxs_dfc_xlate(dfc->cmd));
4071 
4072 			rval = DFC_COPYIN_ERROR;
4073 			goto done;
4074 		}
4075 	}
4076 #endif	/* MBOX_EXT_SUPPORT */
4077 
4078 	rval = 0;
4079 
4080 done:
4081 
4082 	/* Free allocated mbox memory */
4083 	if (extbuf) {
4084 		kmem_free(extbuf, extsize);
4085 	}
4086 	/* Free allocated mbox memory */
4087 	if (mbq) {
4088 		kmem_free(mbq, sizeof (MAILBOXQ));
4089 	}
4090 	/* Free allocated mbuf memory */
4091 	if (rx_mp) {
4092 		(void) emlxs_mem_buf_free(hba, (uint8_t *)rx_mp);
4093 	}
4094 	if (tx_mp) {
4095 		(void) emlxs_mem_buf_free(hba, (uint8_t *)tx_mp);
4096 	}
4097 	return (rval);
4098 
4099 } /* emlxs_dfc_send_mbox() */
4100 
4101 
4102 static int32_t
4103 emlxs_dfc_read_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4104 {
4105 	emlxs_port_t *port = &PPORT;
4106 	uint32_t offset;
4107 	uint32_t cnt;
4108 	uint32_t outsz;
4109 	uint32_t i;
4110 	uint32_t *buffer;
4111 	uint32_t *bptr;
4112 	uint32_t value;
4113 	uint32_t size;
4114 	uint32_t max = 4096;
4115 
4116 	offset = dfc->data1;
4117 	cnt = dfc->data2;
4118 	outsz = dfc->buf1_size;
4119 
4120 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4121 	    "%s: offset=%x count=%d",
4122 	    emlxs_dfc_xlate(dfc->cmd), offset, cnt);
4123 
4124 	if (!dfc->buf1_size || !dfc->buf1) {
4125 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4126 		    "%s: Null buffer1 found.",
4127 		    emlxs_dfc_xlate(dfc->cmd));
4128 
4129 		return (DFC_ARG_NULL);
4130 	}
4131 	if (offset & 0x3) {
4132 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4133 		    "%s: Offset misaligned. (offset=%d)",
4134 		    emlxs_dfc_xlate(dfc->cmd), offset);
4135 
4136 		return (DFC_ARG_MISALIGNED);
4137 	}
4138 	if (cnt & 0x3) {
4139 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4140 		    "%s: Count misaligned. (count=%d)",
4141 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4142 
4143 		return (DFC_ARG_MISALIGNED);
4144 	}
4145 	if (outsz & 0x3) {
4146 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4147 		    "%s: Output size misaligned. (size=%d)",
4148 		    emlxs_dfc_xlate(dfc->cmd), outsz);
4149 
4150 		return (DFC_ARG_MISALIGNED);
4151 	}
4152 	/* Get max PCI config range */
4153 	if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
4154 		max = 256;
4155 	} else {
4156 		max = 4096;
4157 	}
4158 
4159 	if ((cnt + offset) > max) {
4160 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4161 		    "%s: Offset+Count too large."
4162 		    " (offset=%d count=%d max=%d)",
4163 		    emlxs_dfc_xlate(dfc->cmd), offset,
4164 		    cnt, max);
4165 
4166 		return (DFC_ARG_TOOBIG);
4167 	}
4168 	if (outsz > max) {
4169 		outsz = max;
4170 	}
4171 	if (cnt > outsz) {
4172 		cnt = outsz;
4173 	}
4174 	size = cnt;
4175 
4176 	if (!(buffer = (uint32_t *)kmem_zalloc(size, KM_NOSLEEP))) {
4177 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4178 		    "%s: Unable to allocate buffer.",
4179 		    emlxs_dfc_xlate(dfc->cmd));
4180 
4181 		return (DFC_SYSRES_ERROR);
4182 	}
4183 	bptr = buffer;
4184 	for (i = offset; i < (offset + cnt); i += 4) {
4185 		value = ddi_get32(hba->pci_acc_handle,
4186 		    (uint32_t *)(hba->pci_addr + i));
4187 		*bptr++ = PCIMEM_LONG(value);
4188 	}
4189 
4190 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1,
4191 	    outsz, mode) != 0) {
4192 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4193 		    "%s: ddi_copyout failed.",
4194 		    emlxs_dfc_xlate(dfc->cmd));
4195 
4196 		kmem_free(buffer, size);
4197 		return (DFC_COPYOUT_ERROR);
4198 	}
4199 	kmem_free(buffer, size);
4200 	return (0);
4201 
4202 } /* emlxs_dfc_read_pci() */
4203 
4204 
4205 static int32_t
4206 emlxs_dfc_write_pci(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4207 {
4208 	emlxs_port_t *port = &PPORT;
4209 	uint32_t offset;
4210 	uint32_t cnt;
4211 	/* uint32_t outsz; */
4212 	uint32_t value;
4213 	uint32_t i;
4214 	uint32_t max;
4215 	uint8_t buffer[256];
4216 	uint32_t *bptr;
4217 	uint16_t word0;
4218 	uint16_t word1;
4219 
4220 	offset = dfc->data1;
4221 	cnt = dfc->data2;
4222 
4223 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4224 	    "%s: offset = %x count = %d",
4225 	    emlxs_dfc_xlate(dfc->cmd), offset, cnt);
4226 
4227 	if (!dfc->buf1 || !dfc->buf1_size) {
4228 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4229 		    "%s: Null buffer1 found.",
4230 		    emlxs_dfc_xlate(dfc->cmd));
4231 
4232 		return (DFC_ARG_NULL);
4233 	}
4234 	if (offset & 0x3) {
4235 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4236 		    "%s: Offset misaligned. (offset = %d)",
4237 		    emlxs_dfc_xlate(dfc->cmd), offset);
4238 
4239 		return (DFC_ARG_MISALIGNED);
4240 	}
4241 	if (cnt > dfc->buf1_size) {
4242 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4243 		    "%s: Count too large. (count=%d)",
4244 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4245 
4246 		return (DFC_ARG_TOOBIG);
4247 	}
4248 	if (cnt & 0x3) {
4249 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4250 		    "%s: Count misaligned. (count = %d)",
4251 		    emlxs_dfc_xlate(dfc->cmd), cnt);
4252 
4253 		return (DFC_ARG_MISALIGNED);
4254 	}
4255 	/* Get max PCI config range */
4256 	if (hba->model_info.chip <= EMLXS_HELIOS_CHIP) {
4257 		max = 256;
4258 	} else {
4259 		max = 4096;
4260 	}
4261 
4262 	if ((cnt + offset) > max) {
4263 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4264 		    "%s: Count+Offset too large."
4265 		    " (offset = %d count = %d max = %d)",
4266 		    emlxs_dfc_xlate(dfc->cmd), offset, cnt, max);
4267 
4268 		return (DFC_ARG_TOOBIG);
4269 	}
4270 	bzero(buffer, sizeof (buffer));
4271 
4272 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer, cnt, mode) != 0) {
4273 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4274 		    "%s: ddi_copyin failed.",
4275 		    emlxs_dfc_xlate(dfc->cmd));
4276 
4277 		return (DFC_COPYIN_ERROR);
4278 	}
4279 	bptr = (uint32_t *)buffer;
4280 	for (i = offset; i < (offset + cnt); i += 4) {
4281 		value = *bptr++;
4282 		value = PCIMEM_LONG(value);
4283 
4284 		word0 = value & 0xFFFF;
4285 		word1 = value >> 16;
4286 
4287 		/*
4288 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "%s:
4289 		 * Writing. offset=%x cnt=%d value=%08x %04x %04x",
4290 		 * emlxs_dfc_xlate(dfc->cmd), i, value, word0, word1);
4291 		 */
4292 
4293 		/* word0 = PCIMEM_SHORT(word0); */
4294 		(void) ddi_put16(hba->pci_acc_handle,
4295 		    (uint16_t *)(hba->pci_addr + i),
4296 		    (uint16_t)word0);
4297 
4298 		/* word1 = PCIMEM_SHORT(word1); */
4299 		(void) ddi_put16(hba->pci_acc_handle,
4300 		    (uint16_t *)(hba->pci_addr + i + 2), (uint16_t)word1);
4301 	}
4302 
4303 	return (0);
4304 
4305 } /* emlxs_dfc_write_pci() */
4306 
4307 
4308 static int32_t
4309 emlxs_dfc_get_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4310 {
4311 	emlxs_port_t *port = &PPORT;
4312 	dfc_cfgparam_t *cfgparam;
4313 	uint32_t size;
4314 	uint32_t count;
4315 	uint32_t i;
4316 	int32_t rval = 0;
4317 	emlxs_config_t *cfg;
4318 
4319 	if (!dfc->buf1 || !dfc->buf1_size) {
4320 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4321 		    "%s: Null buffer1 found.",
4322 		    emlxs_dfc_xlate(dfc->cmd));
4323 
4324 		return (DFC_ARG_NULL);
4325 	}
4326 	count = dfc->buf1_size / sizeof (dfc_cfgparam_t);
4327 
4328 	if (count > MAX_CFG_PARAM) {
4329 		count = MAX_CFG_PARAM;
4330 	}
4331 	if (count > NUM_CFG_PARAM) {
4332 		count = NUM_CFG_PARAM;
4333 	}
4334 	size = count * sizeof (dfc_cfgparam_t);
4335 
4336 	if (!(cfgparam = (dfc_cfgparam_t *)kmem_zalloc(size, KM_NOSLEEP))) {
4337 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4338 		    "%s: Unable to allocate cfgparm buffer.",
4339 		    emlxs_dfc_xlate(dfc->cmd));
4340 
4341 		return (DFC_SYSRES_ERROR);
4342 	}
4343 	cfg = &CFG;
4344 	for (i = 0; i < count; i++) {
4345 		(void) strncpy(cfgparam[i].a_string, cfg[i].string,
4346 		    sizeof (cfgparam[i].a_string));
4347 		cfgparam[i].a_low = cfg[i].low;
4348 		cfgparam[i].a_hi = cfg[i].hi;
4349 		cfgparam[i].a_default = cfg[i].def;
4350 		cfgparam[i].a_current = cfg[i].current;
4351 
4352 		if (!(cfg[i].flags & PARM_HIDDEN)) {
4353 			cfgparam[i].a_flag |= CFG_EXPORT;
4354 		}
4355 		if ((cfg[i].flags & PARM_DYNAMIC)) {
4356 			if ((cfg[i].flags & PARM_DYNAMIC_RESET) ==
4357 			    PARM_DYNAMIC_RESET) {
4358 				cfgparam[i].a_changestate = CFG_RESTART;
4359 			} else {
4360 				cfgparam[i].a_changestate = CFG_DYMANIC;
4361 			}
4362 		} else {
4363 			cfgparam[i].a_changestate = CFG_REBOOT;
4364 		}
4365 
4366 		(void) strncpy(cfgparam[i].a_help, cfg[i].help,
4367 		    sizeof (cfgparam[i].a_help));
4368 	}
4369 
4370 	if (ddi_copyout((void *)cfgparam, (void *)dfc->buf1,
4371 	    size, mode) != 0) {
4372 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4373 		    "%s: ddi_copyout failed.",
4374 		    emlxs_dfc_xlate(dfc->cmd));
4375 
4376 		rval = DFC_COPYOUT_ERROR;
4377 	}
4378 	rval = 0;
4379 
4380 	kmem_free(cfgparam, size);
4381 
4382 	return (rval);
4383 
4384 } /* emlxs_dfc_get_cfg() */
4385 
4386 
4387 /*ARGSUSED*/
4388 static int32_t
4389 emlxs_dfc_set_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4390 {
4391 	emlxs_port_t *port = &PPORT;
4392 	uint32_t index;
4393 	uint32_t new_value;
4394 	uint32_t rc;
4395 
4396 	index = dfc->data1;
4397 	new_value = dfc->data2;
4398 
4399 	rc = emlxs_set_parm(hba, index, new_value);
4400 
4401 	if (rc) {
4402 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4403 		    "%s: Unable to set parameter. code=%d",
4404 		    emlxs_dfc_xlate(dfc->cmd), rc);
4405 
4406 		switch (rc) {
4407 		case 2:
4408 			return (DFC_NPIV_ACTIVE);
4409 
4410 		default:
4411 			return (DFC_ARG_INVALID);
4412 		}
4413 	}
4414 	return (0);
4415 
4416 } /* emlxs_dfc_set_cfg() */
4417 
4418 
4419 static int32_t
4420 emlxs_dfc_send_ct(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4421 {
4422 	emlxs_port_t *port = &PPORT;
4423 	uint8_t *rsp_buf;
4424 	uint8_t *cmd_buf;
4425 	uint32_t did;
4426 	uint32_t rsp_size;
4427 	uint32_t cmd_size;
4428 	uint32_t timeout;
4429 	fc_packet_t *pkt = NULL;
4430 	uint32_t rval = 0;
4431 	dfc_destid_t destid;
4432 	NODELIST *nlp;
4433 	char buffer[128];
4434 
4435 	cmd_buf = dfc->buf1;
4436 	cmd_size = dfc->buf1_size;
4437 	rsp_buf = dfc->buf2;
4438 	rsp_size = dfc->buf2_size;
4439 	timeout = dfc->data1;
4440 
4441 	if (timeout < (2 * hba->fc_ratov)) {
4442 		timeout = 2 * hba->fc_ratov;
4443 	}
4444 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4445 	    "%s: csize=%d rsize=%d",
4446 	    emlxs_dfc_xlate(dfc->cmd), cmd_size, rsp_size);
4447 
4448 
4449 	if (!cmd_size || !cmd_buf) {
4450 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4451 		    "%s: Null buffer1 found.",
4452 		    emlxs_dfc_xlate(dfc->cmd));
4453 
4454 		rval = DFC_ARG_NULL;
4455 		goto done;
4456 	}
4457 	if (!rsp_size || !rsp_buf) {
4458 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4459 		    "%s: Null buffer2 found.",
4460 		    emlxs_dfc_xlate(dfc->cmd));
4461 
4462 		rval = DFC_ARG_NULL;
4463 		goto done;
4464 	}
4465 	if (!dfc->buf3 || !dfc->buf3_size) {
4466 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4467 		    "%s: Null buffer3 found.",
4468 		    emlxs_dfc_xlate(dfc->cmd));
4469 
4470 		rval = DFC_ARG_NULL;
4471 		goto done;
4472 	}
4473 	if (!dfc->buf4 || !dfc->buf4_size) {
4474 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4475 		    "%s: Null buffer4 found.",
4476 		    emlxs_dfc_xlate(dfc->cmd));
4477 
4478 		rval = DFC_ARG_NULL;
4479 		goto done;
4480 	}
4481 	if (rsp_size > MAX_CT_PAYLOAD) {
4482 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4483 		    "%s: Buffer2 too large. size=%d",
4484 		    emlxs_dfc_xlate(dfc->cmd), rsp_size);
4485 
4486 		rval = DFC_ARG_TOOBIG;
4487 		goto done;
4488 	}
4489 	if (cmd_size > MAX_CT_PAYLOAD) {
4490 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4491 		    "%s: Buffer1 too large. size=%d",
4492 		    emlxs_dfc_xlate(dfc->cmd), cmd_size);
4493 
4494 		rval = DFC_ARG_TOOBIG;
4495 		goto done;
4496 	}
4497 	if (dfc->buf3_size < sizeof (dfc_destid_t)) {
4498 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4499 		    "%s: Buffer3 too small. (size=%d)",
4500 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
4501 
4502 		rval = DFC_ARG_TOOSMALL;
4503 		goto done;
4504 	}
4505 	if (dfc->buf4_size < sizeof (uint32_t)) {
4506 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4507 		    "%s: Buffer4 too small. (size=%d)",
4508 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
4509 
4510 		rval = DFC_ARG_TOOSMALL;
4511 		goto done;
4512 	}
4513 	if (ddi_copyin((void *)dfc->buf3, (void *)&destid,
4514 	    sizeof (dfc_destid_t), mode) != 0) {
4515 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4516 		    "%s: Unable to read destination id.",
4517 		    emlxs_dfc_xlate(dfc->cmd));
4518 
4519 		rval = DFC_COPYIN_ERROR;
4520 		goto done;
4521 	}
4522 	if (destid.idType == 0) {
4523 		if ((nlp = emlxs_node_find_wwpn(port, destid.wwpn)) == NULL) {
4524 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4525 			    "%s: WWPN does not exists. %s",
4526 			    emlxs_dfc_xlate(dfc->cmd),
4527 			    emlxs_wwn_xlate(buffer, destid.wwpn));
4528 
4529 			rval = DFC_ARG_INVALID;
4530 			goto done;
4531 		}
4532 		did = nlp->nlp_DID;
4533 	} else {
4534 		if (emlxs_node_find_did(port, destid.d_id) == NULL) {
4535 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4536 			    "%s: DID does not exist. did=%x",
4537 			    emlxs_dfc_xlate(dfc->cmd), destid.d_id);
4538 
4539 			rval = DFC_ARG_INVALID;
4540 			goto done;
4541 		}
4542 		did = destid.d_id;
4543 	}
4544 
4545 	if (did == 0) {
4546 		did = port->did;
4547 	}
4548 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
4549 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4550 		    "%s: Unable to allocate packet.",
4551 		    emlxs_dfc_xlate(dfc->cmd));
4552 
4553 		rval = DFC_SYSRES_ERROR;
4554 		goto done;
4555 	}
4556 	/* Make this a polled IO */
4557 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
4558 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
4559 	pkt->pkt_comp = NULL;
4560 
4561 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
4562 	pkt->pkt_timeout = (timeout) ? timeout : 30;
4563 
4564 	/* Build the fc header */
4565 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did);
4566 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_UNSOL_CONTROL;
4567 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
4568 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
4569 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
4570 	    F_CTL_SEQ_INITIATIVE;
4571 	pkt->pkt_cmd_fhdr.seq_id = 0;
4572 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4573 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4574 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
4575 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
4576 	pkt->pkt_cmd_fhdr.ro = 0;
4577 
4578 	/* Copy in the command buffer */
4579 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd,
4580 	    cmd_size, mode) != 0) {
4581 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4582 		    "%s: Unable to read command buffer.",
4583 		    emlxs_dfc_xlate(dfc->cmd));
4584 
4585 		rval = DFC_COPYIN_ERROR;
4586 		goto done;
4587 	}
4588 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4589 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4590 		    "%s: Unable to send packet.",
4591 		    emlxs_dfc_xlate(dfc->cmd));
4592 
4593 		rval = DFC_IO_ERROR;
4594 		goto done;
4595 	}
4596 	if ((pkt->pkt_state != FC_PKT_SUCCESS) &&
4597 	    (pkt->pkt_state != FC_PKT_FS_RJT)) {
4598 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
4599 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4600 			    "Pkt Transport error. Pkt Timeout.");
4601 			rval = DFC_TIMEOUT;
4602 		} else {
4603 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4604 			    "Pkt Transport error. state=%x",
4605 			    pkt->pkt_state);
4606 			rval = DFC_IO_ERROR;
4607 		}
4608 		goto done;
4609 	}
4610 	if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf,
4611 	    rsp_size, mode) != 0) {
4612 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4613 		    "%s: Unable to read response.",
4614 		    emlxs_dfc_xlate(dfc->cmd));
4615 
4616 		rval = DFC_COPYOUT_ERROR;
4617 		goto done;
4618 	}
4619 	rsp_size -= pkt->pkt_resp_resid;
4620 	if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf4,
4621 	    dfc->buf4_size, mode) != 0) {
4622 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4623 		    "%s: Unable to write response.",
4624 		    emlxs_dfc_xlate(dfc->cmd));
4625 
4626 		rval = DFC_COPYOUT_ERROR;
4627 		goto done;
4628 	}
4629 	rval = 0;
4630 
4631 done:
4632 
4633 	if (pkt) {
4634 		emlxs_pkt_free(pkt);
4635 	}
4636 	return (rval);
4637 
4638 } /* emlxs_dfc_send_ct() */
4639 
4640 
4641 static int32_t
4642 emlxs_dfc_send_ct_rsp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4643 {
4644 	emlxs_port_t *port = &PPORT;
4645 	uint8_t *cmd_buf;
4646 	uint32_t rx_id;
4647 	uint32_t cmd_size;
4648 	uint32_t timeout;
4649 	fc_packet_t *pkt = NULL;
4650 	uint32_t rval = 0;
4651 	/* dfc_destid_t destid; */
4652 
4653 	cmd_buf = dfc->buf1;
4654 	cmd_size = dfc->buf1_size;
4655 	rx_id = dfc->flag;
4656 	timeout = 2 * hba->fc_ratov;
4657 
4658 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4659 	    "%s: csize=%d",
4660 	    emlxs_dfc_xlate(dfc->cmd), cmd_size);
4661 
4662 	if (!cmd_size || !cmd_buf) {
4663 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4664 		    "%s: Null buffer1 found.",
4665 		    emlxs_dfc_xlate(dfc->cmd));
4666 
4667 		rval = DFC_ARG_NULL;
4668 		goto done;
4669 	}
4670 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, 0, 0, KM_NOSLEEP))) {
4671 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4672 		    "%s: Unable to allocate packet.",
4673 		    emlxs_dfc_xlate(dfc->cmd));
4674 
4675 		rval = DFC_SYSRES_ERROR;
4676 		goto done;
4677 	}
4678 	/* Make this a polled IO */
4679 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
4680 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
4681 	pkt->pkt_comp = NULL;
4682 
4683 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
4684 	pkt->pkt_timeout = (timeout) ? timeout : 30;
4685 
4686 	/* Build the fc header */
4687 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(0);
4688 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_SOLICITED_CONTROL;
4689 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
4690 	pkt->pkt_cmd_fhdr.type = FC_TYPE_FC_SERVICES;
4691 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_LAST_SEQ | F_CTL_END_SEQ |
4692 	    F_CTL_XCHG_CONTEXT;
4693 	pkt->pkt_cmd_fhdr.seq_id = 0;
4694 	pkt->pkt_cmd_fhdr.df_ctl = 0;
4695 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
4696 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
4697 	pkt->pkt_cmd_fhdr.rx_id = rx_id;
4698 	pkt->pkt_cmd_fhdr.ro = 0;
4699 
4700 	/* Copy in the command buffer */
4701 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd,
4702 	    cmd_size, mode) != 0) {
4703 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4704 		    "%s: Unable to read command buffer.",
4705 		    emlxs_dfc_xlate(dfc->cmd));
4706 
4707 		rval = DFC_COPYIN_ERROR;
4708 		goto done;
4709 	}
4710 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
4711 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4712 		    "%s: Unable to send packet.",
4713 		    emlxs_dfc_xlate(dfc->cmd));
4714 
4715 		rval = DFC_IO_ERROR;
4716 		goto done;
4717 	}
4718 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
4719 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
4720 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4721 			    "Pkt Transport error. Pkt Timeout.");
4722 			rval = DFC_TIMEOUT;
4723 		} else {
4724 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4725 			    "Pkt Transport error. state=%x",
4726 			    pkt->pkt_state);
4727 			rval = DFC_IO_ERROR;
4728 		}
4729 		goto done;
4730 	}
4731 	rval = 0;
4732 
4733 done:
4734 
4735 	if (pkt) {
4736 		emlxs_pkt_free(pkt);
4737 	}
4738 	return (rval);
4739 
4740 } /* emlxs_dfc_send_ct_rsp() */
4741 
4742 
4743 #ifdef MENLO_SUPPORT
4744 
4745 static int32_t
4746 emlxs_dfc_send_menlo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
4747 {
4748 	emlxs_port_t *port = &PPORT;
4749 	uint8_t *rsp_buf;
4750 	uint8_t *cmd_buf;
4751 	uint8_t *data_buf;
4752 	/* uint32_t did; */
4753 	uint32_t rsp_size;
4754 	uint32_t cmd_size;
4755 	uint32_t data_size;
4756 	fc_packet_t *pkt = NULL;
4757 	uint32_t rval = 0;
4758 	/* char buffer[128]; */
4759 	menlo_set_cmd_t set_cmd;
4760 	menlo_reset_cmd_t reset_cmd;
4761 	uint32_t rsp_code;
4762 	uint32_t mm_mode;
4763 	uint32_t cmd_code;
4764 	clock_t timeout;
4765 	MAILBOXQ *mbq = NULL;
4766 	MAILBOX *mb;
4767 	uint32_t addr;
4768 	uint32_t value;
4769 	uint32_t mbxstatus;
4770 
4771 	cmd_buf = dfc->buf1;
4772 	cmd_size = dfc->buf1_size;
4773 	rsp_buf = dfc->buf2;
4774 	rsp_size = dfc->buf2_size;
4775 	data_buf = NULL;
4776 	data_size = 0;
4777 	mm_mode = 0;
4778 
4779 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4780 	    "%s: csize=%d rsize=%d",
4781 	    emlxs_dfc_xlate(dfc->cmd), cmd_size, rsp_size);
4782 
4783 	if (hba->model_info.device_id != PCI_DEVICE_ID_LP21000_M) {
4784 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4785 		    "%s: Menlo device not present. device=%x,%x",
4786 		    emlxs_dfc_xlate(dfc->cmd), hba->model_info.device_id,
4787 		    hba->model_info.ssdid);
4788 
4789 		rval = DFC_INVALID_ADAPTER;
4790 		goto done;
4791 	}
4792 	if (!cmd_size || !cmd_buf) {
4793 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4794 		    "%s: Null buffer1 found.",
4795 		    emlxs_dfc_xlate(dfc->cmd));
4796 
4797 		rval = DFC_ARG_NULL;
4798 		goto done;
4799 	}
4800 	if (!rsp_size || !rsp_buf) {
4801 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4802 		    "%s: Null buffer2 found.",
4803 		    emlxs_dfc_xlate(dfc->cmd));
4804 
4805 		rval = DFC_ARG_NULL;
4806 		goto done;
4807 	}
4808 	if (!dfc->buf3 || !dfc->buf3_size) {
4809 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4810 		    "%s: Null buffer3 found.",
4811 		    emlxs_dfc_xlate(dfc->cmd));
4812 
4813 		rval = DFC_ARG_NULL;
4814 		goto done;
4815 	}
4816 	if (dfc->buf3_size < sizeof (uint32_t)) {
4817 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4818 		    "%s: Buffer3 too small. %d < %d",
4819 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size,
4820 		    sizeof (uint32_t));
4821 
4822 		rval = DFC_ARG_TOOSMALL;
4823 		goto done;
4824 	}
4825 	/* Read the command code first */
4826 	if (ddi_copyin((void *)cmd_buf, (void *)&cmd_code,
4827 	    sizeof (uint32_t), mode) != 0) {
4828 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4829 		    "%s: Unable to read command code.",
4830 		    emlxs_dfc_xlate(dfc->cmd));
4831 
4832 		rval = DFC_COPYIN_ERROR;
4833 		goto done;
4834 	}
4835 	cmd_code = SWAP_LONG(cmd_code);
4836 
4837 	/* Look for Zephyr specific commands */
4838 	if (cmd_code & 0x80000000) {
4839 		bzero((uint8_t *)&reset_cmd, sizeof (menlo_reset_cmd_t));
4840 		bzero((uint8_t *)&set_cmd, sizeof (menlo_set_cmd_t));
4841 		bzero((uint8_t *)&rsp_code, sizeof (uint32_t));
4842 
4843 		/* Validate response buffer */
4844 		if (rsp_size < sizeof (uint32_t)) {
4845 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4846 			    "%s: Response overrun.",
4847 			    emlxs_dfc_xlate(dfc->cmd));
4848 			rval = DFC_RSP_BUF_OVERRUN;
4849 			goto done;
4850 		}
4851 		/* All of these responses will be 4 bytes only */
4852 		rsp_size = sizeof (uint32_t);
4853 		rsp_code = 0;
4854 
4855 		/* Validate command buffer */
4856 		switch (cmd_code) {
4857 		case MENLO_CMD_RESET:
4858 			if (cmd_size < sizeof (menlo_reset_cmd_t)) {
4859 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4860 				    "%s: Invalid command size. %d < %d",
4861 				    emlxs_dfc_xlate(dfc->cmd), cmd_size,
4862 				    sizeof (menlo_reset_cmd_t));
4863 				rval = DFC_ARG_INVALID;
4864 				goto done;
4865 			}
4866 			cmd_size = sizeof (menlo_reset_cmd_t);
4867 
4868 			/* Read the command buffer */
4869 			if (ddi_copyin((void *)cmd_buf, (void *)&reset_cmd,
4870 			    cmd_size, mode) != 0) {
4871 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4872 				    "%s: Unable to read command buffer.",
4873 				    emlxs_dfc_xlate(dfc->cmd));
4874 
4875 				rval = DFC_COPYIN_ERROR;
4876 				goto done;
4877 			}
4878 			if (reset_cmd.firmware) {
4879 				/* MENLO_FW_GOLDEN */
4880 				value = 1;
4881 
4882 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4883 				    "%s: Reset with Golden"
4884 				    " firmware requested.",
4885 				    emlxs_dfc_xlate(dfc->cmd));
4886 
4887 			} else {
4888 				/* MENLO_FW_OPERATIONAL */
4889 				value = 0;
4890 
4891 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4892 				    "%s: Reset with Operational"
4893 				    " firmware requested.",
4894 				    emlxs_dfc_xlate(dfc->cmd));
4895 			}
4896 
4897 			addr = 0x103007;
4898 
4899 			break;
4900 
4901 		case MENLO_CMD_SET_MODE:
4902 			if (cmd_size < sizeof (menlo_set_cmd_t)) {
4903 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4904 				    "%s: Invalid command size. %d < %d",
4905 				    emlxs_dfc_xlate(dfc->cmd), cmd_size,
4906 				    sizeof (menlo_set_cmd_t));
4907 				rval = DFC_ARG_INVALID;
4908 				goto done;
4909 			}
4910 			cmd_size = sizeof (menlo_set_cmd_t);
4911 
4912 			/* Read the command buffer */
4913 			if (ddi_copyin((void *)cmd_buf, (void *)&set_cmd,
4914 			    cmd_size, mode) != 0) {
4915 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4916 				    "%s: Unable to read command buffer.",
4917 				    emlxs_dfc_xlate(dfc->cmd));
4918 
4919 				rval = DFC_COPYIN_ERROR;
4920 				goto done;
4921 			}
4922 			if (set_cmd.value1) {
4923 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4924 				    "%s: Maintenance mode"
4925 				    " enable requested.",
4926 				    emlxs_dfc_xlate(dfc->cmd));
4927 
4928 				/* Make sure the mode flag is cleared */
4929 				if (hba->flag & FC_MENLO_MODE) {
4930 					mutex_enter(&EMLXS_PORT_LOCK);
4931 					hba->flag &= ~FC_MENLO_MODE;
4932 					mutex_exit(&EMLXS_PORT_LOCK);
4933 				}
4934 				mm_mode = 1;
4935 			} else {
4936 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
4937 				    "%s: Maintenance mode"
4938 				    " disable requested.",
4939 				    emlxs_dfc_xlate(dfc->cmd));
4940 			}
4941 
4942 			addr = 0x103107;
4943 			value = mm_mode;
4944 
4945 			break;
4946 
4947 		default:
4948 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4949 			    "%s: Invalid command. cmd=%x",
4950 			    emlxs_dfc_xlate(dfc->cmd), cmd_code);
4951 			rval = DFC_ARG_INVALID;
4952 			goto done;
4953 		}
4954 
4955 		if ((mbq = (MAILBOXQ *)
4956 		    kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
4957 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4958 			    "%s: Unable to allocate mailbox buffer.",
4959 			    emlxs_dfc_xlate(dfc->cmd));
4960 
4961 			rval = DFC_SYSRES_ERROR;
4962 			goto done;
4963 		}
4964 		mb = (MAILBOX *)mbq;
4965 
4966 		/* Create the set_variable mailbox request */
4967 		emlxs_mb_set_var(hba, mb, addr, value);
4968 
4969 		mbq->flag |= MBQ_PASSTHRU;
4970 
4971 		/* issue the mbox cmd to the sli */
4972 		mbxstatus = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
4973 
4974 		if (mbxstatus) {
4975 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4976 			    "%s: %s failed. mbxstatus=0x%x",
4977 			    emlxs_dfc_xlate(dfc->cmd),
4978 			    emlxs_mb_cmd_xlate(mb->mbxCommand),
4979 			    mbxstatus);
4980 
4981 			if (mbxstatus == MBX_TIMEOUT) {
4982 				rval = DFC_TIMEOUT;
4983 			} else {
4984 				rval = DFC_IO_ERROR;
4985 			}
4986 			goto done;
4987 		}
4988 		if (ddi_copyout((void *)&rsp_code, (void *)rsp_buf,
4989 		    rsp_size, mode) != 0) {
4990 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
4991 			    "%s: Unable to write response.",
4992 			    emlxs_dfc_xlate(dfc->cmd));
4993 
4994 			rval = DFC_COPYOUT_ERROR;
4995 			goto done;
4996 		}
4997 		if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf3,
4998 		    dfc->buf3_size, mode) != 0) {
4999 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5000 			    "%s: Unable to write response size.",
5001 			    emlxs_dfc_xlate(dfc->cmd));
5002 
5003 			rval = DFC_COPYOUT_ERROR;
5004 			goto done;
5005 		}
5006 		/* Check if we need to wait for maintenance mode */
5007 		if (mm_mode && !(hba->flag & FC_MENLO_MODE)) {
5008 			/* Wait for link to come up in maintenance mode */
5009 			mutex_enter(&EMLXS_LINKUP_LOCK);
5010 
5011 			timeout = emlxs_timeout(hba, 30);
5012 
5013 			rval = 0;
5014 			while ((rval != -1) && !(hba->flag & FC_MENLO_MODE)) {
5015 				rval = cv_timedwait(&EMLXS_LINKUP_CV,
5016 				    &EMLXS_LINKUP_LOCK, timeout);
5017 			}
5018 
5019 			mutex_exit(&EMLXS_LINKUP_LOCK);
5020 
5021 			if (rval == -1) {
5022 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5023 				    "%s: Menlo maintenance mode"
5024 				    " error. Timeout.",
5025 				    emlxs_dfc_xlate(dfc->cmd));
5026 
5027 				rval = DFC_TIMEOUT;
5028 				goto done;
5029 			}
5030 		}
5031 	} else {	/* Standard commands */
5032 		if (hba->state <= FC_LINK_DOWN) {
5033 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5034 			    "%s: Adapter link down.",
5035 			    emlxs_dfc_xlate(dfc->cmd));
5036 
5037 			rval = DFC_LINKDOWN_ERROR;
5038 			goto done;
5039 		}
5040 		if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
5041 			/* Check cmd size */
5042 			/*
5043 			 * Must be at least 12 bytes of command plus 4 bytes
5044 			 * of data
5045 			 */
5046 			if (cmd_size < (12 + 4)) {
5047 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5048 				    "%s: Invalid command size. %d < %d",
5049 				    emlxs_dfc_xlate(dfc->cmd), cmd_size,
5050 				    (12 + 4));
5051 
5052 				rval = DFC_ARG_INVALID;
5053 				goto done;
5054 			}
5055 			/* Extract data buffer from command buffer */
5056 			data_buf = cmd_buf + 12;
5057 			data_size = cmd_size - 12;
5058 			cmd_size = 12;
5059 		}
5060 		if (!(pkt = emlxs_pkt_alloc(port, cmd_size,
5061 		    rsp_size, 0, KM_NOSLEEP))) {
5062 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5063 			    "%s: Unable to allocate packet.",
5064 			    emlxs_dfc_xlate(dfc->cmd));
5065 
5066 			rval = DFC_SYSRES_ERROR;
5067 			goto done;
5068 		}
5069 		/* Make this a polled IO */
5070 		pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5071 		pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5072 		pkt->pkt_comp = NULL;
5073 		pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5074 		pkt->pkt_timeout = 30;
5075 
5076 		/* Build the fc header */
5077 		pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(EMLXS_MENLO_DID);
5078 		pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5079 		pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
5080 		pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5081 		pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
5082 		    F_CTL_SEQ_INITIATIVE;
5083 		pkt->pkt_cmd_fhdr.seq_id = 0;
5084 		pkt->pkt_cmd_fhdr.df_ctl = 0;
5085 		pkt->pkt_cmd_fhdr.seq_cnt = 0;
5086 		pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5087 		pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5088 		pkt->pkt_cmd_fhdr.ro = 0;
5089 
5090 		/* Copy in the command buffer */
5091 		if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd,
5092 		    cmd_size, mode) != 0) {
5093 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5094 			    "%s: Unable to read command buffer.",
5095 			    emlxs_dfc_xlate(dfc->cmd));
5096 
5097 			rval = DFC_COPYIN_ERROR;
5098 			goto done;
5099 		}
5100 		if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5101 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5102 			    "%s: Unable to send packet.",
5103 			    emlxs_dfc_xlate(dfc->cmd));
5104 
5105 			rval = DFC_IO_ERROR;
5106 			goto done;
5107 		}
5108 		if (pkt->pkt_state != FC_PKT_SUCCESS) {
5109 			if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5110 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5111 				    "%s: Pkt Transport error. Pkt Timeout.",
5112 				    emlxs_dfc_xlate(dfc->cmd));
5113 				rval = DFC_TIMEOUT;
5114 			} else if ((pkt->pkt_state == FC_PKT_LOCAL_RJT) &&
5115 			    (pkt->pkt_reason == FC_REASON_OVERRUN)) {
5116 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5117 				    "%s: Pkt Transport error."
5118 				    " Response overrun.",
5119 				    emlxs_dfc_xlate(dfc->cmd));
5120 				rval = DFC_RSP_BUF_OVERRUN;
5121 			} else {
5122 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5123 				    "%s: Pkt Transport error. state=%x",
5124 				    emlxs_dfc_xlate(dfc->cmd),
5125 				    pkt->pkt_state);
5126 				rval = DFC_IO_ERROR;
5127 			}
5128 			goto done;
5129 		}
5130 		if (cmd_code == MENLO_CMD_FW_DOWNLOAD) {
5131 			uint32_t *rsp;
5132 
5133 			/* Check response code */
5134 			rsp = (uint32_t *)pkt->pkt_resp;
5135 			rsp_code = *rsp;
5136 			rsp_code = SWAP_LONG(rsp_code);
5137 
5138 			if (rsp_code == MENLO_RSP_SUCCESS) {
5139 				/* Now transmit the data phase */
5140 
5141 				/* Save last rx_id */
5142 				uint32_t rx_id = pkt->pkt_cmd_fhdr.rx_id;
5143 
5144 				/* Free old pkt */
5145 				emlxs_pkt_free(pkt);
5146 
5147 				/* Allocate data pkt */
5148 				if (!(pkt = emlxs_pkt_alloc(port, data_size,
5149 				    rsp_size, 0, KM_NOSLEEP))) {
5150 					EMLXS_MSGF(EMLXS_CONTEXT,
5151 					    &emlxs_dfc_error_msg,
5152 					    "%s: Unable to allocate"
5153 					    " data packet.",
5154 					    emlxs_dfc_xlate(dfc->cmd));
5155 
5156 					rval = DFC_SYSRES_ERROR;
5157 					goto done;
5158 				}
5159 				/* Make this a polled IO */
5160 				pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5161 				pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5162 				pkt->pkt_comp = NULL;
5163 				pkt->pkt_tran_type = FC_PKT_OUTBOUND;
5164 				pkt->pkt_timeout = 30;
5165 
5166 				/* Build the fc header */
5167 				pkt->pkt_cmd_fhdr.d_id =
5168 				    SWAP_DATA24_LO(EMLXS_MENLO_DID);
5169 				pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5170 				pkt->pkt_cmd_fhdr.s_id =
5171 				    SWAP_DATA24_LO(port->did);
5172 				pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5173 				pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ |
5174 				    F_CTL_END_SEQ | F_CTL_SEQ_INITIATIVE;
5175 				pkt->pkt_cmd_fhdr.seq_id = 0;
5176 				pkt->pkt_cmd_fhdr.df_ctl = 0;
5177 				pkt->pkt_cmd_fhdr.seq_cnt = 0;
5178 				pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5179 				pkt->pkt_cmd_fhdr.rx_id = rx_id;
5180 				pkt->pkt_cmd_fhdr.ro = 0;
5181 
5182 				/* Copy in the data buffer */
5183 				if (ddi_copyin((void *)data_buf,
5184 				    (void *)pkt->pkt_cmd, data_size,
5185 				    mode) != 0) {
5186 					EMLXS_MSGF(EMLXS_CONTEXT,
5187 					    &emlxs_dfc_error_msg,
5188 					    "%s: Unable to read data buffer.",
5189 					    emlxs_dfc_xlate(dfc->cmd));
5190 
5191 					rval = DFC_COPYIN_ERROR;
5192 					goto done;
5193 				}
5194 				if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5195 					EMLXS_MSGF(EMLXS_CONTEXT,
5196 					    &emlxs_dfc_error_msg,
5197 					    "%s: Unable to send data packet.",
5198 					    emlxs_dfc_xlate(dfc->cmd));
5199 
5200 					rval = DFC_IO_ERROR;
5201 					goto done;
5202 				}
5203 				if (pkt->pkt_state != FC_PKT_SUCCESS) {
5204 					if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5205 						EMLXS_MSGF(EMLXS_CONTEXT,
5206 						    &emlxs_dfc_error_msg,
5207 						    "%s: Data Pkt Transport"
5208 						    " error. Pkt Timeout.",
5209 						    emlxs_dfc_xlate(dfc->cmd));
5210 						rval = DFC_TIMEOUT;
5211 					} else if ((pkt->pkt_state ==
5212 					    FC_PKT_LOCAL_RJT) &&
5213 					    (pkt->pkt_reason ==
5214 					    FC_REASON_OVERRUN)) {
5215 						EMLXS_MSGF(EMLXS_CONTEXT,
5216 						    &emlxs_dfc_error_msg,
5217 						    "%s: Data Pkt Transport "
5218 						    "error. Response overrun.",
5219 						    emlxs_dfc_xlate(dfc->cmd));
5220 						rval = DFC_RSP_BUF_OVERRUN;
5221 					} else {
5222 						EMLXS_MSGF(EMLXS_CONTEXT,
5223 						    &emlxs_dfc_error_msg,
5224 						    "%s: Data Pkt Transport "
5225 						    "error. state=%x",
5226 						    emlxs_dfc_xlate(dfc->cmd),
5227 						    pkt->pkt_state);
5228 						rval = DFC_IO_ERROR;
5229 					}
5230 					goto done;
5231 				}
5232 			}
5233 		}
5234 		if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf,
5235 		    rsp_size, mode) != 0) {
5236 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5237 			    "%s: Unable to write response.",
5238 			    emlxs_dfc_xlate(dfc->cmd));
5239 
5240 			rval = DFC_COPYOUT_ERROR;
5241 			goto done;
5242 		}
5243 		rsp_size -= pkt->pkt_resp_resid;
5244 		if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf3,
5245 		    dfc->buf3_size, mode) != 0) {
5246 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5247 			    "%s: Unable to write response size.",
5248 			    emlxs_dfc_xlate(dfc->cmd));
5249 
5250 			rval = DFC_COPYOUT_ERROR;
5251 			goto done;
5252 		}
5253 	}
5254 
5255 	rval = 0;
5256 
5257 done:
5258 
5259 	if (pkt) {
5260 		emlxs_pkt_free(pkt);
5261 	}
5262 	if (mbq) {
5263 		kmem_free(mbq, sizeof (MAILBOXQ));
5264 	}
5265 	return (rval);
5266 
5267 } /* emlxs_dfc_send_menlo() */
5268 
5269 
5270 
5271 extern void
5272 emlxs_fcoe_attention_thread(void *arg)
5273 {
5274 	emlxs_hba_t *hba = (emlxs_hba_t *)arg;
5275 	emlxs_port_t *port = &PPORT;
5276 	menlo_init_rsp_t *rsp;
5277 	menlo_get_cmd_t *cmd;
5278 	fc_packet_t *pkt = NULL;
5279 
5280 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (menlo_get_cmd_t),
5281 	    sizeof (menlo_init_rsp_t), 0, KM_NOSLEEP))) {
5282 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5283 		    "FCoE attention: Unable to allocate packet.");
5284 
5285 		return;
5286 	}
5287 	/* Make this a polled IO */
5288 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5289 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5290 	pkt->pkt_comp = NULL;
5291 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5292 	pkt->pkt_timeout = 30;
5293 
5294 	/* Build the fc header */
5295 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(EMLXS_MENLO_DID);
5296 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_COMMAND;
5297 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
5298 	pkt->pkt_cmd_fhdr.type = EMLXS_MENLO_TYPE;
5299 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
5300 	    F_CTL_SEQ_INITIATIVE;
5301 	pkt->pkt_cmd_fhdr.seq_id = 0;
5302 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5303 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5304 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5305 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5306 	pkt->pkt_cmd_fhdr.ro = 0;
5307 
5308 	cmd = (menlo_get_cmd_t *)pkt->pkt_cmd;
5309 	cmd->code = MENLO_CMD_GET_INIT;
5310 	cmd->context = 0;
5311 	cmd->length = sizeof (menlo_init_rsp_t);
5312 
5313 	/* Little Endian Swap */
5314 	cmd->code = SWAP_LONG(cmd->code);
5315 	cmd->length = SWAP_LONG(cmd->length);
5316 
5317 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5318 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5319 		    "FCoE attention: Unable to send packet.");
5320 
5321 		goto done;
5322 	}
5323 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
5324 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5325 		    "FCoE attention: Pkt Transport error. state=%x",
5326 		    pkt->pkt_state);
5327 
5328 		goto done;
5329 	}
5330 	/* Check response code */
5331 	rsp = (menlo_init_rsp_t *)pkt->pkt_resp;
5332 	rsp->code = SWAP_LONG(rsp->code);
5333 
5334 	if (rsp->code != MENLO_RSP_SUCCESS) {
5335 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5336 		    "FCoE attention: FCOE Response error =%x",
5337 		    rsp->code);
5338 
5339 		goto done;
5340 	}
5341 	/* Little Endian Swap */
5342 	rsp->bb_credit = SWAP_LONG(rsp->bb_credit);
5343 	rsp->frame_size = SWAP_LONG(rsp->frame_size);
5344 	rsp->fw_version = SWAP_LONG(rsp->fw_version);
5345 	rsp->reset_status = SWAP_LONG(rsp->reset_status);
5346 	rsp->maint_status = SWAP_LONG(rsp->maint_status);
5347 	rsp->fw_type = SWAP_LONG(rsp->fw_type);
5348 	rsp->fru_data_valid = SWAP_LONG(rsp->fru_data_valid);
5349 
5350 	/* Log the event */
5351 	emlxs_log_fcoe_event(port, rsp);
5352 
5353 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5354 	    "MENLO_INIT: bb_credit      = 0x%x", rsp->bb_credit);
5355 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5356 	    "MENLO_INIT: frame_size     = 0x%x", rsp->frame_size);
5357 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5358 	    "MENLO_INIT: fw_version     = 0x%x", rsp->fw_version);
5359 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5360 	    "MENLO_INIT: reset_status   = 0x%x", rsp->reset_status);
5361 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5362 	    "MENLO_INIT: maint_status   = 0x%x", rsp->maint_status);
5363 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5364 	    "MENLO_INIT: fw_type        = 0x%x", rsp->fw_type);
5365 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
5366 	    "MENLO_INIT: fru_data_valid = 0x%x", rsp->fru_data_valid);
5367 
5368 	/* Perform attention checks */
5369 	if (rsp->fru_data_valid == 0) {
5370 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_error_msg,
5371 		    "Invalid FRU data found on adapter."
5372 		    " Return adapter to Emulex for repair.");
5373 	}
5374 	switch (rsp->fw_type) {
5375 	case MENLO_FW_TYPE_GOLDEN:
5376 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_warning_msg,
5377 		    "FCoE chip is running Golden firmware."
5378 		    " Update FCoE firmware immediately.");
5379 		break;
5380 
5381 	case MENLO_FW_TYPE_DIAG:
5382 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_adapter_notice_msg,
5383 		    "FCoE chip is running Diagnostic firmware."
5384 		    " Operational use of the adapter is suspended.");
5385 		break;
5386 	}
5387 
5388 done:
5389 
5390 	if (pkt) {
5391 		emlxs_pkt_free(pkt);
5392 	}
5393 	return;
5394 
5395 } /* emlxs_fcoe_attention_thread() */
5396 
5397 #endif	/* MENLO_SUPPORT */
5398 
5399 
5400 static int32_t
5401 emlxs_dfc_write_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5402 {
5403 	emlxs_port_t *port = &PPORT;
5404 	uint32_t offset;
5405 	uint32_t cnt;
5406 	uint8_t *buffer;
5407 	uint8_t *bptr;
5408 	uint32_t i;
5409 
5410 	if (hba->bus_type != SBUS_FC) {
5411 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5412 		    "%s: Invalid bus_type. (bus_type=%x)",
5413 		    emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
5414 
5415 		return (DFC_ARG_INVALID);
5416 	}
5417 	if (!(hba->flag & FC_OFFLINE_MODE)) {
5418 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5419 		    "%s: Adapter not offline.",
5420 		    emlxs_dfc_xlate(dfc->cmd));
5421 
5422 		return (DFC_ONLINE_ERROR);
5423 	}
5424 	if (!dfc->buf1 || !dfc->buf1_size) {
5425 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5426 		    "%s: Null buffer1 found.",
5427 		    emlxs_dfc_xlate(dfc->cmd));
5428 
5429 		return (DFC_ARG_NULL);
5430 	}
5431 	offset = dfc->data1;
5432 	cnt = dfc->data2;
5433 
5434 	if (offset > (64 * 1024)) {
5435 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5436 		    "%s: Offset too large. (offset=%d)",
5437 		    emlxs_dfc_xlate(dfc->cmd), offset);
5438 
5439 		return (DFC_ARG_TOOBIG);
5440 	}
5441 	if (cnt > dfc->buf1_size) {
5442 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5443 		    "%s: Count too large. (count=%d)",
5444 		    emlxs_dfc_xlate(dfc->cmd), cnt);
5445 
5446 		return (DFC_ARG_TOOBIG);
5447 	}
5448 	if ((cnt + offset) > (64 * 1024)) {
5449 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5450 		    "%s: Count+Offset too large. (count=%d offset=%d)",
5451 		    emlxs_dfc_xlate(dfc->cmd), cnt, offset);
5452 
5453 		return (DFC_ARG_TOOBIG);
5454 	}
5455 	if (cnt == 0) {
5456 		return (0);
5457 	}
5458 	if ((buffer = (uint8_t *)kmem_zalloc(cnt, KM_NOSLEEP)) == NULL) {
5459 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5460 		    "%s: Unable to allocate buffer.",
5461 		    emlxs_dfc_xlate(dfc->cmd));
5462 
5463 		return (DFC_SYSRES_ERROR);
5464 	}
5465 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer,
5466 	    cnt, mode) != 0) {
5467 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5468 		    "%s: ddi_copyin failed.",
5469 		    emlxs_dfc_xlate(dfc->cmd));
5470 
5471 		kmem_free(buffer, cnt);
5472 		return (DFC_COPYIN_ERROR);
5473 	}
5474 	bptr = buffer;
5475 	for (i = 0; i < cnt; i++) {
5476 		SBUS_WRITE_FLASH_COPY(hba, offset++, (unsigned long)bptr++);
5477 	}
5478 
5479 	kmem_free(buffer, cnt);
5480 
5481 	return (0);
5482 
5483 } /* emlxs_dfc_write_flash() */
5484 
5485 
5486 static int32_t
5487 emlxs_dfc_read_flash(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5488 {
5489 	emlxs_port_t *port = &PPORT;
5490 	uint32_t offset;
5491 	uint32_t count;
5492 	uint32_t outsz;
5493 	uint8_t *buffer;
5494 	uint8_t *bptr;
5495 	uint32_t i;
5496 
5497 	if (hba->bus_type != SBUS_FC) {
5498 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5499 		    "%s: Invalid bus_type. (bus_type=%x)",
5500 		    emlxs_dfc_xlate(dfc->cmd), hba->bus_type);
5501 
5502 		return (DFC_ARG_INVALID);
5503 	}
5504 	if (!(hba->flag & FC_OFFLINE_MODE)) {
5505 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5506 		    "%s: Adapter not offline.",
5507 		    emlxs_dfc_xlate(dfc->cmd));
5508 
5509 		return (DFC_ONLINE_ERROR);
5510 	}
5511 	if (!dfc->buf1 || !dfc->buf1_size) {
5512 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5513 		    "%s: Null buffer1 found.",
5514 		    emlxs_dfc_xlate(dfc->cmd));
5515 
5516 		return (DFC_ARG_NULL);
5517 	}
5518 	offset = dfc->data1;
5519 	count = dfc->data2;
5520 	outsz = dfc->buf1_size;
5521 
5522 	if (offset > (64 * 1024)) {
5523 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5524 		    "%s: Offset too large. (offset=%d)",
5525 		    emlxs_dfc_xlate(dfc->cmd), offset);
5526 
5527 		return (DFC_ARG_TOOBIG);
5528 	}
5529 	if ((count + offset) > (64 * 1024)) {
5530 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5531 		    "%s: Count+Offset too large. (count = %d offset = %d)",
5532 		    emlxs_dfc_xlate(dfc->cmd), count, offset);
5533 
5534 		return (DFC_ARG_TOOBIG);
5535 	}
5536 	if (count < outsz) {
5537 		outsz = count;
5538 	}
5539 	if ((buffer = (uint8_t *)kmem_zalloc(outsz, KM_NOSLEEP)) == NULL) {
5540 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5541 		    "%s: Unable to allocate buffer.",
5542 		    emlxs_dfc_xlate(dfc->cmd));
5543 
5544 		return (DFC_SYSRES_ERROR);
5545 	}
5546 	bptr = buffer;
5547 	for (i = 0; i < outsz; i++) {
5548 		*bptr++ = SBUS_READ_FLASH_COPY(hba, offset++);
5549 	}
5550 
5551 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1,
5552 	    outsz, mode) != 0) {
5553 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5554 		    "%s: ddi_copyout failed.",
5555 		    emlxs_dfc_xlate(dfc->cmd));
5556 
5557 		kmem_free(buffer, outsz);
5558 		return (DFC_COPYOUT_ERROR);
5559 	}
5560 	kmem_free(buffer, outsz);
5561 
5562 	return (0);
5563 
5564 } /* emlxs_dfc_read_flash() */
5565 
5566 
5567 static int32_t
5568 emlxs_dfc_send_els(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5569 {
5570 	emlxs_port_t *port = &PPORT;
5571 	uint8_t *rsp_buf;
5572 	uint8_t *cmd_buf;
5573 	dfc_destid_t destid;
5574 	uint32_t rsp_size;
5575 	uint32_t cmd_size;
5576 	uint32_t timeout;
5577 	fc_packet_t *pkt = NULL;
5578 	NODELIST *ndlp;
5579 	uint32_t did;
5580 	uint32_t rval = 0;
5581 	char buffer[128];
5582 
5583 	cmd_buf = dfc->buf1;
5584 	cmd_size = dfc->buf1_size;
5585 	rsp_buf = dfc->buf2;
5586 	rsp_size = dfc->buf2_size;
5587 
5588 	timeout = 2 * hba->fc_ratov;
5589 
5590 	if (!cmd_size || !cmd_buf) {
5591 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5592 		    "%s: Null buffer1 found.",
5593 		    emlxs_dfc_xlate(dfc->cmd));
5594 
5595 		rval = DFC_ARG_NULL;
5596 		goto done;
5597 	}
5598 	if (!rsp_buf || !rsp_size) {
5599 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5600 		    "%s: Null buffer2 found.",
5601 		    emlxs_dfc_xlate(dfc->cmd));
5602 
5603 		rval = DFC_ARG_NULL;
5604 		goto done;
5605 	}
5606 	if (!dfc->buf3 || !dfc->buf3_size) {
5607 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5608 		    "%s: Null buffer3 found.",
5609 		    emlxs_dfc_xlate(dfc->cmd));
5610 
5611 		rval = DFC_ARG_NULL;
5612 		goto done;
5613 	}
5614 	if (dfc->buf3_size < sizeof (dfc_destid_t)) {
5615 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5616 		    "%s: Buffer3 too small. (size=%d)",
5617 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
5618 
5619 		rval = DFC_ARG_TOOSMALL;
5620 		goto done;
5621 	}
5622 	if (!dfc->buf4 || !dfc->buf4_size) {
5623 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5624 		    "%s: Null buffer4 found.",
5625 		    emlxs_dfc_xlate(dfc->cmd));
5626 
5627 		rval = DFC_ARG_NULL;
5628 		goto done;
5629 	}
5630 	if (dfc->buf4_size < sizeof (uint32_t)) {
5631 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5632 		    "%s: Buffer4 too small. (size=%d)",
5633 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf4_size);
5634 
5635 		rval = DFC_ARG_TOOSMALL;
5636 		goto done;
5637 	}
5638 	if (ddi_copyin((void *)dfc->buf3, (void *)&destid,
5639 	    sizeof (dfc_destid_t), mode) != 0) {
5640 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5641 		    "%s: ddi_copyin failed.",
5642 		    emlxs_dfc_xlate(dfc->cmd));
5643 
5644 		rval = DFC_COPYIN_ERROR;
5645 		goto done;
5646 	}
5647 	if (destid.idType == 0) {
5648 		if ((ndlp = emlxs_node_find_wwpn(port, destid.wwpn)) == NULL) {
5649 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5650 			    "%s: WWPN does not exists. %s",
5651 			    emlxs_dfc_xlate(dfc->cmd),
5652 			    emlxs_wwn_xlate(buffer, destid.wwpn));
5653 
5654 			rval = DFC_ARG_INVALID;
5655 			goto done;
5656 		}
5657 		did = ndlp->nlp_DID;
5658 	} else {
5659 		if (emlxs_node_find_did(port, destid.d_id) == NULL) {
5660 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5661 			    "%s: DID does not exist. did=%x",
5662 			    emlxs_dfc_xlate(dfc->cmd), destid.d_id);
5663 
5664 			rval = DFC_ARG_INVALID;
5665 			goto done;
5666 		}
5667 		did = destid.d_id;
5668 	}
5669 
5670 	if (did == 0) {
5671 		did = port->did;
5672 	}
5673 	if (!(pkt = emlxs_pkt_alloc(port, cmd_size, rsp_size, 0, KM_NOSLEEP))) {
5674 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5675 		    "%s: Unable to allocate packet.",
5676 		    emlxs_dfc_xlate(dfc->cmd));
5677 
5678 		rval = DFC_SYSRES_ERROR;
5679 		goto done;
5680 	}
5681 	/* Make this a polled IO */
5682 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
5683 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
5684 	pkt->pkt_comp = NULL;
5685 
5686 	pkt->pkt_tran_type = FC_PKT_EXCHANGE;
5687 	pkt->pkt_timeout = (timeout) ? timeout : 30;
5688 
5689 	/* Build the fc header */
5690 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(did);
5691 	pkt->pkt_cmd_fhdr.r_ctl = R_CTL_ELS_REQ;
5692 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
5693 	pkt->pkt_cmd_fhdr.type = FC_TYPE_EXTENDED_LS;
5694 	pkt->pkt_cmd_fhdr.f_ctl = F_CTL_FIRST_SEQ | F_CTL_END_SEQ |
5695 	    F_CTL_SEQ_INITIATIVE;
5696 	pkt->pkt_cmd_fhdr.seq_id = 0;
5697 	pkt->pkt_cmd_fhdr.df_ctl = 0;
5698 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
5699 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
5700 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
5701 	pkt->pkt_cmd_fhdr.ro = 0;
5702 
5703 	/* Copy in the command buffer */
5704 	if (ddi_copyin((void *)cmd_buf, (void *)pkt->pkt_cmd,
5705 	    cmd_size, mode) != 0) {
5706 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5707 		    "%s: ddi_copyin failed.",
5708 		    emlxs_dfc_xlate(dfc->cmd));
5709 
5710 		rval = DFC_COPYIN_ERROR;
5711 		goto done;
5712 	}
5713 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
5714 		rval = DFC_IO_ERROR;
5715 		goto done;
5716 	}
5717 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
5718 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
5719 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5720 			    "Pkt Transport error. Pkt Timeout.");
5721 			rval = DFC_TIMEOUT;
5722 		} else {
5723 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5724 			    "Pkt Transport error. state=%x",
5725 			    pkt->pkt_state);
5726 			rval = DFC_IO_ERROR;
5727 		}
5728 		goto done;
5729 	}
5730 	rsp_size -= pkt->pkt_resp_resid;
5731 	if (ddi_copyout((void *)pkt->pkt_resp, (void *)rsp_buf,
5732 	    rsp_size, mode) != 0) {
5733 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5734 		    "%s: rsp_buf ddi_copyout failed.",
5735 		    emlxs_dfc_xlate(dfc->cmd));
5736 
5737 		rval = DFC_COPYOUT_ERROR;
5738 		goto done;
5739 	}
5740 	if (ddi_copyout((void *)&rsp_size, (void *)dfc->buf4,
5741 	    sizeof (uint32_t), mode) != 0) {
5742 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5743 		    "%s: rsp_size ddi_copyout failed.",
5744 		    emlxs_dfc_xlate(dfc->cmd));
5745 
5746 		rval = DFC_COPYOUT_ERROR;
5747 		goto done;
5748 	}
5749 	rval = 0;
5750 
5751 done:
5752 	if (pkt) {
5753 		emlxs_pkt_free(pkt);
5754 	}
5755 	return (rval);
5756 
5757 } /* emlxs_dfc_send_els() */
5758 
5759 
5760 static int32_t
5761 emlxs_dfc_get_ioinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5762 {
5763 	emlxs_port_t *port = &PPORT;
5764 	dfc_ioinfo_t ioinfo;
5765 	uint32_t i;
5766 
5767 	if (!dfc->buf1 || !dfc->buf1_size) {
5768 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5769 		    "%s: Null buffer1 found.",
5770 		    emlxs_dfc_xlate(dfc->cmd));
5771 
5772 		return (DFC_ARG_NULL);
5773 	}
5774 	if (dfc->buf1_size < sizeof (dfc_ioinfo_t)) {
5775 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5776 		    "%s: Buffer1 too small. (size=%d)",
5777 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
5778 
5779 		return (DFC_ARG_TOOSMALL);
5780 	}
5781 	bzero(&ioinfo, sizeof (dfc_ioinfo_t));
5782 
5783 	ioinfo.a_mboxCmd = HBASTATS.MboxIssued;
5784 	ioinfo.a_mboxCmpl = HBASTATS.MboxCompleted;
5785 	ioinfo.a_mboxErr = HBASTATS.MboxError;
5786 
5787 	for (i = 0; i < MAX_RINGS; i++) {
5788 		ioinfo.a_iocbCmd += HBASTATS.IocbIssued[i];
5789 		ioinfo.a_iocbRsp += HBASTATS.IocbReceived[i];
5790 	}
5791 
5792 	ioinfo.a_adapterIntr =
5793 	    HBASTATS.IntrEvent[0] + HBASTATS.IntrEvent[1] +
5794 	    HBASTATS.IntrEvent[2] + HBASTATS.IntrEvent[3] +
5795 	    HBASTATS.IntrEvent[4] + HBASTATS.IntrEvent[5] +
5796 	    HBASTATS.IntrEvent[6] + HBASTATS.IntrEvent[7];
5797 
5798 	ioinfo.a_fcpCmd = HBASTATS.FcpIssued;
5799 	ioinfo.a_fcpCmpl = HBASTATS.FcpCompleted;
5800 	ioinfo.a_fcpErr =
5801 	    HBASTATS.FcpCompleted - HBASTATS.FcpGood;
5802 
5803 	ioinfo.a_seqXmit = HBASTATS.IpSeqIssued;
5804 	ioinfo.a_seqRcv = HBASTATS.IpSeqReceived;
5805 	ioinfo.a_seqXmitErr =
5806 	    HBASTATS.IpSeqCompleted - HBASTATS.IpSeqGood;
5807 
5808 	ioinfo.a_bcastXmit = HBASTATS.IpBcastIssued;
5809 	ioinfo.a_bcastRcv = HBASTATS.IpBcastReceived;
5810 
5811 	ioinfo.a_elsXmit = HBASTATS.ElsCmdIssued;
5812 	ioinfo.a_elsRcv = HBASTATS.ElsCmdReceived;
5813 	ioinfo.a_elsXmitErr =
5814 	    HBASTATS.ElsCmdCompleted - HBASTATS.ElsCmdGood;
5815 
5816 	ioinfo.a_RSCNRcv = HBASTATS.ElsRscnReceived;
5817 
5818 	ioinfo.a_elsBufPost = HBASTATS.ElsUbPosted;
5819 	ioinfo.a_ipBufPost = HBASTATS.IpUbPosted;
5820 
5821 	ioinfo.a_cnt1 = 0;
5822 	ioinfo.a_cnt2 = 0;
5823 	ioinfo.a_cnt3 = 0;
5824 	ioinfo.a_cnt4 = 0;
5825 
5826 	if (ddi_copyout((void *)&ioinfo, (void *)dfc->buf1,
5827 	    sizeof (dfc_ioinfo_t), mode) != 0) {
5828 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5829 		    "%s: ddi_copyout failed.",
5830 		    emlxs_dfc_xlate(dfc->cmd));
5831 
5832 		return (DFC_COPYOUT_ERROR);
5833 	}
5834 	return (0);
5835 
5836 } /* emlxs_dfc_get_ioinfo() */
5837 
5838 
5839 static int32_t
5840 emlxs_dfc_get_linkinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5841 {
5842 	emlxs_port_t *port = &PPORT;
5843 	dfc_linkinfo_t linkinfo;
5844 
5845 	if (!dfc->buf1 || !dfc->buf1_size) {
5846 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5847 		    "%s: Null buffer1 found.",
5848 		    emlxs_dfc_xlate(dfc->cmd));
5849 
5850 		return (DFC_ARG_NULL);
5851 	}
5852 	if (dfc->buf1_size < sizeof (dfc_linkinfo_t)) {
5853 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5854 		    "%s: Buffer1 too small. (size=%d)",
5855 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
5856 
5857 		return (DFC_ARG_TOOSMALL);
5858 	}
5859 	bzero(&linkinfo, sizeof (dfc_linkinfo_t));
5860 
5861 	linkinfo.a_linkEventTag = hba->link_event_tag;
5862 	linkinfo.a_linkUp = HBASTATS.LinkUp;
5863 	linkinfo.a_linkDown = HBASTATS.LinkDown;
5864 	linkinfo.a_linkMulti = HBASTATS.LinkMultiEvent;
5865 	linkinfo.a_DID = port->did;
5866 	linkinfo.a_topology = 0;
5867 
5868 	if (hba->state <= FC_LINK_DOWN) {
5869 		linkinfo.a_linkState = LNK_DOWN;
5870 	}
5871 #ifdef MENLO_SUPPORT
5872 	else if (hba->flag & FC_MENLO_MODE) {
5873 		linkinfo.a_linkState = LNK_DOWN;
5874 		linkinfo.a_topology = LNK_MENLO_MAINTENANCE;
5875 
5876 	}
5877 #endif	/* MENLO_SUPPORT */
5878 	else if (hba->state < FC_READY) {
5879 		linkinfo.a_linkState = LNK_DISCOVERY;
5880 	} else {
5881 		linkinfo.a_linkState = LNK_READY;
5882 	}
5883 
5884 	if (linkinfo.a_linkState != LNK_DOWN) {
5885 		if (hba->topology == TOPOLOGY_LOOP) {
5886 			if (hba->flag & FC_FABRIC_ATTACHED) {
5887 				linkinfo.a_topology = LNK_PUBLIC_LOOP;
5888 			} else {
5889 				linkinfo.a_topology = LNK_LOOP;
5890 			}
5891 
5892 			linkinfo.a_alpa = port->did & 0xff;
5893 			linkinfo.a_alpaCnt = port->alpa_map[0];
5894 
5895 			if (linkinfo.a_alpaCnt > 127) {
5896 				linkinfo.a_alpaCnt = 127;
5897 			}
5898 			bcopy((void *)&port->alpa_map[1], linkinfo.a_alpaMap,
5899 			    linkinfo.a_alpaCnt);
5900 		} else {
5901 			if (hba->flag & FC_FABRIC_ATTACHED) {
5902 				linkinfo.a_topology = LNK_FABRIC;
5903 			} else {
5904 				linkinfo.a_topology = LNK_PT2PT;
5905 			}
5906 		}
5907 	}
5908 	bcopy(&hba->wwpn, linkinfo.a_wwpName, 8);
5909 	bcopy(&hba->wwnn, linkinfo.a_wwnName, 8);
5910 
5911 	if (ddi_copyout((void *)&linkinfo, (void *)dfc->buf1,
5912 	    sizeof (dfc_linkinfo_t), mode) != 0) {
5913 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5914 		    "%s: ddi_copyout failed.",
5915 		    emlxs_dfc_xlate(dfc->cmd));
5916 
5917 		return (DFC_COPYOUT_ERROR);
5918 	}
5919 	return (0);
5920 
5921 } /* emlxs_dfc_get_linkinfo() */
5922 
5923 #ifdef SFCT_SUPPORT
5924 static int32_t
5925 emlxs_dfc_get_fctstat(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
5926 {
5927 	emlxs_port_t *port = &PPORT;
5928 	emlxs_tgtport_stat_t *statp = &TGTPORTSTAT;
5929 	dfc_tgtport_stat_t dfcstat;
5930 
5931 	if (!dfc->buf1 || !dfc->buf1_size) {
5932 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5933 		    "%s: Null buffer1 found.",
5934 		    emlxs_dfc_xlate(dfc->cmd));
5935 
5936 		return (DFC_ARG_NULL);
5937 	}
5938 	if (dfc->buf1_size < sizeof (emlxs_tgtport_stat_t)) {
5939 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
5940 		    "%s: Buffer1 too small. (size=%d)",
5941 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
5942 
5943 		return (DFC_ARG_TOOSMALL);
5944 	}
5945 	bzero(&dfcstat, sizeof (dfcstat));
5946 
5947 	dfcstat.FctRcvDropped = statp->FctRcvDropped;
5948 	dfcstat.FctOverQDepth = statp->FctOverQDepth;
5949 	dfcstat.FctOutstandingIO = statp->FctOutstandingIO;
5950 	dfcstat.FctFailedPortRegister =
5951 	    statp->FctFailedPortRegister;
5952 	dfcstat.FctPortRegister = statp->FctPortRegister;
5953 	dfcstat.FctPortDeregister = statp->FctPortDeregister;
5954 
5955 	dfcstat.FctAbortSent = statp->FctAbortSent;
5956 	dfcstat.FctNoBuffer = statp->FctNoBuffer;
5957 	dfcstat.FctScsiStatusErr = statp->FctScsiStatusErr;
5958 	dfcstat.FctScsiQfullErr = statp->FctScsiQfullErr;
5959 	dfcstat.FctScsiResidOver = statp->FctScsiResidOver;
5960 	dfcstat.FctScsiResidUnder = statp->FctScsiResidUnder;
5961 	dfcstat.FctScsiSenseErr = statp->FctScsiSenseErr;
5962 
5963 	dfcstat.FctEvent = statp->FctEvent;
5964 	dfcstat.FctCompleted = statp->FctCompleted;
5965 	dfcstat.FctCmplGood = statp->FctCmplGood;
5966 	dfcstat.FctCmplError = statp->FctCmplError;
5967 	dfcstat.FctStray = statp->FctStray;
5968 
5969 	bcopy(&statp->FctP2IOWcnt[0], &dfcstat.FctP2IOWcnt[0],
5970 	    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
5971 	bcopy(&statp->FctP2IORcnt[0], &dfcstat.FctP2IORcnt[0],
5972 	    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
5973 	dfcstat.FctIOCmdCnt = statp->FctIOCmdCnt;
5974 	dfcstat.FctReadBytes = statp->FctReadBytes;
5975 	dfcstat.FctWriteBytes = statp->FctWriteBytes;
5976 	dfcstat.FctCmdReceived = statp->FctCmdReceived;
5977 
5978 	if (dfc->flag) {	/* Clear counters after read */
5979 		bzero(&statp->FctP2IOWcnt[0],
5980 		    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
5981 		bzero(&statp->FctP2IORcnt[0],
5982 		    (sizeof (uint64_t) * MAX_TGTPORT_IOCNT));
5983 		statp->FctIOCmdCnt = 0;
5984 		statp->FctReadBytes = 0;
5985 		statp->FctWriteBytes = 0;
5986 		statp->FctCmdReceived = 0;
5987 	}
5988 	if (hba->state <= FC_LINK_DOWN) {
5989 		dfcstat.FctLinkState = LNK_DOWN;
5990 	}
5991 #ifdef MENLO_SUPPORT
5992 	else if (hba->flag & FC_MENLO_MODE) {
5993 		dfcstat.FctLinkState = LNK_DOWN;
5994 	}
5995 #endif	/* MENLO_SUPPORT */
5996 	else if (hba->state < FC_READY) {
5997 		dfcstat.FctLinkState = LNK_DISCOVERY;
5998 	} else {
5999 		dfcstat.FctLinkState = LNK_READY;
6000 	}
6001 
6002 	if (ddi_copyout((void *)&dfcstat, (void *)dfc->buf1,
6003 	    sizeof (dfc_tgtport_stat_t), mode) != 0) {
6004 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6005 		    "%s: ddi_copyout failed.",
6006 		    emlxs_dfc_xlate(dfc->cmd));
6007 
6008 		return (DFC_COPYOUT_ERROR);
6009 	}
6010 	return (0);
6011 
6012 } /* emlxs_dfc_get_fctstat() */
6013 #endif	/* SFCT_SUPPORT */
6014 
6015 static int32_t
6016 emlxs_dfc_get_nodeinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6017 {
6018 	emlxs_port_t *port;
6019 	emlxs_config_t *cfg = &CFG;
6020 	dfc_node_t *dfc_node;
6021 	dfc_node_t *dnp;
6022 	uint32_t node_count;
6023 	NODELIST *nlp;
6024 	uint32_t size;
6025 	uint32_t i;
6026 
6027 	port = &VPORT(dfc->data1);
6028 
6029 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6030 	    "%s requested.",
6031 	    emlxs_dfc_xlate(dfc->cmd));
6032 
6033 	if (!dfc->buf1 || !dfc->buf1_size) {
6034 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6035 		    "%s: NULL buffer1 found.",
6036 		    emlxs_dfc_xlate(dfc->cmd));
6037 
6038 		return (DFC_ARG_NULL);
6039 	}
6040 	if (dfc->buf1_size < (sizeof (dfc_node_t) * MAX_NODES)) {
6041 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6042 		    "%s: Buffer1 too small. (size=%d)",
6043 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6044 
6045 		return (DFC_ARG_TOOSMALL);
6046 	}
6047 	if (!dfc->buf2 || !dfc->buf2_size) {
6048 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6049 		    "%s: NULL buffer2 found.",
6050 		    emlxs_dfc_xlate(dfc->cmd));
6051 
6052 		return (DFC_ARG_NULL);
6053 	}
6054 	if (dfc->buf2_size < sizeof (uint32_t)) {
6055 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6056 		    "%s: Buffer2 too small. (size=%d)",
6057 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
6058 
6059 		return (DFC_ARG_TOOSMALL);
6060 	}
6061 	node_count = port->node_count;
6062 
6063 	if (node_count == 0) {
6064 		return (0);
6065 	}
6066 	if (node_count > MAX_NODES) {
6067 		node_count = MAX_NODES;
6068 	}
6069 	size = node_count * sizeof (dfc_node_t);
6070 
6071 	if (!(dfc_node = (dfc_node_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6072 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6073 		    "%s: Unable to allocate dfc_node.",
6074 		    emlxs_dfc_xlate(dfc->cmd));
6075 
6076 		return (DFC_SYSRES_ERROR);
6077 	}
6078 	dnp = dfc_node;
6079 
6080 	rw_enter(&port->node_rwlock, RW_READER);
6081 	for (i = 0; i < EMLXS_NUM_HASH_QUES; i++) {
6082 		nlp = port->node_table[i];
6083 		while (nlp != NULL) {
6084 			dnp->port_id = nlp->nlp_DID;
6085 			dnp->rpi = nlp->nlp_Rpi;
6086 			dnp->xri = nlp->nlp_Xri;
6087 
6088 			bcopy((char *)&nlp->sparm, (char *)&dnp->sparm,
6089 			    sizeof (dnp->sparm));
6090 
6091 			if (nlp->nlp_fcp_info & NLP_FCP_TGT_DEVICE) {
6092 				dnp->flags |= PORT_FLAG_FCP_TARGET;
6093 			}
6094 			if (nlp->nlp_fcp_info & NLP_FCP_INI_DEVICE) {
6095 				dnp->flags |= PORT_FLAG_FCP_INI;
6096 
6097 			}
6098 			if (nlp->nlp_fcp_info & NLP_FCP_2_DEVICE) {
6099 				dnp->flags |= PORT_FLAG_FCP2;
6100 			}
6101 			if (cfg[CFG_NETWORK_ON].current && nlp->nlp_Xri) {
6102 				dnp->flags |= PORT_FLAG_IP;
6103 			}
6104 			dnp++;
6105 			nlp = (NODELIST *) nlp->nlp_list_next;
6106 		}
6107 	}
6108 	rw_exit(&port->node_rwlock);
6109 
6110 	if (ddi_copyout((void *)dfc_node, (void *)dfc->buf1,
6111 	    size, mode) != 0) {
6112 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6113 		    "%s: ddi_copyout failed.",
6114 		    emlxs_dfc_xlate(dfc->cmd));
6115 
6116 		kmem_free(dfc_node, size);
6117 		return (DFC_COPYOUT_ERROR);
6118 	}
6119 	if (ddi_copyout((void *)&node_count, (void *)dfc->buf2,
6120 	    sizeof (uint32_t), mode) != 0) {
6121 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6122 		    "%s: ddi_copyout failed.",
6123 		    emlxs_dfc_xlate(dfc->cmd));
6124 
6125 		kmem_free(dfc_node, size);
6126 		return (DFC_COPYOUT_ERROR);
6127 	}
6128 	kmem_free(dfc_node, size);
6129 
6130 	return (0);
6131 
6132 } /* emlxs_dfc_get_nodeinfo() */
6133 
6134 
6135 static int32_t
6136 emlxs_dfc_read_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6137 {
6138 	emlxs_port_t *port = &PPORT;
6139 	uint32_t offset;
6140 	uint32_t size;
6141 	uint32_t max_size;
6142 	uint8_t *buffer;
6143 	uint8_t *slim;
6144 
6145 	offset = dfc->data1;
6146 	size = dfc->data2;
6147 
6148 	if (!dfc->buf1 || !dfc->buf1_size) {
6149 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6150 		    "%s: Null buffer1 found.",
6151 		    emlxs_dfc_xlate(dfc->cmd));
6152 
6153 		return (DFC_ARG_NULL);
6154 	}
6155 	if (size > dfc->buf1_size) {
6156 		size = dfc->buf1_size;
6157 	}
6158 	if (offset % 4) {
6159 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6160 		    "%s: Offset misaligned. (offset=%d)",
6161 		    emlxs_dfc_xlate(dfc->cmd), offset);
6162 
6163 		return (DFC_ARG_MISALIGNED);
6164 	}
6165 	if (size % 4) {
6166 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6167 		    "%s: Size misaligned. (size=%d)",
6168 		    emlxs_dfc_xlate(dfc->cmd), size);
6169 
6170 		return (DFC_ARG_MISALIGNED);
6171 	}
6172 	if (hba->flag & FC_SLIM2_MODE) {
6173 		max_size = SLI2_SLIM2_SIZE;
6174 	} else {
6175 		max_size = 4096;
6176 	}
6177 
6178 	if (offset >= max_size) {
6179 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6180 		    "%s: Offset too large. (offset=%d)",
6181 		    emlxs_dfc_xlate(dfc->cmd), offset);
6182 
6183 		return (DFC_ARG_TOOBIG);
6184 	}
6185 	if ((size + offset) > max_size) {
6186 		size = (max_size - offset);
6187 	}
6188 	if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6189 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6190 		    "%s: Unable to allocate buffer.",
6191 		    emlxs_dfc_xlate(dfc->cmd));
6192 
6193 		return (DFC_SYSRES_ERROR);
6194 	}
6195 	if (hba->flag & FC_SLIM2_MODE) {
6196 		slim = (uint8_t *)hba->slim2.virt + offset;
6197 		emlxs_pcimem_bcopy((uint32_t *)slim, (uint32_t *)buffer,
6198 		    size);
6199 	} else {
6200 		slim = (uint8_t *)hba->slim_addr + offset;
6201 		READ_SLIM_COPY(hba, (uint32_t *)buffer,
6202 		    (uint32_t *)slim, (size / 4));
6203 	}
6204 
6205 	if (ddi_copyout((void *)buffer, (void *)dfc->buf1,
6206 	    size, mode) != 0) {
6207 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6208 		    "%s: ddi_copyout failed.",
6209 		    emlxs_dfc_xlate(dfc->cmd));
6210 
6211 		kmem_free(buffer, size);
6212 		return (DFC_COPYOUT_ERROR);
6213 	}
6214 	kmem_free(buffer, size);
6215 
6216 	return (0);
6217 
6218 } /* emlxs_dfc_read_mem() */
6219 
6220 
6221 static int32_t
6222 emlxs_dfc_write_mem(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6223 {
6224 	emlxs_port_t *port = &PPORT;
6225 	uint32_t offset;
6226 	uint32_t size;
6227 	uint32_t max_size;
6228 	uint8_t *buffer;
6229 	uint8_t *slim;
6230 
6231 	offset = dfc->data1;
6232 	size = dfc->data2;
6233 
6234 	if (!dfc->buf1 || !dfc->buf1_size) {
6235 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6236 		    "%s: Null buffer1 found.",
6237 		    emlxs_dfc_xlate(dfc->cmd));
6238 
6239 		return (DFC_ARG_NULL);
6240 	}
6241 	if (size > dfc->buf1_size) {
6242 		size = dfc->buf1_size;
6243 	}
6244 	if (offset % 4) {
6245 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6246 		    "%s: Offset misaligned. (offset=%d)",
6247 		    emlxs_dfc_xlate(dfc->cmd), offset);
6248 
6249 		return (DFC_ARG_MISALIGNED);
6250 	}
6251 	if (size % 4) {
6252 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6253 		    "%s: Size misaligned. (szie=%d)",
6254 		    emlxs_dfc_xlate(dfc->cmd), size);
6255 
6256 		return (DFC_ARG_MISALIGNED);
6257 	}
6258 	if (hba->flag & FC_SLIM2_MODE) {
6259 		max_size = SLI2_SLIM2_SIZE;
6260 	} else {
6261 		max_size = 4096;
6262 	}
6263 
6264 	if (offset >= max_size) {
6265 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6266 		    "%s: Offset too large. (offset=%d)",
6267 		    emlxs_dfc_xlate(dfc->cmd), offset);
6268 
6269 		return (DFC_ARG_TOOBIG);
6270 	}
6271 	if ((size + offset) > max_size) {
6272 		size = (max_size - offset);
6273 	}
6274 	if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_NOSLEEP))) {
6275 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6276 		    "%s: Unable to allocate buffer.",
6277 		    emlxs_dfc_xlate(dfc->cmd));
6278 
6279 		return (DFC_SYSRES_ERROR);
6280 	}
6281 	if (ddi_copyin((void *)dfc->buf1, (void *)buffer,
6282 	    size, mode) != 0) {
6283 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6284 		    "%s: ddi_copyin failed.",
6285 		    emlxs_dfc_xlate(dfc->cmd));
6286 
6287 		kmem_free(buffer, size);
6288 		return (DFC_COPYIN_ERROR);
6289 	}
6290 	if (hba->flag & FC_SLIM2_MODE) {
6291 		slim = (uint8_t *)hba->slim2.virt + offset;
6292 		emlxs_pcimem_bcopy((uint32_t *)buffer, (uint32_t *)slim,
6293 		    size);
6294 	} else {
6295 		slim = (uint8_t *)hba->slim_addr + offset;
6296 		WRITE_SLIM_COPY(hba, (uint32_t *)buffer, (uint32_t *)slim,
6297 		    (size / 4));
6298 	}
6299 
6300 	kmem_free(buffer, size);
6301 
6302 	return (0);
6303 
6304 } /* emlxs_dfc_write_mem() */
6305 
6306 
6307 /*ARGSUSED*/
6308 static int32_t
6309 emlxs_dfc_write_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6310 {
6311 	emlxs_port_t *port = &PPORT;
6312 	uint32_t offset;
6313 	uint32_t value;
6314 
6315 	offset = dfc->data1;
6316 	value = dfc->data2;
6317 
6318 	if (!(hba->flag & FC_OFFLINE_MODE)) {
6319 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6320 		    "%s: Adapter not offline.",
6321 		    emlxs_dfc_xlate(dfc->cmd));
6322 
6323 		return (DFC_ONLINE_ERROR);
6324 	}
6325 	if (offset % 4) {
6326 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6327 		    "%s: Offset misaligned. (offset=%d)",
6328 		    emlxs_dfc_xlate(dfc->cmd), offset);
6329 
6330 		return (DFC_ARG_MISALIGNED);
6331 	}
6332 	if (offset > 255) {
6333 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6334 		    "%s: Offset too large. (offset=%d)",
6335 		    emlxs_dfc_xlate(dfc->cmd), offset);
6336 
6337 		return (DFC_ARG_TOOBIG);
6338 	}
6339 	WRITE_CSR_REG(hba, (hba->csr_addr + offset), value);
6340 
6341 	return (0);
6342 
6343 } /* emlxs_dfc_write_ctlreg() */
6344 
6345 
6346 static int32_t
6347 emlxs_dfc_read_ctlreg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6348 {
6349 	emlxs_port_t *port = &PPORT;
6350 	uint32_t offset;
6351 	uint32_t value;
6352 
6353 	offset = dfc->data1;
6354 
6355 	if (offset % 4) {
6356 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6357 		    "%s: Offset misaligned. (offset=%d)",
6358 		    emlxs_dfc_xlate(dfc->cmd), offset);
6359 
6360 		return (DFC_ARG_MISALIGNED);
6361 	}
6362 	if (offset > 255) {
6363 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6364 		    "%s: Offset too large. (offset=%d)",
6365 		    emlxs_dfc_xlate(dfc->cmd), offset);
6366 
6367 		return (DFC_ARG_TOOBIG);
6368 	}
6369 	if (!dfc->buf1 || !dfc->buf1_size) {
6370 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6371 		    "%s: Null buffer1 found.",
6372 		    emlxs_dfc_xlate(dfc->cmd));
6373 
6374 		return (DFC_ARG_NULL);
6375 	}
6376 	if (dfc->buf1_size < sizeof (uint32_t)) {
6377 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6378 		    "%s: Buffer1 too small. (size=%d)",
6379 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6380 
6381 		return (DFC_ARG_TOOSMALL);
6382 	}
6383 	value = READ_CSR_REG(hba, (hba->csr_addr + offset));
6384 
6385 	if (ddi_copyout((void *)&value, (void *)dfc->buf1,
6386 	    sizeof (uint32_t), mode) != 0) {
6387 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6388 		    "%s: ddi_copyout failed.",
6389 		    emlxs_dfc_xlate(dfc->cmd));
6390 
6391 		return (DFC_COPYOUT_ERROR);
6392 	}
6393 	return (0);
6394 
6395 } /* emlxs_dfc_read_ctlreg() */
6396 
6397 
6398 static int32_t
6399 emlxs_dfc_set_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6400 {
6401 	emlxs_port_t *port = &PPORT;
6402 	uint32_t event;
6403 	uint32_t enable;
6404 	uint32_t pid;
6405 	uint32_t count;
6406 	uint32_t i;
6407 	emlxs_dfc_event_t *dfc_event;
6408 
6409 	event = dfc->data1;
6410 	pid = dfc->data2;
6411 	enable = dfc->flag;
6412 
6413 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6414 	    "%s: %s. pid=%d enable=%d",
6415 	    emlxs_dfc_xlate(dfc->cmd),
6416 	    emlxs_dfc_event_xlate(event), pid, enable);
6417 
6418 	switch (event) {
6419 	case FC_REG_LINK_EVENT:
6420 	case FC_REG_RSCN_EVENT:
6421 	case FC_REG_CT_EVENT:
6422 	case FC_REG_DUMP_EVENT:
6423 	case FC_REG_TEMP_EVENT:
6424 	case FC_REG_FCOE_EVENT:
6425 		break;
6426 
6427 	case FC_REG_MULTIPULSE_EVENT:
6428 	default:
6429 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6430 		    "%s: %s. Invalid event. pid=%d enable=%d",
6431 		    emlxs_dfc_xlate(dfc->cmd),
6432 		    emlxs_dfc_event_xlate(event), pid, enable);
6433 
6434 		return (DFC_ARG_INVALID);
6435 	}
6436 
6437 	if (enable) {
6438 		if (dfc->buf1_size < sizeof (uint32_t)) {
6439 			dfc->buf1 = NULL;
6440 		} else if (!dfc->buf1) {
6441 			dfc->buf1_size = 0;
6442 		}
6443 		/* Make sure this pid/event is not already registered */
6444 		dfc_event = NULL;
6445 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
6446 			dfc_event = &hba->dfc_event[i];
6447 
6448 			if (dfc_event->pid == pid &&
6449 			    dfc_event->event == event) {
6450 				break;
6451 			}
6452 		}
6453 
6454 		if (i == MAX_DFC_EVENTS) {
6455 			/* Find next available event object */
6456 			for (i = 0; i < MAX_DFC_EVENTS; i++) {
6457 				dfc_event = &hba->dfc_event[i];
6458 
6459 				if (!dfc_event->pid && !dfc_event->event) {
6460 					break;
6461 				}
6462 			}
6463 
6464 			/* Return if all event objects are busy */
6465 			if (i == MAX_DFC_EVENTS) {
6466 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6467 				    "%s: %s. Too many events registered."
6468 				    " pid=%d enable=%d",
6469 				    emlxs_dfc_xlate(dfc->cmd),
6470 				    emlxs_dfc_event_xlate(event),
6471 				    pid, enable);
6472 
6473 				return (DFC_DRVRES_ERROR);
6474 			}
6475 		}
6476 		/* Initialize */
6477 		dfc_event->pid = pid;
6478 		dfc_event->event = event;
6479 		dfc_event->last_id = (uint32_t)-1;
6480 		dfc_event->dataout = NULL;
6481 		dfc_event->size = 0;
6482 		dfc_event->mode = 0;
6483 
6484 		(void) emlxs_get_dfc_event(port, dfc_event, 0);
6485 
6486 		if (dfc->buf1) {
6487 			if (ddi_copyout((void *)&dfc_event->last_id, dfc->buf1,
6488 			    sizeof (uint32_t), mode) != 0) {
6489 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6490 				    "%s: ddi_copyout failed.",
6491 				    emlxs_dfc_xlate(dfc->cmd));
6492 
6493 				return (DFC_COPYOUT_ERROR);
6494 			}
6495 		}
6496 		/*
6497 		 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "%s: %s.
6498 		 * Enabled. pid=%d id=%d", emlxs_dfc_xlate(dfc->cmd),
6499 		 * emlxs_dfc_event_xlate(event), pid, dfc_event->last_id);
6500 		 */
6501 
6502 		hba->log_events |= event;
6503 	} else {	/* Disable */
6504 		/* Find the event entry */
6505 		dfc_event = NULL;
6506 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
6507 			dfc_event = &hba->dfc_event[i];
6508 
6509 			if (dfc_event->pid == pid &&
6510 			    dfc_event->event == event) {
6511 				break;
6512 			}
6513 		}
6514 
6515 		if (i == MAX_DFC_EVENTS) {
6516 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6517 			    "%s: %s. Event not registered."
6518 			    " pid=%d enable=%d",
6519 			    emlxs_dfc_xlate(dfc->cmd),
6520 			    emlxs_dfc_event_xlate(event),
6521 			    pid, enable);
6522 
6523 			return (DFC_ARG_INVALID);
6524 		}
6525 		/* Kill the event thread if it is sleeping */
6526 		(void) emlxs_kill_dfc_event(port, dfc_event);
6527 
6528 		/* Count the number of pids still registered for this event */
6529 		count = 0;
6530 		for (i = 0; i < MAX_DFC_EVENTS; i++) {
6531 			dfc_event = &hba->dfc_event[i];
6532 
6533 			if (dfc_event->event == event) {
6534 				count++;
6535 			}
6536 		}
6537 
6538 		/*
6539 		 * If no more pids need this event, then disable logging for
6540 		 * this event
6541 		 */
6542 		if (count == 0) {
6543 			hba->log_events &= ~event;
6544 		}
6545 	}
6546 
6547 	return (0);
6548 
6549 } /* emlxs_dfc_set_event() */
6550 
6551 
6552 static int32_t
6553 emlxs_dfc_get_eventinfo(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6554 {
6555 	emlxs_port_t *port = &PPORT;
6556 	uint32_t size;
6557 	/* uint32_t i; */
6558 	int32_t rval = 0;
6559 	HBA_EVENTINFO *event_buffer = NULL;
6560 	uint32_t event_count = 0;
6561 	uint32_t missed = 0;
6562 
6563 	if (!dfc->buf1 || !dfc->buf1_size) {
6564 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6565 		    "%s: Null buffer1 buffer.",
6566 		    emlxs_dfc_xlate(dfc->cmd));
6567 
6568 		return (DFC_ARG_NULL);
6569 	}
6570 	event_count = dfc->buf1_size / sizeof (HBA_EVENTINFO);
6571 
6572 	if (!event_count) {
6573 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6574 		    "%s: Buffer1 too small. (size=%d)",
6575 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
6576 
6577 		return (DFC_ARG_TOOSMALL);
6578 	}
6579 	if (!dfc->buf2 || !dfc->buf2_size) {
6580 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6581 		    "%s: Null buffer2 buffer.",
6582 		    emlxs_dfc_xlate(dfc->cmd));
6583 
6584 		return (DFC_ARG_NULL);
6585 	}
6586 	if (dfc->buf2_size < sizeof (uint32_t)) {
6587 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6588 		    "%s: Buffer2 too small. (size=%d)",
6589 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
6590 
6591 		return (DFC_ARG_TOOSMALL);
6592 	}
6593 	if (!dfc->buf3 || !dfc->buf3_size) {
6594 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6595 		    "%s: Null buffer3 found.",
6596 		    emlxs_dfc_xlate(dfc->cmd));
6597 
6598 		return (DFC_ARG_NULL);
6599 	}
6600 	if (dfc->buf3_size < sizeof (uint32_t)) {
6601 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6602 		    "%s: Buffer3 too small. (size=%d)",
6603 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf3_size);
6604 
6605 		return (DFC_ARG_TOOSMALL);
6606 	}
6607 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6608 	    "%s called. max=%d",
6609 	    emlxs_dfc_xlate(dfc->cmd), event_count);
6610 
6611 	size = (event_count * sizeof (HBA_EVENTINFO));
6612 	if (!(event_buffer = (HBA_EVENTINFO *)kmem_zalloc(size, KM_SLEEP))) {
6613 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6614 		    "%s: Unable to allocate buffer. size=%d",
6615 		    emlxs_dfc_xlate(dfc->cmd), size);
6616 
6617 		return (DFC_SYSRES_ERROR);
6618 	}
6619 	if (emlxs_get_dfc_eventinfo(port, event_buffer,
6620 	    &event_count, &missed) != 0) {
6621 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6622 		    "%s: emlxs_get_dfc_eventinfo failed.",
6623 		    emlxs_dfc_xlate(dfc->cmd));
6624 
6625 		rval = DFC_DRV_ERROR;
6626 		goto done;
6627 	}
6628 	if (event_count) {
6629 		if (ddi_copyout((void *)event_buffer, dfc->buf1,
6630 		    (event_count * sizeof (HBA_EVENTINFO)), mode) != 0) {
6631 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6632 			    "%s: ddi_copyout failed.",
6633 			    emlxs_dfc_xlate(dfc->cmd));
6634 
6635 			rval = DFC_COPYOUT_ERROR;
6636 			goto done;
6637 		}
6638 	}
6639 	if (ddi_copyout((void *)&event_count, dfc->buf2,
6640 	    sizeof (uint32_t), mode) != 0) {
6641 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6642 		    "%s: ddi_copyout failed.",
6643 		    emlxs_dfc_xlate(dfc->cmd));
6644 
6645 		rval = DFC_COPYOUT_ERROR;
6646 		goto done;
6647 	}
6648 	if (ddi_copyout((void *)&missed, dfc->buf3,
6649 	    sizeof (uint32_t), mode) != 0) {
6650 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6651 		    "%s: ddi_copyout failed.",
6652 		    emlxs_dfc_xlate(dfc->cmd));
6653 
6654 		rval = DFC_COPYOUT_ERROR;
6655 		goto done;
6656 	}
6657 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6658 	    "%s: events=%d missed=%d new=%d last_id=%d",
6659 	    emlxs_dfc_xlate(dfc->cmd), event_count,
6660 	    hba->hba_event.missed, hba->hba_event.new,
6661 	    hba->hba_event.last_id);
6662 
6663 done:
6664 
6665 	if (event_buffer) {
6666 		kmem_free(event_buffer, size);
6667 	}
6668 	return (rval);
6669 
6670 } /* emlxs_dfc_get_eventinfo() */
6671 
6672 
6673 static int32_t
6674 emlxs_dfc_get_event(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6675 {
6676 	emlxs_port_t *port = &PPORT;
6677 	uint32_t event;
6678 	uint32_t pid;
6679 	uint32_t sleep;
6680 	uint32_t i;
6681 	int32_t rval = DFC_SUCCESS;
6682 	/* char *bp; */
6683 	emlxs_dfc_event_t *dfc_event;
6684 
6685 	event = dfc->data1;
6686 	pid = dfc->data2;
6687 
6688 	if (!dfc->buf1_size) {
6689 		dfc->buf1 = NULL;
6690 	} else if (!dfc->buf1) {
6691 		dfc->buf1_size = 0;
6692 	}
6693 	if (dfc->buf2_size < sizeof (uint32_t)) {
6694 		dfc->buf2 = NULL;
6695 	} else if (!dfc->buf2) {
6696 		dfc->buf2_size = 0;
6697 	}
6698 	if (dfc->buf3_size < sizeof (uint32_t)) {
6699 		dfc->buf3 = NULL;
6700 	} else if (!dfc->buf3) {
6701 		dfc->buf3_size = 0;
6702 	}
6703 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6704 	    "%s: %s. pid=%d size=%d,%p rcv_size=%d,%p id=%d",
6705 	    emlxs_dfc_xlate(dfc->cmd), emlxs_dfc_event_xlate(event),
6706 	    pid, dfc->buf1_size, dfc->buf1, dfc->buf2_size, dfc->buf2,
6707 	    dfc->data3);
6708 
6709 	/* Find the event entry */
6710 	dfc_event = NULL;
6711 	for (i = 0; i < MAX_DFC_EVENTS; i++) {
6712 		dfc_event = &hba->dfc_event[i];
6713 
6714 		if (dfc_event->pid == pid && dfc_event->event == event) {
6715 			break;
6716 		}
6717 	}
6718 
6719 	if (i == MAX_DFC_EVENTS) {
6720 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6721 		    "%s: %s. Event not registered. pid=%d",
6722 		    emlxs_dfc_xlate(dfc->cmd),
6723 		    emlxs_dfc_event_xlate(event), pid);
6724 
6725 		return (DFC_ARG_INVALID);
6726 	}
6727 	if (!(hba->log_events & dfc_event->event)) {
6728 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6729 		    "%s: %s. Event not registered. pid=%d",
6730 		    emlxs_dfc_xlate(dfc->cmd),
6731 		    emlxs_dfc_event_xlate(event), pid);
6732 
6733 		return (DFC_ARG_INVALID);
6734 	}
6735 	/* Initialize event buffer pointers */
6736 	dfc_event->dataout = dfc->buf1;
6737 	dfc_event->size = dfc->buf1_size;
6738 	dfc_event->last_id = dfc->data3;
6739 	dfc_event->mode = mode;
6740 
6741 	sleep = (dfc->flag & 0x01) ? 1 : 0;
6742 
6743 	if ((rval = emlxs_get_dfc_event(port, dfc_event, sleep))) {
6744 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
6745 		    "%s: %s. Exiting. pid=%d rsize=%d id=%d rval=%d",
6746 		    emlxs_dfc_xlate(dfc->cmd),
6747 		    emlxs_dfc_event_xlate(event), pid,
6748 		    dfc_event->size, dfc_event->last_id, rval);
6749 
6750 		return (rval);
6751 	}
6752 	if (dfc->buf2) {
6753 		if (ddi_copyout((void *)&dfc_event->size, dfc->buf2,
6754 		    sizeof (uint32_t), mode) != 0) {
6755 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6756 			    "%s: ddi_copyout failed.",
6757 			    emlxs_dfc_xlate(dfc->cmd));
6758 
6759 			return (DFC_COPYOUT_ERROR);
6760 		}
6761 	}
6762 	if (dfc->buf3) {
6763 		if (ddi_copyout((void *)&dfc_event->last_id, dfc->buf3,
6764 		    sizeof (uint32_t), mode) != 0) {
6765 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6766 			    "%s: ddi_copyout failed.",
6767 			    emlxs_dfc_xlate(dfc->cmd));
6768 
6769 			return (DFC_COPYOUT_ERROR);
6770 		}
6771 	}
6772 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
6773 	    "%s: %s. Completed. pid=%d rsize=%d id=%d",
6774 	    emlxs_dfc_xlate(dfc->cmd),
6775 	    emlxs_dfc_event_xlate(event), pid,
6776 	    dfc_event->size, dfc_event->last_id);
6777 
6778 	return (rval);
6779 
6780 } /* emlxs_dfc_get_event() */
6781 
6782 
6783 
6784 static int32_t
6785 emlxs_dfc_get_dump_region(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
6786 {
6787 	emlxs_port_t *port = &PPORT;
6788 	uint32_t size;
6789 	uint32_t size_only;
6790 	uint32_t rval = 0;
6791 	uint8_t *buffer = NULL;
6792 	uint8_t *memptr;
6793 	uint32_t *wptr;
6794 
6795 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
6796 	    "%s: region=%d size=%d",
6797 	    emlxs_dfc_xlate(dfc->cmd),
6798 	    dfc->data1, dfc->buf1_size);
6799 
6800 	if (!dfc->buf1 || !dfc->buf1_size) {
6801 		size_only = 1;
6802 		size = (uint32_t)-1;
6803 	} else {
6804 		size_only = 0;
6805 		size = dfc->buf1_size;
6806 	}
6807 
6808 	if (!dfc->buf2 || !dfc->buf2_size) {
6809 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6810 		    "%s: Null buffer2 found.",
6811 		    emlxs_dfc_xlate(dfc->cmd));
6812 
6813 		return (DFC_ARG_NULL);
6814 	}
6815 	if (dfc->buf2_size < sizeof (uint32_t)) {
6816 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6817 		    "%s: Buffer2 too small. (size=%d)",
6818 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
6819 
6820 		return (DFC_ARG_TOOSMALL);
6821 	}
6822 	switch (dfc->data1) {
6823 	case 0:	/* SLI Registers */
6824 
6825 		if (size < (4 * sizeof (uint32_t))) {
6826 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6827 			    "%s: Buffer1 too small. (size=%d)",
6828 			    emlxs_dfc_xlate(dfc->cmd), size);
6829 
6830 			rval = DFC_ARG_TOOSMALL;
6831 			goto done;
6832 		}
6833 		size = (4 * sizeof (uint32_t));
6834 
6835 		if (size_only) {
6836 			break;
6837 		}
6838 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6839 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6840 			    "%s: Unable to allocate buffer. size=%d",
6841 			    emlxs_dfc_xlate(dfc->cmd), size);
6842 
6843 			rval = DFC_SYSRES_ERROR;
6844 			goto done;
6845 		}
6846 		wptr = (uint32_t *)buffer;
6847 
6848 		wptr[0] = READ_CSR_REG(hba, FC_HA_REG(hba, hba->csr_addr));
6849 
6850 		wptr[1] = READ_CSR_REG(hba, FC_CA_REG(hba, hba->csr_addr));
6851 
6852 		wptr[2] = READ_CSR_REG(hba, FC_HS_REG(hba, hba->csr_addr));
6853 
6854 		wptr[3] = READ_CSR_REG(hba, FC_HC_REG(hba, hba->csr_addr));
6855 
6856 		break;
6857 
6858 	case 1:	/* SLIM */
6859 
6860 		if (hba->flag & FC_SLIM2_MODE) {
6861 			size = MIN(SLI2_SLIM2_SIZE, size);
6862 		} else {
6863 			size = MIN(4096, size);
6864 		}
6865 
6866 		if (size_only) {
6867 			break;
6868 		}
6869 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6870 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6871 			    "%s: Unable to allocate buffer. size=%d",
6872 			    emlxs_dfc_xlate(dfc->cmd), size);
6873 
6874 			rval = DFC_SYSRES_ERROR;
6875 			goto done;
6876 		}
6877 		if (hba->flag & FC_SLIM2_MODE) {
6878 			memptr = (uint8_t *)hba->slim2.virt;
6879 			emlxs_pcimem_bcopy((uint32_t *)memptr,
6880 			    (uint32_t *)buffer, size);
6881 		} else {
6882 			memptr = (uint8_t *)hba->slim_addr;
6883 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
6884 			    (uint32_t *)memptr, (size / 4));
6885 		}
6886 
6887 		break;
6888 
6889 	case 2:	/* Port Control Block */
6890 
6891 		if (size < sizeof (PCB)) {
6892 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6893 			    "%s: Buffer1 too small. (size=%d)",
6894 			    emlxs_dfc_xlate(dfc->cmd), size);
6895 
6896 			rval = DFC_ARG_TOOSMALL;
6897 			goto done;
6898 		}
6899 		size = sizeof (PCB);
6900 
6901 		if (size_only) {
6902 			break;
6903 		}
6904 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6905 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6906 			    "%s: Unable to allocate buffer. size=%d",
6907 			    emlxs_dfc_xlate(dfc->cmd), size);
6908 
6909 			rval = DFC_SYSRES_ERROR;
6910 			goto done;
6911 		}
6912 		memptr = (uint8_t *)&(((SLIM2 *)hba->slim2.virt)->pcb);
6913 		emlxs_pcimem_bcopy((uint32_t *)memptr,
6914 		    (uint32_t *)buffer, size);
6915 
6916 		break;
6917 
6918 	case 3:	/* MailBox */
6919 
6920 		if (size < MAILBOX_CMD_BSIZE) {
6921 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6922 			    "%s: Buffer1 too small. (size=%d)",
6923 			    emlxs_dfc_xlate(dfc->cmd), size);
6924 
6925 			rval = DFC_ARG_TOOSMALL;
6926 			goto done;
6927 		}
6928 		size = MAILBOX_CMD_BSIZE;
6929 
6930 		if (size_only) {
6931 			break;
6932 		}
6933 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6934 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6935 			    "%s: Unable to allocate buffer. size=%d",
6936 			    emlxs_dfc_xlate(dfc->cmd), size);
6937 
6938 			rval = DFC_SYSRES_ERROR;
6939 			goto done;
6940 		}
6941 		if (hba->flag & FC_SLIM2_MODE) {
6942 			memptr = (uint8_t *)hba->slim2.virt;
6943 			emlxs_pcimem_bcopy((uint32_t *)memptr,
6944 			    (uint32_t *)buffer, size);
6945 		} else {
6946 			memptr = (uint8_t *)hba->slim_addr;
6947 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
6948 			    (uint32_t *)memptr, (size / 4));
6949 		}
6950 
6951 		break;
6952 
6953 	case 4:	/* Host Put/Get pointer array */
6954 
6955 		if (size < MAX_RINGS * sizeof (HGP)) {
6956 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6957 			    "%s: Buffer1 too small. (size=%d)",
6958 			    emlxs_dfc_xlate(dfc->cmd), size);
6959 
6960 			rval = DFC_ARG_TOOSMALL;
6961 			goto done;
6962 		}
6963 		size = MAX_RINGS * sizeof (HGP);
6964 
6965 		if (size_only) {
6966 			break;
6967 		}
6968 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
6969 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6970 			    "%s: Unable to allocate buffer. size=%d",
6971 			    emlxs_dfc_xlate(dfc->cmd), size);
6972 
6973 			rval = DFC_SYSRES_ERROR;
6974 			goto done;
6975 		} {
6976 			memptr = (uint8_t *)hba->slim_addr +
6977 			    hba->hgp_ring_offset;
6978 			READ_SLIM_COPY(hba, (uint32_t *)buffer,
6979 			    (uint32_t *)memptr, (size / 4));
6980 		}
6981 
6982 		break;
6983 
6984 	case 5:	/* Port  Get/Put pointer array */
6985 
6986 		if (size < MAX_RINGS * sizeof (PGP)) {
6987 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
6988 			    "%s: Buffer1 too small. (size=%d)",
6989 			    emlxs_dfc_xlate(dfc->cmd), size);
6990 
6991 			rval = DFC_ARG_TOOSMALL;
6992 			goto done;
6993 		}
6994 		size = MAX_RINGS * sizeof (PGP);
6995 
6996 		if (size_only) {
6997 			break;
6998 		}
6999 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
7000 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7001 			    "%s: Unable to allocate buffer. size=%d",
7002 			    emlxs_dfc_xlate(dfc->cmd), size);
7003 
7004 			rval = DFC_SYSRES_ERROR;
7005 			goto done;
7006 		}
7007 		memptr = (uint8_t *)((SLIM2 *)hba->slim2.virt)->mbx.us.s2.port;
7008 		emlxs_pcimem_bcopy((uint32_t *)memptr,
7009 		    (uint32_t *)buffer, size);
7010 
7011 		break;
7012 
7013 	case 6:	/* Command/Response Ring */
7014 
7015 		if (size < SLI_IOCB_MAX_SIZE) {
7016 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7017 			    "%s: Buffer1 too small. (size=%d)",
7018 			    emlxs_dfc_xlate(dfc->cmd), size);
7019 
7020 			rval = DFC_ARG_TOOSMALL;
7021 			goto done;
7022 		}
7023 		size = SLI_IOCB_MAX_SIZE;
7024 
7025 		if (size_only) {
7026 			break;
7027 		}
7028 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
7029 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7030 			    "%s: Unable to allocate buffer. size=%d",
7031 			    emlxs_dfc_xlate(dfc->cmd), size);
7032 
7033 			rval = DFC_SYSRES_ERROR;
7034 			goto done;
7035 		}
7036 		memptr = (uint8_t *)((SLIM2 *)hba->slim2.virt)->IOCBs;
7037 		emlxs_pcimem_bcopy((uint32_t *)memptr,
7038 		    (uint32_t *)buffer, size);
7039 
7040 		break;
7041 
7042 	case 7:	/* All driver specific structures */
7043 
7044 		if (size < sizeof (emlxs_hba_t)) {
7045 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7046 			    "%s: Buffer1 too small. (size=%d)",
7047 			    emlxs_dfc_xlate(dfc->cmd), size);
7048 
7049 			rval = DFC_ARG_TOOSMALL;
7050 			goto done;
7051 		}
7052 		size = sizeof (emlxs_hba_t);
7053 
7054 		if (size_only) {
7055 			break;
7056 		}
7057 		if (!(buffer = (uint8_t *)kmem_zalloc(size, KM_SLEEP))) {
7058 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7059 			    "%s: Unable to allocate buffer. size=%d",
7060 			    emlxs_dfc_xlate(dfc->cmd), size);
7061 
7062 			rval = DFC_SYSRES_ERROR;
7063 			goto done;
7064 		}
7065 		memptr = (uint8_t *)hba;
7066 		bcopy((void *)memptr, (void *)buffer, size);
7067 
7068 		break;
7069 
7070 	default:
7071 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7072 		    "%s: Invalid id.  id=%d",
7073 		    emlxs_dfc_xlate(dfc->cmd), dfc->data1);
7074 
7075 		rval = DFC_ARG_INVALID;
7076 	}
7077 
7078 	if (rval == 0) {
7079 		if (buffer) {
7080 			if (ddi_copyout((void *)buffer, (void *)dfc->buf1,
7081 			    size, mode) != 0) {
7082 				EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7083 				    "%s: ddi_copyout failed.",
7084 				    emlxs_dfc_xlate(dfc->cmd));
7085 
7086 				rval = DFC_COPYOUT_ERROR;
7087 				goto done;
7088 			}
7089 		}
7090 		if (ddi_copyout((void *)&size, (void *)dfc->buf2,
7091 		    sizeof (uint32_t), mode) != 0) {
7092 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7093 			    "%s: ddi_copyout failed.",
7094 			    emlxs_dfc_xlate(dfc->cmd));
7095 
7096 			rval = DFC_COPYOUT_ERROR;
7097 			goto done;
7098 		}
7099 	}
7100 done:
7101 
7102 	if (buffer) {
7103 		kmem_free(buffer, size);
7104 	}
7105 	return (rval);
7106 
7107 } /* emlxs_dfc_get_dump_region() */
7108 
7109 
7110 
7111 /*ARGSUSED*/
7112 static int32_t
7113 emlxs_dfc_loopback_mode(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7114 {
7115 	emlxs_port_t *port = &PPORT;
7116 	MAILBOXQ *mbq = NULL;
7117 	MAILBOX *mb = NULL;
7118 	uint32_t rval = DFC_SUCCESS;
7119 	uint32_t i;
7120 	uint32_t timeout;
7121 	uint32_t topology;
7122 	uint32_t new_mode;
7123 	NODELIST *ndlp;
7124 
7125 	/* Reinitialize the link */
7126 	switch (dfc->flag) {
7127 	case 0:	/* Disable */
7128 
7129 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7130 		    "%s: Disabling Loopback.",
7131 		    emlxs_dfc_xlate(dfc->cmd));
7132 
7133 		if (!(hba->flag & FC_LOOPBACK_MODE)) {
7134 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7135 			    "%s: Loopback already disabled.",
7136 			    emlxs_dfc_xlate(dfc->cmd));
7137 
7138 			return (0);
7139 		}
7140 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
7141 
7142 		return (0);
7143 
7144 	case 1:	/* Internal loopback */
7145 		new_mode = FC_ILB_MODE;
7146 		topology = FLAGS_LOCAL_LB;
7147 
7148 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7149 		    "%s: Enabling ILB.",
7150 		    emlxs_dfc_xlate(dfc->cmd));
7151 
7152 		/* Check if mode already set */
7153 		if ((hba->flag & FC_ILB_MODE)) {
7154 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7155 			    "%s: ILB mode already enabled.",
7156 			    emlxs_dfc_xlate(dfc->cmd));
7157 
7158 			return (0);
7159 		}
7160 		break;
7161 
7162 	case 2:	/* External loopback */
7163 		new_mode = FC_ELB_MODE;
7164 		topology = FLAGS_TOPOLOGY_MODE_LOOP;
7165 
7166 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7167 		    "%s: Enabling ELB.",
7168 		    emlxs_dfc_xlate(dfc->cmd));
7169 
7170 		/* Check if mode already set */
7171 		if ((hba->flag & FC_ELB_MODE)) {
7172 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7173 			    "%s: ELB mode already enabled.",
7174 			    emlxs_dfc_xlate(dfc->cmd));
7175 
7176 			return (0);
7177 		}
7178 		break;
7179 
7180 	default:
7181 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7182 		    "%s: Invalid loopback mode. (mode=%x)",
7183 		    emlxs_dfc_xlate(dfc->cmd), dfc->flag);
7184 
7185 		return (DFC_ARG_INVALID);
7186 	}
7187 
7188 	/* Make sure adapter is online */
7189 	if (emlxs_online(hba)) {
7190 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7191 		    "%s: Unable to bring adapter online.",
7192 		    emlxs_dfc_xlate(dfc->cmd));
7193 
7194 		return (DFC_OFFLINE_ERROR);
7195 	}
7196 	if ((mbq = (MAILBOXQ *)kmem_zalloc(sizeof (MAILBOXQ), KM_SLEEP)) == 0) {
7197 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7198 		    "%s: Unable to allocate mailbox buffer.",
7199 		    emlxs_dfc_xlate(dfc->cmd));
7200 
7201 		return (DFC_SYSRES_ERROR);
7202 	}
7203 	mb = (MAILBOX *)mbq;
7204 
7205 	/* Take the link down */
7206 	emlxs_mb_down_link(hba, mb);
7207 
7208 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
7209 
7210 	if (rval == MBX_TIMEOUT) {
7211 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7212 		    "%s: Mailbox timed out. cmd=%x",
7213 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
7214 
7215 		rval = DFC_TIMEOUT;
7216 		goto done;
7217 	}
7218 	if (rval) {
7219 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7220 		    "%s: %s failed. status=%x",
7221 		    emlxs_dfc_xlate(dfc->cmd),
7222 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
7223 
7224 		rval = DFC_IO_ERROR;
7225 		goto done;
7226 	}
7227 	/* Reinitialize the link */
7228 	emlxs_mb_init_link(hba, mb, topology, 0);
7229 
7230 	/* Set the loopback mode and timer */
7231 	mutex_enter(&EMLXS_PORT_LOCK);
7232 	hba->flag |= new_mode;
7233 	hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
7234 	mutex_exit(&EMLXS_PORT_LOCK);
7235 
7236 	rval = emlxs_mb_issue_cmd(hba, mb, MBX_WAIT, 0);
7237 
7238 	if (rval == MBX_TIMEOUT) {
7239 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7240 		    "%s: Mailbox timed out. cmd=%x",
7241 		    emlxs_dfc_xlate(dfc->cmd), mb->mbxCommand);
7242 
7243 		rval = DFC_TIMEOUT;
7244 		goto done;
7245 	}
7246 	if (rval) {
7247 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7248 		    "%s: %s failed. status=%x",
7249 		    emlxs_dfc_xlate(dfc->cmd),
7250 		    emlxs_mb_cmd_xlate(mb->mbxCommand), rval);
7251 
7252 		rval = DFC_IO_ERROR;
7253 		goto done;
7254 	}
7255 	/* Wait for adapter to come online */
7256 	timeout = dfc->data1;
7257 	if (!timeout) {
7258 		timeout = 60;
7259 	}
7260 	i = 0;
7261 	while ((hba->state < FC_LINK_UP) && (hba->state != FC_ERROR)) {
7262 		delay(drv_usectohz(500000));
7263 		i++;
7264 
7265 		if (i == timeout) {
7266 			rval = DFC_TIMEOUT;
7267 
7268 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7269 			    "%s: Linkup timeout.",
7270 			    emlxs_dfc_xlate(dfc->cmd));
7271 
7272 			goto done;
7273 		}
7274 	}
7275 
7276 
7277 	/* Create host node */
7278 	if (emlxs_mb_reg_did(port, port->did, (SERV_PARM *)&hba->sparam,
7279 	    NULL, NULL, NULL)) {
7280 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7281 		    "%s: Unable to register host node.",
7282 		    emlxs_dfc_xlate(dfc->cmd));
7283 
7284 		rval = DFC_DRV_ERROR;
7285 		goto done;
7286 	}
7287 	i = 0;
7288 	do {
7289 		if (i++ > 300) {
7290 			break;
7291 		}
7292 		delay(drv_usectohz(100000));
7293 
7294 	} while (!(ndlp = emlxs_node_find_did(port, port->did)));
7295 
7296 	if (!ndlp) {
7297 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7298 		    "%s: Unable to create host node.",
7299 		    emlxs_dfc_xlate(dfc->cmd));
7300 
7301 		rval = DFC_DRV_ERROR;
7302 		goto done;
7303 	}
7304 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7305 	    "%s: Node created. node=%p",
7306 	    emlxs_dfc_xlate(dfc->cmd), ndlp);
7307 
7308 
7309 	/* Create host XRI */
7310 	(void) emlxs_create_xri(port, &hba->ring[FC_CT_RING], ndlp);
7311 
7312 	i = 0;
7313 	do {
7314 		if (i++ > 300) {
7315 			break;
7316 		}
7317 		delay(drv_usectohz(100000));
7318 
7319 	} while (!ndlp->nlp_Xri);
7320 
7321 	if (!ndlp->nlp_Xri) {
7322 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7323 		    "%s: Unable to create XRI.",
7324 		    emlxs_dfc_xlate(dfc->cmd));
7325 
7326 		rval = DFC_DRV_ERROR;
7327 		goto done;
7328 	}
7329 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7330 	    "%s: XRI created. xri=%x",
7331 	    emlxs_dfc_xlate(dfc->cmd), ndlp->nlp_Xri);
7332 
7333 
7334 done:
7335 
7336 	/* Free allocated mbox memory */
7337 	if (mbq) {
7338 		kmem_free(mbq, sizeof (MAILBOXQ));
7339 	}
7340 	if (rval) {
7341 		/* Reset the adapter */
7342 		(void) emlxs_reset(port, FC_FCA_RESET);
7343 	}
7344 	return (rval);
7345 
7346 } /* emlxs_dfc_loopback_mode() */
7347 
7348 
7349 static int32_t
7350 emlxs_dfc_loopback_test(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7351 {
7352 	emlxs_port_t *port = &PPORT;
7353 	uint32_t rval = 0;
7354 	/* uint32_t i; */
7355 	NODELIST *ndlp;
7356 	clock_t timeout;
7357 	/* uint32_t tics_timeout; */
7358 	fc_packet_t *pkt = NULL;
7359 	SLI_CT_REQUEST *CtCmd;
7360 	uint16_t CtRsp;
7361 
7362 	mutex_enter(&EMLXS_PORT_LOCK);
7363 	if (!(hba->flag & FC_LOOPBACK_MODE)) {
7364 		mutex_exit(&EMLXS_PORT_LOCK);
7365 
7366 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7367 		    "%s: Adapter not in loopback mode.",
7368 		    emlxs_dfc_xlate(dfc->cmd));
7369 
7370 		rval = DFC_DRV_ERROR;
7371 		goto done;
7372 	}
7373 	hba->loopback_tics = hba->timer_tics + emlxs_loopback_tmo;
7374 	mutex_exit(&EMLXS_PORT_LOCK);
7375 
7376 	if (!(hba->flag & FC_ONLINE_MODE)) {
7377 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7378 		    "%s: Adapter offline.",
7379 		    emlxs_dfc_xlate(dfc->cmd));
7380 
7381 		rval = DFC_OFFLINE_ERROR;
7382 		goto done;
7383 	}
7384 	if (hba->state < FC_LINK_UP) {
7385 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7386 		    "%s: Link not up.",
7387 		    emlxs_dfc_xlate(dfc->cmd));
7388 
7389 		rval = DFC_OFFLINE_ERROR;
7390 		goto done;
7391 	}
7392 	if (!dfc->buf1 || !dfc->buf1_size) {
7393 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7394 		    "%s: NULL buffer1 found.",
7395 		    emlxs_dfc_xlate(dfc->cmd));
7396 
7397 		rval = DFC_ARG_NULL;
7398 		goto done;
7399 	}
7400 	if (!dfc->buf2 || !dfc->buf2_size) {
7401 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7402 		    "%s: NULL buffer2 found.",
7403 		    emlxs_dfc_xlate(dfc->cmd));
7404 
7405 		rval = DFC_ARG_NULL;
7406 		goto done;
7407 	}
7408 	if (dfc->buf1_size > MAX_CT_PAYLOAD) {
7409 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7410 		    "%s: Buffer1 too large. (size=%d)",
7411 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7412 
7413 		rval = DFC_ARG_TOOBIG;
7414 		goto done;
7415 	}
7416 	/* Check if we have a node for ourselves */
7417 	ndlp = emlxs_node_find_did(port, port->did);
7418 
7419 	if (!ndlp) {
7420 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7421 		    "%s: Host node not found.",
7422 		    emlxs_dfc_xlate(dfc->cmd));
7423 
7424 		rval = DFC_ARG_INVALID;
7425 		goto done;
7426 	}
7427 	if (!ndlp->nlp_Xri) {
7428 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7429 		    "%s: Host XRI not found.",
7430 		    emlxs_dfc_xlate(dfc->cmd));
7431 
7432 		rval = DFC_DRV_ERROR;
7433 		goto done;
7434 	}
7435 	if (!(pkt = emlxs_pkt_alloc(port, dfc->buf1_size + 16,
7436 	    dfc->buf2_size + 16, 0, KM_SLEEP))) {
7437 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7438 		    "%s: Unable to allocate pkt.",
7439 		    emlxs_dfc_xlate(dfc->cmd));
7440 
7441 		rval = DFC_SYSRES_ERROR;
7442 		goto done;
7443 	}
7444 	CtCmd = (SLI_CT_REQUEST *)pkt->pkt_cmd;
7445 	CtRsp = SLI_CT_LOOPBACK;
7446 	CtCmd->CommandResponse.bits.CmdRsp = SWAP_DATA16(CtRsp);
7447 
7448 	if (ddi_copyin((void *)dfc->buf1, (void *)&CtCmd->un.data,
7449 	    dfc->buf1_size, mode) != 0) {
7450 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7451 		    "%s: ddi_copyin failed.",
7452 		    emlxs_dfc_xlate(dfc->cmd));
7453 
7454 		rval = DFC_COPYIN_ERROR;
7455 		goto done;
7456 	}
7457 	pkt->pkt_tran_type = FC_PKT_OUTBOUND;
7458 	pkt->pkt_timeout = 2 * hba->fc_ratov;
7459 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
7460 	pkt->pkt_comp = NULL;
7461 
7462 	pkt->pkt_cmd_fhdr.d_id = port->did;
7463 	pkt->pkt_cmd_fhdr.r_ctl = FC_SOL_CTL;
7464 	pkt->pkt_cmd_fhdr.s_id = port->did;
7465 	pkt->pkt_cmd_fhdr.type = FC_CT_TYPE;
7466 	pkt->pkt_cmd_fhdr.f_ctl = 0;
7467 	pkt->pkt_cmd_fhdr.seq_id = 0;
7468 	pkt->pkt_cmd_fhdr.df_ctl = 0;
7469 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
7470 	pkt->pkt_cmd_fhdr.ox_id = 0xffff;
7471 	pkt->pkt_cmd_fhdr.rx_id = ndlp->nlp_Xri;
7472 	pkt->pkt_cmd_fhdr.ro = 0;
7473 
7474 	mutex_enter(&EMLXS_PKT_LOCK);
7475 	timeout = emlxs_timeout(hba, (pkt->pkt_timeout + 15));
7476 
7477 	if (hba->loopback_pkt) {
7478 		rval = 0;
7479 		while ((rval != -1) && hba->loopback_pkt) {
7480 			rval = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK,
7481 			    timeout);
7482 		}
7483 
7484 		if (rval == -1) {
7485 			mutex_exit(&EMLXS_PKT_LOCK);
7486 
7487 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7488 			    "Loopback busy timeout.");
7489 			rval = DFC_TIMEOUT;
7490 			goto done;
7491 		}
7492 	}
7493 	hba->loopback_pkt = (void *)pkt;
7494 	mutex_exit(&EMLXS_PKT_LOCK);
7495 
7496 	/* Send polled command */
7497 	if ((rval = emlxs_pkt_send(pkt, 1)) != FC_SUCCESS) {
7498 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7499 		    "Pkt Transport error. ret=%x state=%x",
7500 		    rval, pkt->pkt_state);
7501 
7502 		rval = DFC_IO_ERROR;
7503 		goto done;
7504 	}
7505 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
7506 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
7507 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7508 			    "Pkt Transport error. Pkt Timeout.");
7509 			rval = DFC_TIMEOUT;
7510 		} else {
7511 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7512 			    "Pkt Transport error. state=%x",
7513 			    pkt->pkt_state);
7514 			rval = DFC_IO_ERROR;
7515 		}
7516 		goto done;
7517 	}
7518 	/* Wait for sequence completion */
7519 	mutex_enter(&EMLXS_PKT_LOCK);
7520 	rval = 0;
7521 	while ((rval != -1) && !(pkt->pkt_tran_flags & FC_TRAN_COMPLETED)) {
7522 		rval = cv_timedwait(&EMLXS_PKT_CV, &EMLXS_PKT_LOCK, timeout);
7523 	}
7524 	mutex_exit(&EMLXS_PKT_LOCK);
7525 
7526 	if (rval == -1) {
7527 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7528 		    "Loopback sequence timeout.");
7529 
7530 		rval = DFC_TIMEOUT;
7531 		goto done;
7532 	}
7533 	CtCmd = (SLI_CT_REQUEST *)pkt->pkt_resp;
7534 
7535 	if (ddi_copyout((void *)&CtCmd->un.data, (void *)dfc->buf2,
7536 	    dfc->buf2_size, mode) != 0) {
7537 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7538 		    "%s: ddi_copyout failed.",
7539 		    emlxs_dfc_xlate(dfc->cmd));
7540 
7541 		rval = DFC_COPYOUT_ERROR;
7542 		goto done;
7543 	}
7544 	rval = 0;
7545 
7546 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg,
7547 	    "%s: Test completed.",
7548 	    emlxs_dfc_xlate(dfc->cmd));
7549 
7550 done:
7551 
7552 	if (rval) {
7553 		mutex_enter(&EMLXS_PKT_LOCK);
7554 		if (pkt && (hba->loopback_pkt == pkt)) {
7555 			hba->loopback_pkt = NULL;
7556 		}
7557 		mutex_exit(&EMLXS_PKT_LOCK);
7558 
7559 		/* Reset the adapter */
7560 		(void) emlxs_reset(port, FC_FCA_LINK_RESET);
7561 	}
7562 	if (pkt) {
7563 		emlxs_pkt_free(pkt);
7564 	}
7565 	return (rval);
7566 
7567 } /* emlxs_dfc_loopback_test() */
7568 
7569 
7570 extern int32_t
7571 emlxs_dfc_handle_event(emlxs_hba_t *hba, RING *rp, IOCBQ * iocbq)
7572 {
7573 	emlxs_port_t *port = &PPORT;
7574 	IOCB *cmd;
7575 	emlxs_buf_t *sbp;
7576 	/* NODELIST *ndlp; */
7577 
7578 	cmd = &iocbq->iocb;
7579 
7580 	HBASTATS.CtEvent++;
7581 
7582 	sbp = (emlxs_buf_t *)iocbq->sbp;
7583 
7584 	if (!sbp) {
7585 		HBASTATS.CtStray++;
7586 
7587 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7588 		    "Stray interrupt. cmd=0x%x iotag=0x%x"
7589 		    " status=0x%x perr=0x%x",
7590 		    (uint32_t)cmd->ulpCommand,
7591 		    (uint32_t)cmd->ulpIoTag,
7592 		    cmd->ulpStatus, cmd->un.ulpWord[4]);
7593 
7594 		return (DFC_ARG_INVALID);
7595 	}
7596 	if (rp->ringno != FC_CT_RING) {
7597 		HBASTATS.CtStray++;
7598 
7599 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7600 		    "CT Event: Invalid ring: ring=%d iocbq=%p",
7601 		    rp->ringno, iocbq);
7602 
7603 		return (DFC_ARG_INVALID);
7604 	}
7605 	switch (cmd->ulpCommand) {
7606 	case CMD_XMIT_SEQUENCE_CR:
7607 	case CMD_XMIT_SEQUENCE64_CR:
7608 	case CMD_XMIT_SEQUENCE_CX:
7609 	case CMD_XMIT_SEQUENCE64_CX:
7610 
7611 		HBASTATS.CtCmdCompleted++;
7612 
7613 		if (cmd->ulpStatus == 0) {
7614 			HBASTATS.CtCmdGood++;
7615 
7616 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7617 			    "XMIT_SEQUENCE comp: status=0x%x",
7618 			    cmd->ulpStatus);
7619 		} else {
7620 			HBASTATS.CtCmdError++;
7621 
7622 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7623 			    "XMIT_SEQUENCE comp: status=0x%x [%08x,%08x]",
7624 			    cmd->ulpStatus, cmd->un.ulpWord[4],
7625 			    cmd->un.ulpWord[5]);
7626 		}
7627 
7628 		emlxs_pkt_complete(sbp, cmd->ulpStatus,
7629 		    cmd->un.grsp.perr.statLocalError, 1);
7630 
7631 		break;
7632 
7633 	default:
7634 
7635 		HBASTATS.CtStray++;
7636 
7637 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7638 		    "Invalid iocb: cmd=0x%x",
7639 		    cmd->ulpCommand);
7640 
7641 		emlxs_pkt_complete(sbp, cmd->ulpStatus,
7642 		    cmd->un.grsp.perr.statLocalError, 1);
7643 
7644 		break;
7645 
7646 	}	/* switch(cmd->ulpCommand) */
7647 
7648 	return (0);
7649 
7650 } /* emlxs_dfc_handle_event() */
7651 
7652 
7653 /*ARGSUSED*/
7654 extern int
7655 emlxs_dfc_handle_unsol_req(emlxs_port_t *port, RING *rp,
7656 	IOCBQ *iocbq, MATCHMAP *mp, uint32_t size)
7657 {
7658 	emlxs_hba_t *hba = HBA;
7659 	IOCB *iocb;
7660 	uint8_t *bp;
7661 	/* dfc_t *dfc; */
7662 	fc_packet_t *pkt;
7663 
7664 	iocb = &iocbq->iocb;
7665 	bp = (uint8_t *)mp->virt;
7666 
7667 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7668 	    "CT Receive: cmd=%x status=0x%x ",
7669 	    iocb->ulpCommand, iocb->ulpStatus);
7670 
7671 	/*
7672 	 * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_debug_msg, "CT Receive:
7673 	 * payload=%p size=%d [%02x,%02x, %02x, %02x]", bp, size, bp[0],
7674 	 * bp[1], bp[2],bp[3]);
7675 	 */
7676 
7677 	/* Return payload */
7678 	mutex_enter(&EMLXS_PKT_LOCK);
7679 	if (hba->loopback_pkt) {
7680 		pkt = (fc_packet_t *)hba->loopback_pkt;
7681 		hba->loopback_pkt = NULL;
7682 
7683 		size = MIN(size, pkt->pkt_rsplen);
7684 		bcopy(bp, pkt->pkt_resp, size);
7685 		pkt->pkt_tran_flags |= FC_TRAN_COMPLETED;
7686 
7687 		cv_broadcast(&EMLXS_PKT_CV);
7688 	}
7689 	mutex_exit(&EMLXS_PKT_LOCK);
7690 
7691 	return (0);
7692 
7693 } /* emlxs_dfc_handle_unsol_req() */
7694 
7695 
7696 #ifdef DHCHAP_SUPPORT
7697 
7698 static int32_t
7699 emlxs_dfc_init_auth(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7700 {
7701 	emlxs_port_t *port = &PPORT;
7702 	uint8_t lwwpn[8];
7703 	uint8_t rwwpn[8];
7704 	int32_t rval = 0;
7705 
7706 	/*
7707 	 * dfc.cmd = EMLXS_INIT_AUTH; dfc.buf1_size = 8; dfc.buf1
7708 	 * = lwwpn; dfc.buf2_size = 8; dfc.buf2 = rwwpn;
7709 	 */
7710 
7711 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7712 	    "%s requested.",
7713 	    emlxs_dfc_xlate(dfc->cmd));
7714 
7715 	if (!dfc->buf1 || !dfc->buf1_size) {
7716 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7717 		    "%s: Null buffer1 found.",
7718 		    emlxs_dfc_xlate(dfc->cmd));
7719 
7720 		return (DFC_ARG_NULL);
7721 	}
7722 	if (dfc->buf1_size < 8) {
7723 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7724 		    "%s: Buffer1 too small. (size=%d)",
7725 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7726 
7727 		return (DFC_ARG_TOOSMALL);
7728 	}
7729 	if (!dfc->buf2 || !dfc->buf2_size) {
7730 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7731 		    "%s: Null buffer2 found.",
7732 		    emlxs_dfc_xlate(dfc->cmd));
7733 
7734 		return (DFC_ARG_NULL);
7735 	}
7736 	if (dfc->buf2_size < 8) {
7737 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7738 		    "%s: Buffer2 too small. (size=%d)",
7739 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7740 
7741 		return (DFC_ARG_TOOSMALL);
7742 	}
7743 	/* Read the lwwpn */
7744 	if (ddi_copyin((void *)dfc->buf1, (void *)&lwwpn,
7745 	    8, mode) != 0) {
7746 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7747 		    "%s: ddi_copyin failed.",
7748 		    emlxs_dfc_xlate(dfc->cmd));
7749 
7750 		return (DFC_COPYIN_ERROR);
7751 	}
7752 	/* Read the rwwpn */
7753 	if (ddi_copyin((void *)dfc->buf2, (void *)&rwwpn,
7754 	    8, mode) != 0) {
7755 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7756 		    "%s: ddi_copyin failed.",
7757 		    emlxs_dfc_xlate(dfc->cmd));
7758 
7759 		return (DFC_COPYIN_ERROR);
7760 	}
7761 	/* Initiate authentication here */
7762 	rval = emlxs_dhc_init_auth(hba, lwwpn, rwwpn);
7763 
7764 	return (rval);
7765 
7766 } /* emlxs_dfc_init_auth() */
7767 
7768 
7769 static int32_t
7770 emlxs_dfc_get_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7771 {
7772 	emlxs_port_t *port = &PPORT;
7773 	dfc_fcsp_config_t fcsp_config;
7774 	uint32_t rval = DFC_SUCCESS;
7775 
7776 	/*
7777 	 * dfc.cmd = EMLXS_GET_AUTH_CFG; dfc.buf1_size =
7778 	 * sizeof(dfc_fcsp_config_t); dfc.buf1 = config;
7779 	 */
7780 
7781 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7782 	    "%s requested.",
7783 	    emlxs_dfc_xlate(dfc->cmd));
7784 
7785 	if (!dfc->buf1 || !dfc->buf1_size) {
7786 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7787 		    "%s: Null buffer1 found.",
7788 		    emlxs_dfc_xlate(dfc->cmd));
7789 
7790 		return (DFC_ARG_NULL);
7791 	}
7792 	if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
7793 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7794 		    "%s: Buffer1 too small. (size=%d)",
7795 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7796 
7797 		return (DFC_ARG_TOOSMALL);
7798 	}
7799 	/* Read the fcsp_config */
7800 	if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_config,
7801 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
7802 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7803 		    "%s: ddi_copyin failed.",
7804 		    emlxs_dfc_xlate(dfc->cmd));
7805 
7806 		return (DFC_COPYIN_ERROR);
7807 	}
7808 	if ((rval = emlxs_dhc_get_auth_cfg(hba, &fcsp_config)) != 0) {
7809 		return (rval);
7810 	}
7811 	if (ddi_copyout((void *)&fcsp_config, (void *)dfc->buf1,
7812 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
7813 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7814 		    "%s: ddi_copyout failed.",
7815 		    emlxs_dfc_xlate(dfc->cmd));
7816 
7817 	}
7818 	return (0);
7819 
7820 } /* emlxs_dfc_get_auth_cfg() */
7821 
7822 
7823 
7824 static int32_t
7825 emlxs_dfc_set_auth_cfg(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7826 {
7827 	emlxs_port_t *port = &PPORT;
7828 	dfc_fcsp_config_t fcsp_config;
7829 	dfc_password_t dfc_pwd;
7830 	uint32_t rval = DFC_SUCCESS;
7831 
7832 
7833 	/*
7834 	 * dfc.cmd = EMLXS_SET_AUTH_CFG; dfc.flag =
7835 	 * EMLXS_AUTH_CFG_ADD; dfc.buf1_size = sizeof(dfc_fcsp_config_t);
7836 	 * dfc.buf1 = config; dfc.buf2_size = sizeof(dfc_password_t);
7837 	 * dfc.buf2 = password;
7838 	 */
7839 
7840 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7841 	    "%s requested.",
7842 	    emlxs_dfc_xlate(dfc->cmd));
7843 
7844 	if (!dfc->buf1 || !dfc->buf1_size) {
7845 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7846 		    "%s: Null buffer1 found.",
7847 		    emlxs_dfc_xlate(dfc->cmd));
7848 
7849 		return (DFC_ARG_NULL);
7850 	}
7851 	if (dfc->buf1_size < sizeof (dfc_fcsp_config_t)) {
7852 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7853 		    "%s: Buffer1 too small. (size=%d)",
7854 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7855 
7856 		return (DFC_ARG_TOOSMALL);
7857 	}
7858 	if (!dfc->buf2 || !dfc->buf2_size) {
7859 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7860 		    "%s: Null buffer2 found.",
7861 		    emlxs_dfc_xlate(dfc->cmd));
7862 
7863 		return (DFC_ARG_NULL);
7864 	}
7865 	if (dfc->buf2_size < sizeof (dfc_password_t)) {
7866 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7867 		    "%s: Buffer2 too small. (size=%d)",
7868 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7869 
7870 		return (DFC_ARG_TOOSMALL);
7871 	}
7872 	/* Read the fcsp_config */
7873 	if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_config,
7874 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
7875 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7876 		    "%s: ddi_copyin failed.",
7877 		    emlxs_dfc_xlate(dfc->cmd));
7878 
7879 		return (DFC_COPYIN_ERROR);
7880 	}
7881 	/* Read the password */
7882 	if (ddi_copyin((void *)dfc->buf2, (void *)&dfc_pwd,
7883 	    sizeof (dfc_password_t), mode) != 0) {
7884 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7885 		    "%s: ddi_copyin failed.",
7886 		    emlxs_dfc_xlate(dfc->cmd));
7887 
7888 		return (DFC_COPYIN_ERROR);
7889 	}
7890 	switch (dfc->flag) {
7891 	case EMLXS_AUTH_CFG_ADD:
7892 		rval = emlxs_dhc_add_auth_cfg(hba, &fcsp_config, &dfc_pwd);
7893 		break;
7894 
7895 	case EMLXS_AUTH_CFG_DELETE:
7896 		rval = emlxs_dhc_delete_auth_cfg(hba, &fcsp_config, &dfc_pwd);
7897 		break;
7898 	}
7899 
7900 	if (rval) {
7901 		return (rval);
7902 	}
7903 	if (ddi_copyout((void *)&fcsp_config, (void *)dfc->buf1,
7904 	    sizeof (dfc_fcsp_config_t), mode) != 0) {
7905 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7906 		    "%s: ddi_copyout failed.",
7907 		    emlxs_dfc_xlate(dfc->cmd));
7908 
7909 		return (DFC_COPYOUT_ERROR);
7910 	}
7911 	return (0);
7912 
7913 } /* emlxs_dfc_set_auth_cfg() */
7914 
7915 
7916 
7917 static int32_t
7918 emlxs_dfc_get_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7919 {
7920 	emlxs_port_t *port = &PPORT;
7921 	dfc_auth_password_t dfc_pwd;
7922 	uint32_t rval = DFC_SUCCESS;
7923 
7924 
7925 	/*
7926 	 * dfc.cmd = EMLXS_GET_AUTH_PASSWORD; dfc.buf1_size =
7927 	 * sizeof(dfc_auth_password_t); dfc.buf1 = auth_password;
7928 	 */
7929 
7930 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7931 	    "%s requested.",
7932 	    emlxs_dfc_xlate(dfc->cmd));
7933 
7934 	if (!dfc->buf1 || !dfc->buf1_size) {
7935 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7936 		    "%s: Null buffer1 found.",
7937 		    emlxs_dfc_xlate(dfc->cmd));
7938 
7939 		return (DFC_ARG_NULL);
7940 	}
7941 	if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
7942 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7943 		    "%s: Buffer1 too small. (size=%d)",
7944 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
7945 
7946 		return (DFC_ARG_TOOSMALL);
7947 	}
7948 	/* Read the auth password */
7949 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_pwd,
7950 	    sizeof (dfc_auth_password_t), mode) != 0) {
7951 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7952 		    "%s: ddi_copyin failed.",
7953 		    emlxs_dfc_xlate(dfc->cmd));
7954 
7955 		return (DFC_COPYIN_ERROR);
7956 	}
7957 	if ((rval = emlxs_dhc_get_auth_key(hba, &dfc_pwd)) != 0) {
7958 		return (rval);
7959 	}
7960 	if (ddi_copyout((void *)&dfc_pwd, (void *)dfc->buf1,
7961 	    sizeof (dfc_auth_password_t), mode) != 0) {
7962 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7963 		    "%s: ddi_copyout failed.",
7964 		    emlxs_dfc_xlate(dfc->cmd));
7965 
7966 		return (DFC_COPYOUT_ERROR);
7967 	}
7968 	return (0);
7969 
7970 } /* emlxs_dfc_get_auth_pwd() */
7971 
7972 
7973 static int32_t
7974 emlxs_dfc_set_auth_pwd(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
7975 {
7976 	emlxs_port_t *port = &PPORT;
7977 	dfc_auth_password_t dfc_pwd;
7978 	uint32_t rval = DFC_SUCCESS;
7979 
7980 	/*
7981 	 * dfc.cmd = EMLXS_SET_AUTH_PASSWORD; dfc.buf1_size =
7982 	 * sizeof(dfc_auth_password_t); dfc.buf1 = auth_password;
7983 	 */
7984 
7985 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
7986 	    "%s requested.",
7987 	    emlxs_dfc_xlate(dfc->cmd));
7988 
7989 	if (!dfc->buf1 || !dfc->buf1_size) {
7990 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7991 		    "%s: Null buffer1 found.",
7992 		    emlxs_dfc_xlate(dfc->cmd));
7993 
7994 		return (DFC_ARG_NULL);
7995 	}
7996 	if (dfc->buf1_size < sizeof (dfc_auth_password_t)) {
7997 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
7998 		    "%s: Buffer1 too small. (size=%d)",
7999 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8000 
8001 		return (DFC_ARG_TOOSMALL);
8002 	}
8003 	/* Read the auth password */
8004 	if (ddi_copyin((void *)dfc->buf1, (void *)&dfc_pwd,
8005 	    sizeof (dfc_auth_password_t), mode) != 0) {
8006 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8007 		    "%s: ddi_copyin failed.",
8008 		    emlxs_dfc_xlate(dfc->cmd));
8009 
8010 		return (DFC_COPYIN_ERROR);
8011 	}
8012 	if ((rval = emlxs_dhc_set_auth_key(hba, &dfc_pwd))) {
8013 		return (rval);
8014 	}
8015 	if (ddi_copyout((void *)&dfc_pwd, (void *)dfc->buf1,
8016 	    sizeof (dfc_auth_password_t), mode) != 0) {
8017 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8018 		    "%s: ddi_copyout failed.",
8019 		    emlxs_dfc_xlate(dfc->cmd));
8020 
8021 		return (DFC_COPYOUT_ERROR);
8022 	}
8023 	return (0);
8024 
8025 } /* emlxs_dfc_set_auth_pwd() */
8026 
8027 
8028 static int32_t
8029 emlxs_dfc_get_auth_status(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8030 {
8031 	emlxs_port_t *port = &PPORT;
8032 	dfc_auth_status_t fcsp_status;
8033 	uint32_t rval = DFC_SUCCESS;
8034 
8035 	/*
8036 	 * dfc.cmd = EMLXS_GET_AUTH_STATUS; dfc.buf1_size =
8037 	 * sizeof(dfc_auth_status_t); dfc.buf1 = status;
8038 	 */
8039 
8040 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8041 	    "%s requested.",
8042 	    emlxs_dfc_xlate(dfc->cmd));
8043 
8044 	if (!dfc->buf1 || !dfc->buf1_size) {
8045 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8046 		    "%s: Null buffer1 found.",
8047 		    emlxs_dfc_xlate(dfc->cmd));
8048 
8049 		return (DFC_ARG_NULL);
8050 	}
8051 	if (dfc->buf1_size < sizeof (dfc_auth_status_t)) {
8052 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8053 		    "%s: Buffer too small. (size=%d)",
8054 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf1_size);
8055 
8056 		return (DFC_ARG_TOOSMALL);
8057 	}
8058 	/* Read the fcsp_config */
8059 	if (ddi_copyin((void *)dfc->buf1, (void *)&fcsp_status,
8060 	    sizeof (dfc_auth_status_t), mode) != 0) {
8061 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8062 		    "%s: ddi_copyin failed.",
8063 		    emlxs_dfc_xlate(dfc->cmd));
8064 
8065 		return (DFC_COPYIN_ERROR);
8066 	}
8067 	if ((rval = emlxs_dhc_get_auth_status(hba, &fcsp_status)) != 0) {
8068 		return (rval);
8069 	}
8070 	if (ddi_copyout((void *)&fcsp_status, (void *)dfc->buf1,
8071 	    sizeof (dfc_auth_status_t), mode) != 0) {
8072 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8073 		    "%s: ddi_copyout failed.",
8074 		    emlxs_dfc_xlate(dfc->cmd));
8075 
8076 		return (DFC_COPYOUT_ERROR);
8077 	}
8078 	return (0);
8079 
8080 } /* emlxs_dfc_get_auth_status() */
8081 
8082 
8083 static int32_t
8084 emlxs_dfc_get_auth_cfg_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8085 {
8086 	emlxs_port_t *port = &PPORT;
8087 	dfc_fcsp_config_t *fcsp_cfg;
8088 	uint32_t count;
8089 	uint32_t size;
8090 	uint32_t rval = DFC_SUCCESS;
8091 	/* uint32_t count_sent = 0; */
8092 
8093 	/*
8094 	 * dfc.cmd = EMLXS_GET_AUTH_CFG_TABLE; dfc.buf1_size = size;
8095 	 * dfc.buf1 = fcsp_cfg; dfc.buf2_size = sizeof(uint32_t);
8096 	 * dfc.buf2 = &count;
8097 	 */
8098 
8099 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8100 	    "%s requested.",
8101 	    emlxs_dfc_xlate(dfc->cmd));
8102 
8103 	/* Lock cfg table while we do this */
8104 	/* This prevents the table from changing while we get a copy */
8105 	mutex_enter(&hba->auth_lock);
8106 
8107 	if (!dfc->buf2 || !dfc->buf2_size) {
8108 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8109 		    "%s: Null buffer2 found.",
8110 		    emlxs_dfc_xlate(dfc->cmd));
8111 
8112 		mutex_exit(&hba->auth_lock);
8113 		return (DFC_ARG_NULL);
8114 	}
8115 	if (dfc->buf2_size < sizeof (uint32_t)) {
8116 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8117 		    "%s: Buffer2 too small. (size=%d)",
8118 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
8119 
8120 		mutex_exit(&hba->auth_lock);
8121 		return (DFC_ARG_TOOSMALL);
8122 	}
8123 	if (ddi_copyout((void *)&hba->auth_cfg_count, (void *)dfc->buf2,
8124 	    sizeof (uint32_t), mode) != 0) {
8125 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8126 		    "%s: ddi_copyout failed for table count. count=%d",
8127 		    emlxs_dfc_xlate(dfc->cmd), hba->auth_cfg_count);
8128 
8129 		mutex_exit(&hba->auth_lock);
8130 		return (DFC_COPYOUT_ERROR);
8131 	}
8132 	if (!dfc->buf1 || !dfc->buf1_size) {
8133 		mutex_exit(&hba->auth_lock);
8134 		return (DFC_SUCCESS);
8135 	}
8136 	/* Check table size */
8137 	count = dfc->buf1_size / sizeof (dfc_fcsp_config_t);
8138 	if (count < hba->auth_cfg_count) {
8139 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8140 		    "%s: Buffer1 too small. (%d < %d)",
8141 		    emlxs_dfc_xlate(dfc->cmd), count,
8142 		    hba->auth_cfg_count);
8143 
8144 		mutex_exit(&hba->auth_lock);
8145 		return (DFC_ARG_TOOSMALL);
8146 	}
8147 	size = hba->auth_cfg_count * sizeof (dfc_fcsp_config_t);
8148 	if (!(fcsp_cfg = (dfc_fcsp_config_t *)kmem_zalloc(size, KM_SLEEP))) {
8149 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8150 		    "%s: Unable to allocate table buffer.",
8151 		    emlxs_dfc_xlate(dfc->cmd));
8152 
8153 		mutex_exit(&hba->auth_lock);
8154 		return (DFC_SYSRES_ERROR);
8155 	}
8156 	if ((rval = emlxs_dhc_get_auth_cfg_table(hba, fcsp_cfg)) != 0) {
8157 		mutex_exit(&hba->auth_lock);
8158 		kmem_free(fcsp_cfg, size);
8159 		return (rval);
8160 	}
8161 	mutex_exit(&hba->auth_lock);
8162 
8163 	if (ddi_copyout((void *)fcsp_cfg, (void *)dfc->buf1,
8164 	    size, mode) != 0) {
8165 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8166 		    "%s: ddi_copyout failed.",
8167 		    emlxs_dfc_xlate(dfc->cmd));
8168 
8169 		kmem_free(fcsp_cfg, size);
8170 		return (DFC_COPYOUT_ERROR);
8171 	}
8172 	kmem_free(fcsp_cfg, size);
8173 	return (0);
8174 
8175 } /* emlxs_dfc_get_auth_cfg_table() */
8176 
8177 
8178 static int32_t
8179 emlxs_dfc_get_auth_key_table(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8180 {
8181 	emlxs_port_t *port = &PPORT;
8182 	dfc_auth_password_t *auth_pwd;
8183 	uint32_t count;
8184 	uint32_t size;
8185 	uint32_t rval = DFC_SUCCESS;
8186 	/* uint32_t count_sent = 0; */
8187 
8188 	/*
8189 	 * dfc.cmd = EMLXS_GET_AUTH_KEY_TABLE; dfc.buf1_size = size;
8190 	 * dfc.buf1 = auth_pwd; dfc.buf2_size = sizeof(uint32_t);
8191 	 * dfc.buf2 = &count;
8192 	 */
8193 
8194 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_detail_msg,
8195 	    "%s requested.",
8196 	    emlxs_dfc_xlate(dfc->cmd));
8197 
8198 	/* Lock cfg table while we do this */
8199 	/* This prevents the table from changing while we get a copy */
8200 	mutex_enter(&hba->auth_lock);
8201 
8202 	if (!dfc->buf2 || !dfc->buf2_size) {
8203 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8204 		    "%s: Null buffer2 found.",
8205 		    emlxs_dfc_xlate(dfc->cmd));
8206 
8207 		mutex_exit(&hba->auth_lock);
8208 		return (DFC_ARG_NULL);
8209 	}
8210 	if (dfc->buf2_size < sizeof (uint32_t)) {
8211 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8212 		    "%s: Buffer2 too small. (size=%d)",
8213 		    emlxs_dfc_xlate(dfc->cmd), dfc->buf2_size);
8214 
8215 		mutex_exit(&hba->auth_lock);
8216 		return (DFC_ARG_TOOSMALL);
8217 	}
8218 	if (ddi_copyout((void *)&hba->auth_key_count, (void *)dfc->buf2,
8219 	    sizeof (uint32_t), mode) != 0) {
8220 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8221 		    "%s: ddi_copyout failed for table count. count=%d",
8222 		    emlxs_dfc_xlate(dfc->cmd), hba->auth_key_count);
8223 
8224 		mutex_exit(&hba->auth_lock);
8225 		return (DFC_COPYOUT_ERROR);
8226 	}
8227 	if (!dfc->buf1 || !dfc->buf1_size) {
8228 		mutex_exit(&hba->auth_lock);
8229 		return (DFC_SUCCESS);
8230 	}
8231 	/* Check table size */
8232 	count = dfc->buf1_size / sizeof (dfc_auth_password_t);
8233 	if (count < hba->auth_key_count) {
8234 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8235 		    "%s: Buffer1 too small. (%d < %d)",
8236 		    emlxs_dfc_xlate(dfc->cmd), count,
8237 		    hba->auth_key_count);
8238 
8239 		mutex_exit(&hba->auth_lock);
8240 		return (DFC_ARG_TOOSMALL);
8241 	}
8242 	size = hba->auth_key_count * sizeof (dfc_auth_password_t);
8243 	if (!(auth_pwd = (dfc_auth_password_t *)kmem_zalloc(size, KM_SLEEP))) {
8244 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8245 		    "%s: Unable to allocate table buffer.",
8246 		    emlxs_dfc_xlate(dfc->cmd));
8247 
8248 		mutex_exit(&hba->auth_lock);
8249 		return (DFC_SYSRES_ERROR);
8250 	}
8251 	if ((rval = emlxs_dhc_get_auth_key_table(hba, auth_pwd)) != 0) {
8252 		mutex_exit(&hba->auth_lock);
8253 		kmem_free(auth_pwd, size);
8254 		return (rval);
8255 	}
8256 	mutex_exit(&hba->auth_lock);
8257 
8258 	if (ddi_copyout((void *)auth_pwd, (void *)dfc->buf1,
8259 	    size, mode) != 0) {
8260 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8261 		    "%s: ddi_copyout failed.",
8262 		    emlxs_dfc_xlate(dfc->cmd));
8263 
8264 		kmem_free(auth_pwd, size);
8265 		return (DFC_COPYOUT_ERROR);
8266 	}
8267 	kmem_free(auth_pwd, size);
8268 	return (0);
8269 
8270 } /* emlxs_dfc_get_auth_key_table() */
8271 
8272 
8273 
8274 #endif	/* DHCHAP_SUPPORT */
8275 
8276 static int32_t
8277 emlxs_dfc_send_scsi_fcp(emlxs_hba_t *hba, dfc_t *dfc, int32_t mode)
8278 {
8279 	emlxs_port_t *port = &PPORT;
8280 	fc_packet_t *pkt = NULL;
8281 	NODELIST *ndlp;
8282 	FCP_CMND *fcp_cmd;
8283 	FCP_RSP *fcp_rsp;
8284 	/* emlxs_xlat_err_t *entry; */
8285 	void *ptr;
8286 	char buffer[64];
8287 	dfc_send_scsi_fcp_cmd_info_t cmdinfo;
8288 	uint32_t rval = 0;
8289 
8290 	/* cmd info */
8291 	if (!dfc->buf1 ||
8292 	    (dfc->buf1_size != sizeof (dfc_send_scsi_fcp_cmd_info_t))) {
8293 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8294 		    "%s: Null buffer1 found.",
8295 		    emlxs_dfc_xlate(dfc->cmd));
8296 
8297 		rval = DFC_ARG_NULL;
8298 		goto done;
8299 	}
8300 	/* reqBuffer info */
8301 	if (!dfc->buf2 || (dfc->buf2_size != sizeof (FCP_CMND))) {
8302 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8303 		    "%s: Null buffer2 found.",
8304 		    emlxs_dfc_xlate(dfc->cmd));
8305 
8306 		rval = DFC_ARG_NULL;
8307 		goto done;
8308 	}
8309 	/* rspBuffer info, could be 0 for SCSI commands like TUR */
8310 	if (!dfc->buf3 && dfc->buf3_size) {
8311 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8312 		    "%s: Null buffer3 found.",
8313 		    emlxs_dfc_xlate(dfc->cmd));
8314 
8315 		rval = DFC_ARG_NULL;
8316 		goto done;
8317 	}
8318 	/* senseBuffer info */
8319 	if (!dfc->buf4 || !dfc->buf4_size) {
8320 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8321 		    "%s: Null buffer4 found.",
8322 		    emlxs_dfc_xlate(dfc->cmd));
8323 
8324 		rval = DFC_ARG_NULL;
8325 		goto done;
8326 	}
8327 	if (ddi_copyin((void *)dfc->buf1, (void *)&cmdinfo,
8328 	    sizeof (dfc_send_scsi_fcp_cmd_info_t), mode) != 0) {
8329 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8330 		    "%s: ddi_copyin failed.",
8331 		    emlxs_dfc_xlate(dfc->cmd));
8332 
8333 		rval = DFC_COPYIN_ERROR;
8334 		goto done;
8335 	}
8336 	if (cmdinfo.ver == DFC_SEND_SCSI_FCP_V2) {
8337 		port = emlxs_vport_find_wwpn(hba,
8338 		    (uint8_t *)&cmdinfo.src_wwn);
8339 		if (port == NULL) {
8340 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8341 			    "%s: WWPN does not exists. %s",
8342 			    emlxs_dfc_xlate(dfc->cmd),
8343 			    emlxs_wwn_xlate(buffer,
8344 			    (uint8_t *)&cmdinfo.src_wwn));
8345 
8346 			rval = DFC_ARG_INVALID;
8347 			goto done;
8348 		}
8349 	}
8350 	if ((ndlp = emlxs_node_find_wwpn(port,
8351 	    (uint8_t *)&cmdinfo.dst_wwn)) == NULL) {
8352 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8353 		    "%s: WWPN does not exists. %s",
8354 		    emlxs_dfc_xlate(dfc->cmd),
8355 		    emlxs_wwn_xlate(buffer,
8356 		    (uint8_t *)&cmdinfo.dst_wwn));
8357 
8358 		rval = DFC_ARG_INVALID;
8359 		goto done;
8360 	}
8361 	if (!(pkt = emlxs_pkt_alloc(port, sizeof (FCP_CMND),
8362 	    sizeof (FCP_RSP), dfc->buf3_size, KM_NOSLEEP))) {
8363 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8364 		    "%s: Unable to allocate packet.",
8365 		    emlxs_dfc_xlate(dfc->cmd));
8366 
8367 		rval = DFC_SYSRES_ERROR;
8368 		goto done;
8369 	}
8370 	fcp_cmd = (FCP_CMND *)pkt->pkt_cmd;
8371 	/* Copy in the command buffer */
8372 	if (ddi_copyin((void *)dfc->buf2, (void *)fcp_cmd,
8373 	    sizeof (FCP_CMND), mode) != 0) {
8374 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8375 		    "%s: ddi_copyin failed.",
8376 		    emlxs_dfc_xlate(dfc->cmd));
8377 
8378 		rval = DFC_COPYIN_ERROR;
8379 		goto done;
8380 	}
8381 	/* Make this a polled IO */
8382 	pkt->pkt_tran_flags &= ~FC_TRAN_INTR;
8383 	pkt->pkt_tran_flags |= FC_TRAN_NO_INTR;
8384 	pkt->pkt_comp = NULL;
8385 
8386 	/* Build the fc header */
8387 	pkt->pkt_cmd_fhdr.d_id = SWAP_DATA24_LO(ndlp->nlp_DID);
8388 	pkt->pkt_cmd_fhdr.r_ctl = FC_FCP_CMND;
8389 	pkt->pkt_cmd_fhdr.s_id = SWAP_DATA24_LO(port->did);
8390 	pkt->pkt_cmd_fhdr.type = FC_FCP_DATA;
8391 	pkt->pkt_cmd_fhdr.seq_id = 0;
8392 	pkt->pkt_cmd_fhdr.df_ctl = 0;
8393 	pkt->pkt_cmd_fhdr.seq_cnt = 0;
8394 	pkt->pkt_cmd_fhdr.ox_id = 0xFFFF;
8395 	pkt->pkt_cmd_fhdr.rx_id = 0xFFFF;
8396 	pkt->pkt_cmd_fhdr.ro = 0;
8397 
8398 	pkt->pkt_timeout = 30;
8399 
8400 	if ((fcp_cmd->fcpCntl3 == WRITE_DATA) && dfc->buf3_size) {
8401 		pkt->pkt_tran_type = FC_PKT_FCP_WRITE;
8402 		if (ddi_copyin((void *)dfc->buf3, (void *)pkt->pkt_data,
8403 		    dfc->buf3_size, mode) != 0) {
8404 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8405 			    "%s: ddi_copyin failed.",
8406 			    emlxs_dfc_xlate(dfc->cmd));
8407 
8408 			rval = DFC_COPYIN_ERROR;
8409 			goto done;
8410 		}
8411 	} else {
8412 		pkt->pkt_tran_type = FC_PKT_FCP_READ;
8413 	}
8414 
8415 	if (emlxs_pkt_send(pkt, 1) != FC_SUCCESS) {
8416 		rval = DFC_IO_ERROR;
8417 		goto done;
8418 	}
8419 	if (pkt->pkt_state != FC_PKT_SUCCESS) {
8420 		if (pkt->pkt_state == FC_PKT_TIMEOUT) {
8421 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8422 			    "Pkt Transport error. Pkt Timeout.");
8423 			rval = DFC_TIMEOUT;
8424 		} else {
8425 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8426 			    "Pkt Transport error. state=%x",
8427 			    pkt->pkt_state);
8428 			rval = DFC_IO_ERROR;
8429 		}
8430 		goto done;
8431 	}
8432 	if (pkt->pkt_data_resid) {
8433 		if (pkt->pkt_data_resid < dfc->buf3_size)
8434 			dfc->buf3_size -= pkt->pkt_data_resid;
8435 		else
8436 			dfc->buf3_size = 0;
8437 	}
8438 	SCSI_RSP_CNT(cmdinfo) = dfc->buf3_size;
8439 
8440 	fcp_rsp = (FCP_RSP *)pkt->pkt_resp;
8441 	/*
8442 	 * This is sense count for flag = 0. It is fcp response size for flag
8443 	 * = 1.
8444 	 */
8445 	if (dfc->flag) {
8446 		SCSI_SNS_CNT(cmdinfo) = 24 + SWAP_DATA32(fcp_rsp->rspSnsLen) +
8447 		    SWAP_DATA32(fcp_rsp->rspRspLen);
8448 		ptr = (void *)fcp_rsp;
8449 	} else {
8450 		SCSI_SNS_CNT(cmdinfo) = SWAP_DATA32(fcp_rsp->rspSnsLen);
8451 		ptr = (void *)&fcp_rsp->rspSnsInfo[0];
8452 	}
8453 
8454 	if (ddi_copyout((void *)&cmdinfo, (void *)dfc->buf1,
8455 	    sizeof (dfc_send_scsi_fcp_cmd_info_t), mode) != 0) {
8456 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8457 		    "%s: rsp_buf ddi_copyout failed.",
8458 		    emlxs_dfc_xlate(dfc->cmd));
8459 
8460 		rval = DFC_COPYOUT_ERROR;
8461 		goto done;
8462 	}
8463 	if (SCSI_SNS_CNT(cmdinfo)) {
8464 		if (ddi_copyout(ptr, (void *)dfc->buf4,
8465 		    SCSI_SNS_CNT(cmdinfo), mode) != 0) {
8466 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8467 			    "%s: rsp_size ddi_copyout failed.",
8468 			    emlxs_dfc_xlate(dfc->cmd));
8469 
8470 			rval = DFC_COPYOUT_ERROR;
8471 			goto done;
8472 		}
8473 	}
8474 	if (SCSI_RSP_CNT(cmdinfo)) {
8475 		if (ddi_copyout((void *)pkt->pkt_data, (void *)dfc->buf3,
8476 		    SCSI_RSP_CNT(cmdinfo), mode) != 0) {
8477 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_dfc_error_msg,
8478 			    "%s: rsp_size ddi_copyout failed.",
8479 			    emlxs_dfc_xlate(dfc->cmd));
8480 
8481 			rval = DFC_COPYOUT_ERROR;
8482 			goto done;
8483 		}
8484 	}
8485 	rval = 0;
8486 
8487 done:
8488 	if (pkt) {
8489 		emlxs_pkt_free(pkt);
8490 	}
8491 	return (rval);
8492 
8493 } /* emlxs_dfc_send_scsi_fcp() */
8494 
8495 #endif	/* DFC_SUPPORT */
8496