xref: /titanic_51/usr/src/uts/common/io/fibre-channel/fca/emlxs/emlxs_mbox.c (revision 8f23e9fa8abcb5857661066b954e63400d589b65)
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
9  * http://www.opensource.org/licenses/cddl1.txt.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright (c) 2004-2012 Emulex. All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <emlxs.h>
28 
29 /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
30 EMLXS_MSG_DEF(EMLXS_MBOX_C);
31 
32 
33 emlxs_table_t emlxs_mb_status_table[] = {
34 	{MBX_SUCCESS, "SUCCESS"},
35 	{MBX_FAILURE, "FAILURE"},
36 	{MBXERR_NUM_IOCBS, "NUM_IOCBS"},
37 	{MBXERR_IOCBS_EXCEEDED, "IOCBS_EXCEEDED"},
38 	{MBXERR_BAD_RING_NUMBER, "BAD_RING_NUMBER"},
39 	{MBXERR_MASK_ENTRIES_RANGE, "MASK_ENTRIES_RANGE"},
40 	{MBXERR_MASKS_EXCEEDED, "MASKS_EXCEEDED"},
41 	{MBXERR_BAD_PROFILE, "BAD_PROFILE"},
42 	{MBXERR_BAD_DEF_CLASS, "BAD_DEF_CLASS"},
43 	{MBXERR_BAD_MAX_RESPONDER, "BAD_MAX_RESPONDER"},
44 	{MBXERR_BAD_MAX_ORIGINATOR, "BAD_MAX_ORIGINATOR"},
45 	{MBXERR_RPI_REGISTERED, "RPI_REGISTERED"},
46 	{MBXERR_RPI_FULL, "RPI_FULL"},
47 	{MBXERR_NO_RESOURCES, "NO_RESOURCES"},
48 	{MBXERR_BAD_RCV_LENGTH, "BAD_RCV_LENGTH"},
49 	{MBXERR_DMA_ERROR, "DMA_ERROR"},
50 	{MBXERR_NOT_SUPPORTED, "NOT_SUPPORTED"},
51 	{MBXERR_UNSUPPORTED_FEATURE, "UNSUPPORTED_FEATURE"},
52 	{MBXERR_UNKNOWN_COMMAND, "UNKNOWN_COMMAND"},
53 	{MBXERR_BAD_IP_BIT, "BAD_IP_BIT"},
54 	{MBXERR_BAD_PCB_ALIGN, "BAD_PCB_ALIGN"},
55 	{MBXERR_BAD_HBQ_ID, "BAD_HBQ_ID"},
56 	{MBXERR_BAD_HBQ_STATE, "BAD_HBQ_STATE"},
57 	{MBXERR_BAD_HBQ_MASK_NUM, "BAD_HBQ_MASK_NUM"},
58 	{MBXERR_BAD_HBQ_MASK_SUBSET, "BAD_HBQ_MASK_SUBSET"},
59 	{MBXERR_HBQ_CREATE_FAIL, "HBQ_CREATE_FAIL"},
60 	{MBXERR_HBQ_EXISTING, "HBQ_EXISTING"},
61 	{MBXERR_HBQ_RSPRING_FULL, "HBQ_RSPRING_FULL"},
62 	{MBXERR_HBQ_DUP_MASK, "HBQ_DUP_MASK"},
63 	{MBXERR_HBQ_INVAL_GET_PTR, "HBQ_INVAL_GET_PTR"},
64 	{MBXERR_BAD_HBQ_SIZE, "BAD_HBQ_SIZE"},
65 	{MBXERR_BAD_HBQ_ORDER, "BAD_HBQ_ORDER"},
66 	{MBXERR_INVALID_ID, "INVALID_ID"},
67 	{MBXERR_INVALID_VFI, "INVALID_VFI"},
68 	{MBXERR_FLASH_WRITE_FAILED, "FLASH_WRITE_FAILED"},
69 	{MBXERR_INVALID_LINKSPEED, "INVALID_LINKSPEED"},
70 	{MBXERR_BAD_REDIRECT, "BAD_REDIRECT"},
71 	{MBXERR_RING_ALREADY_CONFIG, "RING_ALREADY_CONFIG"},
72 	{MBXERR_RING_INACTIVE, "RING_INACTIVE"},
73 	{MBXERR_RPI_INACTIVE, "RPI_INACTIVE"},
74 	{MBXERR_NO_ACTIVE_XRI, "NO_ACTIVE_XRI"},
75 	{MBXERR_XRI_NOT_ACTIVE, "XRI_NOT_ACTIVE"},
76 	{MBXERR_RPI_INUSE, "RPI_INUSE"},
77 	{MBXERR_NO_LINK_ATTENTION, "NO_LINK_ATTENTION"},
78 	{MBXERR_INVALID_SLI_MODE, "INVALID_SLI_MODE"},
79 	{MBXERR_INVALID_HOST_PTR, "INVALID_HOST_PTR"},
80 	{MBXERR_CANT_CFG_SLI_MODE, "CANT_CFG_SLI_MODE"},
81 	{MBXERR_BAD_OVERLAY, "BAD_OVERLAY"},
82 	{MBXERR_INVALID_FEAT_REQ, "INVALID_FEAT_REQ"},
83 	{MBXERR_CONFIG_CANT_COMPLETE, "CONFIG_CANT_COMPLETE"},
84 	{MBXERR_DID_ALREADY_REGISTERED, "DID_ALREADY_REGISTERED"},
85 	{MBXERR_DID_INCONSISTENT, "DID_INCONSISTENT"},
86 	{MBXERR_VPI_TOO_LARGE, "VPI_TOO_LARGE"},
87 	{MBXERR_STILL_ASSOCIATED, "STILL_ASSOCIATED"},
88 	{MBXERR_INVALID_VF_STATE, "INVALID_VF_STATE"},
89 	{MBXERR_VFI_ALREADY_REGISTERED, "VFI_ALREADY_REGISTERED"},
90 	{MBXERR_VFI_TOO_LARGE, "VFI_TOO_LARGE"},
91 	{MBXERR_LOAD_FW_FAILED, "LOAD_FW_FAILED"},
92 	{MBXERR_FIND_FW_FAILED, "FIND_FW_FAILED"},
93 };
94 
95 emlxs_table_t emlxs_mb_cmd_table[] = {
96 	{MBX_SHUTDOWN, "SHUTDOWN"},
97 	{MBX_LOAD_SM, "LOAD_SM"},
98 	{MBX_READ_NV, "READ_NV"},
99 	{MBX_WRITE_NV, "WRITE_NV"},
100 	{MBX_RUN_BIU_DIAG, "RUN_BIU_DIAG"},
101 	{MBX_INIT_LINK, "INIT_LINK"},
102 	{MBX_DOWN_LINK, "DOWN_LINK"},
103 	{MBX_CONFIG_LINK, "CONFIG_LINK"},
104 	{MBX_PART_SLIM, "PART_SLIM"},
105 	{MBX_CONFIG_RING, "CONFIG_RING"},
106 	{MBX_RESET_RING, "RESET_RING"},
107 	{MBX_READ_CONFIG, "READ_CONFIG"},
108 	{MBX_READ_RCONFIG, "READ_RCONFIG"},
109 	{MBX_READ_SPARM, "READ_SPARM"},
110 	{MBX_READ_STATUS, "READ_STATUS"},
111 	{MBX_READ_RPI, "READ_RPI"},
112 	{MBX_READ_XRI, "READ_XRI"},
113 	{MBX_READ_REV, "READ_REV"},
114 	{MBX_READ_LNK_STAT, "READ_LNK_STAT"},
115 	{MBX_REG_LOGIN, "REG_LOGIN"},
116 	{MBX_UNREG_LOGIN, "UNREG_RPI"},
117 	{MBX_READ_LA, "READ_LA"},
118 	{MBX_CLEAR_LA, "CLEAR_LA"},
119 	{MBX_DUMP_MEMORY, "DUMP_MEMORY"},
120 	{MBX_DUMP_CONTEXT, "DUMP_CONTEXT"},
121 	{MBX_RUN_DIAGS, "RUN_DIAGS"},
122 	{MBX_RESTART, "RESTART"},
123 	{MBX_UPDATE_CFG, "UPDATE_CFG"},
124 	{MBX_DOWN_LOAD, "DOWN_LOAD"},
125 	{MBX_DEL_LD_ENTRY, "DEL_LD_ENTRY"},
126 	{MBX_RUN_PROGRAM, "RUN_PROGRAM"},
127 	{MBX_SET_MASK, "SET_MASK"},
128 	{MBX_SET_VARIABLE, "SET_VARIABLE"},
129 	{MBX_UNREG_D_ID, "UNREG_D_ID"},
130 	{MBX_KILL_BOARD, "KILL_BOARD"},
131 	{MBX_CONFIG_FARP, "CONFIG_FARP"},
132 	{MBX_LOAD_AREA, "LOAD_AREA"},
133 	{MBX_RUN_BIU_DIAG64, "RUN_BIU_DIAG64"},
134 	{MBX_CONFIG_PORT, "CONFIG_PORT"},
135 	{MBX_READ_SPARM64, "READ_SPARM64"},
136 	{MBX_READ_RPI64, "READ_RPI64"},
137 	{MBX_CONFIG_MSI, "CONFIG_MSI"},
138 	{MBX_CONFIG_MSIX, "CONFIG_MSIX"},
139 	{MBX_REG_LOGIN64, "REG_RPI"},
140 	{MBX_READ_LA64, "READ_LA64"},
141 	{MBX_FLASH_WR_ULA, "FLASH_WR_ULA"},
142 	{MBX_SET_DEBUG, "SET_DEBUG"},
143 	{MBX_GET_DEBUG, "GET_DEBUG"},
144 	{MBX_LOAD_EXP_ROM, "LOAD_EXP_ROM"},
145 	{MBX_BEACON, "BEACON"},
146 	{MBX_CONFIG_HBQ, "CONFIG_HBQ"},	/* SLI3 */
147 	{MBX_REG_VPI, "REG_VPI"},	/* NPIV */
148 	{MBX_UNREG_VPI, "UNREG_VPI"},	/* NPIV */
149 	{MBX_ASYNC_EVENT, "ASYNC_EVENT"},
150 	{MBX_HEARTBEAT, "HEARTBEAT"},
151 	{MBX_READ_EVENT_LOG_STATUS, "READ_EVENT_LOG_STATUS"},
152 	{MBX_READ_EVENT_LOG, "READ_EVENT_LOG"},
153 	{MBX_WRITE_EVENT_LOG, "WRITE_EVENT_LOG"},
154 	{MBX_NV_LOG, "NV_LOG"},
155 	{MBX_PORT_CAPABILITIES, "PORT_CAPABILITIES"},
156 	{MBX_IOV_CONTROL, "IOV_CONTROL"},
157 	{MBX_IOV_MBX, "IOV_MBX"},
158 	{MBX_SLI_CONFIG, "SLI_CONFIG"},
159 	{MBX_REQUEST_FEATURES, "REQUEST_FEATURES"},
160 	{MBX_RESUME_RPI, "RESUME_RPI"},
161 	{MBX_REG_VFI, "REG_VFI"},
162 	{MBX_REG_FCFI, "REG_FCFI"},
163 	{MBX_UNREG_VFI, "UNREG_VFI"},
164 	{MBX_UNREG_FCFI, "UNREG_FCFI"},
165 	{MBX_INIT_VFI, "INIT_VFI"},
166 	{MBX_INIT_VPI, "INIT_VPI"},
167 	{MBX_WRITE_VPARMS, "WRITE_VPARMS"},
168 	{MBX_ACCESS_VDATA, "ACCESS_VDATA"}
169 };	/* emlxs_mb_cmd_table */
170 
171 
172 emlxs_table_t emlxs_request_feature_table[] = {
173 	{SLI4_FEATURE_INHIBIT_AUTO_ABTS, "IAA "},	/* Bit 0 */
174 	{SLI4_FEATURE_NPIV, "NPIV "},			/* Bit 1 */
175 	{SLI4_FEATURE_DIF, "DIF "},			/* Bit 2 */
176 	{SLI4_FEATURE_VIRTUAL_FABRICS, "VF "},		/* Bit 3 */
177 	{SLI4_FEATURE_FCP_INITIATOR, "FCPI "},		/* Bit 4 */
178 	{SLI4_FEATURE_FCP_TARGET, "FCPT "},		/* Bit 5 */
179 	{SLI4_FEATURE_FCP_COMBO, "FCPC "},		/* Bit 6 */
180 	{SLI4_FEATURE_RSVD1, "RSVD1 "},			/* Bit 7 */
181 	{SLI4_FEATURE_RQD, "RQD "},			/* Bit 8 */
182 	{SLI4_FEATURE_INHIBIT_AUTO_ABTS_R, "IAAR "},	/* Bit 9 */
183 	{SLI4_FEATURE_HIGH_LOGIN_MODE, "HLM "},		/* Bit 10 */
184 	{SLI4_FEATURE_PERF_HINT, "PERFH "}		/* Bit 11 */
185 };	/* emlxs_request_feature_table */
186 
187 
188 extern char *
189 emlxs_mb_xlate_status(uint32_t status)
190 {
191 	static char	buffer[32];
192 	uint32_t	i;
193 	uint32_t	count;
194 
195 	count = sizeof (emlxs_mb_status_table) / sizeof (emlxs_table_t);
196 	for (i = 0; i < count; i++) {
197 		if (status == emlxs_mb_status_table[i].code) {
198 			return (emlxs_mb_status_table[i].string);
199 		}
200 	}
201 
202 	(void) snprintf(buffer, sizeof (buffer), "status=%x", status);
203 	return (buffer);
204 
205 } /* emlxs_mb_xlate_status() */
206 
207 
208 /* SLI4 */
209 /*ARGSUSED*/
210 extern void
211 emlxs_mb_resetport(emlxs_hba_t *hba, MAILBOXQ *mbq)
212 {
213 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
214 
215 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
216 	mbq->nonembed = NULL;
217 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
218 	mbq->port = (void *)&PPORT;
219 
220 	/*
221 	 * Signifies an embedded command
222 	 */
223 	mb4->un.varSLIConfig.be.embedded = 1;
224 
225 	mb4->mbxCommand = MBX_SLI_CONFIG;
226 	mb4->mbxOwner = OWN_HOST;
227 	mb4->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
228 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
229 	    IOCTL_SUBSYSTEM_COMMON;
230 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_RESET;
231 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
232 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 0;
233 
234 	return;
235 
236 } /* emlxs_mb_resetport() */
237 
238 
239 /* SLI4 */
240 /*ARGSUSED*/
241 extern void
242 emlxs_mb_request_features(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t mask)
243 {
244 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
245 
246 	hba->flag &= ~FC_NPIV_ENABLED;
247 	hba->sli.sli4.flag &= ~(EMLXS_SLI4_PHON | EMLXS_SLI4_PHWQ);
248 
249 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
250 	mbq->nonembed = NULL;
251 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
252 	mbq->port = (void *)&PPORT;
253 
254 	mb4->mbxCommand = MBX_REQUEST_FEATURES;
255 	mb4->mbxOwner = OWN_HOST;
256 
257 	mb4->un.varReqFeatures.featuresRequested = mask;
258 	return;
259 
260 } /* emlxs_mb_request_features() */
261 
262 
263 /* SLI4 */
264 /*ARGSUSED*/
265 extern void
266 emlxs_mb_noop(emlxs_hba_t *hba, MAILBOXQ *mbq)
267 {
268 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
269 	IOCTL_COMMON_NOP *nop;
270 
271 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
272 	mbq->nonembed = NULL;
273 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
274 	mbq->port = (void *)&PPORT;
275 
276 	/*
277 	 * Signifies an embedded command
278 	 */
279 	mb4->un.varSLIConfig.be.embedded = 1;
280 
281 	mb4->mbxCommand = MBX_SLI_CONFIG;
282 	mb4->mbxOwner = OWN_HOST;
283 	mb4->un.varSLIConfig.be.payload_length = sizeof (IOCTL_COMMON_NOP) +
284 	    IOCTL_HEADER_SZ;
285 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
286 	    IOCTL_SUBSYSTEM_COMMON;
287 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_NOP;
288 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
289 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
290 	    sizeof (IOCTL_COMMON_NOP);
291 	nop = (IOCTL_COMMON_NOP *)&mb4->un.varSLIConfig.payload;
292 	nop->params.request.context = -1;
293 
294 	return;
295 
296 } /* emlxs_mb_noop() */
297 
298 
299 /* SLI4 */
300 /*ARGSUSED*/
301 extern int
302 emlxs_mbext_noop(emlxs_hba_t *hba, MAILBOXQ *mbq)
303 {
304 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
305 	IOCTL_COMMON_NOP *nop;
306 	MATCHMAP *mp;
307 	mbox_req_hdr_t	*hdr_req;
308 
309 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
310 
311 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
312 		return (1);
313 	}
314 	/*
315 	 * Save address for completion
316 	 * Signifies a non-embedded command
317 	 */
318 	mb4->un.varSLIConfig.be.embedded = 0;
319 	mbq->nonembed = (void *)mp;
320 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
321 	mbq->port = (void *)&PPORT;
322 
323 	mb4->mbxCommand = MBX_SLI_CONFIG;
324 	mb4->mbxOwner = OWN_HOST;
325 
326 	hdr_req = (mbox_req_hdr_t *)mp->virt;
327 	hdr_req->subsystem = IOCTL_SUBSYSTEM_COMMON;
328 	hdr_req->opcode = COMMON_OPCODE_NOP;
329 	hdr_req->timeout = 0;
330 	hdr_req->req_length = sizeof (IOCTL_COMMON_NOP);
331 	nop = (IOCTL_COMMON_NOP *)(hdr_req + 1);
332 	nop->params.request.context = -1;
333 
334 	return (0);
335 
336 } /* emlxs_mbext_noop() */
337 
338 
339 /* SLI4 */
340 /*ARGSUSED*/
341 extern void
342 emlxs_mb_eq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num)
343 {
344 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
345 	IOCTL_COMMON_EQ_CREATE *qp;
346 	uint64_t	addr;
347 
348 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
349 	mbq->nonembed = NULL;
350 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
351 	mbq->port = (void *)&PPORT;
352 
353 	/*
354 	 * Signifies an embedded command
355 	 */
356 	mb4->un.varSLIConfig.be.embedded = 1;
357 
358 	mb4->mbxCommand = MBX_SLI_CONFIG;
359 	mb4->mbxOwner = OWN_HOST;
360 	mb4->un.varSLIConfig.be.payload_length =
361 	    sizeof (IOCTL_COMMON_EQ_CREATE) + IOCTL_HEADER_SZ;
362 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
363 	    IOCTL_SUBSYSTEM_COMMON;
364 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_EQ_CREATE;
365 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
366 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
367 	    sizeof (IOCTL_COMMON_EQ_CREATE);
368 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 0;
369 
370 	qp = (IOCTL_COMMON_EQ_CREATE *)&mb4->un.varSLIConfig.payload;
371 
372 	/* 1024 * 4 bytes = 4K */
373 	qp->params.request.EQContext.Count = EQ_ELEMENT_COUNT_1024;
374 	qp->params.request.EQContext.Valid = 1;
375 	qp->params.request.EQContext.DelayMult = EQ_DELAY_MULT;
376 
377 	addr = hba->sli.sli4.eq[num].addr.phys;
378 	qp->params.request.NumPages = 1;
379 	qp->params.request.Pages[0].addrLow = PADDR_LO(addr);
380 	qp->params.request.Pages[0].addrHigh = PADDR_HI(addr);
381 
382 	return;
383 
384 } /* emlxs_mb_eq_create() */
385 
386 
387 /* SLI4 */
388 /*ARGSUSED*/
389 extern void
390 emlxs_mb_cq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num)
391 {
392 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
393 	IOCTL_COMMON_CQ_CREATE *qp;
394 	IOCTL_COMMON_CQ_CREATE_V2 *qp2;
395 	uint64_t	addr;
396 	uint32_t	i;
397 
398 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
399 	mbq->nonembed = NULL;
400 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
401 	mbq->port = (void *)&PPORT;
402 
403 	/*
404 	 * Signifies an embedded command
405 	 */
406 	mb4->un.varSLIConfig.be.embedded = 1;
407 
408 	mb4->mbxCommand = MBX_SLI_CONFIG;
409 	mb4->mbxOwner = OWN_HOST;
410 
411 	switch (hba->sli.sli4.param.CQV) {
412 	case 0:
413 		mb4->un.varSLIConfig.be.payload_length =
414 		    sizeof (IOCTL_COMMON_CQ_CREATE) + IOCTL_HEADER_SZ;
415 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
416 		    IOCTL_SUBSYSTEM_COMMON;
417 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
418 		    COMMON_OPCODE_CQ_CREATE;
419 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
420 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
421 		    sizeof (IOCTL_COMMON_CQ_CREATE);
422 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 0;
423 
424 		qp = (IOCTL_COMMON_CQ_CREATE *)
425 		    &mb4->un.varSLIConfig.payload;
426 
427 		/* 256 * 16 bytes = 4K */
428 		qp->params.request.CQContext.Count = CQ_ELEMENT_COUNT_256;
429 		qp->params.request.CQContext.EQId =
430 		    (uint8_t)hba->sli.sli4.cq[num].eqid;
431 		qp->params.request.CQContext.Valid = 1;
432 		qp->params.request.CQContext.Eventable = 1;
433 		qp->params.request.CQContext.NoDelay = 0;
434 		qp->params.request.CQContext.CoalesceWM = 0;
435 
436 		addr = hba->sli.sli4.cq[num].addr.phys;
437 		qp->params.request.NumPages = 1;
438 		qp->params.request.Pages[0].addrLow = PADDR_LO(addr);
439 		qp->params.request.Pages[0].addrHigh = PADDR_HI(addr);
440 
441 		break;
442 
443 	case 2:
444 	default:
445 		mb4->un.varSLIConfig.be.payload_length =
446 		    sizeof (IOCTL_COMMON_CQ_CREATE_V2) + IOCTL_HEADER_SZ;
447 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
448 		    IOCTL_SUBSYSTEM_COMMON;
449 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
450 		    COMMON_OPCODE_CQ_CREATE;
451 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
452 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
453 		    sizeof (IOCTL_COMMON_CQ_CREATE_V2);
454 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 2;
455 
456 		qp2 = (IOCTL_COMMON_CQ_CREATE_V2 *)
457 		    &mb4->un.varSLIConfig.payload;
458 
459 		qp2->params.request.CQContext.CqeCnt = CQ_ELEMENT_COUNT_1024;
460 		qp2->params.request.CQContext.CqeSize = CQE_SIZE_16_BYTES;
461 		qp2->params.request.CQContext.EQId = hba->sli.sli4.cq[num].eqid;
462 		qp2->params.request.CQContext.Valid = 1;
463 		qp2->params.request.CQContext.AutoValid = 0;
464 		qp2->params.request.CQContext.Eventable = 1;
465 		qp2->params.request.CQContext.NoDelay = 0;
466 		qp2->params.request.CQContext.Count1 = 0;
467 		qp2->params.request.CQContext.CoalesceWM = 0;
468 
469 		addr = hba->sli.sli4.cq[num].addr.phys;
470 		qp2->params.request.PageSize = CQ_PAGE_SIZE_4K;
471 		qp2->params.request.NumPages = EMLXS_NUM_CQ_PAGES_V2;
472 
473 		for (i = 0; i < EMLXS_NUM_CQ_PAGES_V2; i++) {
474 			qp2->params.request.Pages[i].addrLow = PADDR_LO(addr);
475 			qp2->params.request.Pages[i].addrHigh = PADDR_HI(addr);
476 			addr += 4096;
477 		}
478 
479 		break;
480 	}
481 	return;
482 
483 } /* emlxs_mb_cq_create() */
484 
485 
486 /* SLI4 */
487 /*ARGSUSED*/
488 extern void
489 emlxs_mb_get_port_name(emlxs_hba_t *hba, MAILBOXQ *mbq)
490 {
491 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
492 
493 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
494 	mbq->nonembed = NULL;
495 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
496 	mbq->port = (void *)&PPORT;
497 
498 	mb4->un.varSLIConfig.be.embedded = 1;
499 	mb4->mbxCommand = MBX_SLI_CONFIG;
500 	mb4->mbxOwner = OWN_HOST;
501 
502 	mb4->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
503 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
504 	    IOCTL_SUBSYSTEM_COMMON;
505 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
506 	    COMMON_OPCODE_GET_PORT_NAME;
507 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
508 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 0;
509 
510 	if (hba->model_info.chip & EMLXS_BE_CHIPS) {
511 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 0; /* V0 */
512 	} else {
513 		IOCTL_COMMON_GET_PORT_NAME_V1 *pn;
514 
515 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 1; /* V1 */
516 
517 		pn = (IOCTL_COMMON_GET_PORT_NAME_V1 *)
518 		    &mb4->un.varSLIConfig.payload;
519 		pn->params.request.pt = PORT_TYPE_FC;
520 	}
521 
522 	return;
523 
524 } /* emlxs_mb_get_port_name() */
525 
526 
527 /* SLI4 */
528 /*ARGSUSED*/
529 extern void
530 emlxs_mb_get_sli4_params(emlxs_hba_t *hba, MAILBOXQ *mbq)
531 {
532 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
533 
534 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
535 	mbq->nonembed = NULL;
536 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
537 	mbq->port = (void *)&PPORT;
538 
539 	mb4->un.varSLIConfig.be.embedded = 1;
540 	mb4->mbxCommand = MBX_SLI_CONFIG;
541 	mb4->mbxOwner = OWN_HOST;
542 
543 	mb4->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
544 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
545 	    IOCTL_SUBSYSTEM_COMMON;
546 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
547 	    COMMON_OPCODE_GET_SLI4_PARAMS;
548 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
549 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length = 0;
550 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 0; /* V0 */
551 
552 	return;
553 
554 } /* emlxs_mb_get_sli4_params() */
555 
556 
557 /* SLI4 */
558 /*ARGSUSED*/
559 extern void
560 emlxs_mb_get_extents_info(emlxs_hba_t *hba, MAILBOXQ *mbq, uint16_t type)
561 {
562 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
563 	IOCTL_COMMON_EXTENTS *ep;
564 
565 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
566 	mbq->nonembed = NULL;
567 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
568 	mbq->port = (void *)&PPORT;
569 
570 	mb4->un.varSLIConfig.be.embedded = 1;
571 	mb4->mbxCommand = MBX_SLI_CONFIG;
572 	mb4->mbxOwner = OWN_HOST;
573 
574 	mb4->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
575 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.subsystem =
576 	    IOCTL_SUBSYSTEM_COMMON;
577 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.opcode =
578 	    COMMON_OPCODE_GET_EXTENTS_INFO;
579 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.timeout = 0;
580 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.req_length =
581 	    sizeof (IOCTL_COMMON_EXTENTS);
582 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.vf_number = 0;
583 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.vh_number = 0;
584 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.pf_number = 0;
585 
586 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.version = 0; /* V0 */
587 
588 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
589 	ep->params.request.RscType = type;
590 
591 	return;
592 
593 } /* emlxs_mb_get_extents_info() */
594 
595 
596 /* SLI4 */
597 /*ARGSUSED*/
598 extern void
599 emlxs_mb_get_extents(emlxs_hba_t *hba, MAILBOXQ *mbq, uint16_t type)
600 {
601 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
602 	IOCTL_COMMON_EXTENTS *ep;
603 
604 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
605 	mbq->nonembed = NULL;
606 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
607 	mbq->port = (void *)&PPORT;
608 
609 	mb4->un.varSLIConfig.be.embedded = 1;
610 	mb4->mbxCommand = MBX_SLI_CONFIG;
611 	mb4->mbxOwner = OWN_HOST;
612 
613 	mb4->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
614 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.subsystem =
615 	    IOCTL_SUBSYSTEM_COMMON;
616 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.opcode =
617 	    COMMON_OPCODE_GET_EXTENTS;
618 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.timeout = 0;
619 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.req_length =
620 	    sizeof (IOCTL_COMMON_EXTENTS);
621 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.vf_number = 0;
622 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.vh_number = 0;
623 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.pf_number = 0;
624 
625 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.version = 0; /* V0 */
626 
627 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
628 	ep->params.request.RscType = type;
629 
630 	return;
631 
632 } /* emlxs_mb_get_extents() */
633 
634 
635 /* SLI4 */
636 /*ARGSUSED*/
637 extern void
638 emlxs_mb_alloc_extents(emlxs_hba_t *hba, MAILBOXQ *mbq, uint16_t type,
639     uint16_t count)
640 {
641 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
642 	IOCTL_COMMON_EXTENTS *ep;
643 
644 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
645 	mbq->nonembed = NULL;
646 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
647 	mbq->port = (void *)&PPORT;
648 
649 	mb4->un.varSLIConfig.be.embedded = 1;
650 	mb4->mbxCommand = MBX_SLI_CONFIG;
651 	mb4->mbxOwner = OWN_HOST;
652 
653 	mb4->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
654 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.subsystem =
655 	    IOCTL_SUBSYSTEM_COMMON;
656 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.opcode =
657 	    COMMON_OPCODE_ALLOC_EXTENTS;
658 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.timeout = 0;
659 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.req_length =
660 	    sizeof (IOCTL_COMMON_EXTENTS);
661 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.vf_number = 0;
662 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.vh_number = 0;
663 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.pf_number = 0;
664 
665 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.version = 0; /* V0 */
666 
667 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
668 	ep->params.request.RscType = type;
669 
670 	count = min(count, MAX_EXTENTS);
671 	ep->params.request.RscCnt = count;
672 
673 	return;
674 
675 } /* emlxs_mb_alloc_extents() */
676 
677 
678 /* SLI4 */
679 /*ARGSUSED*/
680 extern void
681 emlxs_mb_dealloc_extents(emlxs_hba_t *hba, MAILBOXQ *mbq, uint16_t type)
682 {
683 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
684 	IOCTL_COMMON_EXTENTS *ep;
685 
686 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
687 	mbq->nonembed = NULL;
688 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
689 	mbq->port = (void *)&PPORT;
690 
691 	mb4->un.varSLIConfig.be.embedded = 1;
692 	mb4->mbxCommand = MBX_SLI_CONFIG;
693 	mb4->mbxOwner = OWN_HOST;
694 
695 	mb4->un.varSLIConfig.be.payload_length = IOCTL_HEADER_SZ;
696 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.subsystem =
697 	    IOCTL_SUBSYSTEM_COMMON;
698 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.opcode =
699 	    COMMON_OPCODE_DEALLOC_EXTENTS;
700 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.timeout = 0;
701 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.req_length =
702 	    sizeof (IOCTL_COMMON_EXTENTS);
703 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.vf_number = 0;
704 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.vh_number = 0;
705 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.pf_number = 0;
706 
707 	mb4->un.varSLIConfig.be.un_hdr.hdr_req2.version = 0; /* V0 */
708 
709 	ep = (IOCTL_COMMON_EXTENTS *)&mb4->un.varSLIConfig.payload;
710 	ep->params.request.RscType = type;
711 
712 	return;
713 
714 } /* emlxs_mb_dealloc_extents() */
715 
716 
717 /* SLI4 */
718 /*ARGSUSED*/
719 extern void
720 emlxs_mb_wq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num)
721 {
722 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
723 	IOCTL_FCOE_WQ_CREATE *qp;
724 	IOCTL_FCOE_WQ_CREATE_V1 *qp1;
725 	uint64_t addr;
726 	int i;
727 
728 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
729 	mbq->nonembed = NULL;
730 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
731 	mbq->port = (void *)&PPORT;
732 
733 	/*
734 	 * Signifies an embedded command
735 	 */
736 	mb4->un.varSLIConfig.be.embedded = 1;
737 
738 	mb4->mbxCommand = MBX_SLI_CONFIG;
739 	mb4->mbxOwner = OWN_HOST;
740 
741 	switch (hba->sli.sli4.param.WQV) {
742 	case 0:
743 		mb4->un.varSLIConfig.be.payload_length =
744 		    sizeof (IOCTL_FCOE_WQ_CREATE) + IOCTL_HEADER_SZ;
745 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
746 		    IOCTL_SUBSYSTEM_FCOE;
747 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
748 		    FCOE_OPCODE_WQ_CREATE;
749 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
750 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
751 		    sizeof (IOCTL_FCOE_WQ_CREATE);
752 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 0;
753 
754 		addr = hba->sli.sli4.wq[num].addr.phys;
755 		qp = (IOCTL_FCOE_WQ_CREATE *)&mb4->un.varSLIConfig.payload;
756 
757 		qp->params.request.CQId = hba->sli.sli4.wq[num].cqid;
758 
759 		qp->params.request.NumPages = EMLXS_NUM_WQ_PAGES;
760 		for (i = 0; i < EMLXS_NUM_WQ_PAGES; i++) {
761 			qp->params.request.Pages[i].addrLow = PADDR_LO(addr);
762 			qp->params.request.Pages[i].addrHigh = PADDR_HI(addr);
763 			addr += 4096;
764 		}
765 
766 		break;
767 
768 	case 1:
769 	default:
770 		mb4->un.varSLIConfig.be.payload_length =
771 		    sizeof (IOCTL_FCOE_WQ_CREATE_V1) + IOCTL_HEADER_SZ;
772 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
773 		    IOCTL_SUBSYSTEM_FCOE;
774 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
775 		    FCOE_OPCODE_WQ_CREATE;
776 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
777 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
778 		    sizeof (IOCTL_FCOE_WQ_CREATE_V1);
779 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 1;
780 
781 		addr = hba->sli.sli4.wq[num].addr.phys;
782 		qp1 = (IOCTL_FCOE_WQ_CREATE_V1 *)&mb4->un.varSLIConfig.payload;
783 
784 		qp1->params.request.CQId = hba->sli.sli4.wq[num].cqid;
785 		qp1->params.request.NumPages = EMLXS_NUM_WQ_PAGES;
786 
787 		qp1->params.request.WqeCnt = WQ_DEPTH;
788 		qp1->params.request.WqeSize = WQE_SIZE_64_BYTES;
789 		qp1->params.request.PageSize = WQ_PAGE_SIZE_4K;
790 
791 		for (i = 0; i < EMLXS_NUM_WQ_PAGES; i++) {
792 			qp1->params.request.Pages[i].addrLow = PADDR_LO(addr);
793 			qp1->params.request.Pages[i].addrHigh = PADDR_HI(addr);
794 			addr += 4096;
795 		}
796 
797 		break;
798 	}
799 
800 	return;
801 
802 } /* emlxs_mb_wq_create() */
803 
804 
805 /* SLI4 */
806 /*ARGSUSED*/
807 extern void
808 emlxs_mb_rq_create(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t num)
809 {
810 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
811 	IOCTL_FCOE_RQ_CREATE *qp;
812 	IOCTL_FCOE_RQ_CREATE_V1 *qp1;
813 	uint64_t	addr;
814 
815 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
816 	mbq->nonembed = NULL;
817 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
818 	mbq->port = (void *)&PPORT;
819 
820 	/*
821 	 * Signifies an embedded command
822 	 */
823 	mb4->un.varSLIConfig.be.embedded = 1;
824 
825 	mb4->mbxCommand = MBX_SLI_CONFIG;
826 	mb4->mbxOwner = OWN_HOST;
827 
828 	switch (hba->sli.sli4.param.RQV) {
829 	case 0:
830 		mb4->un.varSLIConfig.be.payload_length =
831 		    sizeof (IOCTL_FCOE_RQ_CREATE) + IOCTL_HEADER_SZ;
832 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
833 		    IOCTL_SUBSYSTEM_FCOE;
834 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
835 		    FCOE_OPCODE_RQ_CREATE;
836 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
837 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
838 		    sizeof (IOCTL_FCOE_RQ_CREATE);
839 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 0;
840 
841 		addr = hba->sli.sli4.rq[num].addr.phys;
842 
843 		qp = (IOCTL_FCOE_RQ_CREATE *)&mb4->un.varSLIConfig.payload;
844 
845 		qp->params.request.RQContext.RqeCnt	= RQ_DEPTH_EXPONENT;
846 		qp->params.request.RQContext.BufferSize	= RQB_DATA_SIZE;
847 		qp->params.request.RQContext.CQId	=
848 		    hba->sli.sli4.rq[num].cqid;
849 
850 		qp->params.request.NumPages = 1;
851 		qp->params.request.Pages[0].addrLow = PADDR_LO(addr);
852 		qp->params.request.Pages[0].addrHigh = PADDR_HI(addr);
853 
854 		break;
855 
856 	case 1:
857 	default:
858 		mb4->un.varSLIConfig.be.payload_length =
859 		    sizeof (IOCTL_FCOE_RQ_CREATE_V1) + IOCTL_HEADER_SZ;
860 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
861 		    IOCTL_SUBSYSTEM_FCOE;
862 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
863 		    FCOE_OPCODE_RQ_CREATE;
864 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
865 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
866 		    sizeof (IOCTL_FCOE_RQ_CREATE_V1);
867 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 1;
868 
869 		addr = hba->sli.sli4.rq[num].addr.phys;
870 
871 		qp1 = (IOCTL_FCOE_RQ_CREATE_V1 *)&mb4->un.varSLIConfig.payload;
872 
873 		qp1->params.request.RQContext.RqeCnt	 = RQ_DEPTH;
874 		qp1->params.request.RQContext.RqeSize	 = RQE_SIZE_8_BYTES;
875 		qp1->params.request.RQContext.PageSize	 = RQ_PAGE_SIZE_4K;
876 
877 		qp1->params.request.RQContext.BufferSize = RQB_DATA_SIZE;
878 		qp1->params.request.RQContext.CQId	 =
879 		    hba->sli.sli4.rq[num].cqid;
880 
881 		qp1->params.request.NumPages = 1;
882 		qp1->params.request.Pages[0].addrLow = PADDR_LO(addr);
883 		qp1->params.request.Pages[0].addrHigh = PADDR_HI(addr);
884 
885 		break;
886 	}
887 
888 	return;
889 
890 } /* emlxs_mb_rq_create() */
891 
892 
893 /* SLI4 */
894 /*ARGSUSED*/
895 extern void
896 emlxs_mb_mq_create(emlxs_hba_t *hba, MAILBOXQ *mbq)
897 {
898 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
899 	IOCTL_COMMON_MQ_CREATE *qp;
900 	uint64_t	addr;
901 
902 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
903 	mbq->nonembed = NULL;
904 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
905 	mbq->port = (void *)&PPORT;
906 
907 	/*
908 	 * Signifies an embedded command
909 	 */
910 	mb4->un.varSLIConfig.be.embedded = 1;
911 
912 	mb4->mbxCommand = MBX_SLI_CONFIG;
913 	mb4->mbxOwner = OWN_HOST;
914 	mb4->un.varSLIConfig.be.payload_length =
915 	    sizeof (IOCTL_COMMON_MQ_CREATE) + IOCTL_HEADER_SZ;
916 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
917 	    IOCTL_SUBSYSTEM_COMMON;
918 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode = COMMON_OPCODE_MQ_CREATE;
919 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
920 	mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
921 	    sizeof (IOCTL_COMMON_MQ_CREATE);
922 
923 	addr = hba->sli.sli4.mq.addr.phys;
924 	qp = (IOCTL_COMMON_MQ_CREATE *)&mb4->un.varSLIConfig.payload;
925 
926 	qp->params.request.MQContext.Size = MQ_ELEMENT_COUNT_16;
927 	qp->params.request.MQContext.Valid = 1;
928 	qp->params.request.MQContext.CQId = hba->sli.sli4.mq.cqid;
929 
930 	qp->params.request.NumPages = 1;
931 	qp->params.request.Pages[0].addrLow = PADDR_LO(addr);
932 	qp->params.request.Pages[0].addrHigh = PADDR_HI(addr);
933 
934 	return;
935 
936 } /* emlxs_mb_mq_create() */
937 
938 
939 /* SLI4 */
940 /*ARGSUSED*/
941 extern void
942 emlxs_mb_mq_create_ext(emlxs_hba_t *hba, MAILBOXQ *mbq)
943 {
944 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
945 	IOCTL_COMMON_MQ_CREATE_EXT *qp;
946 	IOCTL_COMMON_MQ_CREATE_EXT_V1 *qp1;
947 	uint64_t	addr;
948 
949 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
950 	mbq->nonembed = NULL;
951 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
952 	mbq->port = (void *)&PPORT;
953 
954 	/*
955 	 * Signifies an embedded command
956 	 */
957 	mb4->un.varSLIConfig.be.embedded = 1;
958 
959 	mb4->mbxCommand = MBX_SLI_CONFIG;
960 	mb4->mbxOwner = OWN_HOST;
961 
962 	switch (hba->sli.sli4.param.MQV) {
963 	case 0:
964 		mb4->un.varSLIConfig.be.payload_length =
965 		    sizeof (IOCTL_COMMON_MQ_CREATE_EXT) + IOCTL_HEADER_SZ;
966 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
967 		    IOCTL_SUBSYSTEM_COMMON;
968 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
969 		    COMMON_OPCODE_MQ_CREATE_EXT;
970 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
971 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
972 		    sizeof (IOCTL_COMMON_MQ_CREATE_EXT);
973 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 0;
974 
975 		addr = hba->sli.sli4.mq.addr.phys;
976 		qp = (IOCTL_COMMON_MQ_CREATE_EXT *)
977 		    &mb4->un.varSLIConfig.payload;
978 
979 		qp->params.request.num_pages = 1;
980 		qp->params.request.async_event_bitmap =
981 		    ASYNC_LINK_EVENT | ASYNC_FCF_EVENT | ASYNC_GROUP5_EVENT;
982 		qp->params.request.context.Size = MQ_ELEMENT_COUNT_16;
983 		qp->params.request.context.Valid = 1;
984 		qp->params.request.context.CQId = hba->sli.sli4.mq.cqid;
985 
986 		qp->params.request.pages[0].addrLow = PADDR_LO(addr);
987 		qp->params.request.pages[0].addrHigh = PADDR_HI(addr);
988 
989 		break;
990 
991 	case 1:
992 	default:
993 		mb4->un.varSLIConfig.be.payload_length =
994 		    sizeof (IOCTL_COMMON_MQ_CREATE) + IOCTL_HEADER_SZ;
995 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.subsystem =
996 		    IOCTL_SUBSYSTEM_COMMON;
997 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.opcode =
998 		    COMMON_OPCODE_MQ_CREATE_EXT;
999 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.timeout = 0;
1000 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.req_length =
1001 		    sizeof (IOCTL_COMMON_MQ_CREATE_EXT_V1);
1002 		mb4->un.varSLIConfig.be.un_hdr.hdr_req.version = 1;
1003 
1004 		addr = hba->sli.sli4.mq.addr.phys;
1005 		qp1 = (IOCTL_COMMON_MQ_CREATE_EXT_V1 *)
1006 		    &mb4->un.varSLIConfig.payload;
1007 
1008 		qp1->params.request.num_pages = 1;
1009 		qp1->params.request.async_event_bitmap =
1010 		    ASYNC_LINK_EVENT | ASYNC_FCF_EVENT | ASYNC_GROUP5_EVENT |
1011 		    ASYNC_FC_EVENT | ASYNC_PORT_EVENT;
1012 		qp1->params.request.context.Size = MQ_ELEMENT_COUNT_16;
1013 		qp1->params.request.context.Valid = 1;
1014 		qp1->params.request.CQId = hba->sli.sli4.mq.cqid;
1015 
1016 		qp1->params.request.pages[0].addrLow = PADDR_LO(addr);
1017 		qp1->params.request.pages[0].addrHigh = PADDR_HI(addr);
1018 
1019 		break;
1020 	}
1021 
1022 	return;
1023 
1024 } /* emlxs_mb_mq_create_ext() */
1025 
1026 
1027 /*ARGSUSED*/
1028 extern void
1029 emlxs_mb_async_event(emlxs_hba_t *hba, MAILBOXQ *mbq)
1030 {
1031 	MAILBOX *mb = (MAILBOX *)mbq;
1032 
1033 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1034 
1035 	mb->mbxCommand = MBX_ASYNC_EVENT;
1036 	mb->mbxOwner = OWN_HOST;
1037 	mb->un.varWords[0] = hba->channel_els;
1038 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1039 	mbq->port = (void *)&PPORT;
1040 
1041 	return;
1042 
1043 } /* emlxs_mb_async_event() */
1044 
1045 
1046 /*ARGSUSED*/
1047 extern void
1048 emlxs_mb_heartbeat(emlxs_hba_t *hba, MAILBOXQ *mbq)
1049 {
1050 	MAILBOX *mb = (MAILBOX *)mbq;
1051 
1052 	bzero((void *) mb, MAILBOX_CMD_BSIZE);
1053 
1054 	mb->mbxCommand = MBX_HEARTBEAT;
1055 	mb->mbxOwner = OWN_HOST;
1056 	mbq->mbox_cmpl = NULL; /* no cmpl needed for hbeat */
1057 	mbq->port = (void *)&PPORT;
1058 
1059 	return;
1060 
1061 } /* emlxs_mb_heartbeat() */
1062 
1063 
1064 #ifdef MSI_SUPPORT
1065 
1066 /*ARGSUSED*/
1067 extern void
1068 emlxs_mb_config_msi(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map,
1069     uint32_t intr_count)
1070 {
1071 	MAILBOX *mb = (MAILBOX *)mbq;
1072 	uint16_t i;
1073 	uint32_t mask;
1074 
1075 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1076 
1077 	mb->mbxCommand = MBX_CONFIG_MSI;
1078 
1079 	/* Set the default message id to zero */
1080 	mb->un.varCfgMSI.defaultPresent = 1;
1081 	mb->un.varCfgMSI.defaultMessageNumber = 0;
1082 
1083 	for (i = 1; i < intr_count; i++) {
1084 		mask = intr_map[i];
1085 
1086 		mb->un.varCfgMSI.attConditions |= mask;
1087 
1088 #ifdef EMLXS_BIG_ENDIAN
1089 		if (mask & HA_R0ATT) {
1090 			mb->un.varCfgMSI.messageNumberByHA[3] = i;
1091 		}
1092 		if (mask & HA_R1ATT) {
1093 			mb->un.varCfgMSI.messageNumberByHA[7] = i;
1094 		}
1095 		if (mask & HA_R2ATT) {
1096 			mb->un.varCfgMSI.messageNumberByHA[11] = i;
1097 		}
1098 		if (mask & HA_R3ATT) {
1099 			mb->un.varCfgMSI.messageNumberByHA[15] = i;
1100 		}
1101 		if (mask & HA_LATT) {
1102 			mb->un.varCfgMSI.messageNumberByHA[29] = i;
1103 		}
1104 		if (mask & HA_MBATT) {
1105 			mb->un.varCfgMSI.messageNumberByHA[30] = i;
1106 		}
1107 		if (mask & HA_ERATT) {
1108 			mb->un.varCfgMSI.messageNumberByHA[31] = i;
1109 		}
1110 #endif	/* EMLXS_BIG_ENDIAN */
1111 
1112 #ifdef EMLXS_LITTLE_ENDIAN
1113 		/* Accounts for half word swap of LE architecture */
1114 		if (mask & HA_R0ATT) {
1115 			mb->un.varCfgMSI.messageNumberByHA[2] = i;
1116 		}
1117 		if (mask & HA_R1ATT) {
1118 			mb->un.varCfgMSI.messageNumberByHA[6] = i;
1119 		}
1120 		if (mask & HA_R2ATT) {
1121 			mb->un.varCfgMSI.messageNumberByHA[10] = i;
1122 		}
1123 		if (mask & HA_R3ATT) {
1124 			mb->un.varCfgMSI.messageNumberByHA[14] = i;
1125 		}
1126 		if (mask & HA_LATT) {
1127 			mb->un.varCfgMSI.messageNumberByHA[28] = i;
1128 		}
1129 		if (mask & HA_MBATT) {
1130 			mb->un.varCfgMSI.messageNumberByHA[31] = i;
1131 		}
1132 		if (mask & HA_ERATT) {
1133 			mb->un.varCfgMSI.messageNumberByHA[30] = i;
1134 		}
1135 #endif	/* EMLXS_LITTLE_ENDIAN */
1136 	}
1137 
1138 	mb->mbxOwner = OWN_HOST;
1139 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1140 	mbq->port = (void *)&PPORT;
1141 
1142 	return;
1143 
1144 } /* emlxs_mb_config_msi() */
1145 
1146 
1147 /*ARGSUSED*/
1148 extern void
1149 emlxs_mb_config_msix(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t *intr_map,
1150     uint32_t intr_count)
1151 {
1152 	MAILBOX *mb = (MAILBOX *)mbq;
1153 	uint8_t i;
1154 	uint32_t mask;
1155 
1156 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1157 
1158 	mb->mbxCommand = MBX_CONFIG_MSIX;
1159 
1160 	/* Set the default message id to zero */
1161 	mb->un.varCfgMSIX.defaultPresent = 1;
1162 	mb->un.varCfgMSIX.defaultMessageNumber = 0;
1163 
1164 	for (i = 1; i < intr_count; i++) {
1165 		mask = intr_map[i];
1166 
1167 		mb->un.varCfgMSIX.attConditions1 |= mask;
1168 
1169 #ifdef EMLXS_BIG_ENDIAN
1170 		if (mask & HA_R0ATT) {
1171 			mb->un.varCfgMSIX.messageNumberByHA[3] = i;
1172 		}
1173 		if (mask & HA_R1ATT) {
1174 			mb->un.varCfgMSIX.messageNumberByHA[7] = i;
1175 		}
1176 		if (mask & HA_R2ATT) {
1177 			mb->un.varCfgMSIX.messageNumberByHA[11] = i;
1178 		}
1179 		if (mask & HA_R3ATT) {
1180 			mb->un.varCfgMSIX.messageNumberByHA[15] = i;
1181 		}
1182 		if (mask & HA_LATT) {
1183 			mb->un.varCfgMSIX.messageNumberByHA[29] = i;
1184 		}
1185 		if (mask & HA_MBATT) {
1186 			mb->un.varCfgMSIX.messageNumberByHA[30] = i;
1187 		}
1188 		if (mask & HA_ERATT) {
1189 			mb->un.varCfgMSIX.messageNumberByHA[31] = i;
1190 		}
1191 #endif	/* EMLXS_BIG_ENDIAN */
1192 
1193 #ifdef EMLXS_LITTLE_ENDIAN
1194 		/* Accounts for word swap of LE architecture */
1195 		if (mask & HA_R0ATT) {
1196 			mb->un.varCfgMSIX.messageNumberByHA[0] = i;
1197 		}
1198 		if (mask & HA_R1ATT) {
1199 			mb->un.varCfgMSIX.messageNumberByHA[4] = i;
1200 		}
1201 		if (mask & HA_R2ATT) {
1202 			mb->un.varCfgMSIX.messageNumberByHA[8] = i;
1203 		}
1204 		if (mask & HA_R3ATT) {
1205 			mb->un.varCfgMSIX.messageNumberByHA[12] = i;
1206 		}
1207 		if (mask & HA_LATT) {
1208 			mb->un.varCfgMSIX.messageNumberByHA[30] = i;
1209 		}
1210 		if (mask & HA_MBATT) {
1211 			mb->un.varCfgMSIX.messageNumberByHA[29] = i;
1212 		}
1213 		if (mask & HA_ERATT) {
1214 			mb->un.varCfgMSIX.messageNumberByHA[28] = i;
1215 		}
1216 #endif	/* EMLXS_LITTLE_ENDIAN */
1217 	}
1218 
1219 	mb->mbxOwner = OWN_HOST;
1220 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1221 	mbq->port = (void *)&PPORT;
1222 
1223 	return;
1224 
1225 } /* emlxs_mb_config_msix() */
1226 
1227 
1228 #endif	/* MSI_SUPPORT */
1229 
1230 
1231 /*ARGSUSED*/
1232 extern void
1233 emlxs_mb_reset_ring(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t ringno)
1234 {
1235 	MAILBOX *mb = (MAILBOX *)mbq;
1236 
1237 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1238 
1239 	mb->mbxCommand = MBX_RESET_RING;
1240 	mb->un.varRstRing.ring_no = ringno;
1241 	mb->mbxOwner = OWN_HOST;
1242 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1243 	mbq->port = (void *)&PPORT;
1244 
1245 	return;
1246 
1247 } /* emlxs_mb_reset_ring() */
1248 
1249 
1250 /*ARGSUSED*/
1251 extern void
1252 emlxs_mb_dump_vpd(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset)
1253 {
1254 
1255 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1256 		MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
1257 
1258 		/* Clear the local dump_region */
1259 		bzero(hba->sli.sli4.dump_region.virt,
1260 		    hba->sli.sli4.dump_region.size);
1261 
1262 		bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
1263 
1264 		mb4->mbxCommand = MBX_DUMP_MEMORY;
1265 		mb4->un.varDmp4.type = DMP_NV_PARAMS;
1266 		mb4->un.varDmp4.entry_index = offset;
1267 		mb4->un.varDmp4.region_id = DMP_VPD_REGION;
1268 
1269 		mb4->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size;
1270 		mb4->un.varDmp4.addrHigh =
1271 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
1272 		mb4->un.varDmp4.addrLow =
1273 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
1274 		mb4->un.varDmp4.rsp_cnt = 0;
1275 
1276 		mb4->mbxOwner = OWN_HOST;
1277 
1278 	} else {
1279 		MAILBOX *mb = (MAILBOX *)mbq;
1280 
1281 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
1282 
1283 		mb->mbxCommand = MBX_DUMP_MEMORY;
1284 		mb->un.varDmp.cv = 1;
1285 		mb->un.varDmp.type = DMP_NV_PARAMS;
1286 		mb->un.varDmp.entry_index = offset;
1287 		mb->un.varDmp.region_id = DMP_VPD_REGION;
1288 
1289 		/* limited by mailbox size */
1290 		mb->un.varDmp.word_cnt = DMP_VPD_DUMP_WCOUNT;
1291 
1292 		mb->un.varDmp.co = 0;
1293 		mb->un.varDmp.resp_offset = 0;
1294 		mb->mbxOwner = OWN_HOST;
1295 	}
1296 
1297 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1298 	mbq->port = (void *)&PPORT;
1299 
1300 } /* emlxs_mb_dump_vpd() */
1301 
1302 
1303 /* SLI4 */
1304 /*ARGSUSED*/
1305 extern void
1306 emlxs_mb_dump_fcoe(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset)
1307 {
1308 	MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
1309 
1310 	if (hba->sli_mode < EMLXS_HBA_SLI4_MODE) {
1311 		return;
1312 	}
1313 
1314 	/* Clear the local dump_region */
1315 	bzero(hba->sli.sli4.dump_region.virt,
1316 	    hba->sli.sli4.dump_region.size);
1317 
1318 	bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
1319 
1320 	mb4->mbxCommand = MBX_DUMP_MEMORY;
1321 	mb4->un.varDmp4.type = DMP_NV_PARAMS;
1322 	mb4->un.varDmp4.entry_index = offset;
1323 	mb4->un.varDmp4.region_id = DMP_FCOE_REGION;
1324 
1325 	mb4->un.varDmp4.available_cnt = hba->sli.sli4.dump_region.size;
1326 	mb4->un.varDmp4.addrHigh =
1327 	    PADDR_HI(hba->sli.sli4.dump_region.phys);
1328 	mb4->un.varDmp4.addrLow =
1329 	    PADDR_LO(hba->sli.sli4.dump_region.phys);
1330 	mb4->un.varDmp4.rsp_cnt = 0;
1331 
1332 	mb4->mbxOwner = OWN_HOST;
1333 
1334 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1335 	mbq->port = (void *)&PPORT;
1336 
1337 } /* emlxs_mb_dump_fcoe() */
1338 
1339 
1340 /*ARGSUSED*/
1341 extern void
1342 emlxs_mb_dump(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t offset, uint32_t words)
1343 {
1344 
1345 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1346 		MAILBOX4 *mb4 = (MAILBOX4 *)mbq;
1347 
1348 		/* Clear the local dump_region */
1349 		bzero(hba->sli.sli4.dump_region.virt,
1350 		    hba->sli.sli4.dump_region.size);
1351 
1352 		bzero((void *) mb4, MAILBOX_CMD_SLI4_BSIZE);
1353 
1354 		mb4->mbxCommand = MBX_DUMP_MEMORY;
1355 		mb4->un.varDmp4.type = DMP_MEM_REG;
1356 		mb4->un.varDmp4.entry_index = offset;
1357 		mb4->un.varDmp4.region_id = 0;
1358 
1359 		mb4->un.varDmp4.available_cnt = min((words*4),
1360 		    hba->sli.sli4.dump_region.size);
1361 		mb4->un.varDmp4.addrHigh =
1362 		    PADDR_HI(hba->sli.sli4.dump_region.phys);
1363 		mb4->un.varDmp4.addrLow =
1364 		    PADDR_LO(hba->sli.sli4.dump_region.phys);
1365 		mb4->un.varDmp4.rsp_cnt = 0;
1366 
1367 		mb4->mbxOwner = OWN_HOST;
1368 
1369 	} else {
1370 
1371 		MAILBOX *mb = (MAILBOX *)mbq;
1372 
1373 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
1374 
1375 		mb->mbxCommand = MBX_DUMP_MEMORY;
1376 		mb->un.varDmp.type = DMP_MEM_REG;
1377 		mb->un.varDmp.word_cnt = words;
1378 		mb->un.varDmp.base_adr = offset;
1379 
1380 		mb->un.varDmp.co = 0;
1381 		mb->un.varDmp.resp_offset = 0;
1382 		mb->mbxOwner = OWN_HOST;
1383 	}
1384 
1385 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1386 	mbq->port = (void *)&PPORT;
1387 
1388 	return;
1389 
1390 } /* emlxs_mb_dump() */
1391 
1392 
1393 /*
1394  *  emlxs_mb_read_nv  Issue a READ NVPARAM mailbox command
1395  */
1396 /*ARGSUSED*/
1397 extern void
1398 emlxs_mb_read_nv(emlxs_hba_t *hba, MAILBOXQ *mbq)
1399 {
1400 	MAILBOX *mb = (MAILBOX *)mbq;
1401 
1402 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1403 
1404 	mb->mbxCommand = MBX_READ_NV;
1405 	mb->mbxOwner = OWN_HOST;
1406 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1407 	mbq->port = (void *)&PPORT;
1408 
1409 } /* emlxs_mb_read_nv() */
1410 
1411 
1412 /*
1413  * emlxs_mb_read_rev  Issue a READ REV mailbox command
1414  */
1415 /*ARGSUSED*/
1416 extern void
1417 emlxs_mb_read_rev(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t v3)
1418 {
1419 	MAILBOX *mb = (MAILBOX *)mbq;
1420 
1421 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
1422 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
1423 		mbq->nonembed = NULL;
1424 	} else {
1425 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
1426 
1427 		mb->un.varRdRev.cv = 1;
1428 
1429 		if (v3) {
1430 			mb->un.varRdRev.cv3 = 1;
1431 		}
1432 	}
1433 
1434 	mb->mbxCommand = MBX_READ_REV;
1435 	mb->mbxOwner = OWN_HOST;
1436 	mbq->mbox_cmpl = NULL;
1437 	mbq->port = (void *)&PPORT;
1438 
1439 } /* emlxs_mb_read_rev() */
1440 
1441 
1442 /*
1443  * emlxs_mb_run_biu_diag  Issue a RUN_BIU_DIAG mailbox command
1444  */
1445 /*ARGSUSED*/
1446 extern uint32_t
1447 emlxs_mb_run_biu_diag(emlxs_hba_t *hba, MAILBOXQ *mbq, uint64_t out,
1448     uint64_t in)
1449 {
1450 	MAILBOX *mb = (MAILBOX *)mbq;
1451 
1452 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1453 
1454 	mb->mbxCommand = MBX_RUN_BIU_DIAG64;
1455 	mb->un.varBIUdiag.un.s2.xmit_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE;
1456 	mb->un.varBIUdiag.un.s2.xmit_bde64.addrHigh = PADDR_HI(out);
1457 	mb->un.varBIUdiag.un.s2.xmit_bde64.addrLow = PADDR_LO(out);
1458 	mb->un.varBIUdiag.un.s2.rcv_bde64.tus.f.bdeSize = MEM_ELSBUF_SIZE;
1459 	mb->un.varBIUdiag.un.s2.rcv_bde64.addrHigh = PADDR_HI(in);
1460 	mb->un.varBIUdiag.un.s2.rcv_bde64.addrLow = PADDR_LO(in);
1461 	mb->mbxOwner = OWN_HOST;
1462 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1463 	mbq->port = (void *)&PPORT;
1464 
1465 	return (0);
1466 } /* emlxs_mb_run_biu_diag() */
1467 
1468 
1469 /* This should only be called with active MBX_NOWAIT mailboxes */
1470 void
1471 emlxs_mb_retry(emlxs_hba_t *hba, MAILBOXQ *mbq)
1472 {
1473 	MAILBOX	*mb;
1474 	MAILBOX	*mbox;
1475 	int rc;
1476 
1477 	mbox = (MAILBOX *)emlxs_mem_get(hba, MEM_MBOX);
1478 	if (!mbox) {
1479 		return;
1480 	}
1481 	mb = (MAILBOX *)mbq;
1482 	bcopy((uint8_t *)mb, (uint8_t *)mbox, MAILBOX_CMD_BSIZE);
1483 	mbox->mbxOwner = OWN_HOST;
1484 	mbox->mbxStatus = 0;
1485 
1486 	mutex_enter(&EMLXS_PORT_LOCK);
1487 
1488 	HBASTATS.MboxCompleted++;
1489 
1490 	if (mb->mbxStatus != 0) {
1491 		HBASTATS.MboxError++;
1492 	} else {
1493 		HBASTATS.MboxGood++;
1494 	}
1495 
1496 	hba->mbox_mbq = NULL;
1497 	hba->mbox_queue_flag = 0;
1498 
1499 	mutex_exit(&EMLXS_PORT_LOCK);
1500 
1501 	rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbox, MBX_NOWAIT, 0);
1502 	if ((rc != MBX_BUSY) && (rc != MBX_SUCCESS)) {
1503 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbox);
1504 	}
1505 	return;
1506 
1507 } /* emlxs_mb_retry() */
1508 
1509 
1510 /* SLI3 */
1511 static uint32_t
1512 emlxs_read_la_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
1513 {
1514 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
1515 	MAILBOX *mb;
1516 	MAILBOXQ *mbox;
1517 	MATCHMAP *mp;
1518 	READ_LA_VAR la;
1519 	int i;
1520 	uint32_t  control;
1521 
1522 	mb = (MAILBOX *)mbq;
1523 	if (mb->mbxStatus) {
1524 		if (mb->mbxStatus == MBXERR_NO_RESOURCES) {
1525 			control = mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize;
1526 			if (control == 0) {
1527 				(void) emlxs_mb_read_la(hba, mbq);
1528 			}
1529 			emlxs_mb_retry(hba, mbq);
1530 			return (1);
1531 		}
1532 		/* Enable Link Attention interrupts */
1533 		mutex_enter(&EMLXS_PORT_LOCK);
1534 
1535 		if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) {
1536 			hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
1537 			WRITE_CSR_REG(hba, FC_HC_REG(hba),
1538 			    hba->sli.sli3.hc_copy);
1539 #ifdef FMA_SUPPORT
1540 			/* Access handle validation */
1541 			EMLXS_CHK_ACC_HANDLE(hba,
1542 			    hba->sli.sli3.csr_acc_handle);
1543 #endif  /* FMA_SUPPORT */
1544 		}
1545 
1546 		mutex_exit(&EMLXS_PORT_LOCK);
1547 		return (0);
1548 	}
1549 	bcopy((void *)&mb->un.varReadLA, (void *)&la, sizeof (READ_LA_VAR));
1550 
1551 	mp = (MATCHMAP *)mbq->bp;
1552 	if (mp) {
1553 		bcopy((caddr_t)mp->virt, (caddr_t)port->alpa_map, 128);
1554 	} else {
1555 		bzero((caddr_t)port->alpa_map, 128);
1556 	}
1557 
1558 	if (la.attType == AT_LINK_UP) {
1559 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_linkup_atten_msg,
1560 		    "tag=%d -> %d  ALPA=%x",
1561 		    (uint32_t)hba->link_event_tag,
1562 		    (uint32_t)la.eventTag,
1563 		    (uint32_t)la.granted_AL_PA);
1564 	} else {
1565 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_linkdown_atten_msg,
1566 		    "tag=%d -> %d  ALPA=%x",
1567 		    (uint32_t)hba->link_event_tag,
1568 		    (uint32_t)la.eventTag,
1569 		    (uint32_t)la.granted_AL_PA);
1570 	}
1571 
1572 	if (la.pb) {
1573 		hba->flag |= FC_BYPASSED_MODE;
1574 	} else {
1575 		hba->flag &= ~FC_BYPASSED_MODE;
1576 	}
1577 
1578 	if (hba->link_event_tag == la.eventTag) {
1579 		HBASTATS.LinkMultiEvent++;
1580 	} else if (hba->link_event_tag + 1 < la.eventTag) {
1581 		HBASTATS.LinkMultiEvent++;
1582 
1583 		/* Make sure link is declared down */
1584 		emlxs_linkdown(hba);
1585 	}
1586 
1587 	hba->link_event_tag = la.eventTag;
1588 	port->lip_type = 0;
1589 
1590 	/* If link not already up then declare it up now */
1591 	if ((la.attType == AT_LINK_UP) && (hba->state < FC_LINK_UP)) {
1592 
1593 #ifdef MENLO_SUPPORT
1594 		if ((hba->model_info.device_id == PCI_DEVICE_ID_HORNET) &&
1595 		    (hba->flag & (FC_ILB_MODE | FC_ELB_MODE))) {
1596 			la.topology = TOPOLOGY_LOOP;
1597 			la.granted_AL_PA = 0;
1598 			port->alpa_map[0] = 1;
1599 			port->alpa_map[1] = 0;
1600 			la.lipType = LT_PORT_INIT;
1601 		}
1602 #endif /* MENLO_SUPPORT */
1603 		/* Save the linkspeed */
1604 		hba->linkspeed = la.UlnkSpeed;
1605 
1606 		/* Check for old model adapters that only */
1607 		/* supported 1Gb */
1608 		if ((hba->linkspeed == 0) &&
1609 		    (hba->model_info.chip & EMLXS_DRAGONFLY_CHIP)) {
1610 			hba->linkspeed = LA_1GHZ_LINK;
1611 		}
1612 
1613 		if ((hba->topology = la.topology) == TOPOLOGY_LOOP) {
1614 			port->granted_alpa = la.granted_AL_PA;
1615 			port->did = port->granted_alpa;
1616 			port->lip_type = la.lipType;
1617 			if (hba->flag & FC_SLIM2_MODE) {
1618 				i = la.un.lilpBde64.tus.f.bdeSize;
1619 			} else {
1620 				i = la.un.lilpBde.bdeSize;
1621 			}
1622 
1623 			if (i == 0) {
1624 				port->alpa_map[0] = 0;
1625 			} else {
1626 				uint8_t *alpa_map;
1627 				uint32_t j;
1628 
1629 				/* Check number of devices in map */
1630 				if (port->alpa_map[0] > 127) {
1631 					port->alpa_map[0] = 127;
1632 				}
1633 
1634 				alpa_map = (uint8_t *)port->alpa_map;
1635 
1636 				EMLXS_MSGF(EMLXS_CONTEXT,
1637 				    &emlxs_link_atten_msg,
1638 				    "alpa_map: %d device(s):      "
1639 				    "%02x %02x %02x %02x %02x %02x "
1640 				    "%02x", alpa_map[0], alpa_map[1],
1641 				    alpa_map[2], alpa_map[3],
1642 				    alpa_map[4], alpa_map[5],
1643 				    alpa_map[6], alpa_map[7]);
1644 
1645 				for (j = 8; j <= alpa_map[0]; j += 8) {
1646 					EMLXS_MSGF(EMLXS_CONTEXT,
1647 					    &emlxs_link_atten_msg,
1648 					    "alpa_map:             "
1649 					    "%02x %02x %02x %02x %02x "
1650 					    "%02x %02x %02x",
1651 					    alpa_map[j],
1652 					    alpa_map[j + 1],
1653 					    alpa_map[j + 2],
1654 					    alpa_map[j + 3],
1655 					    alpa_map[j + 4],
1656 					    alpa_map[j + 5],
1657 					    alpa_map[j + 6],
1658 					    alpa_map[j + 7]);
1659 				}
1660 			}
1661 		}
1662 #ifdef MENLO_SUPPORT
1663 		/* Check if Menlo maintenance mode is enabled */
1664 		if (hba->model_info.device_id ==
1665 		    PCI_DEVICE_ID_HORNET) {
1666 			if (la.mm == 1) {
1667 				EMLXS_MSGF(EMLXS_CONTEXT,
1668 				    &emlxs_link_atten_msg,
1669 				    "Maintenance Mode enabled.");
1670 
1671 				mutex_enter(&EMLXS_PORT_LOCK);
1672 				hba->flag |= FC_MENLO_MODE;
1673 				mutex_exit(&EMLXS_PORT_LOCK);
1674 
1675 				mutex_enter(&EMLXS_LINKUP_LOCK);
1676 				cv_broadcast(&EMLXS_LINKUP_CV);
1677 				mutex_exit(&EMLXS_LINKUP_LOCK);
1678 			} else {
1679 				EMLXS_MSGF(EMLXS_CONTEXT,
1680 				    &emlxs_link_atten_msg,
1681 				    "Maintenance Mode disabled.");
1682 			}
1683 
1684 			/* Check FCoE attention bit */
1685 			if (la.fa == 1) {
1686 				emlxs_thread_spawn(hba,
1687 				    emlxs_fcoe_attention_thread,
1688 				    0, 0);
1689 			}
1690 		}
1691 #endif /* MENLO_SUPPORT */
1692 
1693 		if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1694 		    MEM_MBOX))) {
1695 			/* This should turn on DELAYED ABTS for */
1696 			/* ELS timeouts */
1697 			emlxs_mb_set_var(hba, mbox, 0x00052198, 0x1);
1698 
1699 			emlxs_mb_put(hba, mbox);
1700 		}
1701 
1702 		if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1703 		    MEM_MBOX))) {
1704 			/* If link not already down then */
1705 			/* declare it down now */
1706 			if (emlxs_mb_read_sparam(hba, mbox) == 0) {
1707 				emlxs_mb_put(hba, mbox);
1708 			} else {
1709 				emlxs_mem_put(hba, MEM_MBOX,
1710 				    (void *)mbox);
1711 			}
1712 		}
1713 
1714 		if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1715 		    MEM_MBOX))) {
1716 			emlxs_mb_config_link(hba, mbox);
1717 
1718 			emlxs_mb_put(hba, mbox);
1719 		}
1720 
1721 		/* Declare the linkup here */
1722 		emlxs_linkup(hba);
1723 	}
1724 
1725 	/* If link not already down then declare it down now */
1726 	else if (la.attType == AT_LINK_DOWN) {
1727 		/* Make sure link is declared down */
1728 		emlxs_linkdown(hba);
1729 	}
1730 
1731 	/* Enable Link attention interrupt */
1732 	mutex_enter(&EMLXS_PORT_LOCK);
1733 
1734 	if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) {
1735 		hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
1736 		WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
1737 #ifdef FMA_SUPPORT
1738 		/* Access handle validation */
1739 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
1740 #endif  /* FMA_SUPPORT */
1741 	}
1742 
1743 	mutex_exit(&EMLXS_PORT_LOCK);
1744 
1745 	return (0);
1746 
1747 } /* emlxs_read_la_mbcmpl() */
1748 
1749 
1750 extern uint32_t
1751 emlxs_mb_read_la(emlxs_hba_t *hba, MAILBOXQ *mbq)
1752 {
1753 	MAILBOX *mb = (MAILBOX *)mbq;
1754 	MATCHMAP *mp;
1755 
1756 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1757 
1758 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
1759 		mb->mbxCommand = MBX_READ_LA64;
1760 
1761 		return (1);
1762 	}
1763 
1764 	mb->mbxCommand = MBX_READ_LA64;
1765 	mb->un.varReadLA.un.lilpBde64.tus.f.bdeSize = 128;
1766 	mb->un.varReadLA.un.lilpBde64.addrHigh = PADDR_HI(mp->phys);
1767 	mb->un.varReadLA.un.lilpBde64.addrLow = PADDR_LO(mp->phys);
1768 	mb->mbxOwner = OWN_HOST;
1769 	mbq->mbox_cmpl = emlxs_read_la_mbcmpl;
1770 	mbq->port = (void *)&PPORT;
1771 
1772 	/*
1773 	 * save address for completion
1774 	 */
1775 	mbq->bp = (void *)mp;
1776 
1777 	return (0);
1778 
1779 } /* emlxs_mb_read_la() */
1780 
1781 
1782 /* SLI3 */
1783 static uint32_t
1784 emlxs_clear_la_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
1785 {
1786 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
1787 	MAILBOX *mb;
1788 	MAILBOXQ *mbox;
1789 	emlxs_port_t *vport;
1790 	uint32_t la_enable;
1791 	int i, rc;
1792 
1793 	mb = (MAILBOX *)mbq;
1794 	if (mb->mbxStatus) {
1795 		la_enable = 1;
1796 
1797 		if (mb->mbxStatus == 0x1601) {
1798 			/* Get a buffer which will be used for */
1799 			/* mailbox commands */
1800 			if ((mbox = (MAILBOXQ *)emlxs_mem_get(hba,
1801 			    MEM_MBOX))) {
1802 				/* Get link attention message */
1803 				if (emlxs_mb_read_la(hba, mbox) == 0) {
1804 					rc =  EMLXS_SLI_ISSUE_MBOX_CMD(hba,
1805 					    (MAILBOX *)mbox, MBX_NOWAIT, 0);
1806 					if ((rc != MBX_BUSY) &&
1807 					    (rc != MBX_SUCCESS)) {
1808 						emlxs_mem_put(hba,
1809 						    MEM_MBOX, (void *)mbox);
1810 					}
1811 					la_enable = 0;
1812 				} else {
1813 					emlxs_mem_put(hba, MEM_MBOX,
1814 					    (void *)mbox);
1815 				}
1816 			}
1817 		}
1818 
1819 		mutex_enter(&EMLXS_PORT_LOCK);
1820 		if (la_enable) {
1821 			if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) {
1822 				/* Enable Link Attention interrupts */
1823 				hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
1824 				WRITE_CSR_REG(hba, FC_HC_REG(hba),
1825 				    hba->sli.sli3.hc_copy);
1826 #ifdef FMA_SUPPORT
1827 				/* Access handle validation */
1828 				EMLXS_CHK_ACC_HANDLE(hba,
1829 				    hba->sli.sli3.csr_acc_handle);
1830 #endif  /* FMA_SUPPORT */
1831 			}
1832 		} else {
1833 			if (hba->sli.sli3.hc_copy & HC_LAINT_ENA) {
1834 				/* Disable Link Attention interrupts */
1835 				hba->sli.sli3.hc_copy &= ~HC_LAINT_ENA;
1836 				WRITE_CSR_REG(hba, FC_HC_REG(hba),
1837 				    hba->sli.sli3.hc_copy);
1838 #ifdef FMA_SUPPORT
1839 				/* Access handle validation */
1840 				EMLXS_CHK_ACC_HANDLE(hba,
1841 				    hba->sli.sli3.csr_acc_handle);
1842 #endif  /* FMA_SUPPORT */
1843 			}
1844 		}
1845 		mutex_exit(&EMLXS_PORT_LOCK);
1846 
1847 		return (0);
1848 	}
1849 	/* Enable on Link Attention interrupts */
1850 	mutex_enter(&EMLXS_PORT_LOCK);
1851 
1852 	if (!(hba->sli.sli3.hc_copy & HC_LAINT_ENA)) {
1853 		hba->sli.sli3.hc_copy |= HC_LAINT_ENA;
1854 		WRITE_CSR_REG(hba, FC_HC_REG(hba), hba->sli.sli3.hc_copy);
1855 #ifdef FMA_SUPPORT
1856 		/* Access handle validation */
1857 		EMLXS_CHK_ACC_HANDLE(hba, hba->sli.sli3.csr_acc_handle);
1858 #endif  /* FMA_SUPPORT */
1859 	}
1860 
1861 	if (hba->state >= FC_LINK_UP) {
1862 		EMLXS_STATE_CHANGE_LOCKED(hba, FC_READY);
1863 	}
1864 
1865 	mutex_exit(&EMLXS_PORT_LOCK);
1866 
1867 	/* Adapter is now ready for FCP traffic */
1868 	if (hba->state == FC_READY) {
1869 
1870 		/* Register vpi's for all ports that have did's */
1871 		for (i = 0; i < MAX_VPORTS; i++) {
1872 			vport = &VPORT(i);
1873 
1874 			if (!(vport->flag & EMLXS_PORT_BOUND) ||
1875 			    !(vport->did)) {
1876 				continue;
1877 			}
1878 
1879 			(void) emlxs_mb_reg_vpi(vport, NULL);
1880 		}
1881 
1882 		/* Attempt to send any pending IO */
1883 		EMLXS_SLI_ISSUE_IOCB_CMD(hba, &hba->chan[hba->channel_fcp], 0);
1884 	}
1885 	return (0);
1886 
1887 } /* emlxs_clear_la_mbcmpl() */
1888 
1889 
1890 /* SLI3 */
1891 extern void
1892 emlxs_mb_clear_la(emlxs_hba_t *hba, MAILBOXQ *mbq)
1893 {
1894 	MAILBOX *mb = (MAILBOX *)mbq;
1895 
1896 #ifdef FC_RPI_CHECK
1897 	emlxs_rpi_check(hba);
1898 #endif	/* FC_RPI_CHECK */
1899 
1900 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1901 
1902 	mb->un.varClearLA.eventTag = hba->link_event_tag;
1903 	mb->mbxCommand = MBX_CLEAR_LA;
1904 	mb->mbxOwner = OWN_HOST;
1905 	mbq->mbox_cmpl = emlxs_clear_la_mbcmpl;
1906 	mbq->port = (void *)&PPORT;
1907 
1908 	return;
1909 
1910 } /* emlxs_mb_clear_la() */
1911 
1912 
1913 /*
1914  * emlxs_mb_read_status  Issue a READ STATUS mailbox command
1915  */
1916 /*ARGSUSED*/
1917 extern void
1918 emlxs_mb_read_status(emlxs_hba_t *hba, MAILBOXQ *mbq)
1919 {
1920 	MAILBOX *mb = (MAILBOX *)mbq;
1921 
1922 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1923 
1924 	mb->mbxCommand = MBX_READ_STATUS;
1925 	mb->mbxOwner = OWN_HOST;
1926 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1927 	mbq->port = (void *)&PPORT;
1928 
1929 } /* fc_read_status() */
1930 
1931 
1932 /*
1933  * emlxs_mb_read_lnk_stat  Issue a LINK STATUS mailbox command
1934  */
1935 /*ARGSUSED*/
1936 extern void
1937 emlxs_mb_read_lnk_stat(emlxs_hba_t *hba, MAILBOXQ *mbq)
1938 {
1939 	MAILBOX *mb = (MAILBOX *)mbq;
1940 
1941 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1942 
1943 	mb->mbxCommand = MBX_READ_LNK_STAT;
1944 	mb->mbxOwner = OWN_HOST;
1945 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1946 	mbq->port = (void *)&PPORT;
1947 
1948 } /* emlxs_mb_read_lnk_stat() */
1949 
1950 
1951 
1952 
1953 
1954 
1955 /*
1956  * emlxs_mb_config_ring  Issue a CONFIG RING mailbox command
1957  */
1958 extern void
1959 emlxs_mb_config_ring(emlxs_hba_t *hba, int32_t ring, MAILBOXQ *mbq)
1960 {
1961 	MAILBOX *mb = (MAILBOX *)mbq;
1962 	int32_t i;
1963 	int32_t j;
1964 
1965 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
1966 
1967 	j = 0;
1968 	for (i = 0; i < ring; i++) {
1969 		j += hba->sli.sli3.ring_masks[i];
1970 	}
1971 
1972 	for (i = 0; i < hba->sli.sli3.ring_masks[ring]; i++) {
1973 		if ((j + i) >= 6) {
1974 			break;
1975 		}
1976 
1977 		mb->un.varCfgRing.rrRegs[i].rval  =
1978 		    hba->sli.sli3.ring_rval[j + i];
1979 		mb->un.varCfgRing.rrRegs[i].rmask =
1980 		    hba->sli.sli3.ring_rmask[j + i];
1981 		mb->un.varCfgRing.rrRegs[i].tval  =
1982 		    hba->sli.sli3.ring_tval[j + i];
1983 		mb->un.varCfgRing.rrRegs[i].tmask =
1984 		    hba->sli.sli3.ring_tmask[j + i];
1985 	}
1986 
1987 	mb->un.varCfgRing.ring = ring;
1988 	mb->un.varCfgRing.profile = 0;
1989 	mb->un.varCfgRing.maxOrigXchg = 0;
1990 	mb->un.varCfgRing.maxRespXchg = 0;
1991 	mb->un.varCfgRing.recvNotify = 1;
1992 	mb->un.varCfgRing.numMask = hba->sli.sli3.ring_masks[ring];
1993 	mb->mbxCommand = MBX_CONFIG_RING;
1994 	mb->mbxOwner = OWN_HOST;
1995 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
1996 	mbq->port = (void *)&PPORT;
1997 
1998 	return;
1999 
2000 } /* emlxs_mb_config_ring() */
2001 
2002 
2003 /*
2004  *  emlxs_mb_config_link  Issue a CONFIG LINK mailbox command
2005  */
2006 extern void
2007 emlxs_mb_config_link(emlxs_hba_t *hba, MAILBOXQ *mbq)
2008 {
2009 	MAILBOX	*mb = (MAILBOX *)mbq;
2010 	emlxs_port_t   *port = &PPORT;
2011 	emlxs_config_t *cfg = &CFG;
2012 
2013 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2014 
2015 	/*
2016 	 * NEW_FEATURE SLI-2, Coalescing Response Feature.
2017 	 */
2018 	if (cfg[CFG_CR_DELAY].current) {
2019 		mb->un.varCfgLnk.cr = 1;
2020 		mb->un.varCfgLnk.ci = 1;
2021 		mb->un.varCfgLnk.cr_delay = cfg[CFG_CR_DELAY].current;
2022 		mb->un.varCfgLnk.cr_count = cfg[CFG_CR_COUNT].current;
2023 	}
2024 
2025 	if (cfg[CFG_ACK0].current) {
2026 		mb->un.varCfgLnk.ack0_enable = 1;
2027 	}
2028 
2029 	mb->un.varCfgLnk.myId = port->did;
2030 	mb->un.varCfgLnk.edtov = hba->fc_edtov;
2031 	mb->un.varCfgLnk.arbtov = hba->fc_arbtov;
2032 	mb->un.varCfgLnk.ratov = hba->fc_ratov;
2033 	mb->un.varCfgLnk.rttov = hba->fc_rttov;
2034 	mb->un.varCfgLnk.altov = hba->fc_altov;
2035 	mb->un.varCfgLnk.crtov = hba->fc_crtov;
2036 	mb->un.varCfgLnk.citov = hba->fc_citov;
2037 	mb->mbxCommand = MBX_CONFIG_LINK;
2038 	mb->mbxOwner = OWN_HOST;
2039 	mbq->mbox_cmpl = NULL;
2040 	mbq->port = (void *)port;
2041 
2042 	return;
2043 
2044 } /* emlxs_mb_config_link() */
2045 
2046 
2047 static uint32_t
2048 emlxs_init_link_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
2049 {
2050 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
2051 	emlxs_config_t	*cfg = &CFG;
2052 	MAILBOX *mb;
2053 
2054 	mb = (MAILBOX *)mbq;
2055 	if (mb->mbxStatus) {
2056 		if ((hba->flag & FC_SLIM2_MODE) &&
2057 		    (hba->mbox_queue_flag == MBX_NOWAIT)) {
2058 			/* Retry only MBX_NOWAIT requests */
2059 
2060 			if ((cfg[CFG_LINK_SPEED].current > 0) &&
2061 			    ((mb->mbxStatus == 0x0011) ||
2062 			    (mb->mbxStatus == 0x0500))) {
2063 
2064 				EMLXS_MSGF(EMLXS_CONTEXT,
2065 				    &emlxs_mbox_event_msg,
2066 				    "Retrying.  %s: status=%x. Auto-speed set.",
2067 				    emlxs_mb_cmd_xlate(mb->mbxCommand),
2068 				    (uint32_t)mb->mbxStatus);
2069 
2070 				mb->un.varInitLnk.link_flags &=
2071 				    ~FLAGS_LINK_SPEED;
2072 				mb->un.varInitLnk.link_speed = 0;
2073 
2074 				emlxs_mb_retry(hba, mbq);
2075 				return (1);
2076 			}
2077 		}
2078 	}
2079 	return (0);
2080 
2081 } /* emlxs_init_link_mbcmpl() */
2082 
2083 
2084 /*
2085  *  emlxs_mb_init_link  Issue an INIT LINK mailbox command
2086  */
2087 extern void
2088 emlxs_mb_init_link(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t topology,
2089     uint32_t linkspeed)
2090 {
2091 	MAILBOX *mb = (MAILBOX *)mbq;
2092 	emlxs_vpd_t	*vpd = &VPD;
2093 	emlxs_config_t	*cfg = &CFG;
2094 
2095 	if ((hba->sli_mode == EMLXS_HBA_SLI4_MODE) &&
2096 	    (SLI4_FCOE_MODE)) {
2097 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
2098 		mbq->nonembed = NULL;
2099 		mbq->mbox_cmpl = NULL; /* no cmpl needed */
2100 		mbq->port = (void *)&PPORT;
2101 
2102 		mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK;
2103 		mb->mbxOwner = OWN_HOST;
2104 		return;
2105 	}
2106 
2107 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2108 
2109 	switch (topology) {
2110 	case FLAGS_LOCAL_LB:
2111 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
2112 		mb->un.varInitLnk.link_flags |= FLAGS_LOCAL_LB;
2113 		break;
2114 	case FLAGS_TOPOLOGY_MODE_LOOP_PT:
2115 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
2116 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
2117 		break;
2118 	case FLAGS_TOPOLOGY_MODE_PT_PT:
2119 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
2120 		break;
2121 	case FLAGS_TOPOLOGY_MODE_LOOP:
2122 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_LOOP;
2123 		break;
2124 	case FLAGS_TOPOLOGY_MODE_PT_LOOP:
2125 		mb->un.varInitLnk.link_flags = FLAGS_TOPOLOGY_MODE_PT_PT;
2126 		mb->un.varInitLnk.link_flags |= FLAGS_TOPOLOGY_FAILOVER;
2127 		break;
2128 	}
2129 
2130 	if (cfg[CFG_LILP_ENABLE].current == 0) {
2131 		/* Disable LIRP/LILP support */
2132 		mb->un.varInitLnk.link_flags |= FLAGS_LIRP_LILP;
2133 	}
2134 
2135 	/*
2136 	 * Setting up the link speed
2137 	 */
2138 	switch (linkspeed) {
2139 	case 0:
2140 		break;
2141 
2142 	case 1:
2143 		if (!(vpd->link_speed & LMT_1GB_CAPABLE)) {
2144 			linkspeed = 0;
2145 		}
2146 		break;
2147 
2148 	case 2:
2149 		if (!(vpd->link_speed & LMT_2GB_CAPABLE)) {
2150 			linkspeed = 0;
2151 		}
2152 		break;
2153 
2154 	case 4:
2155 		if (!(vpd->link_speed & LMT_4GB_CAPABLE)) {
2156 			linkspeed = 0;
2157 		}
2158 		break;
2159 
2160 	case 8:
2161 		if (!(vpd->link_speed & LMT_8GB_CAPABLE)) {
2162 			linkspeed = 0;
2163 		}
2164 		break;
2165 
2166 	case 10:
2167 		if (!(vpd->link_speed & LMT_10GB_CAPABLE)) {
2168 			linkspeed = 0;
2169 		}
2170 		break;
2171 
2172 	case 16:
2173 		if (!(vpd->link_speed & LMT_16GB_CAPABLE)) {
2174 			linkspeed = 0;
2175 		}
2176 		break;
2177 
2178 	default:
2179 		linkspeed = 0;
2180 		break;
2181 
2182 	}
2183 
2184 	if ((linkspeed > 0) && (vpd->feaLevelHigh >= 0x02)) {
2185 		mb->un.varInitLnk.link_flags |= FLAGS_LINK_SPEED;
2186 		mb->un.varInitLnk.link_speed = linkspeed;
2187 	}
2188 
2189 	mb->un.varInitLnk.link_flags |= FLAGS_PREABORT_RETURN;
2190 
2191 	mb->un.varInitLnk.fabric_AL_PA =
2192 	    (uint8_t)cfg[CFG_ASSIGN_ALPA].current;
2193 	mb->mbxCommand = (volatile uint8_t) MBX_INIT_LINK;
2194 	mb->mbxOwner = OWN_HOST;
2195 	mbq->mbox_cmpl = emlxs_init_link_mbcmpl;
2196 	mbq->port = (void *)&PPORT;
2197 
2198 
2199 	return;
2200 
2201 } /* emlxs_mb_init_link() */
2202 
2203 
2204 /*
2205  *  emlxs_mb_down_link  Issue a DOWN LINK mailbox command
2206  */
2207 /*ARGSUSED*/
2208 extern void
2209 emlxs_mb_down_link(emlxs_hba_t *hba, MAILBOXQ *mbq)
2210 {
2211 	MAILBOX *mb = (MAILBOX *)mbq;
2212 
2213 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2214 
2215 	mb->mbxCommand = MBX_DOWN_LINK;
2216 	mb->mbxOwner = OWN_HOST;
2217 	mbq->mbox_cmpl = NULL;
2218 	mbq->port = (void *)&PPORT;
2219 
2220 	return;
2221 
2222 } /* emlxs_mb_down_link() */
2223 
2224 
2225 static uint32_t
2226 emlxs_read_sparam_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
2227 {
2228 	emlxs_port_t *port = &PPORT;
2229 	MAILBOX *mb;
2230 	MATCHMAP *mp;
2231 	emlxs_port_t *vport;
2232 	int32_t i;
2233 	uint32_t  control;
2234 	uint8_t null_wwn[8];
2235 
2236 	mb = (MAILBOX *)mbq;
2237 	if (mb->mbxStatus) {
2238 		if (mb->mbxStatus == MBXERR_NO_RESOURCES) {
2239 			control = mb->un.varRdSparm.un.sp64.tus.f.bdeSize;
2240 			if (control == 0) {
2241 				(void) emlxs_mb_read_sparam(hba, mbq);
2242 			}
2243 			emlxs_mb_retry(hba, mbq);
2244 			return (1);
2245 		}
2246 		return (0);
2247 	}
2248 	mp = (MATCHMAP *)mbq->bp;
2249 	if (!mp) {
2250 		return (0);
2251 	}
2252 
2253 	bcopy((caddr_t)mp->virt, (caddr_t)&hba->sparam, sizeof (SERV_PARM));
2254 
2255 	/* Initialize the node name and port name only once */
2256 	bzero(null_wwn, 8);
2257 	if ((bcmp((caddr_t)&hba->wwnn, (caddr_t)null_wwn, 8) == 0) &&
2258 	    (bcmp((caddr_t)&hba->wwpn, (caddr_t)null_wwn, 8) == 0)) {
2259 		bcopy((caddr_t)&hba->sparam.nodeName,
2260 		    (caddr_t)&hba->wwnn, sizeof (NAME_TYPE));
2261 
2262 		bcopy((caddr_t)&hba->sparam.portName,
2263 		    (caddr_t)&hba->wwpn, sizeof (NAME_TYPE));
2264 	} else {
2265 		bcopy((caddr_t)&hba->wwnn,
2266 		    (caddr_t)&hba->sparam.nodeName, sizeof (NAME_TYPE));
2267 
2268 		bcopy((caddr_t)&hba->wwpn,
2269 		    (caddr_t)&hba->sparam.portName, sizeof (NAME_TYPE));
2270 	}
2271 
2272 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2273 	    "SPARAM: EDTOV hba=%x mbox_csp=%x BBC=%x",
2274 	    hba->fc_edtov, hba->sparam.cmn.e_d_tov,
2275 	    hba->sparam.cmn.bbCreditlsb);
2276 
2277 	/* Initialize the physical port */
2278 	bcopy((caddr_t)&hba->sparam, (caddr_t)&port->sparam,
2279 	    sizeof (SERV_PARM));
2280 	bcopy((caddr_t)&hba->wwpn, (caddr_t)&port->wwpn,
2281 	    sizeof (NAME_TYPE));
2282 	bcopy((caddr_t)&hba->wwnn, (caddr_t)&port->wwnn,
2283 	    sizeof (NAME_TYPE));
2284 
2285 	/* Initialize the virtual ports */
2286 	for (i = 1; i < MAX_VPORTS; i++) {
2287 		vport = &VPORT(i);
2288 		if (! (vport->flag & EMLXS_PORT_BOUND)) {
2289 			continue;
2290 		}
2291 
2292 		bcopy((caddr_t)&hba->sparam,
2293 		    (caddr_t)&vport->sparam,
2294 		    sizeof (SERV_PARM));
2295 
2296 		bcopy((caddr_t)&vport->wwnn,
2297 		    (caddr_t)&vport->sparam.nodeName,
2298 		    sizeof (NAME_TYPE));
2299 
2300 		bcopy((caddr_t)&vport->wwpn,
2301 		    (caddr_t)&vport->sparam.portName,
2302 		    sizeof (NAME_TYPE));
2303 	}
2304 
2305 	return (0);
2306 
2307 } /* emlxs_read_sparam_mbcmpl() */
2308 
2309 
2310 /*
2311  * emlxs_mb_read_sparam  Issue a READ SPARAM mailbox command
2312  */
2313 extern uint32_t
2314 emlxs_mb_read_sparam(emlxs_hba_t *hba, MAILBOXQ *mbq)
2315 {
2316 	MAILBOX *mb = (MAILBOX *)mbq;
2317 	MATCHMAP *mp;
2318 
2319 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2320 
2321 	if ((mp = (MATCHMAP *)emlxs_mem_get(hba, MEM_BUF)) == 0) {
2322 		mb->mbxCommand = MBX_READ_SPARM64;
2323 
2324 		return (1);
2325 	}
2326 
2327 	mb->un.varRdSparm.un.sp64.tus.f.bdeSize = sizeof (SERV_PARM);
2328 	mb->un.varRdSparm.un.sp64.addrHigh = PADDR_HI(mp->phys);
2329 	mb->un.varRdSparm.un.sp64.addrLow = PADDR_LO(mp->phys);
2330 	mb->mbxCommand = MBX_READ_SPARM64;
2331 	mb->mbxOwner = OWN_HOST;
2332 	mbq->mbox_cmpl = emlxs_read_sparam_mbcmpl;
2333 	mbq->port = (void *)&PPORT;
2334 
2335 	/*
2336 	 * save address for completion
2337 	 */
2338 	mbq->bp = (void *)mp;
2339 
2340 	return (0);
2341 
2342 } /* emlxs_mb_read_sparam() */
2343 
2344 
2345 /*
2346  * emlxs_mb_read_rpi    Issue a READ RPI mailbox command
2347  */
2348 /*ARGSUSED*/
2349 extern uint32_t
2350 emlxs_mb_read_rpi(emlxs_hba_t *hba, uint32_t rpi, MAILBOXQ *mbq,
2351     uint32_t flag)
2352 {
2353 	MAILBOX *mb = (MAILBOX *)mbq;
2354 
2355 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2356 
2357 	/*
2358 	 * Set flag to issue action on cmpl
2359 	 */
2360 	mb->un.varWords[30] = flag;
2361 	mb->un.varRdRPI.reqRpi = (volatile uint16_t) rpi;
2362 	mb->mbxCommand = MBX_READ_RPI64;
2363 	mb->mbxOwner = OWN_HOST;
2364 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2365 	mbq->port = (void *)&PPORT;
2366 
2367 	return (0);
2368 } /* emlxs_mb_read_rpi() */
2369 
2370 
2371 /*
2372  * emlxs_mb_read_xri    Issue a READ XRI mailbox command
2373  */
2374 /*ARGSUSED*/
2375 extern uint32_t
2376 emlxs_mb_read_xri(emlxs_hba_t *hba, uint32_t xri, MAILBOXQ *mbq,
2377     uint32_t flag)
2378 {
2379 	MAILBOX *mb = (MAILBOX *)mbq;
2380 
2381 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2382 
2383 	/*
2384 	 * Set flag to issue action on cmpl
2385 	 */
2386 	mb->un.varWords[30] = flag;
2387 	mb->un.varRdXRI.reqXri = (volatile uint16_t)xri;
2388 	mb->mbxCommand = MBX_READ_XRI;
2389 	mb->mbxOwner = OWN_HOST;
2390 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2391 	mbq->port = (void *)&PPORT;
2392 
2393 	return (0);
2394 } /* emlxs_mb_read_xri() */
2395 
2396 
2397 /*ARGSUSED*/
2398 extern int32_t
2399 emlxs_mb_check_sparm(emlxs_hba_t *hba, SERV_PARM *nsp)
2400 {
2401 	uint32_t nsp_value;
2402 	uint32_t *iptr;
2403 
2404 	if (nsp->cmn.fPort) {
2405 		return (0);
2406 	}
2407 
2408 	/* Validate the service parameters */
2409 	iptr = (uint32_t *)&nsp->portName;
2410 	if (iptr[0] == 0 && iptr[1] == 0) {
2411 		return (1);
2412 	}
2413 
2414 	iptr = (uint32_t *)&nsp->nodeName;
2415 	if (iptr[0] == 0 && iptr[1] == 0) {
2416 		return (2);
2417 	}
2418 
2419 	if (nsp->cls2.classValid) {
2420 		nsp_value =
2421 		    ((nsp->cls2.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls2.
2422 		    rcvDataSizeLsb;
2423 
2424 		/* If the receive data length is zero then set it to */
2425 		/* the CSP value */
2426 		if (!nsp_value) {
2427 			nsp->cls2.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb;
2428 			nsp->cls2.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb;
2429 			return (0);
2430 		}
2431 	}
2432 
2433 	if (nsp->cls3.classValid) {
2434 		nsp_value =
2435 		    ((nsp->cls3.rcvDataSizeMsb & 0x0f) << 8) | nsp->cls3.
2436 		    rcvDataSizeLsb;
2437 
2438 		/* If the receive data length is zero then set it to */
2439 		/* the CSP value */
2440 		if (!nsp_value) {
2441 			nsp->cls3.rcvDataSizeMsb = nsp->cmn.bbRcvSizeMsb;
2442 			nsp->cls3.rcvDataSizeLsb = nsp->cmn.bbRcvSizeLsb;
2443 			return (0);
2444 		}
2445 	}
2446 
2447 	return (0);
2448 
2449 } /* emlxs_mb_check_sparm() */
2450 
2451 
2452 
2453 
2454 /*
2455  * emlxs_mb_set_var   Issue a special debug mbox command to write slim
2456  */
2457 /*ARGSUSED*/
2458 extern void
2459 emlxs_mb_set_var(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t addr,
2460     uint32_t value)
2461 {
2462 	MAILBOX *mb = (MAILBOX *)mbq;
2463 
2464 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2465 
2466 	/* addr = 0x090597 is AUTO ABTS disable for ELS commands */
2467 	/* addr = 0x052198 is DELAYED ABTS enable for ELS commands */
2468 	/* addr = 0x100506 is for setting PCI MAX READ value */
2469 
2470 	/*
2471 	 * Always turn on DELAYED ABTS for ELS timeouts
2472 	 */
2473 	if ((addr == 0x052198) && (value == 0)) {
2474 		value = 1;
2475 	}
2476 
2477 	mb->un.varWords[0] = addr;
2478 	mb->un.varWords[1] = value;
2479 	mb->mbxCommand = MBX_SET_VARIABLE;
2480 	mb->mbxOwner = OWN_HOST;
2481 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2482 	mbq->port = (void *)&PPORT;
2483 
2484 } /* emlxs_mb_set_var() */
2485 
2486 
2487 /*
2488  * Disable Traffic Cop
2489  */
2490 /*ARGSUSED*/
2491 extern void
2492 emlxs_disable_tc(emlxs_hba_t *hba, MAILBOXQ *mbq)
2493 {
2494 	MAILBOX *mb = (MAILBOX *)mbq;
2495 
2496 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2497 
2498 	mb->un.varWords[0] = 0x50797;
2499 	mb->un.varWords[1] = 0;
2500 	mb->un.varWords[2] = 0xfffffffe;
2501 	mb->mbxCommand = MBX_SET_VARIABLE;
2502 	mb->mbxOwner = OWN_HOST;
2503 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2504 	mbq->port = (void *)&PPORT;
2505 
2506 } /* emlxs_disable_tc() */
2507 
2508 
2509 extern void
2510 emlxs_mb_config_hbq(emlxs_hba_t *hba, MAILBOXQ *mbq, int hbq_id)
2511 {
2512 	HBQ_INIT_t	*hbq;
2513 	MAILBOX		*mb = (MAILBOX *)mbq;
2514 	int		i;
2515 
2516 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2517 
2518 	hbq = &hba->sli.sli3.hbq_table[hbq_id];
2519 
2520 	mb->un.varCfgHbq.hbqId = hbq_id;
2521 	mb->un.varCfgHbq.numEntries = hbq->HBQ_numEntries;
2522 	mb->un.varCfgHbq.recvNotify = hbq->HBQ_recvNotify;
2523 	mb->un.varCfgHbq.numMask = hbq->HBQ_num_mask;
2524 	mb->un.varCfgHbq.profile = hbq->HBQ_profile;
2525 	mb->un.varCfgHbq.ringMask = hbq->HBQ_ringMask;
2526 	mb->un.varCfgHbq.headerLen = hbq->HBQ_headerLen;
2527 	mb->un.varCfgHbq.logEntry = hbq->HBQ_logEntry;
2528 	mb->un.varCfgHbq.hbqaddrLow = PADDR_LO(hbq->HBQ_host_buf.phys);
2529 	mb->un.varCfgHbq.hbqaddrHigh = PADDR_HI(hbq->HBQ_host_buf.phys);
2530 	mb->mbxCommand = MBX_CONFIG_HBQ;
2531 	mb->mbxOwner = OWN_HOST;
2532 	mbq->mbox_cmpl = NULL;
2533 	mbq->port = (void *)&PPORT;
2534 
2535 	/* Copy info for profiles 2,3,5. Other profiles this area is reserved */
2536 	if ((hbq->HBQ_profile == 2) || (hbq->HBQ_profile == 3) ||
2537 	    (hbq->HBQ_profile == 5)) {
2538 		bcopy(&hbq->profiles.allprofiles,
2539 		    &mb->un.varCfgHbq.profiles.allprofiles,
2540 		    sizeof (hbq->profiles));
2541 	}
2542 
2543 	/* Return if no rctl / type masks for this HBQ */
2544 	if (!hbq->HBQ_num_mask) {
2545 		return;
2546 	}
2547 
2548 	/* Otherwise we setup specific rctl / type masks for this HBQ */
2549 	for (i = 0; i < hbq->HBQ_num_mask; i++) {
2550 		mb->un.varCfgHbq.hbqMasks[i].tmatch =
2551 		    hbq->HBQ_Masks[i].tmatch;
2552 		mb->un.varCfgHbq.hbqMasks[i].tmask = hbq->HBQ_Masks[i].tmask;
2553 		mb->un.varCfgHbq.hbqMasks[i].rctlmatch =
2554 		    hbq->HBQ_Masks[i].rctlmatch;
2555 		mb->un.varCfgHbq.hbqMasks[i].rctlmask =
2556 		    hbq->HBQ_Masks[i].rctlmask;
2557 	}
2558 
2559 	return;
2560 
2561 } /* emlxs_mb_config_hbq() */
2562 
2563 
2564 /* SLI3 */
2565 static uint32_t
2566 emlxs_reg_vpi_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
2567 {
2568 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
2569 	MAILBOX *mb;
2570 
2571 	mb = (MAILBOX *)mbq;
2572 
2573 	mutex_enter(&EMLXS_PORT_LOCK);
2574 
2575 	if (mb->mbxStatus != MBX_SUCCESS) {
2576 		port->flag &= ~EMLXS_PORT_REG_VPI;
2577 		mutex_exit(&EMLXS_PORT_LOCK);
2578 
2579 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2580 		    "cmpl_reg_vpi:%d failed. status=%x",
2581 		    port->vpi, mb->mbxStatus);
2582 		return (0);
2583 	}
2584 
2585 	port->flag |= EMLXS_PORT_REG_VPI_CMPL;
2586 
2587 	mutex_exit(&EMLXS_PORT_LOCK);
2588 
2589 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2590 	    "cmpl_reg_vpi:%d ",
2591 	    port->vpi);
2592 
2593 	return (0);
2594 
2595 } /* emlxs_reg_vpi_mbcmpl */
2596 
2597 
2598 /* SLI3 */
2599 extern uint32_t
2600 emlxs_mb_reg_vpi(emlxs_port_t *port, emlxs_buf_t *sbp)
2601 {
2602 	emlxs_hba_t *hba = HBA;
2603 	MAILBOXQ *mbq;
2604 	MAILBOX	*mb;
2605 	int rval;
2606 
2607 	if (hba->sli_mode > EMLXS_HBA_SLI3_MODE) {
2608 		return (1);
2609 	}
2610 
2611 	if (!(hba->flag & FC_NPIV_ENABLED)) {
2612 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2613 		    "reg_vpi:%d failed. NPIV disabled.",
2614 		    port->vpi);
2615 		return (1);
2616 	}
2617 
2618 	if (port->flag & EMLXS_PORT_REG_VPI) {
2619 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2620 		    "reg_vpi:%d failed. Already registered.",
2621 		    port->vpi);
2622 		return (0);
2623 	}
2624 
2625 	mutex_enter(&EMLXS_PORT_LOCK);
2626 
2627 	/* Can't reg vpi until ClearLA is sent */
2628 	if (hba->state != FC_READY) {
2629 		mutex_exit(&EMLXS_PORT_LOCK);
2630 
2631 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2632 		    "reg_vpi:%d failed. HBA state not READY",
2633 		    port->vpi);
2634 		return (1);
2635 	}
2636 
2637 	/* Must have port id */
2638 	if (!port->did) {
2639 		mutex_exit(&EMLXS_PORT_LOCK);
2640 
2641 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2642 		    "reg_vpi:%d failed. Port did=0",
2643 		    port->vpi);
2644 		return (1);
2645 	}
2646 
2647 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
2648 		mutex_exit(&EMLXS_PORT_LOCK);
2649 
2650 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2651 		    "reg_vpi:%d failed. Unable to allocate mbox.",
2652 		    port->vpi);
2653 		return (1);
2654 	}
2655 
2656 	port->flag |= EMLXS_PORT_REG_VPI;
2657 
2658 	mutex_exit(&EMLXS_PORT_LOCK);
2659 
2660 	mb = (MAILBOX *)mbq->mbox;
2661 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2662 
2663 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2664 	    "reg_vpi:%d", port->vpi);
2665 
2666 	mb->un.varRegVpi.vpi = port->vpi;
2667 	mb->un.varRegVpi.sid = port->did;
2668 	mb->mbxCommand = MBX_REG_VPI;
2669 	mb->mbxOwner = OWN_HOST;
2670 
2671 	mbq->sbp = (void *)sbp;
2672 	mbq->mbox_cmpl = emlxs_reg_vpi_mbcmpl;
2673 	mbq->context = NULL;
2674 	mbq->port = (void *)port;
2675 
2676 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
2677 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
2678 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2679 		    "reg_vpi:%d failed. Unable to send request.",
2680 		    port->vpi);
2681 
2682 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2683 		return (1);
2684 	}
2685 
2686 	return (0);
2687 
2688 } /* emlxs_mb_reg_vpi() */
2689 
2690 
2691 /* SLI3 */
2692 static uint32_t
2693 emlxs_unreg_vpi_mbcmpl(emlxs_hba_t *hba, MAILBOXQ *mbq)
2694 {
2695 	emlxs_port_t *port = (emlxs_port_t *)mbq->port;
2696 	MAILBOX *mb;
2697 
2698 	mb  = (MAILBOX *)mbq->mbox;
2699 
2700 	if (mb->mbxStatus != MBX_SUCCESS) {
2701 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2702 		    "unreg_vpi_mbcmpl:%d failed. status=%x",
2703 		    port->vpi, mb->mbxStatus);
2704 		return (0);
2705 	}
2706 
2707 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2708 	    "unreg_vpi_mbcmpl:%d", port->vpi);
2709 
2710 	mutex_enter(&EMLXS_PORT_LOCK);
2711 	port->flag &= ~EMLXS_PORT_REG_VPI_CMPL;
2712 	mutex_exit(&EMLXS_PORT_LOCK);
2713 
2714 	return (0);
2715 
2716 } /* emlxs_unreg_vpi_mbcmpl() */
2717 
2718 
2719 /* SLI3 */
2720 extern uint32_t
2721 emlxs_mb_unreg_vpi(emlxs_port_t *port)
2722 {
2723 	emlxs_hba_t	*hba = HBA;
2724 	MAILBOXQ	*mbq;
2725 	MAILBOX		*mb;
2726 	int		rval;
2727 
2728 	if (hba->sli_mode > EMLXS_HBA_SLI3_MODE) {
2729 		return (1);
2730 	}
2731 
2732 	mutex_enter(&EMLXS_PORT_LOCK);
2733 
2734 	if (!(port->flag & EMLXS_PORT_REG_VPI) ||
2735 	    !(port->flag & EMLXS_PORT_REG_VPI_CMPL)) {
2736 
2737 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2738 		    "unreg_vpi:%d failed. Not registered. flag=%x",
2739 		    port->vpi, port->flag);
2740 
2741 		mutex_exit(&EMLXS_PORT_LOCK);
2742 		return (0);
2743 	}
2744 
2745 	if (!(mbq = (MAILBOXQ *)emlxs_mem_get(hba, MEM_MBOX))) {
2746 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2747 		    "unreg_vpi:%d failed. Unable to allocate mbox.",
2748 		    port->vpi);
2749 
2750 		mutex_exit(&EMLXS_PORT_LOCK);
2751 		return (1);
2752 	}
2753 
2754 	port->flag &= ~EMLXS_PORT_REG_VPI;
2755 
2756 	mutex_exit(&EMLXS_PORT_LOCK);
2757 
2758 	EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2759 	    "unreg_vpi:%d", port->vpi);
2760 
2761 	mb = (MAILBOX *)mbq->mbox;
2762 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2763 	mb->un.varUnregVpi.vpi = port->vpi;
2764 	mb->mbxCommand = MBX_UNREG_VPI;
2765 	mb->mbxOwner = OWN_HOST;
2766 
2767 	mbq->mbox_cmpl = emlxs_unreg_vpi_mbcmpl;
2768 	mbq->context = NULL;
2769 	mbq->port = (void *)port;
2770 
2771 	rval = EMLXS_SLI_ISSUE_MBOX_CMD(hba, mbq, MBX_NOWAIT, 0);
2772 	if ((rval != MBX_BUSY) && (rval != MBX_SUCCESS)) {
2773 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_sli_detail_msg,
2774 		    "unreg_vpi:%d failed. Unable to send request.",
2775 		    port->vpi);
2776 
2777 		emlxs_mem_put(hba, MEM_MBOX, (void *)mbq);
2778 		return (1);
2779 	}
2780 
2781 	return (0);
2782 
2783 } /* emlxs_mb_unreg_vpi() */
2784 
2785 
2786 /*
2787  * emlxs_mb_config_farp  Issue a CONFIG FARP mailbox command
2788  */
2789 extern void
2790 emlxs_mb_config_farp(emlxs_hba_t *hba, MAILBOXQ *mbq)
2791 {
2792 	MAILBOX *mb = (MAILBOX *)mbq;
2793 
2794 	bzero((void *)mb, MAILBOX_CMD_BSIZE);
2795 
2796 	bcopy((uint8_t *)&hba->wwpn,
2797 	    (uint8_t *)&mb->un.varCfgFarp.portname, sizeof (NAME_TYPE));
2798 
2799 	bcopy((uint8_t *)&hba->wwpn,
2800 	    (uint8_t *)&mb->un.varCfgFarp.nodename, sizeof (NAME_TYPE));
2801 
2802 	mb->un.varCfgFarp.filterEnable = 1;
2803 	mb->un.varCfgFarp.portName = 1;
2804 	mb->un.varCfgFarp.nodeName = 1;
2805 	mb->mbxCommand = MBX_CONFIG_FARP;
2806 	mb->mbxOwner = OWN_HOST;
2807 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2808 	mbq->port = (void *)&PPORT;
2809 
2810 } /* emlxs_mb_config_farp() */
2811 
2812 
2813 /*
2814  * emlxs_mb_read_nv  Issue a READ CONFIG mailbox command
2815  */
2816 /*ARGSUSED*/
2817 extern void
2818 emlxs_mb_read_config(emlxs_hba_t *hba, MAILBOXQ *mbq)
2819 {
2820 	MAILBOX *mb = (MAILBOX *)mbq;
2821 
2822 	if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
2823 		bzero((void *) mb, MAILBOX_CMD_SLI4_BSIZE);
2824 		mbq->nonembed = NULL;
2825 	} else {
2826 		bzero((void *)mb, MAILBOX_CMD_BSIZE);
2827 	}
2828 
2829 	mb->mbxCommand = MBX_READ_CONFIG;
2830 	mb->mbxOwner = OWN_HOST;
2831 	mbq->mbox_cmpl = NULL; /* no cmpl needed */
2832 	mbq->port = (void *)&PPORT;
2833 
2834 } /* emlxs_mb_read_config() */
2835 
2836 
2837 /*
2838  * NAME:     emlxs_mb_put
2839  *
2840  * FUNCTION: put mailbox cmd onto the mailbox queue.
2841  *
2842  * EXECUTION ENVIRONMENT: process and interrupt level.
2843  *
2844  * NOTES:
2845  *
2846  * CALLED FROM: EMLXS_SLI_ISSUE_MBOX_CMD
2847  *
2848  * INPUT: hba           - pointer to the device info area
2849  *      mbp             - pointer to mailbox queue entry of mailbox cmd
2850  *
2851  * RETURNS: NULL - command queued
2852  */
2853 extern void
2854 emlxs_mb_put(emlxs_hba_t *hba, MAILBOXQ *mbq)
2855 {
2856 
2857 	mutex_enter(&EMLXS_MBOX_LOCK);
2858 
2859 	if (hba->mbox_queue.q_first) {
2860 
2861 		/*
2862 		 * queue command to end of list
2863 		 */
2864 		((MAILBOXQ *)hba->mbox_queue.q_last)->next = mbq;
2865 		hba->mbox_queue.q_last = (uint8_t *)mbq;
2866 		hba->mbox_queue.q_cnt++;
2867 	} else {
2868 
2869 		/*
2870 		 * add command to empty list
2871 		 */
2872 		hba->mbox_queue.q_first = (uint8_t *)mbq;
2873 		hba->mbox_queue.q_last = (uint8_t *)mbq;
2874 		hba->mbox_queue.q_cnt = 1;
2875 	}
2876 
2877 	mbq->next = NULL;
2878 
2879 	mutex_exit(&EMLXS_MBOX_LOCK);
2880 } /* emlxs_mb_put() */
2881 
2882 
2883 /*
2884  * NAME:     emlxs_mb_get
2885  *
2886  * FUNCTION: get a mailbox command from mailbox command queue
2887  *
2888  * EXECUTION ENVIRONMENT: interrupt level.
2889  *
2890  * NOTES:
2891  *
2892  * CALLED FROM: emlxs_handle_mb_event
2893  *
2894  * INPUT: hba       - pointer to the device info area
2895  *
2896  * RETURNS: NULL - no match found mb pointer - pointer to a mailbox command
2897  */
2898 extern MAILBOXQ *
2899 emlxs_mb_get(emlxs_hba_t *hba)
2900 {
2901 	MAILBOXQ	*p_first = NULL;
2902 
2903 	mutex_enter(&EMLXS_MBOX_LOCK);
2904 
2905 	if (hba->mbox_queue.q_first) {
2906 		p_first = (MAILBOXQ *)hba->mbox_queue.q_first;
2907 		hba->mbox_queue.q_first = (uint8_t *)p_first->next;
2908 
2909 		if (hba->mbox_queue.q_first == NULL) {
2910 			hba->mbox_queue.q_last = NULL;
2911 			hba->mbox_queue.q_cnt = 0;
2912 		} else {
2913 			hba->mbox_queue.q_cnt--;
2914 		}
2915 
2916 		p_first->next = NULL;
2917 	}
2918 
2919 	mutex_exit(&EMLXS_MBOX_LOCK);
2920 
2921 	return (p_first);
2922 
2923 } /* emlxs_mb_get() */
2924 
2925 
2926 /* EMLXS_PORT_LOCK must be held when calling this */
2927 void
2928 emlxs_mb_init(emlxs_hba_t *hba, MAILBOXQ *mbq, uint32_t flag, uint32_t tmo)
2929 {
2930 	MATCHMAP	*mp;
2931 
2932 	HBASTATS.MboxIssued++;
2933 	hba->mbox_queue_flag = flag;
2934 
2935 	/* Set the Mailbox timer */
2936 	if (hba->timer_tics) {
2937 		hba->mbox_timer = hba->timer_tics + tmo;
2938 	} else {
2939 		hba->mbox_timer = DRV_TIME + tmo;
2940 	}
2941 
2942 	/* Initialize mailbox */
2943 	mbq->flag &= MBQ_INIT_MASK;
2944 	mbq->next = 0;
2945 
2946 	mutex_enter(&EMLXS_MBOX_LOCK);
2947 	hba->mbox_mbq = (void *)mbq;
2948 	mutex_exit(&EMLXS_MBOX_LOCK);
2949 
2950 	if (mbq->nonembed) {
2951 		mp = (MATCHMAP *) mbq->nonembed;
2952 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
2953 		    DDI_DMA_SYNC_FORDEV);
2954 	}
2955 
2956 	if (mbq->bp) {
2957 		mp = (MATCHMAP *) mbq->bp;
2958 		EMLXS_MPDATA_SYNC(mp->dma_handle, 0, mp->size,
2959 		    DDI_DMA_SYNC_FORDEV);
2960 	}
2961 	return;
2962 
2963 } /* emlxs_mb_init() */
2964 
2965 
2966 extern void
2967 emlxs_mb_fini(emlxs_hba_t *hba, MAILBOX *mb, uint32_t mbxStatus)
2968 {
2969 	emlxs_port_t	*port = &PPORT;
2970 	MATCHMAP	*mbox_nonembed;
2971 	MATCHMAP	*mbox_bp;
2972 	emlxs_buf_t	*mbox_sbp;
2973 	fc_unsol_buf_t	*mbox_ubp;
2974 	IOCBQ		*mbox_iocbq;
2975 	MAILBOXQ	*mbox_mbq;
2976 	MAILBOX		*mbox;
2977 	uint32_t	mbox_queue_flag;
2978 
2979 	mutex_enter(&EMLXS_PORT_LOCK);
2980 
2981 	if (hba->mbox_queue_flag) {
2982 		HBASTATS.MboxCompleted++;
2983 
2984 		if (mbxStatus != MBX_SUCCESS) {
2985 			HBASTATS.MboxError++;
2986 		} else {
2987 			HBASTATS.MboxGood++;
2988 		}
2989 	}
2990 
2991 	mutex_enter(&EMLXS_MBOX_LOCK);
2992 	mbox_queue_flag = hba->mbox_queue_flag;
2993 	mbox_mbq = (MAILBOXQ *)hba->mbox_mbq;
2994 
2995 	if (mbox_mbq) {
2996 		mbox_nonembed = (MATCHMAP *)mbox_mbq->nonembed;
2997 		mbox_bp = (MATCHMAP *)mbox_mbq->bp;
2998 		mbox_sbp = (emlxs_buf_t *)mbox_mbq->sbp;
2999 		mbox_ubp = (fc_unsol_buf_t *)mbox_mbq->ubp;
3000 		mbox_iocbq = (IOCBQ *)mbox_mbq->iocbq;
3001 	} else {
3002 		mbox_nonembed = NULL;
3003 		mbox_bp = NULL;
3004 		mbox_sbp = NULL;
3005 		mbox_ubp = NULL;
3006 		mbox_iocbq = NULL;
3007 	}
3008 
3009 	hba->mbox_mbq = NULL;
3010 	hba->mbox_queue_flag = 0;
3011 	hba->mbox_timer = 0;
3012 	mutex_exit(&EMLXS_MBOX_LOCK);
3013 
3014 	mutex_exit(&EMLXS_PORT_LOCK);
3015 
3016 #ifdef SFCT_SUPPORT
3017 	if (mb && mbox_sbp && mbox_sbp->fct_cmd) {
3018 		EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_fct_detail_msg,
3019 		    "FCT mailbox: %s: status=%x",
3020 		    emlxs_mb_cmd_xlate(mb->mbxCommand),
3021 		    mb->mbxStatus);
3022 	}
3023 #endif /* SFCT_SUPPORT */
3024 
3025 	if (mbox_queue_flag == MBX_NOWAIT) {
3026 		/* Check for deferred MBUF cleanup */
3027 		if (mbox_bp) {
3028 			emlxs_mem_put(hba, MEM_BUF, (void *)mbox_bp);
3029 		}
3030 		if (mbox_nonembed) {
3031 			emlxs_mem_put(hba, MEM_BUF,
3032 			    (void *)mbox_nonembed);
3033 		}
3034 		if (mbox_mbq) {
3035 			emlxs_mem_put(hba, MEM_MBOX,
3036 			    (void *)mbox_mbq);
3037 		}
3038 	} else {  /* MBX_WAIT */
3039 		if (mbox_mbq) {
3040 			if (mb) {
3041 				/* Copy the local mailbox provided back into */
3042 				/* the original mailbox */
3043 				if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
3044 					bcopy((uint32_t *)mb,
3045 					    (uint32_t *)mbox_mbq,
3046 					    MAILBOX_CMD_SLI4_BSIZE);
3047 				} else {
3048 					bcopy((uint32_t *)mb,
3049 					    (uint32_t *)mbox_mbq,
3050 					    MAILBOX_CMD_BSIZE);
3051 				}
3052 			}
3053 
3054 			mbox = (MAILBOX *)mbox_mbq;
3055 			mbox->mbxStatus = (uint16_t)mbxStatus;
3056 
3057 			/* Mark mailbox complete */
3058 			mbox_mbq->flag |= MBQ_COMPLETED;
3059 		}
3060 
3061 		/* Wake up the sleeping thread */
3062 		if (mbox_queue_flag == MBX_SLEEP) {
3063 			mutex_enter(&EMLXS_MBOX_LOCK);
3064 			cv_broadcast(&EMLXS_MBOX_CV);
3065 			mutex_exit(&EMLXS_MBOX_LOCK);
3066 		}
3067 	}
3068 
3069 	emlxs_mb_deferred_cmpl(port, mbxStatus, mbox_sbp, mbox_ubp, mbox_iocbq);
3070 
3071 	return;
3072 
3073 } /* emlxs_mb_fini() */
3074 
3075 
3076 extern void
3077 emlxs_mb_deferred_cmpl(emlxs_port_t *port, uint32_t mbxStatus, emlxs_buf_t *sbp,
3078     fc_unsol_buf_t *ubp, IOCBQ *iocbq)
3079 {
3080 	emlxs_hba_t *hba = HBA;
3081 	emlxs_ub_priv_t	*ub_priv;
3082 
3083 #ifdef SFCT_SUPPORT
3084 	if (sbp && sbp->fct_cmd && (sbp->fct_state == EMLXS_FCT_REG_PENDING)) {
3085 		mutex_enter(&EMLXS_PKT_LOCK);
3086 		sbp->fct_flags |= EMLXS_FCT_REGISTERED;
3087 		cv_broadcast(&EMLXS_PKT_CV);
3088 		mutex_exit(&EMLXS_PKT_LOCK);
3089 
3090 		sbp = NULL;
3091 	}
3092 #endif /* SFCT_SUPPORT */
3093 
3094 	/* Check for deferred pkt completion */
3095 	if (sbp) {
3096 		if (mbxStatus != MBX_SUCCESS) {
3097 			/* Set error status */
3098 			sbp->pkt_flags &= ~PACKET_STATE_VALID;
3099 			emlxs_set_pkt_state(sbp, IOSTAT_LOCAL_REJECT,
3100 			    IOERR_NO_RESOURCES, 1);
3101 		}
3102 
3103 		emlxs_pkt_complete(sbp, -1, 0, 1);
3104 	}
3105 
3106 	/* Check for deferred ub completion */
3107 	if (ubp) {
3108 		ub_priv = ubp->ub_fca_private;
3109 
3110 		if (mbxStatus == MBX_SUCCESS) {
3111 			emlxs_ub_callback(ub_priv->port, ubp);
3112 		} else {
3113 			(void) emlxs_fca_ub_release(ub_priv->port, 1,
3114 			    &ubp->ub_token);
3115 		}
3116 	}
3117 
3118 	/* Special handling for restricted login */
3119 	if (iocbq == (IOCBQ *)1) {
3120 		iocbq = NULL;
3121 	}
3122 
3123 	/* Check for deferred iocb tx */
3124 	if (iocbq) {
3125 		/* Check for driver special codes */
3126 		/* These indicate the mailbox is being flushed */
3127 		if (mbxStatus >= MBX_DRIVER_RESERVED) {
3128 			/* Set the error status and return it */
3129 			iocbq->iocb.ULPSTATUS = IOSTAT_LOCAL_REJECT;
3130 			iocbq->iocb.un.grsp.perr.statLocalError =
3131 			    IOERR_ABORT_REQUESTED;
3132 
3133 			emlxs_proc_channel_event(hba, iocbq->channel,
3134 			    iocbq);
3135 		} else {
3136 			EMLXS_SLI_ISSUE_IOCB_CMD(hba, iocbq->channel,
3137 			    iocbq);
3138 		}
3139 	}
3140 
3141 	return;
3142 
3143 } /* emlxs_mb_deferred_cmpl() */
3144 
3145 
3146 extern void
3147 emlxs_mb_flush(emlxs_hba_t *hba)
3148 {
3149 	MAILBOXQ	*mbq;
3150 	uint32_t	mbxStatus;
3151 
3152 	mbxStatus = (hba->flag & FC_HARDWARE_ERROR) ?
3153 	    MBX_HARDWARE_ERROR : MBX_NOT_FINISHED;
3154 
3155 	/* Flush out the active mbox command */
3156 	emlxs_mb_fini(hba, NULL, mbxStatus);
3157 
3158 	/* Flush out the queued mbox commands */
3159 	while (mbq = (MAILBOXQ *)emlxs_mb_get(hba)) {
3160 		mutex_enter(&EMLXS_MBOX_LOCK);
3161 		hba->mbox_queue_flag = MBX_NOWAIT;
3162 		hba->mbox_mbq = (void *)mbq;
3163 		mutex_exit(&EMLXS_MBOX_LOCK);
3164 
3165 		emlxs_mb_fini(hba, NULL, mbxStatus);
3166 	}
3167 
3168 	return;
3169 
3170 } /* emlxs_mb_flush */
3171 
3172 
3173 extern char *
3174 emlxs_mb_cmd_xlate(uint8_t cmd)
3175 {
3176 	static char	buffer[32];
3177 	uint32_t	i;
3178 	uint32_t	count;
3179 
3180 	count = sizeof (emlxs_mb_cmd_table) / sizeof (emlxs_table_t);
3181 	for (i = 0; i < count; i++) {
3182 		if (cmd == emlxs_mb_cmd_table[i].code) {
3183 			return (emlxs_mb_cmd_table[i].string);
3184 		}
3185 	}
3186 
3187 	(void) snprintf(buffer, sizeof (buffer), "Cmd=0x%x", cmd);
3188 	return (buffer);
3189 
3190 } /* emlxs_mb_cmd_xlate() */
3191 
3192 extern char *
3193 emlxs_request_feature_xlate(uint32_t mask)
3194 {
3195 	static char	buffer[64];
3196 	uint32_t	i;
3197 
3198 	bzero((char *)&buffer[0], 64);
3199 	for (i = 0; i < 12; i++) {
3200 		if (mask & (1<<i)) {
3201 			(void) strlcat(buffer,
3202 			    emlxs_request_feature_table[i].string,
3203 			    sizeof (buffer));
3204 		}
3205 	}
3206 	return (buffer);
3207 }
3208