1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2009 Emulex.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 
28 #include <emlxs.h>
29 
30 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
31 EMLXS_MSG_DEF(EMLXS_MBOX_C);
32 
33 static void	emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOXQ *mbq,
34 			uint32_t hbainit);
35 static void	emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOXQ *mbq,
36 			uint32_t mask, uint32_t ringno);
37 static void	emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOXQ *mbq,
38 			uint32_t word0, uint32_t word1, uint32_t word2);
39 static void	emlxs_mb_write_nv(emlxs_hba_t *hba, MAILBOXQ *mbq);
40 
41 
42 emlxs_table_t emlxs_mb_cmd_table[] = {
43 	{MBX_SHUTDOWN, "SHUTDOWN"},
44 	{MBX_LOAD_SM, "LOAD_SM"},
45 	{MBX_READ_NV, "READ_NV"},
46 	{MBX_WRITE_NV, "WRITE_NV"},
47 	{MBX_RUN_BIU_DIAG, "RUN_BIU_DIAG"},
48 	{MBX_INIT_LINK, "INIT_LINK"},
49 	{MBX_DOWN_LINK, "DOWN_LINK"},
50 	{MBX_CONFIG_LINK, "CONFIG_LINK"},
51 	{MBX_PART_SLIM, "PART_SLIM"},
52 	{MBX_CONFIG_RING, "CONFIG_RING"},
53 	{MBX_RESET_RING, "RESET_RING"},
54 	{MBX_READ_CONFIG, "READ_CONFIG"},
55 	{MBX_READ_RCONFIG, "READ_RCONFIG"},
56 	{MBX_READ_SPARM, "READ_SPARM"},
57 	{MBX_READ_STATUS, "READ_STATUS"},
58 	{MBX_READ_RPI, "READ_RPI"},
59 	{MBX_READ_XRI, "READ_XRI"},
60 	{MBX_READ_REV, "READ_REV"},
61 	{MBX_READ_LNK_STAT, "READ_LNK_STAT"},
62 	{MBX_REG_LOGIN, "REG_LOGIN"},
63 	{MBX_UNREG_LOGIN, "UNREG_LOGIN"},
64 	{MBX_READ_LA, "READ_LA"},
65 	{MBX_CLEAR_LA, "CLEAR_LA"},
66 	{MBX_DUMP_MEMORY, "DUMP_MEMORY"},
67 	{MBX_DUMP_CONTEXT, "DUMP_CONTEXT"},
68 	{MBX_RUN_DIAGS, "RUN_DIAGS"},
69 	{MBX_RESTART, "RESTART"},
70 	{MBX_UPDATE_CFG, "UPDATE_CFG"},
71 	{MBX_DOWN_LOAD, "DOWN_LOAD"},
72 	{MBX_DEL_LD_ENTRY, "DEL_LD_ENTRY"},
73 	{MBX_RUN_PROGRAM, "RUN_PROGRAM"},
74 	{MBX_SET_MASK, "SET_MASK"},
75 	{MBX_SET_VARIABLE, "SET_VARIABLE"},
76 	{MBX_UNREG_D_ID, "UNREG_D_ID"},
77 	{MBX_KILL_BOARD, "KILL_BOARD"},
78 	{MBX_CONFIG_FARP, "CONFIG_FARP"},
79 	{MBX_LOAD_AREA, "LOAD_AREA"},
80 	{MBX_RUN_BIU_DIAG64, "RUN_BIU_DIAG64"},
81 	{MBX_CONFIG_PORT, "CONFIG_PORT"},
82 	{MBX_READ_SPARM64, "READ_SPARM64"},
83 	{MBX_READ_RPI64, "READ_RPI64"},
84 	{MBX_CONFIG_MSI, "CONFIG_MSI"},
85 	{MBX_CONFIG_MSIX, "CONFIG_MSIX"},
86 	{MBX_REG_LOGIN64, "REG_LOGIN64"},
87 	{MBX_READ_LA64, "READ_LA64"},
88 	{MBX_FLASH_WR_ULA, "FLASH_WR_ULA"},
89 	{MBX_SET_DEBUG, "SET_DEBUG"},
90 	{MBX_GET_DEBUG, "GET_DEBUG"},
91 	{MBX_LOAD_EXP_ROM, "LOAD_EXP_ROM"},
92 	{MBX_BEACON, "BEACON"},
93 	{MBX_CONFIG_HBQ, "CONFIG_HBQ"},	/* SLI3 */
94 	{MBX_REG_VPI, "REG_VPI"},	/* NPIV */
95 	{MBX_UNREG_VPI, "UNREG_VPI"},	/* NPIV */
96 	{MBX_ASYNC_EVENT, "ASYNC_EVENT"},
97 	{MBX_HEARTBEAT, "HEARTBEAT"},
98 	{MBX_READ_EVENT_LOG_STATUS, "READ_EVENT_LOG_STATUS"},
99 	{MBX_READ_EVENT_LOG, "READ_EVENT_LOG"},
100 	{MBX_WRITE_EVENT_LOG, "WRITE_EVENT_LOG"},
101 	{MBX_NV_LOG, "NV_LOG"},
102 	{MBX_PORT_CAPABILITIES, "PORT_CAPABILITIES"},
103 	{MBX_IOV_CONTROL, "IOV_CONTROL"},
104 	{MBX_IOV_MBX, "IOV_MBX"},
105 	{MBX_SLI_CONFIG, "SLI_CONFIG"},
106 	{MBX_REQUEST_FEATURES, "REQUEST_FEATURES"},
107 	{MBX_RESUME_RPI, "RESUME_RPI"},
108 	{MBX_REG_VFI, "REG_VFI"},
109 	{MBX_REG_FCFI, "REG_FCFI"},
110 	{MBX_UNREG_VFI, "UNREG_VFI"},
111 	{MBX_UNREG_FCFI, "UNREG_FCFI"},
112 	{MBX_INIT_VFI, "INIT_VFI"},
113 	{MBX_INIT_VPI, "INIT_VPI"}
114 };	/* emlxs_mb_cmd_table */
115 
116 
117 /*
118  * emlxs_mb_resetport  Issue a Port Reset mailbox command
119  */
120 /*ARGSUSED*/
121 extern void
122 emlxs_mb_resetport(emlxs_hba_t *hba, MAILBOXQ *mbq)
123 {
124 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
125 
126 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
127 	mbq->nonembed = NULL;
128 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
129 
130 	/*
131 	 * Signifies an embedded command
132 	 */
133 	mb->un.varSLIConfig.be.embedded = 1;
134 
135 	mb->mbxCommand = MBX_SLI_CONFIG;
136 	mb->mbxOwner = OWN_HOST;
137 	mb->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
138 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
139 	    IOCTL_SUBSYSTEM_COMMON;
140 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_RESET;
141 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
142 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 0;
143 
144 	return;
145 
146 } /* emlxs_mb_resetport() */
147 
148 
149 /*
150  * emlxs_mb_request_features  Issue a REQUEST FEATURES mailbox command
151  */
152 /*ARGSUSED*/
153 extern void
154 emlxs_mb_request_features(emlxs_hba_t *hba, MAILBOXQ *mbq)
155 {
156 	emlxs_config_t	*cfg = &CFG;
157 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
158 
159 	hba->flag &= ~FC_NPIV_ENABLED;
160 
161 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
162 	mbq->nonembed = NULL;
163 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
164 
165 	mb->mbxCommand = MBX_REQUEST_FEATURES;
166 	mb->mbxOwner = OWN_HOST;
167 	mb->un.varReqFeatures.featuresRequested |=
168 	    SLI4_FEATURE_FCP_INITIATOR;
169 
170 	if (cfg[CFG_NPIV_ENABLE].current) {
171 		mb->un.varReqFeatures.featuresRequested |=
172 		    SLI4_FEATURE_NPIV;
173 	}
174 
175 } /* emlxs_mb_request_features() */
176 
177 
178 /*
179  * emlxs_mb_resume_rpi  Issue a RESUME_RPI mailbox command
180  */
181 /*ARGSUSED*/
182 extern int
183 emlxs_mb_resume_rpi(emlxs_hba_t *hba, emlxs_buf_t *sbp, uint16_t rpi)
184 {
185 	MAILBOX4 *mb;
186 	MAILBOXQ *mbq;
187 	uint32_t rval;
188 
189 	(void) emlxs_sli4_find_rpi(hba, rpi);
190 
191 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
192 		return (1);
193 	}
194 	mb = (MAILBOX4 *)mbq;
195 
196 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
197 	mbq->nonembed = NULL;
198 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
199 	mbq->sbp = (uint8_t *)sbp;
200 
201 	mb->mbxCommand = MBX_RESUME_RPI;
202 	mb->mbxOwner = OWN_HOST;
203 	mb->un.varResumeRPI.EventTag = hba->link_event_tag;
204 	mb->un.varResumeRPI.RPI = rpi;
205 
206 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
207 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
208 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
209 	}
210 	return (rval);
211 
212 } /* emlxs_mb_resume_rpi() */
213 
214 
215 /*ARGSUSED*/
216 extern void
217 emlxs_mb_noop(emlxs_hba_t *hba, MAILBOXQ *mbq)
218 {
219 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
220 	IOCTL_COMMON_NOP *nop;
221 
222 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
223 	mbq->nonembed = NULL;
224 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
225 
226 	/*
227 	 * Signifies an embedded command
228 	 */
229 	mb->un.varSLIConfig.be.embedded = 1;
230 
231 	mb->mbxCommand = MBX_SLI_CONFIG;
232 	mb->mbxOwner = OWN_HOST;
233 	mb->un.varSLIConfig.be.payload_length = sizeof (IOCTL_COMMON_NOP) +
234 	    IOCTL_HEADER_SZ;
235 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
236 	    IOCTL_SUBSYSTEM_COMMON;
237 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_NOP;
238 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
239 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
240 	    sizeof (IOCTL_COMMON_NOP);
241 	nop = (IOCTL_COMMON_NOP *)&mb->un.varSLIConfig.payload;
242 	nop->params.request.context = -1;
243 
244 	return;
245 
246 } /* emlxs_mb_noop() */
247 
248 
249 /*ARGSUSED*/
250 extern int
251 emlxs_mbext_noop(emlxs_hba_t *hba, MAILBOXQ *mbq)
252 {
253 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
254 	IOCTL_COMMON_NOP *nop;
255 	MATCHMAP *mp;
256 	mbox_req_hdr_t	*hdr_req;
257 
258 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
259 
260 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
261 		return (1);
262 	}
263 	/*
264 	 * Save address for completion
265 	 * Signifies a non-embedded command
266 	 */
267 	mb->un.varSLIConfig.be.embedded = 0;
268 	mbq->nonembed = (uint8_t *)mp;
269 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
270 
271 	mb->mbxCommand = MBX_SLI_CONFIG;
272 	mb->mbxOwner = OWN_HOST;
273 
274 	hdr_req = (mbox_req_hdr_t *)mp->virt;
275 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
276 	hdr_req->opcode = COMMON_OPCODE_NOP;
277 	hdr_req->timeout = 0;
278 	hdr_req->req_length = sizeof (IOCTL_COMMON_NOP);
279 	nop = (IOCTL_COMMON_NOP *)(hdr_req + 1);
280 	nop->params.request.context = -1;
281 
282 	return (0);
283 
284 } /* emlxs_mbext_noop() */
285 
286 
287 int
288 emlxs_cmpl_read_fcf_table(void *arg1, MAILBOXQ *mbq)
289 {
290 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
291 	emlxs_port_t *port = &PPORT;
292 	mbox_rsp_hdr_t	*hdr_rsp;
293 	IOCTL_FCOE_READ_FCF_TABLE *fcf;
294 	FCF_RECORD_t *fcfrec;
295 	FCFIobj_t *fcfp;
296 	MAILBOX4 *mb;
297 	MATCHMAP *mp;
298 	MAILBOXQ *fcfmbq;
299 	uint32_t i, *iptr;
300 	uint16_t s, *sptr;
301 	int rc;
302 
303 	mb = (MAILBOX4 *)mbq;
304 	mp = (MATCHMAP *)mbq->nonembed;
305 	hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
306 
307 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
308 	    "CMPL read fcf: stats: %x %x %x",
309 	    mb->mbxStatus, hdr_rsp->status, hdr_rsp->extra_status);
310 
311 	if (mb->mbxStatus || hdr_rsp->status) {
312 		/* Wait for FCF found async event */
313 		return (0);
314 	}
315 
316 	/*
317 	 * Only support 1 FCF for now, so we don't need to walk
318 	 * thru the FCF table.
319 	 */
320 	fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_rsp + 1);
321 	fcfrec = &fcf->params.response.fcf_entry[0];
322 
323 	/* Fix up data in FCF record */
324 	BE_SWAP32_BUFFER(&fcfrec->fabric_name_identifier[0], 8);
325 	BE_SWAP32_BUFFER(&fcfrec->switch_name_identifier[0], 8);
326 	BE_SWAP32_BUFFER(&fcfrec->vlan_bitmap[0], 512);
327 	iptr = (uint32_t *)&fcfrec->fcf_mac_address_hi[0];
328 	i = *iptr;
329 	*iptr = BE_SWAP32(i);
330 	sptr = (uint16_t *)&fcfrec->fcf_mac_address_low[0];
331 	s = *sptr;
332 	*sptr = BE_SWAP16(s);
333 #ifdef EMLXS_BIG_ENDIAN
334 	i = fcfrec->fc_map[0];
335 	fcfrec->fc_map[0] = fcfrec->fc_map[2];
336 	fcfrec->fc_map[2] = i;
337 #endif
338 
339 	/* Assign a FCFI object for the fcf_index */
340 	fcfp = emlxs_sli4_assign_fcfi(hba, fcfrec);
341 	if (!fcfp) {
342 		return (0);
343 	}
344 	fcfp->EventTag = fcf->params.response.event_tag;
345 
346 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
347 	    "CMPL read fcf: info: x%x x%x",
348 	    fcfp->EventTag, fcf->params.response.next_valid_fcf_index);
349 
350 	if (emlxs_sli4_bind_fcfi(hba)) {
351 		/*
352 		 * In this phase, if we successfully bind to just
353 		 * 1 FCFI we are done.
354 		 */
355 		return (0);
356 	}
357 
358 	if (fcf->params.response.next_valid_fcf_index == 0xffff) {
359 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
360 		    "Waiting for a valid FCF to be discovered");
361 		return (0);
362 	}
363 
364 	/* Get the next one */
365 	if (!(fcfmbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
366 		return (0);
367 	}
368 	rc =  emlxs_mbext_read_fcf_table(hba, fcfmbq,
369 	    fcf->params.response.next_valid_fcf_index);
370 	if (rc == 0) {
371 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)fcfmbq);
372 		return (0);
373 	}
374 
375 	rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, fcfmbq, MBX_NOWAIT, 0);
376 	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
377 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)fcfmbq);
378 	}
379 	return (0);
380 } /* emlxs_cmpl_read_fcf_table() */
381 
382 
383 extern int
384 emlxs_mbext_read_fcf_table(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t index)
385 {
386 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
387 	IOCTL_FCOE_READ_FCF_TABLE *fcf;
388 	MATCHMAP *mp;
389 	mbox_req_hdr_t	*hdr_req;
390 
391 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
392 
393 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
394 		return (0);
395 	}
396 	/*
397 	 * Save address for completion
398 	 * Signifies a non-embedded command
399 	 */
400 	mb->un.varSLIConfig.be.embedded = 0;
401 	mbq->nonembed = (uint8_t *)mp;
402 	mbq->mbox_cmpl = emlxs_cmpl_read_fcf_table;
403 
404 	mb->mbxCommand = MBX_SLI_CONFIG;
405 	mb->mbxOwner = OWN_HOST;
406 
407 	hdr_req = (mbox_req_hdr_t *)mp->virt;
408 	hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
409 	hdr_req->opcode = FCOE_OPCODE_READ_FCF_TABLE;
410 	hdr_req->timeout = 0;
411 	hdr_req->req_length = sizeof (IOCTL_FCOE_READ_FCF_TABLE);
412 	fcf = (IOCTL_FCOE_READ_FCF_TABLE *)(hdr_req + 1);
413 	fcf->params.request.fcf_index = index;
414 
415 	return (1);
416 
417 } /* emlxs_mbext_read_fcf_table() */
418 
419 
420 int
421 emlxs_cmpl_add_fcf_table(void *arg1, MAILBOXQ *mbq)
422 {
423 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
424 	emlxs_port_t *port = &PPORT;
425 	MAILBOX4 *mb;
426 	MAILBOXQ *mq;
427 	MATCHMAP *mp;
428 	mbox_rsp_hdr_t *hdr_rsp;
429 	uint32_t rc;
430 
431 	mb = (MAILBOX4 *)mbq;
432 	mp = (MATCHMAP *)mbq->nonembed;
433 
434 	hdr_rsp = (mbox_rsp_hdr_t *)mp->virt;
435 
436 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
437 	    "CMPL add fcf: stats: %x %x %x",
438 	    mb->mbxStatus, hdr_rsp->status, hdr_rsp->extra_status);
439 
440 	if (mbq->nonembed) {
441 		(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbq->nonembed);
442 		mbq->nonembed = 0;
443 	}
444 
445 	if (mb->mbxStatus) {
446 		/* In nonFIP mode, FCF Entries are persistent */
447 		if (!hdr_rsp->status ||
448 		    (hdr_rsp->status != MGMT_STATUS_FCF_IN_USE)) {
449 			return (0);
450 		}
451 	}
452 
453 	/*
454 	 * Now that we have a fcf table entry, read it back
455 	 * to fall into the normal link up processing.
456 	 */
457 	if (!(mq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
458 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
459 		    "CMPL add fcf: Cannot alloc mbox");
460 		return (0);
461 	}
462 	rc =  emlxs_mbext_read_fcf_table(hba, mq, -1);
463 
464 	if (rc == 0) {
465 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
466 		    "CMPL add fcf: Cannot build read fcf mbox");
467 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mq);
468 		return (0);
469 	}
470 
471 	rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mq, MBX_NOWAIT, 0);
472 	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
473 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
474 		    "CMPL add fcf: Cannot issue read fcf mbox");
475 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mq);
476 	}
477 	return (0);
478 } /* emlxs_cmpl_add_fcf_table() */
479 
480 
481 extern int
482 emlxs_mbext_add_fcf_table(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t index)
483 {
484 	emlxs_port_t *port = &PPORT;
485 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
486 	IOCTL_FCOE_ADD_FCF_TABLE *fcf;
487 	FCF_RECORD_t *fcfrec;
488 	MATCHMAP *mp;
489 	mbox_req_hdr_t	*hdr_req;
490 	uint16_t i;
491 	uint8_t bitmap[512];
492 
493 
494 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
495 
496 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
497 		return (0);
498 	}
499 	/*
500 	 * Save address for completion
501 	 * Signifies a non-embedded command
502 	 */
503 	mb->un.varSLIConfig.be.embedded = 0;
504 	mbq->nonembed = (uint8_t *)mp;
505 	mbq->mbox_cmpl = emlxs_cmpl_add_fcf_table;
506 
507 	mb->mbxCommand = MBX_SLI_CONFIG;
508 	mb->mbxOwner = OWN_HOST;
509 
510 	hdr_req = (mbox_req_hdr_t *)mp->virt;
511 	hdr_req->subsystem = IOCTL_SUBSYSTEM_FCOE;
512 	hdr_req->opcode = FCOE_OPCODE_ADD_FCF_TABLE;
513 	hdr_req->timeout = 0;
514 	hdr_req->req_length = sizeof (IOCTL_FCOE_ADD_FCF_TABLE);
515 	fcf = (IOCTL_FCOE_ADD_FCF_TABLE *)(hdr_req + 1);
516 	fcf->params.request.fcf_index = index;
517 
518 	fcfrec = &fcf->params.request.fcf_entry;
519 	fcfrec->max_recv_size = EMLXS_FCOE_MAX_RCV_SZ;
520 	fcfrec->fka_adv_period = 0;
521 	fcfrec->fip_priority = 128;
522 #ifdef EMLXS_BIG_ENDIAN
523 	fcfrec->fcf_mac_address_hi[0] = FCOE_FCF_MAC3;
524 	fcfrec->fcf_mac_address_hi[1] = FCOE_FCF_MAC2;
525 	fcfrec->fcf_mac_address_hi[2] = FCOE_FCF_MAC1;
526 	fcfrec->fcf_mac_address_hi[3] = FCOE_FCF_MAC0;
527 	fcfrec->fcf_mac_address_low[0] = FCOE_FCF_MAC5;
528 	fcfrec->fcf_mac_address_low[1] = FCOE_FCF_MAC4;
529 	fcfrec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[2];
530 	fcfrec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
531 	fcfrec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[0];
532 #endif
533 #ifdef EMLXS_LITTLE_ENDIAN
534 	fcfrec->fcf_mac_address_hi[0] = FCOE_FCF_MAC0;
535 	fcfrec->fcf_mac_address_hi[1] = FCOE_FCF_MAC1;
536 	fcfrec->fcf_mac_address_hi[2] = FCOE_FCF_MAC2;
537 	fcfrec->fcf_mac_address_hi[3] = FCOE_FCF_MAC3;
538 	fcfrec->fcf_mac_address_low[0] = FCOE_FCF_MAC4;
539 	fcfrec->fcf_mac_address_low[1] = FCOE_FCF_MAC5;
540 	fcfrec->fc_map[0] = hba->sli.sli4.cfgFCOE.FCMap[0];
541 	fcfrec->fc_map[1] = hba->sli.sli4.cfgFCOE.FCMap[1];
542 	fcfrec->fc_map[2] = hba->sli.sli4.cfgFCOE.FCMap[2];
543 #endif
544 
545 	if (hba->sli.sli4.cfgFCOE.fip_flags & TLV_FCOE_VLAN) {
546 		bzero((void *) bitmap, 512);
547 		i = hba->sli.sli4.cfgFCOE.VLanId;
548 		bitmap[i / 8] = (1 << (i % 8));
549 		BE_SWAP32_BCOPY(bitmap, fcfrec->vlan_bitmap, 512);
550 	} else {
551 		bzero((void *) bitmap, 512);
552 		bitmap[0] = 1; /* represents bit 0 */
553 		BE_SWAP32_BCOPY(bitmap, fcfrec->vlan_bitmap, 512);
554 	}
555 
556 	fcfrec->fcf_valid = 1;
557 	fcfrec->fcf_available = 1;
558 
559 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
560 	    "ADD FCF %d: av: %x %x ste %x macp %x "
561 	    "addr: %02x:%02x:%02x:%02x:%02x:%02x",
562 	    fcfrec->fcf_index,
563 	    fcfrec->fcf_available,
564 	    fcfrec->fcf_valid,
565 	    fcfrec->fcf_state,
566 	    fcfrec->mac_address_provider,
567 	    fcfrec->fcf_mac_address_hi[0],
568 	    fcfrec->fcf_mac_address_hi[1],
569 	    fcfrec->fcf_mac_address_hi[2],
570 	    fcfrec->fcf_mac_address_hi[3],
571 	    fcfrec->fcf_mac_address_low[0],
572 	    fcfrec->fcf_mac_address_low[1]);
573 	return (1);
574 
575 } /* emlxs_mbext_add_fcf_table() */
576 
577 
578 /*ARGSUSED*/
579 extern void
580 emlxs_mb_eq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num)
581 {
582 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
583 	IOCTL_COMMON_EQ_CREATE *qp;
584 	uint64_t	addr;
585 
586 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
587 	mbq->nonembed = NULL;
588 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
589 
590 	/*
591 	 * Signifies an embedded command
592 	 */
593 	mb->un.varSLIConfig.be.embedded = 1;
594 
595 	mb->mbxCommand = MBX_SLI_CONFIG;
596 	mb->mbxOwner = OWN_HOST;
597 	mb->un.varSLIConfig.be.payload_length =
598 	    sizeof (IOCTL_COMMON_EQ_CREATE) + IOCTL_HEADER_SZ;
599 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
600 	    IOCTL_SUBSYSTEM_COMMON;
601 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_EQ_CREATE;
602 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
603 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
604 	    sizeof (IOCTL_COMMON_EQ_CREATE);
605 	qp = (IOCTL_COMMON_EQ_CREATE *)&mb->un.varSLIConfig.payload;
606 
607 	/* 1024 * 4 bytes = 4K */
608 	qp->params.request.EQContext.Count = EQ_ELEMENT_COUNT_1024;
609 	qp->params.request.EQContext.Valid = 1;
610 	qp->params.request.EQContext.NoDelay = 0;
611 	qp->params.request.EQContext.DelayMult = EQ_DELAY_MULT;
612 
613 	addr = hba->sli.sli4.eq[num].addr.phys;
614 	qp->params.request.NumPages = 1;
615 	qp->params.request.Pages[0].addrLow = PADDR_LO(addr);
616 	qp->params.request.Pages[0].addrHigh = PADDR_HI(addr);
617 
618 	return;
619 
620 } /* emlxs_mb_eq_create() */
621 
622 
623 /*ARGSUSED*/
624 extern void
625 emlxs_mb_cq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num)
626 {
627 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
628 	IOCTL_COMMON_CQ_CREATE *qp;
629 	uint64_t	addr;
630 
631 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
632 	mbq->nonembed = NULL;
633 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
634 
635 	/*
636 	 * Signifies an embedded command
637 	 */
638 	mb->un.varSLIConfig.be.embedded = 1;
639 
640 	mb->mbxCommand = MBX_SLI_CONFIG;
641 	mb->mbxOwner = OWN_HOST;
642 	mb->un.varSLIConfig.be.payload_length =
643 	    sizeof (IOCTL_COMMON_CQ_CREATE) + IOCTL_HEADER_SZ;
644 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
645 	    IOCTL_SUBSYSTEM_COMMON;
646 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_CQ_CREATE;
647 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
648 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
649 	    sizeof (IOCTL_COMMON_CQ_CREATE);
650 	qp = (IOCTL_COMMON_CQ_CREATE *)&mb->un.varSLIConfig.payload;
651 
652 	/* 256 * 16 bytes = 4K */
653 	qp->params.request.CQContext.Count = CQ_ELEMENT_COUNT_256;
654 	qp->params.request.CQContext.EQId = hba->sli.sli4.cq[num].eqid;
655 	qp->params.request.CQContext.Valid = 1;
656 	qp->params.request.CQContext.Eventable = 1;
657 	qp->params.request.CQContext.NoDelay = 0;
658 
659 	addr = hba->sli.sli4.cq[num].addr.phys;
660 	qp->params.request.NumPages = 1;
661 	qp->params.request.Pages[0].addrLow = PADDR_LO(addr);
662 	qp->params.request.Pages[0].addrHigh = PADDR_HI(addr);
663 
664 	return;
665 
666 } /* emlxs_mb_cq_create() */
667 
668 
669 /*ARGSUSED*/
670 extern void
671 emlxs_mb_wq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num)
672 {
673 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
674 	IOCTL_FCOE_WQ_CREATE *qp;
675 	uint64_t addr;
676 	int i;
677 
678 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
679 	mbq->nonembed = NULL;
680 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
681 
682 	/*
683 	 * Signifies an embedded command
684 	 */
685 	mb->un.varSLIConfig.be.embedded = 1;
686 
687 	mb->mbxCommand = MBX_SLI_CONFIG;
688 	mb->mbxOwner = OWN_HOST;
689 	mb->un.varSLIConfig.be.payload_length =
690 	    sizeof (IOCTL_FCOE_WQ_CREATE) + IOCTL_HEADER_SZ;
691 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
692 	    IOCTL_SUBSYSTEM_FCOE;
693 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = FCOE_OPCODE_WQ_CREATE;
694 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
695 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
696 	    sizeof (IOCTL_FCOE_WQ_CREATE);
697 
698 	addr = hba->sli.sli4.wq[num].addr.phys;
699 	qp = (IOCTL_FCOE_WQ_CREATE *)&mb->un.varSLIConfig.payload;
700 
701 	qp->params.request.CQId = hba->sli.sli4.wq[num].cqid;
702 
703 	qp->params.request.NumPages = EMLXS_NUM_WQ_PAGES;
704 	for (i = 0; i < EMLXS_NUM_WQ_PAGES; i++) {
705 		qp->params.request.Pages[i].addrLow = PADDR_LO(addr);
706 		qp->params.request.Pages[i].addrHigh = PADDR_HI(addr);
707 		addr += 4096;
708 	}
709 
710 	return;
711 
712 } /* emlxs_mb_wq_create() */
713 
714 
715 /*ARGSUSED*/
716 extern void
717 emlxs_mb_rq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num)
718 {
719 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
720 	IOCTL_FCOE_RQ_CREATE *qp;
721 	uint64_t	addr;
722 
723 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
724 	mbq->nonembed = NULL;
725 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
726 
727 	/*
728 	 * Signifies an embedded command
729 	 */
730 	mb->un.varSLIConfig.be.embedded = 1;
731 
732 	mb->mbxCommand = MBX_SLI_CONFIG;
733 	mb->mbxOwner = OWN_HOST;
734 	mb->un.varSLIConfig.be.payload_length =
735 	    sizeof (IOCTL_FCOE_RQ_CREATE) + IOCTL_HEADER_SZ;
736 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
737 	    IOCTL_SUBSYSTEM_FCOE;
738 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = FCOE_OPCODE_RQ_CREATE;
739 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
740 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
741 	    sizeof (IOCTL_FCOE_RQ_CREATE);
742 	addr = hba->sli.sli4.rq[num].addr.phys;
743 
744 	qp = (IOCTL_FCOE_RQ_CREATE *)&mb->un.varSLIConfig.payload;
745 
746 	qp->params.request.RQContext.RQSize	= RQ_DEPTH_EXPONENT;
747 	qp->params.request.RQContext.BufferSize	= RQB_DATA_SIZE;
748 	qp->params.request.RQContext.CQIdRecv	= hba->sli.sli4.rq[num].cqid;
749 
750 	qp->params.request.NumPages = 1;
751 	qp->params.request.Pages[0].addrLow = PADDR_LO(addr);
752 	qp->params.request.Pages[0].addrHigh = PADDR_HI(addr);
753 
754 	return;
755 
756 } /* emlxs_mb_rq_create() */
757 
758 
759 /*ARGSUSED*/
760 extern void
761 emlxs_mb_mq_create(emlxs_hba_t *hba, MAILBOXQ *mbq)
762 {
763 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
764 	IOCTL_COMMON_MQ_CREATE *qp;
765 	uint64_t	addr;
766 
767 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
768 	mbq->nonembed = NULL;
769 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
770 
771 	/*
772 	 * Signifies an embedded command
773 	 */
774 	mb->un.varSLIConfig.be.embedded = 1;
775 
776 	mb->mbxCommand = MBX_SLI_CONFIG;
777 	mb->mbxOwner = OWN_HOST;
778 	mb->un.varSLIConfig.be.payload_length =
779 	    sizeof (IOCTL_COMMON_MQ_CREATE) + IOCTL_HEADER_SZ;
780 	mb->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
781 	    IOCTL_SUBSYSTEM_COMMON;
782 	mb->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_MQ_CREATE;
783 	mb->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
784 	mb->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
785 	    sizeof (IOCTL_COMMON_MQ_CREATE);
786 
787 	addr = hba->sli.sli4.mq.addr.phys;
788 	qp = (IOCTL_COMMON_MQ_CREATE *)&mb->un.varSLIConfig.payload;
789 
790 	qp->params.request.MQContext.Size = MQ_ELEMENT_COUNT_16;
791 	qp->params.request.MQContext.Valid = 1;
792 	qp->params.request.MQContext.CQId = hba->sli.sli4.mq.cqid;
793 
794 	qp->params.request.NumPages = 1;
795 	qp->params.request.Pages[0].addrLow = PADDR_LO(addr);
796 	qp->params.request.Pages[0].addrHigh = PADDR_HI(addr);
797 
798 	return;
799 
800 } /* emlxs_mb_mq_create() */
801 
802 
803 static int
804 emlxs_cmpl_reg_fcfi(void *arg1, MAILBOXQ *mbq)
805 {
806 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
807 	emlxs_port_t *port = &PPORT;
808 	FCFIobj_t *fcfp;
809 	VFIobj_t *vfip;
810 	RPIobj_t *rpip;
811 	MAILBOX4 *mb;
812 
813 	mb = (MAILBOX4 *)mbq;
814 	fcfp = (FCFIobj_t *)mbq->context;
815 
816 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
817 	    "CMPL reg fcfi: status: %x", mb->mbxStatus);
818 
819 	if (mb->mbxStatus) {
820 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
821 		    "Unable to register FCFI for FCFI %d index %d",
822 		    mb->un.varRegFCFI.FCFI, mb->un.varRegFCFI.InfoIndex);
823 		(void) emlxs_sli4_free_fcfi(hba, fcfp);
824 		return (0);
825 	}
826 
827 	fcfp->state |= RESOURCE_FCFI_REG;
828 
829 	if (!fcfp->fcf_vfi) {
830 		vfip = emlxs_sli4_alloc_vfi(hba, fcfp);
831 		if (!vfip) {
832 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
833 			    "Unable to alloc VFI for Fabric, fcf index %d",
834 			    fcfp->FCF_index);
835 			(void) emlxs_sli4_free_fcfi(hba, fcfp);
836 			return (0);
837 		}
838 		fcfp->fcf_vfi = vfip;
839 	}
840 
841 	if (!fcfp->fcf_vpi) {
842 		fcfp->fcf_vpi = port;
843 		port->VFIp = fcfp->fcf_vfi;
844 		port->VFIp->outstandingVPIs++;
845 	}
846 
847 	rpip = &fcfp->scratch_rpi;
848 	rpip->state = RESOURCE_ALLOCATED;
849 	rpip->VPIp = fcfp->fcf_vpi;
850 	rpip->RPI = 0xffff;
851 	rpip->index = 0xffff;
852 
853 	fcfp->FCFI = mb->un.varRegFCFI.FCFI;
854 
855 	/* Declare the linkup here */
856 	if (!(fcfp->state & RESOURCE_FCFI_DISC)) {
857 		fcfp->state |= RESOURCE_FCFI_DISC;
858 		emlxs_linkup(hba);
859 	}
860 	return (0);
861 
862 } /* emlxs_cmpl_reg_fcfi() */
863 
864 
865 /*ARGSUSED*/
866 extern void
867 emlxs_mb_reg_fcfi(emlxs_hba_t *hba, MAILBOXQ *mbq, FCFIobj_t *fcfp)
868 {
869 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
870 
871 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
872 
873 	mb->mbxCommand = MBX_REG_FCFI;
874 	mb->mbxOwner = OWN_HOST;
875 	mb->un.varRegFCFI.FCFI = 0; /* FCFI will be returned by firmware */
876 	mb->un.varRegFCFI.InfoIndex = fcfp->FCF_index;
877 
878 	mb->un.varRegFCFI.RQId0 = hba->sli.sli4.rq[EMLXS_FCFI_RQ0_INDEX].qid;
879 	mb->un.varRegFCFI.Id0_rctl_mask = EMLXS_FCFI_RQ0_RMASK;
880 	mb->un.varRegFCFI.Id0_rctl = EMLXS_FCFI_RQ0_RCTL;
881 	mb->un.varRegFCFI.Id0_type_mask = EMLXS_FCFI_RQ0_TMASK;
882 	mb->un.varRegFCFI.Id0_type = EMLXS_FCFI_RQ0_TYPE;
883 
884 	mb->un.varRegFCFI.RQId1 = 0xffff;
885 	mb->un.varRegFCFI.RQId2 = 0xffff;
886 	mb->un.varRegFCFI.RQId3 = 0xffff;
887 
888 	if (fcfp->state & RESOURCE_FCFI_VLAN_ID) {
889 		mb->un.varRegFCFI.vv = 1;
890 		mb->un.varRegFCFI.vlanTag = fcfp->vlan_id;
891 	}
892 
893 	/* Ignore the fcf record and force FPMA */
894 	mb->un.varRegFCFI.mam = EMLXS_REG_FCFI_MAM_FPMA;
895 
896 	mbq->mbox_cmpl = emlxs_cmpl_reg_fcfi;
897 	mbq->context = (uint8_t *)fcfp;
898 	return;
899 
900 } /* emlxs_mb_reg_fcfi() */
901 
902 
903 /* SLI4 */
904 static int
905 emlxs_cmpl_unreg_fcfi(void *arg1, MAILBOXQ *mbq)
906 {
907 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
908 	emlxs_port_t *port = &PPORT;
909 	FCFIobj_t *fcfp;
910 	MAILBOX4 *mb;
911 
912 	mb = (MAILBOX4 *)mbq;
913 	fcfp = (FCFIobj_t *)mbq->context;
914 
915 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
916 	    "CMPL unreg fcfi: status: %x", mb->mbxStatus);
917 
918 	if (mb->mbxStatus) {
919 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
920 		    "Unable to unregister FCFI %d index %d",
921 		    fcfp->FCFI, fcfp->FCF_index);
922 	}
923 
924 	(void) emlxs_sli4_free_fcfi(hba, fcfp);
925 
926 	/* Make sure link is declared down */
927 	emlxs_linkdown(hba);
928 
929 	return (0);
930 
931 } /* emlxs_cmpl_unreg_fcfi() */
932 
933 
934 /* ARGSUSED */
935 extern int
936 emlxs_mb_unreg_fcfi(emlxs_hba_t *hba, FCFIobj_t *fcfp)
937 {
938 	MAILBOXQ *mbq;
939 	MAILBOX4 *mb;
940 	uint32_t rval;
941 
942 	mutex_enter(&EMLXS_PORT_LOCK);
943 
944 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
945 		mutex_exit(&EMLXS_PORT_LOCK);
946 		return (1);
947 	}
948 	mb = (MAILBOX4 *)mbq;
949 	mutex_exit(&EMLXS_PORT_LOCK);
950 
951 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
952 
953 	mb->mbxCommand = MBX_UNREG_FCFI;
954 	mb->mbxOwner = OWN_HOST;
955 	mb->un.varUnRegFCFI.FCFI = fcfp->FCFI;
956 
957 	mbq->mbox_cmpl = emlxs_cmpl_unreg_fcfi;
958 	mbq->context = (uint8_t *)fcfp;
959 	fcfp->fcf_vfi = NULL;
960 	fcfp->fcf_vpi = NULL;
961 
962 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
963 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
964 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
965 	}
966 
967 	return (0);
968 
969 } /* emlxs_mb_unreg_fcfi() */
970 
971 
972 int
973 emlxs_mb_cmpl_reg_vfi(void *arg1, MAILBOXQ *mbq)
974 {
975 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
976 	emlxs_port_t *port = &PPORT;
977 	MAILBOX4 *mb;
978 	MAILBOXQ *mbox;
979 	MATCHMAP *mp;
980 	NODELIST *ndlp;
981 	emlxs_port_t *vport;
982 	VFIobj_t *vfip;
983 	uint8_t *wwn;
984 	volatile SERV_PARM *sp;
985 	int32_t i;
986 	uint32_t ldid;
987 	emlxs_vvl_fmt_t vvl;
988 
989 	mb = (MAILBOX4 *)mbq;
990 	if (mb->mbxStatus) {
991 		EMLXS_MSGF(EMLXS_CONTEXT,
992 		    &emlxs_sli_detail_msg,
993 		    "REG_VFI failed. status=x%x", mb->mbxStatus);
994 		return (0);
995 	}
996 
997 	vport = (emlxs_port_t *)mbq->context;
998 	vfip = vport->VFIp;
999 	vfip->state |= RESOURCE_VFI_REG;
1000 
1001 	if (mb->un.varRegVFI4.vp) {
1002 		vport->flag |= EMLXS_PORT_REGISTERED;
1003 	}
1004 
1005 	mp = (MATCHMAP *)mbq->bp;
1006 	if (!mp) {
1007 		return (0);
1008 	}
1009 	sp = (volatile SERV_PARM *)mp->virt;
1010 
1011 	ldid = FABRIC_DID;
1012 	ndlp = emlxs_node_find_did(port, ldid);
1013 
1014 	if (!ndlp) {
1015 		/* Attempt to create a node */
1016 		if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) {
1017 			ndlp->nlp_Rpi = 0xffff;
1018 			ndlp->nlp_DID = ldid;
1019 
1020 			bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm,
1021 			    sizeof (SERV_PARM));
1022 
1023 			bcopy((uint8_t *)&sp->nodeName,
1024 			    (uint8_t *)&ndlp->nlp_nodename,
1025 			    sizeof (NAME_TYPE));
1026 
1027 			bcopy((uint8_t *)&sp->portName,
1028 			    (uint8_t *)&ndlp->nlp_portname,
1029 			    sizeof (NAME_TYPE));
1030 
1031 			ndlp->nlp_active = 1;
1032 			ndlp->nlp_flag[hba->channel_ct]  |= NLP_CLOSED;
1033 			ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED;
1034 			ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED;
1035 			ndlp->nlp_flag[hba->channel_ip]  |= NLP_CLOSED;
1036 
1037 			/* Add the node */
1038 			emlxs_node_add(port, ndlp);
1039 
1040 			/* Open the node */
1041 			emlxs_node_open(port, ndlp, hba->channel_ct);
1042 			emlxs_node_open(port, ndlp, hba->channel_els);
1043 			emlxs_node_open(port, ndlp, hba->channel_ip);
1044 			emlxs_node_open(port, ndlp, hba->channel_fcp);
1045 		} else {
1046 			wwn = (uint8_t *)&sp->portName;
1047 			EMLXS_MSGF(EMLXS_CONTEXT,
1048 			    &emlxs_node_create_failed_msg,
1049 			    "Unable to allocate node. did=%06x "
1050 			    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
1051 			    ldid, wwn[0], wwn[1], wwn[2],
1052 			    wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
1053 
1054 			return (0);
1055 		}
1056 	} else {
1057 		mutex_enter(&EMLXS_PORT_LOCK);
1058 
1059 		ndlp->nlp_Rpi = 0xffff;
1060 		ndlp->nlp_DID = ldid;
1061 
1062 		bcopy((uint8_t *)sp,
1063 		    (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM));
1064 
1065 		bcopy((uint8_t *)&sp->nodeName,
1066 		    (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE));
1067 
1068 		bcopy((uint8_t *)&sp->portName,
1069 		    (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE));
1070 
1071 		wwn = (uint8_t *)&ndlp->nlp_portname;
1072 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg,
1073 		    "node=%p did=%06x rpi=%x "
1074 		    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
1075 		    ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
1076 		    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
1077 
1078 		mutex_exit(&EMLXS_PORT_LOCK);
1079 
1080 		/* Open the node */
1081 		emlxs_node_open(port, ndlp, hba->channel_ct);
1082 		emlxs_node_open(port, ndlp, hba->channel_els);
1083 		emlxs_node_open(port, ndlp, hba->channel_ip);
1084 		emlxs_node_open(port, ndlp, hba->channel_fcp);
1085 	}
1086 
1087 	bzero((char *)&vvl, sizeof (emlxs_vvl_fmt_t));
1088 
1089 	if (sp->VALID_VENDOR_VERSION) {
1090 
1091 		bcopy((caddr_t *)&sp->vendorVersion[0],
1092 		    (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t));
1093 
1094 		vvl.un0.word0 = LE_SWAP32(vvl.un0.word0);
1095 		vvl.un1.word1 = LE_SWAP32(vvl.un1.word1);
1096 
1097 		if ((vvl.un0.w0.oui == 0x0000C9) &&
1098 		    (vvl.un1.w1.vport)) {
1099 			ndlp->nlp_fcp_info |= NLP_EMLX_VPORT;
1100 		}
1101 	}
1102 
1103 	if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
1104 		/* If link not already down then */
1105 		/* declare it down now */
1106 		if (emlxs_mb_read_sparam(hba, mbox) == 0) {
1107 			emlxs_mb_put(hba, mbox);
1108 		} else {
1109 			(void) emlxs_mem_put(hba, MEM_MBOX,
1110 			    (uint8_t *)mbox);
1111 		}
1112 	}
1113 
1114 	/* Since this is a fabric login */
1115 	/*
1116 	 * If NPIV Fabric support has just been established on
1117 	 * the physical port, then notify the vports of the
1118 	 * link up
1119 	 */
1120 	EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY);
1121 	if ((hba->flag & FC_NPIV_ENABLED) &&
1122 	    (hba->flag & FC_NPIV_SUPPORTED)) {
1123 		/* Skip the physical port */
1124 		for (i = 1; i < MAX_VPORTS; i++) {
1125 			vport = &VPORT(i);
1126 
1127 			if (!(vport->flag & EMLXS_PORT_BOUND) ||
1128 			    !(vport->flag & EMLXS_PORT_ENABLE)) {
1129 				continue;
1130 			}
1131 
1132 			emlxs_port_online(vport);
1133 		}
1134 	}
1135 
1136 #ifdef SFCT_SUPPORT
1137 	if (mbq->sbp && ((emlxs_buf_t *)mbq->sbp)->fct_cmd) {
1138 		emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)mbq->sbp;
1139 
1140 		if (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) {
1141 			mbq->sbp = NULL;
1142 
1143 			mutex_enter(&EMLXS_PKT_LOCK);
1144 			cmd_sbp->node = ndlp;
1145 			cv_broadcast(&EMLXS_PKT_CV);
1146 			mutex_exit(&EMLXS_PKT_LOCK);
1147 		}
1148 	}
1149 #endif /* SFCT_SUPPORT */
1150 	return (0);
1151 
1152 } /* emlxs_mb_cmpl_reg_vfi */
1153 
1154 
1155 /*ARGSUSED*/
1156 extern int
1157 emlxs_mb_reg_vfi(emlxs_hba_t *hba, MAILBOXQ *mbq, VFIobj_t *vfip,
1158     emlxs_port_t *port)
1159 {
1160 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
1161 	FCFIobj_t *fcfp;
1162 	MATCHMAP *mp;
1163 
1164 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1165 
1166 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
1167 		return (0);
1168 	}
1169 
1170 	mb->mbxCommand = MBX_REG_VFI;
1171 	mb->mbxOwner = OWN_HOST;
1172 	mb->un.varRegVFI4.vfi = vfip->VFI;
1173 	if (!(port->flag & EMLXS_PORT_REGISTERED)) {
1174 		mb->un.varRegVFI4.vp = 1;
1175 		mb->un.varRegVFI4.vpi = port->vpi + hba->vpi_base;
1176 	}
1177 	fcfp = vfip->FCFIp;
1178 	mb->un.varRegVFI4.fcfi = fcfp->FCFI;
1179 	mb->un.varRegVFI4.sid = port->did;
1180 
1181 	/* in ms */
1182 	mb->un.varRegVFI4.edtov = fcfp->fcf_sparam.cmn.e_d_tov;
1183 
1184 	/* Convert to seconds */
1185 	mb->un.varRegVFI4.ratov = (fcfp->fcf_sparam.cmn.w2.r_a_tov +
1186 	    999) / 1000;
1187 
1188 	mb->un.varRegVFI4.bde.tus.f.bdeSize = sizeof (SERV_PARM);
1189 	mb->un.varRegVFI4.bde.addrHigh = PADDR_HI(mp->phys);
1190 	mb->un.varRegVFI4.bde.addrLow = PADDR_LO(mp->phys);
1191 	bcopy((uint32_t *)&fcfp->fcf_sparam,
1192 	    (uint32_t *)mp->virt, sizeof (SERV_PARM));
1193 
1194 	mbq->mbox_cmpl = emlxs_mb_cmpl_reg_vfi;
1195 
1196 	/*
1197 	 * save address for completion
1198 	 */
1199 	mbq->bp = (uint8_t *)mp;
1200 	mbq->context = (uint8_t *)port;
1201 	return (1);
1202 
1203 } /* emlxs_mb_reg_vfi() */
1204 
1205 
1206 /*ARGSUSED*/
1207 extern int
1208 emlxs_mb_unreg_vfi(emlxs_hba_t *hba, VFIobj_t *vfip)
1209 {
1210 	FCFIobj_t *fcfp;
1211 	MAILBOX4 *mb;
1212 	MAILBOXQ *mbq;
1213 	uint32_t rval;
1214 
1215 	mutex_enter(&EMLXS_PORT_LOCK);
1216 	if (!(vfip->state & RESOURCE_VFI_REG)) {
1217 		mutex_exit(&EMLXS_PORT_LOCK);
1218 		return (1);
1219 
1220 	}
1221 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
1222 		mutex_exit(&EMLXS_PORT_LOCK);
1223 		return (1);
1224 	}
1225 
1226 	vfip->state &= ~RESOURCE_VFI_REG;
1227 	mutex_exit(&EMLXS_PORT_LOCK);
1228 
1229 	mb = (MAILBOX4 *)mbq->mbox;
1230 
1231 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1232 
1233 	mb->mbxCommand = MBX_UNREG_VFI;
1234 	mb->mbxOwner = OWN_HOST;
1235 
1236 	mb->un.varUnRegVFI4.vfi = vfip->VFI;
1237 
1238 	mbq->mbox_cmpl = NULL;
1239 
1240 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
1241 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
1242 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
1243 	}
1244 
1245 	fcfp = vfip->FCFIp;
1246 	if (vfip == fcfp->fcf_vfi) {
1247 		fcfp->fcf_vfi = NULL;
1248 	}
1249 	emlxs_sli4_free_vfi(hba, vfip);
1250 	return (1);
1251 
1252 } /* emlxs_mb_unreg_vfi() */
1253 
1254 
1255 /*ARGSUSED*/
1256 extern void
1257 emlxs_mb_async_event(emlxs_hba_t *hba, MAILBOXQ *mbq)
1258 {
1259 	MAILBOX *mb = (MAILBOX *)mbq;
1260 
1261 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1262 
1263 	mb->mbxCommand = MBX_ASYNC_EVENT;
1264 	mb->mbxOwner = OWN_HOST;
1265 	mb->un.varWords[0] = hba->channel_els;
1266 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1267 
1268 	return;
1269 
1270 } /* emlxs_mb_async_event() */
1271 
1272 
1273 /*ARGSUSED*/
1274 extern void
1275 emlxs_mb_heartbeat(emlxs_hba_t *hba, MAILBOXQ *mbq)
1276 {
1277 	MAILBOX *mb = (MAILBOX *)mbq;
1278 
1279 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1280 
1281 	mb->mbxCommand = MBX_HEARTBEAT;
1282 	mb->mbxOwner = OWN_HOST;
1283 	mbq->mbox_cmpl = NULL; /* no cmpl needed for hbeat */
1284 
1285 	return;
1286 
1287 } /* emlxs_mb_heartbeat() */
1288 
1289 
1290 #ifdef MSI_SUPPORT
1291 
1292 /*ARGSUSED*/
1293 extern void
1294 emlxs_mb_config_msi(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map,
1295     uint32_t intr_count)
1296 {
1297 	MAILBOX *mb = (MAILBOX *)mbq;
1298 	uint32_t i;
1299 	uint32_t mask;
1300 
1301 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1302 
1303 	mb->mbxCommand = MBX_CONFIG_MSI;
1304 
1305 	/* Set the default message id to zero */
1306 	mb->un.varCfgMSI.defaultPresent = 1;
1307 	mb->un.varCfgMSI.defaultMessageNumber = 0;
1308 
1309 	for (i = 1; i < intr_count; i++) {
1310 		mask = intr_map[i];
1311 
1312 		mb->un.varCfgMSI.attConditions |= mask;
1313 
1314 #ifdef EMLXS_BIG_ENDIAN
1315 		if (mask & HA_R0ATT) {
1316 			mb->un.varCfgMSI.messageNumberByHA[3] = i;
1317 		}
1318 		if (mask & HA_R1ATT) {
1319 			mb->un.varCfgMSI.messageNumberByHA[7] = i;
1320 		}
1321 		if (mask & HA_R2ATT) {
1322 			mb->un.varCfgMSI.messageNumberByHA[11] = i;
1323 		}
1324 		if (mask & HA_R3ATT) {
1325 			mb->un.varCfgMSI.messageNumberByHA[15] = i;
1326 		}
1327 		if (mask & HA_LATT) {
1328 			mb->un.varCfgMSI.messageNumberByHA[29] = i;
1329 		}
1330 		if (mask & HA_MBATT) {
1331 			mb->un.varCfgMSI.messageNumberByHA[30] = i;
1332 		}
1333 		if (mask & HA_ERATT) {
1334 			mb->un.varCfgMSI.messageNumberByHA[31] = i;
1335 		}
1336 #endif	/* EMLXS_BIG_ENDIAN */
1337 
1338 #ifdef EMLXS_LITTLE_ENDIAN
1339 		/* Accounts for half word swap of LE architecture */
1340 		if (mask & HA_R0ATT) {
1341 			mb->un.varCfgMSI.messageNumberByHA[2] = i;
1342 		}
1343 		if (mask & HA_R1ATT) {
1344 			mb->un.varCfgMSI.messageNumberByHA[6] = i;
1345 		}
1346 		if (mask & HA_R2ATT) {
1347 			mb->un.varCfgMSI.messageNumberByHA[10] = i;
1348 		}
1349 		if (mask & HA_R3ATT) {
1350 			mb->un.varCfgMSI.messageNumberByHA[14] = i;
1351 		}
1352 		if (mask & HA_LATT) {
1353 			mb->un.varCfgMSI.messageNumberByHA[28] = i;
1354 		}
1355 		if (mask & HA_MBATT) {
1356 			mb->un.varCfgMSI.messageNumberByHA[31] = i;
1357 		}
1358 		if (mask & HA_ERATT) {
1359 			mb->un.varCfgMSI.messageNumberByHA[30] = i;
1360 		}
1361 #endif	/* EMLXS_LITTLE_ENDIAN */
1362 	}
1363 
1364 	mb->mbxOwner = OWN_HOST;
1365 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1366 
1367 	return;
1368 
1369 } /* emlxs_mb_config_msi() */
1370 
1371 
1372 /*ARGSUSED*/
1373 extern void
1374 emlxs_mb_config_msix(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map,
1375     uint32_t intr_count)
1376 {
1377 	MAILBOX *mb = (MAILBOX *)mbq;
1378 	uint32_t i;
1379 	uint32_t mask;
1380 
1381 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1382 
1383 	mb->mbxCommand = MBX_CONFIG_MSIX;
1384 
1385 	/* Set the default message id to zero */
1386 	mb->un.varCfgMSIX.defaultPresent = 1;
1387 	mb->un.varCfgMSIX.defaultMessageNumber = 0;
1388 
1389 	for (i = 1; i < intr_count; i++) {
1390 		mask = intr_map[i];
1391 
1392 		mb->un.varCfgMSIX.attConditions1 |= mask;
1393 
1394 #ifdef EMLXS_BIG_ENDIAN
1395 		if (mask & HA_R0ATT) {
1396 			mb->un.varCfgMSIX.messageNumberByHA[3] = i;
1397 		}
1398 		if (mask & HA_R1ATT) {
1399 			mb->un.varCfgMSIX.messageNumberByHA[7] = i;
1400 		}
1401 		if (mask & HA_R2ATT) {
1402 			mb->un.varCfgMSIX.messageNumberByHA[11] = i;
1403 		}
1404 		if (mask & HA_R3ATT) {
1405 			mb->un.varCfgMSIX.messageNumberByHA[15] = i;
1406 		}
1407 		if (mask & HA_LATT) {
1408 			mb->un.varCfgMSIX.messageNumberByHA[29] = i;
1409 		}
1410 		if (mask & HA_MBATT) {
1411 			mb->un.varCfgMSIX.messageNumberByHA[30] = i;
1412 		}
1413 		if (mask & HA_ERATT) {
1414 			mb->un.varCfgMSIX.messageNumberByHA[31] = i;
1415 		}
1416 #endif	/* EMLXS_BIG_ENDIAN */
1417 
1418 #ifdef EMLXS_LITTLE_ENDIAN
1419 		/* Accounts for word swap of LE architecture */
1420 		if (mask & HA_R0ATT) {
1421 			mb->un.varCfgMSIX.messageNumberByHA[0] = i;
1422 		}
1423 		if (mask & HA_R1ATT) {
1424 			mb->un.varCfgMSIX.messageNumberByHA[4] = i;
1425 		}
1426 		if (mask & HA_R2ATT) {
1427 			mb->un.varCfgMSIX.messageNumberByHA[8] = i;
1428 		}
1429 		if (mask & HA_R3ATT) {
1430 			mb->un.varCfgMSIX.messageNumberByHA[12] = i;
1431 		}
1432 		if (mask & HA_LATT) {
1433 			mb->un.varCfgMSIX.messageNumberByHA[30] = i;
1434 		}
1435 		if (mask & HA_MBATT) {
1436 			mb->un.varCfgMSIX.messageNumberByHA[29] = i;
1437 		}
1438 		if (mask & HA_ERATT) {
1439 			mb->un.varCfgMSIX.messageNumberByHA[28] = i;
1440 		}
1441 #endif	/* EMLXS_LITTLE_ENDIAN */
1442 	}
1443 
1444 	mb->mbxOwner = OWN_HOST;
1445 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1446 
1447 	return;
1448 
1449 } /* emlxs_mb_config_msix() */
1450 
1451 
1452 #endif	/* MSI_SUPPORT */
1453 
1454 
1455 /*ARGSUSED*/
1456 extern void
1457 emlxs_mb_reset_ring(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t ringno)
1458 {
1459 	MAILBOX *mb = (MAILBOX *)mbq;
1460 
1461 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1462 
1463 	mb->mbxCommand = MBX_RESET_RING;
1464 	mb->un.varRstRing.ring_no = ringno;
1465 	mb->mbxOwner = OWN_HOST;
1466 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1467 
1468 	return;
1469 
1470 } /* emlxs_mb_reset_ring() */
1471 
1472 
1473 /*ARGSUSED*/
1474 extern void
1475 emlxs_mb_dump_vpd(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset)
1476 {
1477 
1478 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1479 		MAILBOX4 *mb = (MAILBOX4 *)mbq;
1480 
1481 		/* Clear the local dump_region */
1482 		bzero(hba->sli.sli4.dump_region.virt,
1483 		    hba->sli.sli4.dump_region.size);
1484 
1485 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1486 
1487 		mb->mbxCommand = MBX_DUMP_MEMORY;
1488 		mb->un.varDmp4.type = DMP_NV_PARAMS;
1489 		mb->un.varDmp4.entry_index = offset;
1490 		mb->un.varDmp4.region_id = DMP_VPD_REGION;
1491 
1492 		mb->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size;
1493 		mb->un.varDmp4.addrHigh =
1494 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
1495 		mb->un.varDmp4.addrLow =
1496 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
1497 		mb->un.varDmp4.rsp_cnt = 0;
1498 
1499 		mb->mbxOwner = OWN_HOST;
1500 
1501 	} else {
1502 		MAILBOX *mb = (MAILBOX *)mbq;
1503 
1504 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
1505 
1506 		mb->mbxCommand = MBX_DUMP_MEMORY;
1507 		mb->un.varDmp.cv = 1;
1508 		mb->un.varDmp.type = DMP_NV_PARAMS;
1509 		mb->un.varDmp.entry_index = offset;
1510 		mb->un.varDmp.region_id = DMP_VPD_REGION;
1511 
1512 		/* limited by mailbox size */
1513 		mb->un.varDmp.word_cnt = DMP_VPD_DUMP_WCOUNT;
1514 
1515 		mb->un.varDmp.co = 0;
1516 		mb->un.varDmp.resp_offset = 0;
1517 		mb->mbxOwner = OWN_HOST;
1518 	}
1519 
1520 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1521 
1522 } /* emlxs_mb_dump_vpd() */
1523 
1524 
1525 /*ARGSUSED*/
1526 extern void
1527 emlxs_mb_dump_fcoe(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset)
1528 {
1529 	MAILBOX4 *mb = (MAILBOX4 *)mbq;
1530 
1531 	if (hba->sli_mode != EMLXS_HBA_SLI4_MODE) {
1532 		return;
1533 	}
1534 	/* Clear the local dump_region */
1535 	bzero(hba->sli.sli4.dump_region.virt,
1536 	    hba->sli.sli4.dump_region.size);
1537 
1538 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1539 
1540 	mb->mbxCommand = MBX_DUMP_MEMORY;
1541 	mb->un.varDmp4.type = DMP_NV_PARAMS;
1542 	mb->un.varDmp4.entry_index = offset;
1543 	mb->un.varDmp4.region_id = DMP_FCOE_REGION;
1544 
1545 	mb->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size;
1546 	mb->un.varDmp4.addrHigh =
1547 	    PADDR_HI(hba->sli.sli4.dump_region.phys);
1548 	mb->un.varDmp4.addrLow =
1549 	    PADDR_LO(hba->sli.sli4.dump_region.phys);
1550 	mb->un.varDmp4.rsp_cnt = 0;
1551 
1552 	mb->mbxOwner = OWN_HOST;
1553 
1554 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1555 
1556 } /* emlxs_mb_dump_fcoe() */
1557 
1558 
1559 /*ARGSUSED*/
1560 extern void
1561 emlxs_mb_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset, uint32_t words)
1562 {
1563 
1564 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1565 		MAILBOX4 *mb = (MAILBOX4 *)mbq;
1566 
1567 		/* Clear the local dump_region */
1568 		bzero(hba->sli.sli4.dump_region.virt,
1569 		    hba->sli.sli4.dump_region.size);
1570 
1571 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1572 
1573 		mb->mbxCommand = MBX_DUMP_MEMORY;
1574 		mb->un.varDmp4.type = DMP_MEM_REG;
1575 		mb->un.varDmp4.entry_index = offset;
1576 		mb->un.varDmp4.region_id = 0;
1577 
1578 		mb->un.varDmp4.available_cnt = min((words*4),
1579 		    hba->sli.sli4.dump_region.size);
1580 		mb->un.varDmp4.addrHigh =
1581 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
1582 		mb->un.varDmp4.addrLow =
1583 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
1584 		mb->un.varDmp4.rsp_cnt = 0;
1585 
1586 		mb->mbxOwner = OWN_HOST;
1587 
1588 	} else {
1589 
1590 		MAILBOX *mb = (MAILBOX *)mbq;
1591 
1592 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
1593 
1594 		mb->mbxCommand = MBX_DUMP_MEMORY;
1595 		mb->un.varDmp.type = DMP_MEM_REG;
1596 		mb->un.varDmp.word_cnt = words;
1597 		mb->un.varDmp.base_adr = offset;
1598 
1599 		mb->un.varDmp.co = 0;
1600 		mb->un.varDmp.resp_offset = 0;
1601 		mb->mbxOwner = OWN_HOST;
1602 	}
1603 
1604 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1605 
1606 	return;
1607 
1608 } /* emlxs_mb_dump() */
1609 
1610 
1611 /*
1612  *  emlxs_mb_read_nv  Issue a READ NVPARAM mailbox command
1613  */
1614 /*ARGSUSED*/
1615 extern void
1616 emlxs_mb_read_nv(emlxs_hba_t *hba, MAILBOXQ *mbq)
1617 {
1618 	MAILBOX *mb = (MAILBOX *)mbq;
1619 
1620 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1621 
1622 	mb->mbxCommand = MBX_READ_NV;
1623 	mb->mbxOwner = OWN_HOST;
1624 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1625 
1626 } /* emlxs_mb_read_nv() */
1627 
1628 
1629 /*
1630  * emlxs_mb_read_rev  Issue a READ REV mailbox command
1631  */
1632 /*ARGSUSED*/
1633 extern void
1634 emlxs_mb_read_rev(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t v3)
1635 {
1636 	MAILBOX *mb = (MAILBOX *)mbq;
1637 
1638 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1639 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1640 		mbq->nonembed = NULL;
1641 	} else {
1642 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
1643 
1644 		mb->un.varRdRev.cv = 1;
1645 
1646 		if (v3) {
1647 			mb->un.varRdRev.cv3 = 1;
1648 		}
1649 	}
1650 
1651 	mb->mbxCommand = MBX_READ_REV;
1652 	mb->mbxOwner = OWN_HOST;
1653 	mbq->mbox_cmpl = NULL;
1654 
1655 } /* emlxs_mb_read_rev() */
1656 
1657 
1658 /*
1659  * emlxs_mb_run_biu_diag  Issue a RUN_BIU_DIAG mailbox command
1660  */
1661 /*ARGSUSED*/
1662 extern uint32_t
1663 emlxs_mb_run_biu_diag(emlxs_hba_t *hba, MAILBOXQ *mbq, uint64_t out,
1664     uint64_t in)
1665 {
1666 	MAILBOX *mb = (MAILBOX *)mbq;
1667 
1668 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1669 
1670 	mb->mbxCommand = MBX_RUN_BIU_DIAG64;
1671 	mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE;
1672 	mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = PADDR_HI(out);
1673 	mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = PADDR_LO(out);
1674 	mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE;
1675 	mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = PADDR_HI(in);
1676 	mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = PADDR_LO(in);
1677 	mb->mbxOwner = OWN_HOST;
1678 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1679 
1680 	return (0);
1681 } /* emlxs_mb_run_biu_diag() */
1682 
1683 
1684 /* This should only be called with active MBX_NOWAIT mailboxes */
1685 void
1686 emlxs_mb_retry(emlxs_hba_t *hba, MAILBOXQ *mbq)
1687 {
1688 	MAILBOX	*mb;
1689 	MAILBOX	*mbox;
1690 	int rc;
1691 
1692 	mbox = (MAILBOX *)emlxs_mem_get(hba, MEM_MBOX, 1);
1693 	if (!mbox) {
1694 		return;
1695 	}
1696 	mb = (MAILBOX *)mbq;
1697 	bcopy((uint8_t *)mb, (uint8_t *)mbox, MAILBOX_CMD_BSIZE);
1698 	mbox->mbxOwner = OWN_HOST;
1699 	mbox->mbxStatus = 0;
1700 
1701 	mutex_enter(&EMLXS_PORT_LOCK);
1702 
1703 	HBASTATS.MboxCompleted++;
1704 
1705 	if (mb->mbxStatus != 0) {
1706 		HBASTATS.MboxError++;
1707 	} else {
1708 		HBASTATS.MboxGood++;
1709 	}
1710 
1711 	hba->mbox_mbq = 0;
1712 	hba->mbox_queue_flag = 0;
1713 
1714 	mutex_exit(&EMLXS_PORT_LOCK);
1715 
1716 	rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0);
1717 	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
1718 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbox);
1719 	}
1720 	return;
1721 
1722 } /* emlxs_mb_retry() */
1723 
1724 
1725 int
1726 emlxs_cmpl_read_la(void *arg1, MAILBOXQ *mbq)
1727 {
1728 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
1729 	emlxs_port_t *port = &PPORT;
1730 	MAILBOX *mb;
1731 	MAILBOXQ *mbox;
1732 	MATCHMAP *mp;
1733 	READ_LA_VAR la;
1734 	int i;
1735 	uint32_t  control;
1736 
1737 	mb = (MAILBOX *)mbq;
1738 	if (mb->mbxStatus) {
1739 		if (mb->mbxStatus == MBXERR_NO_RESOURCES) {
1740 			control = mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize;
1741 			if (control == 0) {
1742 				(void) emlxs_mb_read_la(hba, mbq);
1743 			}
1744 			emlxs_mb_retry(hba, mbq);
1745 			return (1);
1746 		}
1747 		/* Enable Link Attention interrupts */
1748 		mutex_enter(&EMLXS_PORT_LOCK);
1749 
1750 		if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) {
1751 			hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
1752 			WRITE_CSR_REG(hba, FC_HC_REG(hba),
1753 			    hba->sli.sli3.hc_copy);
1754 #ifdef FMA_SUPPORT
1755 			/* Access handle validation */
1756 			EMLXS_CHK_ACC_HANDLE(hba,
1757 			    hba->sli.sli3.csr_acc_handle);
1758 #endif  /* FMA_SUPPORT */
1759 		}
1760 
1761 		mutex_exit(&EMLXS_PORT_LOCK);
1762 		return (0);
1763 	}
1764 	bcopy((uint32_t *)((char *)mb + sizeof (uint32_t)),
1765 	    (uint32_t *)&la, sizeof (READ_LA_VAR));
1766 
1767 	mp = (MATCHMAP *)mbq->bp;
1768 	if (mp) {
1769 		bcopy((caddr_t)mp->virt, (caddr_t)port->alpa_map, 128);
1770 	} else {
1771 		bzero((caddr_t)port->alpa_map, 128);
1772 	}
1773 
1774 	if (la.attType == AT_LINK_UP) {
1775 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_linkup_atten_msg,
1776 		    "tag=%d -> %d  ALPA=%x",
1777 		    (uint32_t)hba->link_event_tag,
1778 		    (uint32_t)la.eventTag,
1779 		    (uint32_t)la.granted_AL_PA);
1780 	} else {
1781 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_linkdown_atten_msg,
1782 		    "tag=%d -> %d  ALPA=%x",
1783 		    (uint32_t)hba->link_event_tag,
1784 		    (uint32_t)la.eventTag,
1785 		    (uint32_t)la.granted_AL_PA);
1786 	}
1787 
1788 	if (la.pb) {
1789 		hba->flag |= FC_BYPASSED_MODE;
1790 	} else {
1791 		hba->flag &= ~FC_BYPASSED_MODE;
1792 	}
1793 
1794 	if (hba->link_event_tag == la.eventTag) {
1795 		HBASTATS.LinkMultiEvent++;
1796 	} else if (hba->link_event_tag + 1 < la.eventTag) {
1797 		HBASTATS.LinkMultiEvent++;
1798 
1799 		/* Make sure link is declared down */
1800 		emlxs_linkdown(hba);
1801 	}
1802 
1803 	hba->link_event_tag = la.eventTag;
1804 	port->lip_type = 0;
1805 
1806 	/* If link not already up then declare it up now */
1807 	if ((la.attType == AT_LINK_UP) && (hba->state < FC_LINK_UP)) {
1808 
1809 #ifdef MENLO_SUPPORT
1810 		if ((hba->model_info.device_id == PCI_DEVICE_ID_LP21000_M) &&
1811 		    (hba->flag & (FC_ILB_MODE | FC_ELB_MODE))) {
1812 			la.topology = TOPOLOGY_LOOP;
1813 			la.granted_AL_PA = 0;
1814 			port->alpa_map[0] = 1;
1815 			port->alpa_map[1] = 0;
1816 			la.lipType = LT_PORT_INIT;
1817 		}
1818 #endif /* MENLO_SUPPORT */
1819 		/* Save the linkspeed */
1820 		hba->linkspeed = la.UlnkSpeed;
1821 
1822 		/* Check for old model adapters that only */
1823 		/* supported 1Gb */
1824 		if ((hba->linkspeed == 0) &&
1825 		    (hba->model_info.chip & EMLXS_DRAGONFLY_CHIP)) {
1826 			hba->linkspeed = LA_1GHZ_LINK;
1827 		}
1828 
1829 		if ((hba->topology = la.topology) == TOPOLOGY_LOOP) {
1830 			port->did = la.granted_AL_PA;
1831 			port->lip_type = la.lipType;
1832 			if (hba->flag & FC_SLIM2_MODE) {
1833 				i = la.un.lilpBde64.tus.f.bdeSize;
1834 			} else {
1835 				i = la.un.lilpBde.bdeSize;
1836 			}
1837 
1838 			if (i == 0) {
1839 				port->alpa_map[0] = 0;
1840 			} else {
1841 				uint8_t *alpa_map;
1842 				uint32_t j;
1843 
1844 				/* Check number of devices in map */
1845 				if (port->alpa_map[0] > 127) {
1846 					port->alpa_map[0] = 127;
1847 				}
1848 
1849 				alpa_map = (uint8_t *)port->alpa_map;
1850 
1851 				EMLXS_MSGF(EMLXS_CONTEXT,
1852 				    &emlxs_link_atten_msg,
1853 				    "alpa_map: %d device(s):      "
1854 				    "%02x %02x %02x %02x %02x %02x "
1855 				    "%02x", alpa_map[0], alpa_map[1],
1856 				    alpa_map[2], alpa_map[3],
1857 				    alpa_map[4], alpa_map[5],
1858 				    alpa_map[6], alpa_map[7]);
1859 
1860 				for (j = 8; j <= alpa_map[0]; j += 8) {
1861 					EMLXS_MSGF(EMLXS_CONTEXT,
1862 					    &emlxs_link_atten_msg,
1863 					    "alpa_map:             "
1864 					    "%02x %02x %02x %02x %02x "
1865 					    "%02x %02x %02x",
1866 					    alpa_map[j],
1867 					    alpa_map[j + 1],
1868 					    alpa_map[j + 2],
1869 					    alpa_map[j + 3],
1870 					    alpa_map[j + 4],
1871 					    alpa_map[j + 5],
1872 					    alpa_map[j + 6],
1873 					    alpa_map[j + 7]);
1874 				}
1875 			}
1876 		}
1877 #ifdef MENLO_SUPPORT
1878 		/* Check if Menlo maintenance mode is enabled */
1879 		if (hba->model_info.device_id ==
1880 		    PCI_DEVICE_ID_LP21000_M) {
1881 			if (la.mm == 1) {
1882 				EMLXS_MSGF(EMLXS_CONTEXT,
1883 				    &emlxs_link_atten_msg,
1884 				    "Maintenance Mode enabled.");
1885 
1886 				mutex_enter(&EMLXS_PORT_LOCK);
1887 				hba->flag |= FC_MENLO_MODE;
1888 				mutex_exit(&EMLXS_PORT_LOCK);
1889 
1890 				mutex_enter(&EMLXS_LINKUP_LOCK);
1891 				cv_broadcast(&EMLXS_LINKUP_CV);
1892 				mutex_exit(&EMLXS_LINKUP_LOCK);
1893 			} else {
1894 				EMLXS_MSGF(EMLXS_CONTEXT,
1895 				    &emlxs_link_atten_msg,
1896 				    "Maintenance Mode disabled.");
1897 			}
1898 
1899 			/* Check FCoE attention bit */
1900 			if (la.fa == 1) {
1901 				emlxs_thread_spawn(hba,
1902 				    emlxs_fcoe_attention_thread,
1903 				    NULL, NULL);
1904 			}
1905 		}
1906 #endif /* MENLO_SUPPORT */
1907 
1908 		if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1909 		    MEM_MBOX, 1))) {
1910 			/* This should turn on DELAYED ABTS for */
1911 			/* ELS timeouts */
1912 			emlxs_mb_set_var(hba, mbox, 0x00052198, 0x1);
1913 
1914 			emlxs_mb_put(hba, mbox);
1915 		}
1916 
1917 		if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1918 		    MEM_MBOX, 1))) {
1919 			/* If link not already down then */
1920 			/* declare it down now */
1921 			if (emlxs_mb_read_sparam(hba, mbox) == 0) {
1922 				emlxs_mb_put(hba, mbox);
1923 			} else {
1924 				(void) emlxs_mem_put(hba, MEM_MBOX,
1925 				    (uint8_t *)mbox);
1926 			}
1927 		}
1928 
1929 		if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1930 		    MEM_MBOX, 1))) {
1931 			emlxs_mb_config_link(hba, mbox);
1932 
1933 			emlxs_mb_put(hba, mbox);
1934 		}
1935 
1936 		/* Declare the linkup here */
1937 		emlxs_linkup(hba);
1938 	}
1939 
1940 	/* If link not already down then declare it down now */
1941 	else if (la.attType == AT_LINK_DOWN) {
1942 		/* Make sure link is declared down */
1943 		emlxs_linkdown(hba);
1944 	}
1945 
1946 	/* Enable Link attention interrupt */
1947 	mutex_enter(&EMLXS_PORT_LOCK);
1948 
1949 	if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) {
1950 		hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
1951 		WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
1952 #ifdef FMA_SUPPORT
1953 		/* Access handle validation */
1954 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
1955 #endif  /* FMA_SUPPORT */
1956 	}
1957 
1958 	mutex_exit(&EMLXS_PORT_LOCK);
1959 
1960 	/* Log the link event */
1961 	emlxs_log_link_event(port);
1962 	return (0);
1963 
1964 } /* emlxs_cmpl_read_la() */
1965 
1966 
1967 /*
1968  *  emlxs_mb_read_la  Issue a READ LA mailbox command
1969  */
1970 extern uint32_t
1971 emlxs_mb_read_la(emlxs_hba_t *hba, MAILBOXQ *mbq)
1972 {
1973 	MAILBOX *mb = (MAILBOX *)mbq;
1974 	MATCHMAP *mp;
1975 
1976 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1977 
1978 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
1979 		mb->mbxCommand = MBX_READ_LA64;
1980 
1981 		return (1);
1982 	}
1983 
1984 	mb->mbxCommand = MBX_READ_LA64;
1985 	mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
1986 	mb->un.varReadLA.un.lilpBde64.addrHigh = PADDR_HI(mp->phys);
1987 	mb->un.varReadLA.un.lilpBde64.addrLow = PADDR_LO(mp->phys);
1988 	mb->mbxOwner = OWN_HOST;
1989 	mbq->mbox_cmpl = emlxs_cmpl_read_la;
1990 
1991 	/*
1992 	 * save address for completion
1993 	 */
1994 	((MAILBOXQ *)mb)->bp = (uint8_t *)mp;
1995 
1996 	return (0);
1997 
1998 } /* emlxs_mb_read_la() */
1999 
2000 
2001 int
2002 emlxs_cmpl_clear_la(void *arg1, MAILBOXQ *mbq)
2003 {
2004 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
2005 	emlxs_port_t *port = &PPORT;
2006 	MAILBOX *mb;
2007 	MAILBOXQ *mbox;
2008 	emlxs_port_t *vport;
2009 	uint32_t la_enable;
2010 	int i, rc;
2011 
2012 	mb = (MAILBOX *)mbq;
2013 	if (mb->mbxStatus) {
2014 		la_enable = 1;
2015 
2016 		if (mb->mbxStatus == 0x1601) {
2017 			/* Get a buffer which will be used for */
2018 			/* mailbox commands */
2019 			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
2020 			    MEM_MBOX, 1))) {
2021 				/* Get link attention message */
2022 				if (emlxs_mb_read_la(hba, mbox) == 0) {
2023 					rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba,
2024 					    (MAILBOX *)mbox, MBX_NOWAIT, 0);
2025 					if ((rc != MBX_BUSY) &&
2026 					    (rc != MBX_SUCCESS)) {
2027 						(void) emlxs_mem_put(hba,
2028 						    MEM_MBOX, (uint8_t *)mbox);
2029 					}
2030 					la_enable = 0;
2031 				} else {
2032 					(void) emlxs_mem_put(hba, MEM_MBOX,
2033 					    (uint8_t *)mbox);
2034 				}
2035 			}
2036 		}
2037 
2038 		mutex_enter(&EMLXS_PORT_LOCK);
2039 		if (la_enable) {
2040 			if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) {
2041 				/* Enable Link Attention interrupts */
2042 				hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
2043 				WRITE_CSR_REG(hba, FC_HC_REG(hba),
2044 				    hba->sli.sli3.hc_copy);
2045 #ifdef FMA_SUPPORT
2046 				/* Access handle validation */
2047 				EMLXS_CHK_ACC_HANDLE(hba,
2048 				    hba->sli.sli3.csr_acc_handle);
2049 #endif  /* FMA_SUPPORT */
2050 			}
2051 		} else {
2052 			if (hba->sli.sli3.hc_copy & HC_LAINT_ENA) {
2053 				/* Disable Link Attention interrupts */
2054 				hba->sli.sli3.hc_copy &= ~HC_LAINT_ENA;
2055 				WRITE_CSR_REG(hba, FC_HC_REG(hba),
2056 				    hba->sli.sli3.hc_copy);
2057 #ifdef FMA_SUPPORT
2058 				/* Access handle validation */
2059 				EMLXS_CHK_ACC_HANDLE(hba,
2060 				    hba->sli.sli3.csr_acc_handle);
2061 #endif  /* FMA_SUPPORT */
2062 			}
2063 		}
2064 		mutex_exit(&EMLXS_PORT_LOCK);
2065 
2066 		return (0);
2067 	}
2068 	/* Enable on Link Attention interrupts */
2069 	mutex_enter(&EMLXS_PORT_LOCK);
2070 
2071 	if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) {
2072 		hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
2073 		WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
2074 #ifdef FMA_SUPPORT
2075 		/* Access handle validation */
2076 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
2077 #endif  /* FMA_SUPPORT */
2078 	}
2079 
2080 	if (hba->state >= FC_LINK_UP) {
2081 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY);
2082 	}
2083 
2084 	mutex_exit(&EMLXS_PORT_LOCK);
2085 
2086 	/* Adapter is now ready for FCP traffic */
2087 	if (hba->state == FC_READY) {
2088 		/* Register vpi's for all ports that have did's */
2089 		for (i = 0; i < MAX_VPORTS; i++) {
2090 			vport = &VPORT(i);
2091 
2092 			if (!(vport->flag & EMLXS_PORT_BOUND) ||
2093 			    !(vport->did)) {
2094 				continue;
2095 			}
2096 
2097 			(void) emlxs_mb_reg_vpi(vport, NULL);
2098 		}
2099 
2100 		/* Attempt to send any pending IO */
2101 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[hba->channel_fcp], 0);
2102 	}
2103 	return (0);
2104 
2105 } /* emlxs_cmpl_clear_la() */
2106 
2107 
2108 /*
2109  *  emlxs_mb_clear_la  Issue a CLEAR LA mailbox command
2110  */
2111 extern void
2112 emlxs_mb_clear_la(emlxs_hba_t *hba, MAILBOXQ *mbq)
2113 {
2114 	MAILBOX *mb = (MAILBOX *)mbq;
2115 
2116 #ifdef FC_RPI_CHECK
2117 	emlxs_rpi_check(hba);
2118 #endif	/* FC_RPI_CHECK */
2119 
2120 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2121 
2122 	mb->un.varClearLA.eventTag = hba->link_event_tag;
2123 	mb->mbxCommand = MBX_CLEAR_LA;
2124 	mb->mbxOwner = OWN_HOST;
2125 	mbq->mbox_cmpl = emlxs_cmpl_clear_la;
2126 
2127 	return;
2128 
2129 } /* emlxs_mb_clear_la() */
2130 
2131 
2132 /*
2133  * emlxs_mb_read_status  Issue a READ STATUS mailbox command
2134  */
2135 /*ARGSUSED*/
2136 extern void
2137 emlxs_mb_read_status(emlxs_hba_t *hba, MAILBOXQ *mbq)
2138 {
2139 	MAILBOX *mb = (MAILBOX *)mbq;
2140 
2141 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2142 
2143 	mb->mbxCommand = MBX_READ_STATUS;
2144 	mb->mbxOwner = OWN_HOST;
2145 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2146 
2147 } /* fc_read_status() */
2148 
2149 
2150 /*
2151  * emlxs_mb_read_lnk_stat  Issue a LINK STATUS mailbox command
2152  */
2153 /*ARGSUSED*/
2154 extern void
2155 emlxs_mb_read_lnk_stat(emlxs_hba_t *hba, MAILBOXQ *mbq)
2156 {
2157 	MAILBOX *mb = (MAILBOX *)mbq;
2158 
2159 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2160 
2161 	mb->mbxCommand = MBX_READ_LNK_STAT;
2162 	mb->mbxOwner = OWN_HOST;
2163 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2164 
2165 } /* emlxs_mb_read_lnk_stat() */
2166 
2167 
2168 /*
2169  * emlxs_mb_write_nv  Issue a WRITE NVPARAM mailbox command
2170  */
2171 static void
2172 emlxs_emb_mb_write_nv(emlxs_hba_t *hba, MAILBOXQ *mbq)
2173 {
2174 	MAILBOX *mb = (MAILBOX *)mbq;
2175 	int32_t		i;
2176 	emlxs_config_t	*cfg = &CFG;
2177 
2178 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2179 
2180 	bcopy((void *)&hba->wwnn,
2181 	    (void *)mb->un.varWTnvp.nodename, sizeof (NAME_TYPE));
2182 
2183 	bcopy((void *)&hba->wwpn,
2184 	    (void *)mb->un.varWTnvp.portname, sizeof (NAME_TYPE));
2185 
2186 	mb->un.varWTnvp.pref_DID = 0;
2187 	mb->un.varWTnvp.hardAL_PA = (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
2188 	mb->un.varWTnvp.rsvd1[0] = 0xffffffff;
2189 	mb->un.varWTnvp.rsvd1[1] = 0xffffffff;
2190 	mb->un.varWTnvp.rsvd1[2] = 0xffffffff;
2191 	for (i = 0; i < 21; i++) {
2192 		mb->un.varWTnvp.rsvd3[i] = 0xffffffff;
2193 	}
2194 
2195 	mb->mbxCommand = MBX_WRITE_NV;
2196 	mb->mbxOwner = OWN_HOST;
2197 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2198 
2199 } /* emlxs_mb_write_nv() */
2200 
2201 
2202 /*
2203  * emlxs_mb_part_slim  Issue a PARTITION SLIM mailbox command
2204  */
2205 static void
2206 emlxs_mb_part_slim(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t hbainit)
2207 {
2208 	MAILBOX *mb = (MAILBOX *)mbq;
2209 
2210 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2211 
2212 
2213 	mb->un.varSlim.numRing = hba->chan_count;
2214 	mb->un.varSlim.hbainit = hbainit;
2215 	mb->mbxCommand = MBX_PART_SLIM;
2216 	mb->mbxOwner = OWN_HOST;
2217 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2218 
2219 } /* emlxs_mb_part_slim() */
2220 
2221 
2222 /*
2223  * emlxs_mb_config_ring  Issue a CONFIG RING mailbox command
2224  */
2225 extern void
2226 emlxs_mb_config_ring(emlxs_hba_t *hba, int32_t ring, MAILBOXQ *mbq)
2227 {
2228 	MAILBOX *mb = (MAILBOX *)mbq;
2229 	int32_t i;
2230 	int32_t j;
2231 
2232 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2233 
2234 	j = 0;
2235 	for (i = 0; i < ring; i++) {
2236 		j += hba->sli.sli3.ring_masks[i];
2237 	}
2238 
2239 	for (i = 0; i < hba->sli.sli3.ring_masks[ring]; i++) {
2240 		if ((j + i) >= 6) {
2241 			break;
2242 		}
2243 
2244 		mb->un.varCfgRing.rrRegs[i].rval  =
2245 		    hba->sli.sli3.ring_rval[j + i];
2246 		mb->un.varCfgRing.rrRegs[i].rmask =
2247 		    hba->sli.sli3.ring_rmask[j + i];
2248 		mb->un.varCfgRing.rrRegs[i].tval  =
2249 		    hba->sli.sli3.ring_tval[j + i];
2250 		mb->un.varCfgRing.rrRegs[i].tmask =
2251 		    hba->sli.sli3.ring_tmask[j + i];
2252 	}
2253 
2254 	mb->un.varCfgRing.ring = ring;
2255 	mb->un.varCfgRing.profile = 0;
2256 	mb->un.varCfgRing.maxOrigXchg = 0;
2257 	mb->un.varCfgRing.maxRespXchg = 0;
2258 	mb->un.varCfgRing.recvNotify = 1;
2259 	mb->un.varCfgRing.numMask = hba->sli.sli3.ring_masks[ring];
2260 	mb->mbxCommand = MBX_CONFIG_RING;
2261 	mb->mbxOwner = OWN_HOST;
2262 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2263 
2264 	return;
2265 
2266 } /* emlxs_mb_config_ring() */
2267 
2268 
2269 /*
2270  *  emlxs_mb_config_link  Issue a CONFIG LINK mailbox command
2271  */
2272 extern void
2273 emlxs_mb_config_link(emlxs_hba_t *hba, MAILBOXQ *mbq)
2274 {
2275 	MAILBOX	*mb = (MAILBOX *)mbq;
2276 	emlxs_port_t   *port = &PPORT;
2277 	emlxs_config_t *cfg = &CFG;
2278 
2279 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2280 
2281 	/*
2282 	 * NEW_FEATURE SLI-2, Coalescing Response Feature.
2283 	 */
2284 	if (cfg[CFG_CR_DELAY].current) {
2285 		mb->un.varCfgLnk.cr = 1;
2286 		mb->un.varCfgLnk.ci = 1;
2287 		mb->un.varCfgLnk.cr_delay = cfg[CFG_CR_DELAY].current;
2288 		mb->un.varCfgLnk.cr_count = cfg[CFG_CR_COUNT].current;
2289 	}
2290 
2291 	if (cfg[CFG_ACK0].current)
2292 		mb->un.varCfgLnk.ack0_enable = 1;
2293 
2294 	mb->un.varCfgLnk.myId = port->did;
2295 	mb->un.varCfgLnk.edtov = hba->fc_edtov;
2296 	mb->un.varCfgLnk.arbtov = hba->fc_arbtov;
2297 	mb->un.varCfgLnk.ratov = hba->fc_ratov;
2298 	mb->un.varCfgLnk.rttov = hba->fc_rttov;
2299 	mb->un.varCfgLnk.altov = hba->fc_altov;
2300 	mb->un.varCfgLnk.crtov = hba->fc_crtov;
2301 	mb->un.varCfgLnk.citov = hba->fc_citov;
2302 	mb->mbxCommand = MBX_CONFIG_LINK;
2303 	mb->mbxOwner = OWN_HOST;
2304 	mbq->mbox_cmpl = NULL;
2305 
2306 	return;
2307 
2308 } /* emlxs_mb_config_link() */
2309 
2310 
2311 int
2312 emlxs_cmpl_init_link(void *arg1, MAILBOXQ *mbq)
2313 {
2314 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
2315 	emlxs_port_t *port = &PPORT;
2316 	emlxs_config_t	*cfg = &CFG;
2317 	MAILBOX *mb;
2318 
2319 	mb = (MAILBOX *)mbq;
2320 	if (mb->mbxStatus) {
2321 		if ((hba->flag & FC_SLIM2_MODE) &&
2322 		    (hba->mbox_queue_flag == MBX_NOWAIT)) {
2323 			/* Retry only MBX_NOWAIT requests */
2324 
2325 			if ((cfg[CFG_LINK_SPEED].current > 0) &&
2326 			    ((mb->mbxStatus == 0x0011) ||
2327 			    (mb->mbxStatus == 0x0500))) {
2328 
2329 				EMLXS_MSGF(EMLXS_CONTEXT,
2330 				    &emlxs_mbox_event_msg,
2331 				    "Retrying.  %s: status=%x. Auto-speed set.",
2332 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2333 				    (uint32_t)mb->mbxStatus);
2334 
2335 				mb->un.varInitLnk.link_flags &=
2336 				    ~FLAGS_LINK_SPEED;
2337 				mb->un.varInitLnk.link_speed = 0;
2338 
2339 				emlxs_mb_retry(hba, mbq);
2340 				return (1);
2341 			}
2342 		}
2343 	}
2344 	return (0);
2345 
2346 } /* emlxs_cmpl_init_link() */
2347 
2348 
2349 /*
2350  *  emlxs_mb_init_link  Issue an INIT LINK mailbox command
2351  */
2352 extern void
2353 emlxs_mb_init_link(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t topology,
2354     uint32_t linkspeed)
2355 {
2356 	MAILBOX *mb = (MAILBOX *)mbq;
2357 	emlxs_vpd_t	*vpd = &VPD;
2358 	emlxs_config_t	*cfg = &CFG;
2359 
2360 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2361 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
2362 		mbq->nonembed = NULL;
2363 		mbq->mbox_cmpl = NULL; /* no cmpl needed */
2364 
2365 		mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK;
2366 		mb->mbxOwner = OWN_HOST;
2367 		return;
2368 	}
2369 
2370 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2371 
2372 	switch (topology) {
2373 	case FLAGS_LOCAL_LB:
2374 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
2375 		mb->un.varInitLnk.link_flags |= FLAGS_LOCAL_LB;
2376 		break;
2377 	case FLAGS_TOPOLOGY_MODE_LOOP_PT:
2378 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
2379 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
2380 		break;
2381 	case FLAGS_TOPOLOGY_MODE_PT_PT:
2382 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
2383 		break;
2384 	case FLAGS_TOPOLOGY_MODE_LOOP:
2385 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
2386 		break;
2387 	case FLAGS_TOPOLOGY_MODE_PT_LOOP:
2388 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
2389 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
2390 		break;
2391 	}
2392 
2393 	if (cfg[CFG_LILP_ENABLE].current == 0) {
2394 		/* Disable LIRP/LILP support */
2395 		mb->un.varInitLnk.link_flags |= FLAGS_LIRP_LILP;
2396 	}
2397 
2398 	/*
2399 	 * Setting up the link speed
2400 	 */
2401 	switch (linkspeed) {
2402 	case 0:
2403 		break;
2404 
2405 	case 1:
2406 		if (!(vpd->link_speed & LMT_1GB_CAPABLE)) {
2407 			linkspeed = 0;
2408 		}
2409 		break;
2410 
2411 	case 2:
2412 		if (!(vpd->link_speed & LMT_2GB_CAPABLE)) {
2413 			linkspeed = 0;
2414 		}
2415 		break;
2416 
2417 	case 4:
2418 		if (!(vpd->link_speed & LMT_4GB_CAPABLE)) {
2419 			linkspeed = 0;
2420 		}
2421 		break;
2422 
2423 	case 8:
2424 		if (!(vpd->link_speed & LMT_8GB_CAPABLE)) {
2425 			linkspeed = 0;
2426 		}
2427 		break;
2428 
2429 	case 10:
2430 		if (!(vpd->link_speed & LMT_10GB_CAPABLE)) {
2431 			linkspeed = 0;
2432 		}
2433 		break;
2434 
2435 	default:
2436 		linkspeed = 0;
2437 		break;
2438 
2439 	}
2440 
2441 	if ((linkspeed > 0) && (vpd->feaLevelHigh >= 0x02)) {
2442 		mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
2443 		mb->un.varInitLnk.link_speed = linkspeed;
2444 	}
2445 
2446 	mb->un.varInitLnk.link_flags |= FLAGS_PREABORT_RETURN;
2447 
2448 	mb->un.varInitLnk.fabric_AL_PA =
2449 	    (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
2450 	mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK;
2451 	mb->mbxOwner = OWN_HOST;
2452 	mbq->mbox_cmpl = emlxs_cmpl_init_link;
2453 
2454 
2455 	return;
2456 
2457 } /* emlxs_mb_init_link() */
2458 
2459 
2460 /*
2461  *  emlxs_mb_down_link  Issue a DOWN LINK mailbox command
2462  */
2463 /*ARGSUSED*/
2464 extern void
2465 emlxs_mb_down_link(emlxs_hba_t *hba, MAILBOXQ *mbq)
2466 {
2467 	MAILBOX *mb = (MAILBOX *)mbq;
2468 
2469 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2470 
2471 	mb->mbxCommand = MBX_DOWN_LINK;
2472 	mb->mbxOwner = OWN_HOST;
2473 	mbq->mbox_cmpl = NULL;
2474 
2475 	return;
2476 
2477 } /* emlxs_mb_down_link() */
2478 
2479 
2480 int
2481 emlxs_cmpl_read_sparam(void *arg1, MAILBOXQ *mbq)
2482 {
2483 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
2484 	emlxs_port_t *port = &PPORT;
2485 	MAILBOX *mb;
2486 	MATCHMAP *mp;
2487 	emlxs_port_t *vport;
2488 	int32_t i;
2489 	uint32_t  control;
2490 	uint8_t null_wwn[8];
2491 
2492 	mb = (MAILBOX *)mbq;
2493 	if (mb->mbxStatus) {
2494 		if (mb->mbxStatus == MBXERR_NO_RESOURCES) {
2495 			control = mb->un.varRdSparm.un.sp64.tus.f.bdeSize;
2496 			if (control == 0) {
2497 				(void) emlxs_mb_read_sparam(hba, mbq);
2498 			}
2499 			emlxs_mb_retry(hba, mbq);
2500 			return (1);
2501 		}
2502 		return (0);
2503 	}
2504 	mp = (MATCHMAP *)mbq->bp;
2505 	if (!mp) {
2506 		return (0);
2507 	}
2508 
2509 	bcopy((caddr_t)mp->virt, (caddr_t)&hba->sparam, sizeof (SERV_PARM));
2510 
2511 	/* Initialize the node name and port name only once */
2512 	bzero(null_wwn, 8);
2513 	if ((bcmp((caddr_t)&hba->wwnn, (caddr_t)null_wwn, 8) == 0) &&
2514 	    (bcmp((caddr_t)&hba->wwpn, (caddr_t)null_wwn, 8) == 0)) {
2515 		bcopy((caddr_t)&hba->sparam.nodeName,
2516 		    (caddr_t)&hba->wwnn, sizeof (NAME_TYPE));
2517 
2518 		bcopy((caddr_t)&hba->sparam.portName,
2519 		    (caddr_t)&hba->wwpn, sizeof (NAME_TYPE));
2520 	} else {
2521 		bcopy((caddr_t)&hba->wwnn,
2522 		    (caddr_t)&hba->sparam.nodeName, sizeof (NAME_TYPE));
2523 
2524 		bcopy((caddr_t)&hba->wwpn,
2525 		    (caddr_t)&hba->sparam.portName, sizeof (NAME_TYPE));
2526 	}
2527 
2528 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2529 	    "SPARAM: EDTOV hba=x%x mbox_csp=x%x,  BBC=x%x",
2530 	    hba->fc_edtov, hba->sparam.cmn.e_d_tov,
2531 	    hba->sparam.cmn.bbCreditlsb);
2532 
2533 	hba->sparam.cmn.e_d_tov = hba->fc_edtov;
2534 
2535 	/* Initialize the physical port */
2536 	bcopy((caddr_t)&hba->sparam,
2537 	    (caddr_t)&port->sparam, sizeof (SERV_PARM));
2538 	bcopy((caddr_t)&hba->wwpn, (caddr_t)&port->wwpn,
2539 	    sizeof (NAME_TYPE));
2540 	bcopy((caddr_t)&hba->wwnn, (caddr_t)&port->wwnn,
2541 	    sizeof (NAME_TYPE));
2542 
2543 	/* Initialize the virtual ports */
2544 	for (i = 1; i < MAX_VPORTS; i++) {
2545 		vport = &VPORT(i);
2546 		if (vport->flag & EMLXS_PORT_BOUND) {
2547 			continue;
2548 		}
2549 
2550 		bcopy((caddr_t)&hba->sparam,
2551 		    (caddr_t)&vport->sparam,
2552 		    sizeof (SERV_PARM));
2553 
2554 		bcopy((caddr_t)&vport->wwnn,
2555 		    (caddr_t)&vport->sparam.nodeName,
2556 		    sizeof (NAME_TYPE));
2557 
2558 		bcopy((caddr_t)&vport->wwpn,
2559 		    (caddr_t)&vport->sparam.portName,
2560 		    sizeof (NAME_TYPE));
2561 	}
2562 
2563 	return (0);
2564 
2565 } /* emlxs_cmpl_read_sparam() */
2566 
2567 
2568 /*
2569  * emlxs_mb_read_sparam  Issue a READ SPARAM mailbox command
2570  */
2571 extern uint32_t
2572 emlxs_mb_read_sparam(emlxs_hba_t *hba, MAILBOXQ *mbq)
2573 {
2574 	MAILBOX *mb = (MAILBOX *)mbq;
2575 	MATCHMAP *mp;
2576 
2577 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2578 
2579 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
2580 		mb->mbxCommand = MBX_READ_SPARM64;
2581 
2582 		return (1);
2583 	}
2584 
2585 	mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
2586 	mb->un.varRdSparm.un.sp64.addrHigh = PADDR_HI(mp->phys);
2587 	mb->un.varRdSparm.un.sp64.addrLow = PADDR_LO(mp->phys);
2588 	mb->mbxCommand = MBX_READ_SPARM64;
2589 	mb->mbxOwner = OWN_HOST;
2590 	mbq->mbox_cmpl = emlxs_cmpl_read_sparam;
2591 
2592 	/*
2593 	 * save address for completion
2594 	 */
2595 	mbq->bp = (uint8_t *)mp;
2596 
2597 	return (0);
2598 
2599 } /* emlxs_mb_read_sparam() */
2600 
2601 
2602 /*
2603  * emlxs_mb_read_rpi    Issue a READ RPI mailbox command
2604  */
2605 /*ARGSUSED*/
2606 extern uint32_t
2607 emlxs_mb_read_rpi(emlxs_hba_t *hba, uint32_t rpi, MAILBOXQ *mbq,
2608     uint32_t flag)
2609 {
2610 	MAILBOX *mb = (MAILBOX *)mbq;
2611 
2612 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2613 
2614 	/*
2615 	 * Set flag to issue action on cmpl
2616 	 */
2617 	mb->un.varWords[30] = flag;
2618 	mb->un.varRdRPI.reqRpi = (volatile uint16_t) rpi;
2619 	mb->mbxCommand = MBX_READ_RPI64;
2620 	mb->mbxOwner = OWN_HOST;
2621 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2622 
2623 	return (0);
2624 } /* emlxs_mb_read_rpi() */
2625 
2626 
2627 /*
2628  * emlxs_mb_read_xri    Issue a READ XRI mailbox command
2629  */
2630 /*ARGSUSED*/
2631 extern uint32_t
2632 emlxs_mb_read_xri(emlxs_hba_t *hba, uint32_t xri, MAILBOXQ *mbq,
2633     uint32_t flag)
2634 {
2635 	MAILBOX *mb = (MAILBOX *)mbq;
2636 
2637 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2638 
2639 	/*
2640 	 * Set flag to issue action on cmpl
2641 	 */
2642 	mb->un.varWords[30] = flag;
2643 	mb->un.varRdXRI.reqXri = (volatile uint16_t)xri;
2644 	mb->mbxCommand = MBX_READ_XRI;
2645 	mb->mbxOwner = OWN_HOST;
2646 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2647 
2648 	return (0);
2649 } /* emlxs_mb_read_xri() */
2650 
2651 
2652 /*ARGSUSED*/
2653 extern int32_t
2654 emlxs_mb_check_sparm(emlxs_hba_t *hba, SERV_PARM *nsp)
2655 {
2656 	uint32_t nsp_value;
2657 	uint32_t *iptr;
2658 
2659 	if (nsp->cmn.fPort) {
2660 		return (0);
2661 	}
2662 
2663 	/* Validate the service parameters */
2664 	iptr = (uint32_t *)&nsp->portName;
2665 	if (iptr[0] == 0 && iptr[1] == 0) {
2666 		return (1);
2667 	}
2668 
2669 	iptr = (uint32_t *)&nsp->nodeName;
2670 	if (iptr[0] == 0 && iptr[1] == 0) {
2671 		return (2);
2672 	}
2673 
2674 	if (nsp->cls2.classValid) {
2675 		nsp_value =
2676 		    ((nsp->cls2.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls2.
2677 		    rcvDataSizeLsb;
2678 
2679 		/* If the receive data length is zero then set it to */
2680 		/* the CSP value */
2681 		if (!nsp_value) {
2682 			nsp->cls2.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb;
2683 			nsp->cls2.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb;
2684 			return (0);
2685 		}
2686 	}
2687 
2688 	if (nsp->cls3.classValid) {
2689 		nsp_value =
2690 		    ((nsp->cls3.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls3.
2691 		    rcvDataSizeLsb;
2692 
2693 		/* If the receive data length is zero then set it to */
2694 		/* the CSP value */
2695 		if (!nsp_value) {
2696 			nsp->cls3.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb;
2697 			nsp->cls3.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb;
2698 			return (0);
2699 		}
2700 	}
2701 
2702 	return (0);
2703 
2704 } /* emlxs_mb_check_sparm() */
2705 
2706 
2707 int
2708 emlxs_cmpl_reg_did(void *arg1, MAILBOXQ *mbq)
2709 {
2710 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
2711 	emlxs_port_t *port = &PPORT;
2712 	MAILBOX *mb;
2713 	MATCHMAP *mp;
2714 	NODELIST *ndlp;
2715 	emlxs_port_t *vport;
2716 	uint8_t *wwn;
2717 	volatile SERV_PARM *sp;
2718 	int32_t i;
2719 	uint32_t  control;
2720 	uint32_t ldata;
2721 	uint32_t ldid;
2722 	uint16_t lrpi;
2723 	uint16_t lvpi;
2724 	emlxs_vvl_fmt_t vvl;
2725 
2726 	mb = (MAILBOX *)mbq;
2727 	if (mb->mbxStatus) {
2728 		if (mb->mbxStatus == MBXERR_NO_RESOURCES) {
2729 			control = mb->un.varRegLogin.un.sp.bdeSize;
2730 			if (control == 0) {
2731 				/* Special handle for vport PLOGI */
2732 				if (mbq->iocbq == (uint8_t *)1) {
2733 					mbq->iocbq = NULL;
2734 				}
2735 				return (0);
2736 			}
2737 			emlxs_mb_retry(hba, mbq);
2738 			return (1);
2739 		}
2740 		if (mb->mbxStatus == MBXERR_RPI_FULL) {
2741 			port = &VPORT((mb->un.varRegLogin.vpi - hba->vpi_base));
2742 
2743 			EMLXS_MSGF(EMLXS_CONTEXT,
2744 			    &emlxs_node_create_failed_msg,
2745 			    "Limit reached. count=%d", port->node_count);
2746 		}
2747 
2748 		/* Special handle for vport PLOGI */
2749 		if (mbq->iocbq == (uint8_t *)1) {
2750 			mbq->iocbq = NULL;
2751 		}
2752 
2753 		return (0);
2754 	}
2755 
2756 	mp = (MATCHMAP *)mbq->bp;
2757 	if (!mp) {
2758 		return (0);
2759 	}
2760 	ldata = mb->un.varWords[5];
2761 	lvpi = (ldata & 0xffff) - hba->vpi_base;
2762 	port = &VPORT(lvpi);
2763 
2764 	/* First copy command data */
2765 	ldata = mb->un.varWords[0];	/* get rpi */
2766 	lrpi = ldata & 0xffff;
2767 
2768 	ldata = mb->un.varWords[1];	/* get did */
2769 	ldid = ldata & MASK_DID;
2770 
2771 	sp = (volatile SERV_PARM *)mp->virt;
2772 	ndlp = emlxs_node_find_did(port, ldid);
2773 
2774 	if (!ndlp) {
2775 		/* Attempt to create a node */
2776 		if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) {
2777 			ndlp->nlp_Rpi = lrpi;
2778 			ndlp->nlp_DID = ldid;
2779 
2780 			bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm,
2781 			    sizeof (SERV_PARM));
2782 
2783 			bcopy((uint8_t *)&sp->nodeName,
2784 			    (uint8_t *)&ndlp->nlp_nodename,
2785 			    sizeof (NAME_TYPE));
2786 
2787 			bcopy((uint8_t *)&sp->portName,
2788 			    (uint8_t *)&ndlp->nlp_portname,
2789 			    sizeof (NAME_TYPE));
2790 
2791 			ndlp->nlp_active = 1;
2792 			ndlp->nlp_flag[hba->channel_ct]  |= NLP_CLOSED;
2793 			ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED;
2794 			ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED;
2795 			ndlp->nlp_flag[hba->channel_ip]  |= NLP_CLOSED;
2796 
2797 			/* Add the node */
2798 			emlxs_node_add(port, ndlp);
2799 
2800 			/* Open the node */
2801 			emlxs_node_open(port, ndlp, hba->channel_ct);
2802 			emlxs_node_open(port, ndlp, hba->channel_els);
2803 			emlxs_node_open(port, ndlp, hba->channel_ip);
2804 			emlxs_node_open(port, ndlp, hba->channel_fcp);
2805 		} else {
2806 			wwn = (uint8_t *)&sp->portName;
2807 			EMLXS_MSGF(EMLXS_CONTEXT,
2808 			    &emlxs_node_create_failed_msg,
2809 			    "Unable to allocate node. did=%06x rpi=%x "
2810 			    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
2811 			    ldid, lrpi, wwn[0], wwn[1], wwn[2],
2812 			    wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
2813 
2814 			return (0);
2815 		}
2816 	} else {
2817 		mutex_enter(&EMLXS_PORT_LOCK);
2818 
2819 		ndlp->nlp_Rpi = lrpi;
2820 		ndlp->nlp_DID = ldid;
2821 
2822 		bcopy((uint8_t *)sp,
2823 		    (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM));
2824 
2825 		bcopy((uint8_t *)&sp->nodeName,
2826 		    (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE));
2827 
2828 		bcopy((uint8_t *)&sp->portName,
2829 		    (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE));
2830 
2831 		wwn = (uint8_t *)&ndlp->nlp_portname;
2832 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg,
2833 		    "node=%p did=%06x rpi=%x "
2834 		    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
2835 		    ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
2836 		    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
2837 
2838 		mutex_exit(&EMLXS_PORT_LOCK);
2839 
2840 		/* Open the node */
2841 		emlxs_node_open(port, ndlp, hba->channel_ct);
2842 		emlxs_node_open(port, ndlp, hba->channel_els);
2843 		emlxs_node_open(port, ndlp, hba->channel_ip);
2844 		emlxs_node_open(port, ndlp, hba->channel_fcp);
2845 	}
2846 
2847 	bzero((char *)&vvl, sizeof (emlxs_vvl_fmt_t));
2848 
2849 	if (sp->VALID_VENDOR_VERSION) {
2850 
2851 		bcopy((caddr_t *)&sp->vendorVersion[0],
2852 		    (caddr_t *)&vvl, sizeof (emlxs_vvl_fmt_t));
2853 
2854 		vvl.un0.word0 = LE_SWAP32(vvl.un0.word0);
2855 		vvl.un1.word1 = LE_SWAP32(vvl.un1.word1);
2856 
2857 		if ((vvl.un0.w0.oui == 0x0000C9) &&
2858 		    (vvl.un1.w1.vport)) {
2859 			ndlp->nlp_fcp_info |= NLP_EMLX_VPORT;
2860 		}
2861 	}
2862 
2863 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
2864 	    (ndlp->nlp_DID == NAMESERVER_DID)) {
2865 			EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY);
2866 	}
2867 
2868 	/* If this was a fabric login */
2869 	if (ndlp->nlp_DID == FABRIC_DID) {
2870 		/* If CLEAR_LA has been sent, then attempt to */
2871 		/* register the vpi now */
2872 		if (hba->state == FC_READY) {
2873 			(void) emlxs_mb_reg_vpi(port, NULL);
2874 		}
2875 
2876 		/*
2877 		 * If NPIV Fabric support has just been established on
2878 		 * the physical port, then notify the vports of the
2879 		 * link up
2880 		 */
2881 		if ((lvpi == 0) &&
2882 		    (hba->flag & FC_NPIV_ENABLED) &&
2883 		    (hba->flag & FC_NPIV_SUPPORTED)) {
2884 			/* Skip the physical port */
2885 			for (i = 1; i < MAX_VPORTS; i++) {
2886 				vport = &VPORT(i);
2887 
2888 				if (!(vport->flag & EMLXS_PORT_BOUND) ||
2889 				    !(vport->flag & EMLXS_PORT_ENABLE)) {
2890 					continue;
2891 				}
2892 
2893 				emlxs_port_online(vport);
2894 			}
2895 		}
2896 	}
2897 
2898 	if (mbq->iocbq == (uint8_t *)1) {
2899 		mbq->iocbq = NULL;
2900 		(void) emlxs_mb_unreg_did(port, ldid, NULL, NULL, NULL);
2901 	}
2902 
2903 #ifdef DHCHAP_SUPPORT
2904 	if (mbq->sbp || mbq->ubp) {
2905 		if (emlxs_dhc_auth_start(port, ndlp, mbq->sbp,
2906 		    mbq->ubp) == 0) {
2907 			/* Auth started - auth completion will */
2908 			/* handle sbp and ubp now */
2909 			mbq->sbp = NULL;
2910 			mbq->ubp = NULL;
2911 		}
2912 	}
2913 #endif	/* DHCHAP_SUPPORT */
2914 
2915 #ifdef SFCT_SUPPORT
2916 	if (mbq->sbp && ((emlxs_buf_t *)mbq->sbp)->fct_cmd) {
2917 		emlxs_buf_t *cmd_sbp = (emlxs_buf_t *)mbq->sbp;
2918 
2919 		if (cmd_sbp->fct_state == EMLXS_FCT_REG_PENDING) {
2920 			mbq->sbp = NULL;
2921 
2922 			mutex_enter(&EMLXS_PKT_LOCK);
2923 			cmd_sbp->node = ndlp;
2924 			cv_broadcast(&EMLXS_PKT_CV);
2925 			mutex_exit(&EMLXS_PKT_LOCK);
2926 		}
2927 	}
2928 #endif /* SFCT_SUPPORT */
2929 	return (0);
2930 
2931 } /* emlxs_cmpl_reg_did() */
2932 
2933 
2934 /*
2935  * emlxs_mb_reg_did  Issue a REG_LOGIN mailbox command
2936  */
2937 extern uint32_t
2938 emlxs_mb_reg_did(emlxs_port_t *port, uint32_t did, SERV_PARM *param,
2939     emlxs_buf_t *sbp, fc_unsol_buf_t *ubp, IOCBQ *iocbq)
2940 {
2941 	emlxs_hba_t	*hba = HBA;
2942 	MATCHMAP	*mp;
2943 	MAILBOXQ	*mbq;
2944 	MAILBOX		*mb;
2945 	NODELIST	*node;
2946 	RPIobj_t	*rp = NULL;
2947 	uint32_t	rval;
2948 
2949 	/* Check for invalid node ids to register */
2950 	if ((did == 0) && (!(hba->flag & FC_LOOPBACK_MODE))) {
2951 		return (1);
2952 	}
2953 
2954 	if (did & 0xff000000) {
2955 		return (1);
2956 	}
2957 
2958 	if ((rval = emlxs_mb_check_sparm(hba, param))) {
2959 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
2960 		    "Invalid service parameters. did=%06x rval=%d", did,
2961 		    rval);
2962 
2963 		return (1);
2964 	}
2965 
2966 	/* Check if the node limit has been reached */
2967 	if (port->node_count >= hba->max_nodes) {
2968 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
2969 		    "Limit reached. did=%06x count=%d", did,
2970 		    port->node_count);
2971 
2972 		return (1);
2973 	}
2974 
2975 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
2976 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
2977 		    "Unable to allocate mailbox. did=%x", did);
2978 
2979 		return (1);
2980 	}
2981 	mb = (MAILBOX *)mbq->mbox;
2982 
2983 	/* Build login request */
2984 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF, 1)) == 0) {
2985 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
2986 		    "Unable to allocate buffer. did=%x", did);
2987 
2988 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
2989 		return (1);
2990 	}
2991 
2992 	/*
2993 	 * If we are SLI4, the RPI number gets assigned by the driver.
2994 	 * For SLI3, the firmware assigns the RPI number.
2995 	 */
2996 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2997 		node = emlxs_node_find_did(port, did);
2998 		rp = EMLXS_NODE_TO_RPI(hba, node);
2999 
3000 		if (!rp) {
3001 			rp = emlxs_sli4_alloc_rpi(port);
3002 		}
3003 
3004 		if (!rp) {
3005 			EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_create_failed_msg,
3006 			    "Unable to get an rpi. did=%x", did);
3007 
3008 			(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
3009 			return (1);
3010 		}
3011 		rp->state &= ~RESOURCE_RPI_PAUSED;
3012 	}
3013 
3014 	bcopy((void *)param, (void *)mp->virt, sizeof (SERV_PARM));
3015 
3016 	mb->un.varRegLogin.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
3017 	mb->un.varRegLogin.un.sp64.addrHigh = PADDR_HI(mp->phys);
3018 	mb->un.varRegLogin.un.sp64.addrLow = PADDR_LO(mp->phys);
3019 	mb->un.varRegLogin.did = did;
3020 	mb->un.varWords[30] = 0;	/* flags */
3021 	mb->mbxCommand = MBX_REG_LOGIN64;
3022 	mb->mbxOwner = OWN_HOST;
3023 	mb->un.varRegLogin.vpi = port->vpi + hba->vpi_base;
3024 	mb->un.varRegLogin.rpi = (rp)? rp->RPI: 0;
3025 
3026 	mbq->sbp = (uint8_t *)sbp;
3027 	mbq->ubp = (uint8_t *)ubp;
3028 	mbq->iocbq = (uint8_t *)iocbq;
3029 	mbq->bp = (uint8_t *)mp;
3030 	mbq->mbox_cmpl = emlxs_cmpl_reg_did;
3031 
3032 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3033 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3034 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
3035 		if (rp) {
3036 			emlxs_sli4_free_rpi(hba, rp);
3037 		}
3038 	}
3039 
3040 	return (0);
3041 
3042 } /* emlxs_mb_reg_did() */
3043 
3044 /*
3045  * emlxs_mb_unreg_rpi  Issue a UNREG_LOGIN mailbox command
3046  */
3047 extern uint32_t
3048 emlxs_mb_unreg_rpi(emlxs_port_t *port, uint32_t rpi, emlxs_buf_t *sbp,
3049     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
3050 {
3051 	emlxs_hba_t	*hba = HBA;
3052 	MAILBOXQ	*mbq;
3053 	MAILBOX		*mb;
3054 	NODELIST	*ndlp;
3055 	int rval;
3056 
3057 	if (rpi != 0xffff) {
3058 		/* Make sure the node does already exist */
3059 		ndlp = emlxs_node_find_rpi(port, rpi);
3060 
3061 
3062 		if (ndlp) {
3063 			/*
3064 			 * If we just unregistered the host node then
3065 			 * clear the host DID
3066 			 */
3067 			if (ndlp->nlp_DID == port->did) {
3068 				port->did = 0;
3069 			}
3070 
3071 			/* remove it */
3072 			emlxs_node_rm(port, ndlp);
3073 
3074 		} else {
3075 			return (1);
3076 		}
3077 	} else {	/* Unreg all */
3078 
3079 		emlxs_node_destroy_all(port);
3080 	}
3081 
3082 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
3083 		return (1);
3084 	}
3085 
3086 	mb = (MAILBOX *)mbq->mbox;
3087 
3088 #define	INDEX_INDICATOR_VPI	1
3089 
3090 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) && (rpi == 0xffff)) {
3091 		mb->un.varUnregLogin.ll = INDEX_INDICATOR_VPI;
3092 		mb->un.varUnregLogin.rpi = (uint16_t)port->vpi + hba->vpi_base;
3093 	} else {
3094 		mb->un.varUnregLogin.rpi = (uint16_t)rpi;
3095 	}
3096 
3097 	mb->un.varUnregLogin.vpi = port->vpi + hba->vpi_base;
3098 	mb->mbxCommand = MBX_UNREG_LOGIN;
3099 	mb->mbxOwner = OWN_HOST;
3100 	mbq->sbp = (uint8_t *)sbp;
3101 	mbq->ubp = (uint8_t *)ubp;
3102 	mbq->iocbq = (uint8_t *)iocbq;
3103 	mbq->mbox_cmpl = NULL;
3104 
3105 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3106 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3107 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
3108 	}
3109 
3110 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3111 		port->outstandingRPIs--;
3112 		if ((port->outstandingRPIs == 0) &&
3113 		    (hba->state == FC_LINK_DOWN)) {
3114 			/* No more RPIs so unreg the VPI */
3115 			(void) emlxs_mb_unreg_vpi(port);
3116 		}
3117 	}
3118 
3119 	return (0);
3120 } /* emlxs_mb_unreg_rpi() */
3121 
3122 
3123 /*
3124  * emlxs_mb_unreg_did  Issue a UNREG_DID mailbox command
3125  */
3126 extern uint32_t
3127 emlxs_mb_unreg_did(emlxs_port_t *port, uint32_t did, emlxs_buf_t *sbp,
3128     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
3129 {
3130 	emlxs_hba_t	*hba = HBA;
3131 	NODELIST	*ndlp;
3132 	MAILBOXQ	*mbq;
3133 	MAILBOX		*mb;
3134 	int rval = 0;
3135 
3136 	/*
3137 	 * Unregister all default RPIs if did == 0xffffffff
3138 	 */
3139 	if (did != 0xffffffff) {
3140 		/* Check for base node */
3141 		if (did == BCAST_DID) {
3142 			/* just flush base node */
3143 			(void) emlxs_tx_node_flush(port, &port->node_base,
3144 			    0, 0, 0);
3145 			(void) emlxs_chipq_node_flush(port, 0,
3146 			    &port->node_base, 0);
3147 
3148 			/* Return now */
3149 			return (1);
3150 		}
3151 
3152 
3153 		/*
3154 		 * A zero DID means that we are trying to unreg the host node
3155 		 * after a link bounce
3156 		 */
3157 
3158 		/*
3159 		 * If the prev_did == 0 then the adapter has been reset and
3160 		 * there is no need in unregistering
3161 		 */
3162 
3163 		/*
3164 		 * If the prev_did != 0 then we can look for the hosts
3165 		 * last known DID node
3166 		 */
3167 
3168 		if (did == 0) {
3169 			if (port->prev_did == 0) {
3170 				return (1);
3171 			}
3172 
3173 			did = port->prev_did;
3174 		}
3175 
3176 		/* Make sure the node does already exist */
3177 		ndlp = emlxs_node_find_did(port, did);
3178 
3179 		if (ndlp) {
3180 			if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3181 				/* Use UNREG_RPI for SLI4 */
3182 				if (ndlp->nlp_Rpi != 0xffff) {
3183 					rval = emlxs_mb_unreg_rpi(port,
3184 					    ndlp->nlp_Rpi, sbp, ubp, iocbq);
3185 				}
3186 				return (rval);
3187 			}
3188 			/* remove it */
3189 			emlxs_node_rm(port, ndlp);
3190 
3191 			/*
3192 			 * If we just unregistered the host node then
3193 			 * clear the host DID
3194 			 */
3195 			if (did == port->did) {
3196 				port->did = 0;
3197 			}
3198 
3199 		} else {
3200 			return (1);
3201 		}
3202 	} else {
3203 		/* SLI4 doesn't have dflt RPIs in SLI Port */
3204 		if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3205 			return (0);
3206 		}
3207 	}
3208 
3209 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
3210 		return (1);
3211 	}
3212 
3213 	mb = (MAILBOX *)mbq->mbox;
3214 	mb->un.varUnregDID.did = did;
3215 	mb->un.varUnregDID.vpi = port->vpi + hba->vpi_base;
3216 	mb->mbxCommand = MBX_UNREG_D_ID;
3217 	mb->mbxOwner = OWN_HOST;
3218 	mbq->sbp = (uint8_t *)sbp;
3219 	mbq->ubp = (uint8_t *)ubp;
3220 	mbq->iocbq = (uint8_t *)iocbq;
3221 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
3222 
3223 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3224 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3225 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
3226 	}
3227 
3228 	return (0);
3229 
3230 } /* emlxs_mb_unreg_did() */
3231 
3232 
3233 /*
3234  * emlxs_mb_set_mask   Issue a SET MASK mailbox command
3235  */
3236 /*ARGSUSED*/
3237 static void
3238 emlxs_mb_set_mask(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t mask,
3239     uint32_t ringno)
3240 {
3241 	MAILBOX *mb = (MAILBOX *)mbq;
3242 
3243 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
3244 
3245 	mb->un.varWords[0] = 0x11223344;	/* set passwd */
3246 	mb->un.varWords[1] = mask;	/* set mask */
3247 	mb->un.varWords[2] = ringno;	/* set ringno */
3248 	mb->mbxCommand = MBX_SET_MASK;
3249 	mb->mbxOwner = OWN_HOST;
3250 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
3251 
3252 } /* emlxs_mb_set_mask() */
3253 
3254 
3255 /*
3256  * emlxs_mb_set_debug  Issue a special debug mailbox command
3257  */
3258 /*ARGSUSED*/
3259 static void
3260 emlxs_mb_set_debug(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t word0,
3261     uint32_t word1, uint32_t word2)
3262 {
3263 	MAILBOX *mb = (MAILBOX *)mbq;
3264 
3265 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
3266 
3267 	mb->un.varWords[0] = word0;
3268 	mb->un.varWords[1] = word1;
3269 	mb->un.varWords[2] = word2;
3270 	mb->mbxCommand = MBX_SET_DEBUG;
3271 	mb->mbxOwner = OWN_HOST;
3272 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
3273 
3274 } /* emlxs_mb_set_debug() */
3275 
3276 
3277 /*
3278  * emlxs_mb_set_var   Issue a special debug mbox command to write slim
3279  */
3280 /*ARGSUSED*/
3281 extern void
3282 emlxs_mb_set_var(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t addr,
3283     uint32_t value)
3284 {
3285 	MAILBOX *mb = (MAILBOX *)mbq;
3286 
3287 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
3288 
3289 	/* addr = 0x090597 is AUTO ABTS disable for ELS commands */
3290 	/* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
3291 	/* addr = 0x100506 is for setting PCI MAX READ value */
3292 
3293 	/*
3294 	 * Always turn on DELAYED ABTS for ELS timeouts
3295 	 */
3296 	if ((addr == 0x052198) && (value == 0)) {
3297 		value = 1;
3298 	}
3299 
3300 	mb->un.varWords[0] = addr;
3301 	mb->un.varWords[1] = value;
3302 	mb->mbxCommand = MBX_SET_VARIABLE;
3303 	mb->mbxOwner = OWN_HOST;
3304 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
3305 
3306 } /* emlxs_mb_set_var() */
3307 
3308 
3309 /*
3310  * Disable Traffic Cop
3311  */
3312 /*ARGSUSED*/
3313 extern void
3314 emlxs_disable_tc(emlxs_hba_t *hba, MAILBOXQ *mbq)
3315 {
3316 	MAILBOX *mb = (MAILBOX *)mbq;
3317 
3318 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
3319 
3320 	mb->un.varWords[0] = 0x50797;
3321 	mb->un.varWords[1] = 0;
3322 	mb->un.varWords[2] = 0xfffffffe;
3323 	mb->mbxCommand = MBX_SET_VARIABLE;
3324 	mb->mbxOwner = OWN_HOST;
3325 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
3326 
3327 } /* emlxs_disable_tc() */
3328 
3329 
3330 extern void
3331 emlxs_mb_config_hbq(emlxs_hba_t *hba, MAILBOXQ *mbq, int hbq_id)
3332 {
3333 	HBQ_INIT_t	*hbq;
3334 	MAILBOX		*mb = (MAILBOX *)mbq;
3335 	int		i;
3336 
3337 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
3338 
3339 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
3340 
3341 	mb->un.varCfgHbq.hbqId = hbq_id;
3342 	mb->un.varCfgHbq.numEntries = hbq->HBQ_numEntries;
3343 	mb->un.varCfgHbq.recvNotify = hbq->HBQ_recvNotify;
3344 	mb->un.varCfgHbq.numMask = hbq->HBQ_num_mask;
3345 	mb->un.varCfgHbq.profile = hbq->HBQ_profile;
3346 	mb->un.varCfgHbq.ringMask = hbq->HBQ_ringMask;
3347 	mb->un.varCfgHbq.headerLen = hbq->HBQ_headerLen;
3348 	mb->un.varCfgHbq.logEntry = hbq->HBQ_logEntry;
3349 	mb->un.varCfgHbq.hbqaddrLow = PADDR_LO(hbq->HBQ_host_buf.phys);
3350 	mb->un.varCfgHbq.hbqaddrHigh = PADDR_HI(hbq->HBQ_host_buf.phys);
3351 	mb->mbxCommand = MBX_CONFIG_HBQ;
3352 	mb->mbxOwner = OWN_HOST;
3353 	mbq->mbox_cmpl = NULL;
3354 
3355 	/* Copy info for profiles 2,3,5. Other profiles this area is reserved */
3356 	if ((hbq->HBQ_profile == 2) || (hbq->HBQ_profile == 3) ||
3357 	    (hbq->HBQ_profile == 5)) {
3358 		bcopy(&hbq->profiles.allprofiles,
3359 		    &mb->un.varCfgHbq.profiles.allprofiles,
3360 		    sizeof (hbq->profiles));
3361 	}
3362 
3363 	/* Return if no rctl / type masks for this HBQ */
3364 	if (!hbq->HBQ_num_mask) {
3365 		return;
3366 	}
3367 
3368 	/* Otherwise we setup specific rctl / type masks for this HBQ */
3369 	for (i = 0; i < hbq->HBQ_num_mask; i++) {
3370 		mb->un.varCfgHbq.hbqMasks[i].tmatch =
3371 		    hbq->HBQ_Masks[i].tmatch;
3372 		mb->un.varCfgHbq.hbqMasks[i].tmask = hbq->HBQ_Masks[i].tmask;
3373 		mb->un.varCfgHbq.hbqMasks[i].rctlmatch =
3374 		    hbq->HBQ_Masks[i].rctlmatch;
3375 		mb->un.varCfgHbq.hbqMasks[i].rctlmask =
3376 		    hbq->HBQ_Masks[i].rctlmask;
3377 	}
3378 
3379 	return;
3380 
3381 } /* emlxs_mb_config_hbq() */
3382 
3383 int
3384 emlxs_cmpl_init_vpi(void *arg1, MAILBOXQ *mbq)
3385 {
3386 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
3387 	emlxs_port_t *port = &PPORT;
3388 	emlxs_port_t *vport;
3389 	MAILBOX4 *mb;
3390 
3391 	mb = (MAILBOX4 *)mbq;
3392 
3393 	if (mb->mbxStatus == MBX_SUCCESS) {
3394 		vport = &VPORT((mb->un.varInitVPI4.vpi - hba->vpi_base));
3395 		vport->flag |= EMLXS_PORT_INIT_VPI_CMPL;
3396 	}
3397 
3398 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3399 	    "CMPL init_vpi: stats: %x", mb->mbxStatus);
3400 
3401 	return (0);
3402 
3403 } /* emlxs_cmpl_init_vpi() */
3404 
3405 
3406 extern uint32_t
3407 emlxs_mb_init_vpi(emlxs_port_t *port)
3408 {
3409 	emlxs_hba_t	*hba = HBA;
3410 	emlxs_port_t    *phy_port = &PPORT;
3411 	MAILBOXQ	*mbq;
3412 	MAILBOX4	*mb;
3413 	int rval;
3414 
3415 	if (!(hba->flag & FC_NPIV_ENABLED)) {
3416 		return (0);
3417 	}
3418 
3419 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
3420 		return (1);
3421 	}
3422 
3423 
3424 	mb = (MAILBOX4 *)mbq->mbox;
3425 	bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
3426 	mbq->nonembed = NULL;
3427 	mb->un.varInitVPI4.vfi = phy_port->VFIp->VFI;
3428 	mb->un.varInitVPI4.vpi = port->vpi + hba->vpi_base;
3429 	mb->mbxCommand = MBX_INIT_VPI;
3430 	mb->mbxOwner = OWN_HOST;
3431 	mbq->mbox_cmpl = emlxs_cmpl_init_vpi;
3432 
3433 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_WAIT, 0);
3434 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3435 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
3436 	}
3437 
3438 	return (0);
3439 
3440 } /* emlxs_mb_init_vpi() */
3441 
3442 
3443 /* Leadville wll start sending PLOGI right after */
3444 /* FDISC completion, we need to wait for REG_VPI */
3445 /* completion, before sending back the FDISK request */
3446 /* Also, allocate a node structure for Fabric port */
3447 int
3448 emlxs_cmpl_reg_vpi(void *arg1, MAILBOXQ *mbq)
3449 {
3450 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
3451 	emlxs_port_t *port = &PPORT;
3452 	emlxs_port_t *vport;
3453 	MAILBOX *mb;
3454 	emlxs_buf_t *sbp;
3455 	SERV_PARM *sp;
3456 	fc_packet_t *pkt;
3457 	NODELIST *ndlp;
3458 	uint32_t ldid;
3459 	uint8_t *wwn;
3460 
3461 	mb = (MAILBOX *)mbq;
3462 
3463 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
3464 	    "CMPL reg_vpi: stats: %x", mb->mbxStatus);
3465 
3466 	if (mb->mbxStatus != MBX_SUCCESS) {
3467 		return (0);
3468 	}
3469 
3470 	vport = &VPORT((mb->un.varRegVpi.vpi - hba->vpi_base));
3471 	vport->flag |= EMLXS_PORT_REG_VPI_CMPL;
3472 	sbp = (emlxs_buf_t *)mbq->sbp;
3473 
3474 	if (!sbp) {
3475 		return (0);
3476 	}
3477 
3478 	pkt = PRIV2PKT(sbp);
3479 	sp = (SERV_PARM *)((caddr_t)pkt->pkt_resp + sizeof (uint32_t));
3480 
3481 	vport->VFIp->outstandingVPIs++;
3482 
3483 	ldid = FABRIC_DID;
3484 	ndlp = emlxs_node_find_did(vport, ldid);
3485 
3486 	if (!ndlp) {
3487 		/* Attempt to create a node */
3488 		if ((ndlp = (NODELIST *)emlxs_mem_get(hba, MEM_NLP, 0))) {
3489 			ndlp->nlp_Rpi = 0xffff;
3490 			ndlp->nlp_DID = ldid;
3491 
3492 			bcopy((uint8_t *)sp, (uint8_t *)&ndlp->sparm,
3493 			    sizeof (SERV_PARM));
3494 
3495 			bcopy((uint8_t *)&sp->nodeName,
3496 			    (uint8_t *)&ndlp->nlp_nodename,
3497 			    sizeof (NAME_TYPE));
3498 
3499 			bcopy((uint8_t *)&sp->portName,
3500 			    (uint8_t *)&ndlp->nlp_portname,
3501 			    sizeof (NAME_TYPE));
3502 
3503 			ndlp->nlp_active = 1;
3504 			ndlp->nlp_flag[hba->channel_ct]  |= NLP_CLOSED;
3505 			ndlp->nlp_flag[hba->channel_els] |= NLP_CLOSED;
3506 			ndlp->nlp_flag[hba->channel_fcp] |= NLP_CLOSED;
3507 			ndlp->nlp_flag[hba->channel_ip]  |= NLP_CLOSED;
3508 
3509 			/* Add the node */
3510 			emlxs_node_add(vport, ndlp);
3511 
3512 			/* Open the node */
3513 			emlxs_node_open(vport, ndlp, hba->channel_ct);
3514 			emlxs_node_open(vport, ndlp, hba->channel_els);
3515 			emlxs_node_open(vport, ndlp, hba->channel_ip);
3516 			emlxs_node_open(vport, ndlp, hba->channel_fcp);
3517 		} else {
3518 			wwn = (uint8_t *)&sp->portName;
3519 			EMLXS_MSGF(EMLXS_CONTEXT,
3520 			    &emlxs_node_create_failed_msg,
3521 			    "Unable to allocate node. did=%06x "
3522 			    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
3523 			    ldid, wwn[0], wwn[1], wwn[2],
3524 			    wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
3525 
3526 			return (0);
3527 		}
3528 	} else {
3529 		mutex_enter(&EMLXS_PORT_LOCK);
3530 
3531 		ndlp->nlp_Rpi = 0xffff;
3532 		ndlp->nlp_DID = ldid;
3533 
3534 		bcopy((uint8_t *)sp,
3535 		    (uint8_t *)&ndlp->sparm, sizeof (SERV_PARM));
3536 
3537 		bcopy((uint8_t *)&sp->nodeName,
3538 		    (uint8_t *)&ndlp->nlp_nodename, sizeof (NAME_TYPE));
3539 
3540 		bcopy((uint8_t *)&sp->portName,
3541 		    (uint8_t *)&ndlp->nlp_portname, sizeof (NAME_TYPE));
3542 
3543 		wwn = (uint8_t *)&ndlp->nlp_portname;
3544 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_node_update_msg,
3545 		    "node=%p did=%06x rpi=%x "
3546 		    "wwpn=%02x%02x%02x%02x%02x%02x%02x%02x",
3547 		    ndlp, ndlp->nlp_DID, ndlp->nlp_Rpi, wwn[0],
3548 		    wwn[1], wwn[2], wwn[3], wwn[4], wwn[5], wwn[6], wwn[7]);
3549 
3550 		mutex_exit(&EMLXS_PORT_LOCK);
3551 
3552 		/* Open the node */
3553 		emlxs_node_open(vport, ndlp, hba->channel_ct);
3554 		emlxs_node_open(vport, ndlp, hba->channel_els);
3555 		emlxs_node_open(vport, ndlp, hba->channel_ip);
3556 		emlxs_node_open(vport, ndlp, hba->channel_fcp);
3557 	}
3558 
3559 	return (0);
3560 } /* emlxs_cmpl_reg_vpi */
3561 
3562 
3563 extern uint32_t
3564 emlxs_mb_reg_vpi(emlxs_port_t *port, emlxs_buf_t *sbp)
3565 {
3566 	emlxs_hba_t *hba = HBA;
3567 	MAILBOXQ *mbq;
3568 	MAILBOX	*mb;
3569 	uint32_t *pn;
3570 	int rval;
3571 
3572 	if (!(hba->flag & FC_NPIV_ENABLED)) {
3573 		return (0);
3574 	}
3575 
3576 	mutex_enter(&EMLXS_PORT_LOCK);
3577 
3578 	/* Can't reg vpi until ClearLA is sent */
3579 	if (hba->state != FC_READY) {
3580 		mutex_exit(&EMLXS_PORT_LOCK);
3581 
3582 		return (1);
3583 	}
3584 
3585 	/* Must have port id */
3586 	if (!port->did) {
3587 		mutex_exit(&EMLXS_PORT_LOCK);
3588 
3589 		return (1);
3590 	}
3591 
3592 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
3593 		mutex_exit(&EMLXS_PORT_LOCK);
3594 
3595 		return (1);
3596 	}
3597 
3598 	port->flag |= EMLXS_PORT_REGISTERED;
3599 
3600 	mutex_exit(&EMLXS_PORT_LOCK);
3601 
3602 	mb = (MAILBOX *)mbq->mbox;
3603 
3604 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3605 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
3606 		mbq->nonembed = NULL;
3607 		mb->un.varRegVpi.vfi = port->VFIp->VFI;
3608 
3609 		pn = (uint32_t *)&port->wwpn;
3610 		mb->un.varRegVpi.portname[0] = BE_SWAP32(*pn);
3611 		pn++;
3612 		mb->un.varRegVpi.portname[1] = BE_SWAP32(*pn);
3613 
3614 		mbq->mbox_cmpl = emlxs_cmpl_reg_vpi;
3615 	} else {
3616 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3617 		mbq->mbox_cmpl = NULL; /* no cmpl needed */
3618 	}
3619 
3620 	if (sbp) {
3621 		mbq->sbp = (uint8_t *)sbp;
3622 	}
3623 
3624 	mb->un.varRegVpi.vpi = port->vpi + hba->vpi_base;
3625 	mb->un.varRegVpi.sid = port->did;
3626 	mb->mbxCommand = MBX_REG_VPI;
3627 	mb->mbxOwner = OWN_HOST;
3628 
3629 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3630 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3631 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
3632 	}
3633 
3634 	return (0);
3635 
3636 } /* emlxs_mb_reg_vpi() */
3637 
3638 
3639 int
3640 emlxs_cmpl_unreg_vpi(void *arg1, MAILBOXQ *mbq)
3641 {
3642 	emlxs_hba_t *hba = (emlxs_hba_t *)arg1;
3643 	emlxs_port_t *vport;
3644 	MAILBOX *mb;
3645 
3646 	mb = (MAILBOX *)mbq;
3647 	if (mb->mbxStatus == MBX_SUCCESS) {
3648 		vport = &VPORT(mb->un.varUnregVpi.vpi);
3649 		vport->flag &= ~EMLXS_PORT_INIT_VPI_CMPL;
3650 		vport->flag &= ~EMLXS_PORT_REG_VPI_CMPL;
3651 	}
3652 	return (0);
3653 
3654 } /* emlxs_cmpl_unreg_vpi() */
3655 
3656 
3657 extern uint32_t
3658 emlxs_mb_unreg_vpi(emlxs_port_t *port)
3659 {
3660 	emlxs_hba_t	*hba = HBA;
3661 	MAILBOXQ	*mbq;
3662 	MAILBOX		*mb;
3663 	MAILBOX4	*mb4;
3664 	VFIobj_t	*vfip;
3665 	FCFIobj_t	*fcfp;
3666 	int		rval;
3667 
3668 	mutex_enter(&EMLXS_PORT_LOCK);
3669 
3670 	if (!(port->flag & EMLXS_PORT_REGISTERED)) {
3671 		mutex_exit(&EMLXS_PORT_LOCK);
3672 		return (0);
3673 	}
3674 
3675 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX, 1))) {
3676 		mutex_exit(&EMLXS_PORT_LOCK);
3677 		return (1);
3678 	}
3679 
3680 	port->flag &= ~EMLXS_PORT_REGISTERED;
3681 
3682 	mutex_exit(&EMLXS_PORT_LOCK);
3683 
3684 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3685 		mb4 = (MAILBOX4 *)mbq->mbox;
3686 		bzero((void *)mb4, MAILBOX_CMD_SLI4_BSIZE);
3687 		mb4->un.varUnRegVPI4.ii = 0; /* index is a VPI */
3688 		mb4->un.varUnRegVPI4.index = port->vpi + hba->vpi_base;
3689 		mb4->mbxCommand = MBX_UNREG_VPI;
3690 		mb4->mbxOwner = OWN_HOST;
3691 		mbq->mbox_cmpl = emlxs_cmpl_unreg_vpi;
3692 	} else {
3693 		mb = (MAILBOX *)mbq->mbox;
3694 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3695 		mb->un.varUnregVpi.vpi = port->vpi + hba->vpi_base;
3696 		mb->mbxCommand = MBX_UNREG_VPI;
3697 		mb->mbxOwner = OWN_HOST;
3698 		mbq->mbox_cmpl = NULL; /* no cmpl needed */
3699 	}
3700 
3701 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
3702 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
3703 		(void) emlxs_mem_put(hba, MEM_MBOX, (uint8_t *)mbq);
3704 	}
3705 
3706 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3707 		if ((vfip = port->VFIp) != NULL) {
3708 
3709 			fcfp = vfip->FCFIp;
3710 			if (port == fcfp->fcf_vpi) {
3711 				fcfp->fcf_vpi = NULL;
3712 			}
3713 
3714 			mutex_enter(&EMLXS_PORT_LOCK);
3715 			vfip->outstandingVPIs--;
3716 			if ((vfip->outstandingVPIs == 0) &&
3717 			    (hba->state == FC_LINK_DOWN)) {
3718 				mutex_exit(&EMLXS_PORT_LOCK);
3719 
3720 				/* No more VPIs so unreg the VFI */
3721 				(void) emlxs_mb_unreg_vfi(hba, vfip);
3722 			} else {
3723 				mutex_exit(&EMLXS_PORT_LOCK);
3724 			}
3725 		}
3726 	}
3727 	return (0);
3728 
3729 } /* emlxs_mb_unreg_vpi() */
3730 
3731 
3732 /*
3733  * emlxs_mb_config_farp  Issue a CONFIG FARP mailbox command
3734  */
3735 extern void
3736 emlxs_mb_config_farp(emlxs_hba_t *hba, MAILBOXQ *mbq)
3737 {
3738 	MAILBOX *mb = (MAILBOX *)mbq;
3739 
3740 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
3741 
3742 	bcopy((uint8_t *)&hba->wwpn,
3743 	    (uint8_t *)&mb->un.varCfgFarp.portname, sizeof (NAME_TYPE));
3744 
3745 	bcopy((uint8_t *)&hba->wwpn,
3746 	    (uint8_t *)&mb->un.varCfgFarp.nodename, sizeof (NAME_TYPE));
3747 
3748 	mb->un.varCfgFarp.filterEnable = 1;
3749 	mb->un.varCfgFarp.portName = 1;
3750 	mb->un.varCfgFarp.nodeName = 1;
3751 	mb->mbxCommand = MBX_CONFIG_FARP;
3752 	mb->mbxOwner = OWN_HOST;
3753 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
3754 } /* emlxs_mb_config_farp() */
3755 
3756 
3757 /*
3758  * emlxs_mb_read_nv  Issue a READ CONFIG mailbox command
3759  */
3760 /*ARGSUSED*/
3761 extern void
3762 emlxs_mb_read_config(emlxs_hba_t *hba, MAILBOXQ *mbq)
3763 {
3764 	MAILBOX *mb = (MAILBOX *)mbq;
3765 
3766 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3767 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
3768 		mbq->nonembed = NULL;
3769 	} else {
3770 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
3771 	}
3772 
3773 	mb->mbxCommand = MBX_READ_CONFIG;
3774 	mb->mbxOwner = OWN_HOST;
3775 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
3776 } /* emlxs_mb_read_config() */
3777 
3778 
3779 /*
3780  * NAME:     emlxs_mb_put
3781  *
3782  * FUNCTION: put mailbox cmd onto the mailbox queue.
3783  *
3784  * EXECUTION ENVIRONMENT: process and interrupt level.
3785  *
3786  * NOTES:
3787  *
3788  * CALLED FROM: EMLXS_SLI_ISSUE_MBOX_CMD
3789  *
3790  * INPUT: hba           - pointer to the device info area
3791  *      mbp             - pointer to mailbox queue entry of mailbox cmd
3792  *
3793  * RETURNS: NULL - command queued
3794  */
3795 extern void
3796 emlxs_mb_put(emlxs_hba_t *hba, MAILBOXQ *mbq)
3797 {
3798 
3799 	mutex_enter(&EMLXS_MBOX_LOCK);
3800 
3801 	if (hba->mbox_queue.q_first) {
3802 
3803 		/*
3804 		 * queue command to end of list
3805 		 */
3806 		((MAILBOXQ *)hba->mbox_queue.q_last)->next = mbq;
3807 		hba->mbox_queue.q_last = (uint8_t *)mbq;
3808 		hba->mbox_queue.q_cnt++;
3809 	} else {
3810 
3811 		/*
3812 		 * add command to empty list
3813 		 */
3814 		hba->mbox_queue.q_first = (uint8_t *)mbq;
3815 		hba->mbox_queue.q_last = (uint8_t *)mbq;
3816 		hba->mbox_queue.q_cnt = 1;
3817 	}
3818 
3819 	mbq->next = NULL;
3820 
3821 	mutex_exit(&EMLXS_MBOX_LOCK);
3822 } /* emlxs_mb_put() */
3823 
3824 
3825 /*
3826  * NAME:     emlxs_mb_get
3827  *
3828  * FUNCTION: get a mailbox command from mailbox command queue
3829  *
3830  * EXECUTION ENVIRONMENT: interrupt level.
3831  *
3832  * NOTES:
3833  *
3834  * CALLED FROM: emlxs_handle_mb_event
3835  *
3836  * INPUT: hba       - pointer to the device info area
3837  *
3838  * RETURNS: NULL - no match found mb pointer - pointer to a mailbox command
3839  */
3840 extern MAILBOXQ *
3841 emlxs_mb_get(emlxs_hba_t *hba)
3842 {
3843 	MAILBOXQ	*p_first = NULL;
3844 
3845 	mutex_enter(&EMLXS_MBOX_LOCK);
3846 
3847 	if (hba->mbox_queue.q_first) {
3848 		p_first = (MAILBOXQ *)hba->mbox_queue.q_first;
3849 		hba->mbox_queue.q_first = (uint8_t *)p_first->next;
3850 
3851 		if (hba->mbox_queue.q_first == NULL) {
3852 			hba->mbox_queue.q_last = NULL;
3853 			hba->mbox_queue.q_cnt = 0;
3854 		} else {
3855 			hba->mbox_queue.q_cnt--;
3856 		}
3857 
3858 		p_first->next = NULL;
3859 	}
3860 
3861 	mutex_exit(&EMLXS_MBOX_LOCK);
3862 
3863 	return (p_first);
3864 
3865 } /* emlxs_mb_get() */
3866 
3867 
3868 /* EMLXS_PORT_LOCK must be held when calling this */
3869 void
3870 emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag, uint32_t tmo)
3871 {
3872 	MATCHMAP	*mp;
3873 
3874 	HBASTATS.MboxIssued++;
3875 	hba->mbox_queue_flag = flag;
3876 
3877 	/* Set the Mailbox timer */
3878 	hba->mbox_timer = hba->timer_tics + tmo;
3879 
3880 	/* Initialize mailbox */
3881 	mbq->flag &= MBQ_INIT_MASK;
3882 	mbq->next = 0;
3883 
3884 	mutex_enter(&EMLXS_MBOX_LOCK);
3885 	hba->mbox_mbq = (uint8_t *)mbq;
3886 	mutex_exit(&EMLXS_MBOX_LOCK);
3887 
3888 	if (mbq->nonembed) {
3889 		mp = (MATCHMAP *) mbq->nonembed;
3890 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
3891 		    DDI_DMA_SYNC_FORDEV);
3892 	}
3893 
3894 	if (mbq->bp) {
3895 		mp = (MATCHMAP *) mbq->bp;
3896 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
3897 		    DDI_DMA_SYNC_FORDEV);
3898 	}
3899 	return;
3900 
3901 } /* emlxs_mb_init() */
3902 
3903 
3904 extern void
3905 emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus)
3906 {
3907 	emlxs_port_t	*port = &PPORT;
3908 	MATCHMAP	*mbox_nonembed;
3909 	MATCHMAP	*mbox_bp;
3910 	emlxs_buf_t	*mbox_sbp;
3911 	fc_unsol_buf_t	*mbox_ubp;
3912 	IOCBQ		*mbox_iocbq;
3913 	MAILBOXQ	*mbox_mbq;
3914 	MAILBOX		*mbox;
3915 	uint32_t	mbox_queue_flag;
3916 	emlxs_ub_priv_t	*ub_priv;
3917 
3918 	mutex_enter(&EMLXS_PORT_LOCK);
3919 
3920 	if (hba->mbox_queue_flag) {
3921 		HBASTATS.MboxCompleted++;
3922 
3923 		if (mbxStatus != MBX_SUCCESS) {
3924 			HBASTATS.MboxError++;
3925 		} else {
3926 			HBASTATS.MboxGood++;
3927 		}
3928 	}
3929 
3930 	mutex_enter(&EMLXS_MBOX_LOCK);
3931 	mbox_queue_flag = hba->mbox_queue_flag;
3932 	mbox_mbq = (MAILBOXQ *)hba->mbox_mbq;
3933 
3934 	if (mbox_mbq) {
3935 		mbox_nonembed = (MATCHMAP *)mbox_mbq->nonembed;
3936 		mbox_bp = (MATCHMAP *)mbox_mbq->bp;
3937 		mbox_sbp = (emlxs_buf_t *)mbox_mbq->sbp;
3938 		mbox_ubp = (fc_unsol_buf_t *)mbox_mbq->ubp;
3939 		mbox_iocbq = (IOCBQ *)mbox_mbq->iocbq;
3940 	} else {
3941 		mbox_nonembed = NULL;
3942 		mbox_bp = NULL;
3943 		mbox_sbp = NULL;
3944 		mbox_ubp = NULL;
3945 		mbox_iocbq = NULL;
3946 	}
3947 
3948 	hba->mbox_mbq = 0;
3949 	hba->mbox_queue_flag = 0;
3950 	hba->mbox_timer = 0;
3951 	mutex_exit(&EMLXS_MBOX_LOCK);
3952 
3953 	mutex_exit(&EMLXS_PORT_LOCK);
3954 
3955 	if (mbox_queue_flag == MBX_NOWAIT) {
3956 		/* Check for deferred MBUF cleanup */
3957 		if (mbox_bp) {
3958 			(void) emlxs_mem_put(hba, MEM_BUF, (uint8_t *)mbox_bp);
3959 		}
3960 		if (mbox_nonembed) {
3961 			(void) emlxs_mem_put(hba, MEM_BUF,
3962 			    (uint8_t *)mbox_nonembed);
3963 		}
3964 		if (mbox_mbq) {
3965 			(void) emlxs_mem_put(hba, MEM_MBOX,
3966 			    (uint8_t *)mbox_mbq);
3967 		}
3968 	} else {  /* MBX_WAIT */
3969 		if (mbox_mbq) {
3970 			if (mb) {
3971 				/* Copy the local mailbox provided back into */
3972 				/* the original mailbox */
3973 				if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3974 					bcopy((uint32_t *)mb,
3975 					    (uint32_t *)mbox_mbq,
3976 					    MAILBOX_CMD_SLI4_BSIZE);
3977 				} else {
3978 					bcopy((uint32_t *)mb,
3979 					    (uint32_t *)mbox_mbq,
3980 					    MAILBOX_CMD_BSIZE);
3981 				}
3982 			}
3983 
3984 			mbox = (MAILBOX *)mbox_mbq;
3985 			mbox->mbxStatus = mbxStatus;
3986 
3987 			/* Mark mailbox complete */
3988 			mbox_mbq->flag |= MBQ_COMPLETED;
3989 		}
3990 
3991 		/* Wake up the sleeping thread */
3992 		if (mbox_queue_flag == MBX_SLEEP) {
3993 			mutex_enter(&EMLXS_MBOX_LOCK);
3994 			cv_broadcast(&EMLXS_MBOX_CV);
3995 			mutex_exit(&EMLXS_MBOX_LOCK);
3996 		}
3997 	}
3998 
3999 #ifdef SFCT_SUPPORT
4000 	if (mb && mbox_sbp && mbox_sbp->fct_cmd) {
4001 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
4002 		    "FCT mailbox: %s: status=%x",
4003 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
4004 		    (uint32_t)mb->mbxStatus);
4005 	}
4006 #endif /* SFCT_SUPPORT */
4007 
4008 	/* Check for deferred pkt completion */
4009 	if (mbox_sbp) {
4010 		if (mbxStatus != MBX_SUCCESS) {
4011 			/* Set error status */
4012 			mbox_sbp->pkt_flags &= ~PACKET_STATE_VALID;
4013 			emlxs_set_pkt_state(mbox_sbp, IOSTAT_LOCAL_REJECT,
4014 			    IOERR_NO_RESOURCES, 1);
4015 		}
4016 
4017 		emlxs_pkt_complete(mbox_sbp, -1, 0, 1);
4018 	}
4019 
4020 	/* Check for deferred ub completion */
4021 	if (mbox_ubp) {
4022 		ub_priv = mbox_ubp->ub_fca_private;
4023 		port = ub_priv->port;
4024 
4025 		emlxs_ub_callback(port, mbox_ubp);
4026 	}
4027 
4028 	/* Special handling for vport PLOGI */
4029 	if (mbox_iocbq == (IOCBQ *)1) {
4030 		mbox_iocbq = NULL;
4031 	}
4032 
4033 	/* Check for deferred iocb tx */
4034 	if (mbox_iocbq) {
4035 		/* Check for driver special codes */
4036 		/* These indicate the mailbox is being flushed */
4037 		if (mbxStatus >= MBX_DRIVER_RESERVED) {
4038 			/* Set the error status and return it */
4039 			mbox_iocbq->iocb.ULPSTATUS = IOSTAT_LOCAL_REJECT;
4040 			mbox_iocbq->iocb.un.grsp.perr.statLocalError =
4041 			    IOERR_ABORT_REQUESTED;
4042 
4043 			emlxs_proc_channel_event(hba, mbox_iocbq->channel,
4044 			    mbox_iocbq);
4045 		} else {
4046 			EMLXS_SLI_ISSUE_IOCB_CMD(hba, mbox_iocbq->channel,
4047 			    mbox_iocbq);
4048 		}
4049 	}
4050 	return;
4051 
4052 } /* emlxs_mb_fini() */
4053 
4054 
4055 extern void
4056 emlxs_mb_flush(emlxs_hba_t *hba)
4057 {
4058 	MAILBOXQ	*mbq;
4059 	uint32_t	mbxStatus;
4060 
4061 	mbxStatus = (hba->flag & FC_HARDWARE_ERROR) ?
4062 	    MBX_HARDWARE_ERROR : MBX_NOT_FINISHED;
4063 
4064 	/* Flush out the active mbox command */
4065 	emlxs_mb_fini(hba, NULL, mbxStatus);
4066 
4067 	/* Flush out the queued mbox commands */
4068 	while (mbq = (MAILBOXQ *)emlxs_mb_get(hba)) {
4069 		mutex_enter(&EMLXS_MBOX_LOCK);
4070 		hba->mbox_queue_flag = MBX_NOWAIT;
4071 		hba->mbox_mbq = (uint8_t *)mbq;
4072 		mutex_exit(&EMLXS_MBOX_LOCK);
4073 
4074 		emlxs_mb_fini(hba, NULL, mbxStatus);
4075 	}
4076 
4077 	return;
4078 
4079 } /* emlxs_mb_flush */
4080 
4081 
4082 extern char *
4083 emlxs_mb_cmd_xlate(uint8_t cmd)
4084 {
4085 	static char	buffer[32];
4086 	uint32_t	i;
4087 	uint32_t	count;
4088 
4089 	count = sizeof (emlxs_mb_cmd_table) / sizeof (emlxs_table_t);
4090 	for (i = 0; i < count; i++) {
4091 		if (cmd == emlxs_mb_cmd_table[i].code) {
4092 			return (emlxs_mb_cmd_table[i].string);
4093 		}
4094 	}
4095 
4096 	(void) sprintf(buffer, "Cmd=0x%x", cmd);
4097 	return (buffer);
4098 
4099 } /* emlxs_mb_cmd_xlate() */
4100